Package: coreutils
Version: 5.97-5.2
Followup-For: Bug #400467
Hi,
here is a ptahc that does implement IP address sorting. It currently
only does IPv4 (though adding IPv6 would not be complicated). What's
still missing is documentation and possibly configure checks for
inet_pton and ntohl. Any chance something like this could be added?
Best,
Norbert
-- System Information:
Debian Release: 4.0
APT prefers unstable
APT policy: (500, 'unstable'), (1, 'experimental')
Architecture: i386 (i686)
Shell: /bin/sh linked to /bin/bash
Kernel: Linux 2.6.18.2
Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8)
Versions of packages coreutils depends on:
ii libacl1 2.2.41-1 Access control list shared library
ii libc6 2.3.6.ds1-8 GNU C Library: Shared libraries
ii libselinux1 1.32-3 SELinux shared libraries
coreutils recommends no packages.
-- no debconf information
--- src/sort.c~ 2006-11-26 03:57:00.000000000 -0800
+++ src/sort.c 2006-11-26 10:37:04.000000000 -0800
@@ -25,6 +25,8 @@
#include <getopt.h>
#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
#include <signal.h>
#include "system.h"
#include "error.h"
@@ -150,6 +152,7 @@
bool general_numeric; /* Flag for general, numeric comparison.
Handle numbers in exponential notation. */
bool month; /* Flag for comparison by month name. */
+ bool ipaddress; /* Flag for comparison as ip address. */
bool reverse; /* Reverse the sense of comparison. */
struct keyfield *next; /* Next keyfield to try. */
};
@@ -302,6 +305,7 @@
-g, --general-numeric-sort compare according to general numerical value\n\
-i, --ignore-nonprinting consider only printable characters\n\
-M, --month-sort compare (unknown) < `JAN' < ... < `DEC'\n\
+ -I, --ipaddress-sort compare according to IP address value\n\
-n, --numeric-sort compare according to string numerical value\n\
-r, --reverse reverse the result of comparisons\n\
\n\
@@ -353,7 +357,7 @@
exit (status);
}
-static char const short_options[] = "-bcdfgik:mMno:rsS:t:T:uy:z";
+static char const short_options[] = "-bcdfgik:mMIno:rsS:t:T:uy:z";
static struct option const long_options[] =
{
@@ -366,6 +370,7 @@
{"key", required_argument, NULL, 'k'},
{"merge", no_argument, NULL, 'm'},
{"month-sort", no_argument, NULL, 'M'},
+ {"ipaddress-sort", no_argument, NULL, 'I'},
{"numeric-sort", no_argument, NULL, 'n'},
{"output", required_argument, NULL, 'o'},
{"reverse", no_argument, NULL, 'r'},
@@ -1106,6 +1111,31 @@
: memcmp ((char *) &a, (char *) &b, sizeof a));
}
+static int
+ipaddresscompare (const char *a, const char *b)
+{
+ struct in_addr ia;
+ struct in_addr ib;
+
+ int is_a;
+ int is_b;
+
+ while (blanks[to_uchar (*a)])
+ a++;
+ while (blanks[to_uchar (*b)])
+ b++;
+
+ is_a = inet_pton (AF_INET, a, &ia);
+ is_b = inet_pton (AF_INET, b, &ib);
+ if (is_a > 0 && is_b > 0)
+ {
+ uint32_t sa = ntohl (ia.s_addr);
+ uint32_t sb = ntohl (ib.s_addr);
+ return sa == sb ? 0 : sa < sb ? -1 : 1;
+ }
+ return is_a > 0 ? -1 : is_b > 0 ? 1 : 0;
+}
+
/* Return an integer in 1..12 of the month name MONTH with length LEN.
Return 0 if the name in S is not recognized. */
@@ -1192,6 +1222,14 @@
diff = getmonth (texta, lena) - getmonth (textb, lenb);
/* Sorting like this may become slow, so in a simple locale the user
can select a faster sort that is similar to ascii sort. */
+ else if (key->ipaddress)
+ {
+ char savea = *lima, saveb = *limb;
+
+ *lima = *limb = '\0';
+ diff = ipaddresscompare (texta, textb);
+ *lima = savea, *limb = saveb;
+ }
else if (hard_LC_COLLATE)
{
if (ignore || translate)
@@ -2078,6 +2116,9 @@
case 'M':
key->month = true;
break;
+ case 'I':
+ key->ipaddress = true;
+ break;
case 'n':
key->numeric = true;
break;
@@ -2187,7 +2228,7 @@
gkey.sword = gkey.eword = SIZE_MAX;
gkey.ignore = NULL;
gkey.translate = NULL;
- gkey.numeric = gkey.general_numeric = gkey.month = gkey.reverse = false;
+ gkey.numeric = gkey.general_numeric = gkey.month = gkey.ipaddress = gkey.reverse = false;
gkey.skipsblanks = gkey.skipeblanks = false;
files = xnmalloc (argc, sizeof *files);
@@ -2263,6 +2304,7 @@
case 'g':
case 'i':
case 'M':
+ case 'I':
case 'n':
case 'r':
{
@@ -2419,7 +2461,7 @@
for (key = keylist; key; key = key->next)
if (! (key->ignore || key->translate
|| (key->skipsblanks | key->reverse
- | key->skipeblanks | key->month | key->numeric
+ | key->skipeblanks | key->month | key->ipaddress | key->numeric
| key->general_numeric)))
{
key->ignore = gkey.ignore;
@@ -2427,13 +2469,14 @@
key->skipsblanks = gkey.skipsblanks;
key->skipeblanks = gkey.skipeblanks;
key->month = gkey.month;
+ key->ipaddress = gkey.ipaddress;
key->numeric = gkey.numeric;
key->general_numeric = gkey.general_numeric;
key->reverse = gkey.reverse;
}
if (!keylist && (gkey.ignore || gkey.translate
- || (gkey.skipsblanks | gkey.skipeblanks | gkey.month
+ || (gkey.skipsblanks | gkey.skipeblanks | gkey.month | gkey.ipaddress
| gkey.numeric | gkey.general_numeric)))
insertkey (&gkey);
reverse = gkey.reverse;