Date: Mon, 10 Dec 2012 03:11:20 +0000 (UTC) From: Greg Lehey <grog@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org Subject: svn commit: r244075 - stable/9/bin/ls Message-ID: <201212100311.qBA3BKL6004047@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: grog Date: Mon Dec 10 03:11:19 2012 New Revision: 244075 URL: http://svnweb.freebsd.org/changeset/base/244075 Log: MFC to r242840: Add y flag and environment variable LS_SAMESORT to specify the same sorting order for time and name with the -t option. IEEE Std 1003.2 (POSIX.2) mandates that the -t option sort in descending order, and that if two files have the same timestamp, they should be sorted in ascending order of their names. The -r flag reverses both of these sort orders, so they're never the same. This creates significant problems for sequentially named files stored on FAT file systems, where it can be impossible to list them in the order in which they were created. Add , (comma) option to print file sizes grouped and separated by thousands using the non-monetary separator returned by localeconv(3), typically a comma or period. Modified: stable/9/bin/ls/Makefile stable/9/bin/ls/cmp.c stable/9/bin/ls/ls.1 stable/9/bin/ls/ls.c stable/9/bin/ls/ls.h stable/9/bin/ls/print.c stable/9/bin/ls/util.c Modified: stable/9/bin/ls/Makefile ============================================================================== --- stable/9/bin/ls/Makefile Mon Dec 10 02:44:47 2012 (r244074) +++ stable/9/bin/ls/Makefile Mon Dec 10 03:11:19 2012 (r244075) @@ -1,6 +1,8 @@ # @(#)Makefile 8.1 (Berkeley) 6/2/93 # $FreeBSD$ +.include <bsd.own.mk> + PROG= ls SRCS= cmp.c ls.c print.c util.c DPADD= ${LIBUTIL} Modified: stable/9/bin/ls/cmp.c ============================================================================== --- stable/9/bin/ls/cmp.c Mon Dec 10 02:44:47 2012 (r244074) +++ stable/9/bin/ls/cmp.c Mon Dec 10 03:11:19 2012 (r244075) @@ -78,6 +78,9 @@ modcmp(const FTSENT *a, const FTSENT *b) if (b->fts_statp->st_mtim.tv_nsec < a->fts_statp->st_mtim.tv_nsec) return (-1); + if (f_samesort) + return (strcoll(b->fts_name, a->fts_name)); + else return (strcoll(a->fts_name, b->fts_name)); } @@ -104,6 +107,9 @@ acccmp(const FTSENT *a, const FTSENT *b) if (b->fts_statp->st_atim.tv_nsec < a->fts_statp->st_atim.tv_nsec) return (-1); + if (f_samesort) + return (strcoll(b->fts_name, a->fts_name)); + else return (strcoll(a->fts_name, b->fts_name)); } @@ -130,6 +136,9 @@ birthcmp(const FTSENT *a, const FTSENT * if (b->fts_statp->st_birthtim.tv_nsec < a->fts_statp->st_birthtim.tv_nsec) return (-1); + if (f_samesort) + return (strcoll(b->fts_name, a->fts_name)); + else return (strcoll(a->fts_name, b->fts_name)); } @@ -156,6 +165,9 @@ statcmp(const FTSENT *a, const FTSENT *b if (b->fts_statp->st_ctim.tv_nsec < a->fts_statp->st_ctim.tv_nsec) return (-1); + if (f_samesort) + return (strcoll(b->fts_name, a->fts_name)); + else return (strcoll(a->fts_name, b->fts_name)); } Modified: stable/9/bin/ls/ls.1 ============================================================================== --- stable/9/bin/ls/ls.1 Mon Dec 10 02:44:47 2012 (r244074) +++ stable/9/bin/ls/ls.1 Mon Dec 10 03:11:19 2012 (r244075) @@ -32,7 +32,7 @@ .\" @(#)ls.1 8.7 (Berkeley) 7/29/94 .\" $FreeBSD$ .\" -.Dd April 4, 2008 +.Dd November 8, 2012 .Dt LS 1 .Os .Sh NAME @@ -40,7 +40,7 @@ .Nd list directory contents .Sh SYNOPSIS .Nm -.Op Fl ABCFGHILPRSTUWZabcdfghiklmnopqrstuwx1 +.Op Fl ABCFGHILPRSTUWZabcdfghiklmnopqrstuwxy1, .Op Fl D Ar format .Op Ar .Sh DESCRIPTION @@ -130,6 +130,8 @@ This option is equivalent to defining .Ev CLICOLOR in the environment. (See below.) +This functionality can be compiled out by removing the definition of +.Ev COLORLS . .It Fl H Symbolic links on the command line are followed. This option is assumed if @@ -249,12 +251,35 @@ subsection below, except (if the long fo the directory totals are not output when the output is in a single column, even if multi-column output is requested. .It Fl t -Sort by time modified (most recently modified -first) before sorting the operands in lexicographical -order. +Sort by descending time modified (most recently modified first). If two files +have the same modification timestamp, sort their names in ascending +lexicographical order. +The +.Fl r +option reverses both of these sort orders. +.Pp +Note that these sort orders are contradictory: the time sequence is in +descending order, the lexicographical sort is in ascending order. +This behavior is mandated by +.St -p1003.2 . +This feature can cause problems listing files stored with sequential names on +FAT file systems, such as from digital cameras, where it is possible to have +more than one image with the same timestamp. +In such a case, the photos cannot be listed in the sequence in which +they were taken. +To ensure the same sort order for time and for lexicographical sorting, set the +environment variable +.Ev LS_SAMESORT +or use the +.Fl y +option. +This causes +.Nm +to reverse the lexicographal sort order when sorting files with the +same modification timestamp. .It Fl u Use time of last access, -instead of last modification +instead of time of last modification of the file for sorting .Pq Fl t or printing @@ -268,6 +293,15 @@ The same as .Fl C , except that the multi-column output is produced with entries sorted across, rather than down, the columns. +.It Fl y +When the +.Fl t +option is set, sort the alphabetical output in the same order as the time output. +This has the same effect as setting +.Ev LS_SAMESORT . +See the description of the +.Fl t +option for more details. .It Fl 1 (The numeric digit .Dq one . ) @@ -275,6 +309,15 @@ Force output to be one entry per line. This is the default when output is not to a terminal. +.It Fl , +(Comma) When the +.Fl l +option is set, print file sizes grouped and separated by thousands using the +non-monetary separator returned by +.Xr localeconv 3 , +typically a comma or period. +If no locale is set, or the locale does not have a non-monetary separator, this +option has no effect. .El .Pp The @@ -357,8 +400,7 @@ option is given, the numeric ID's are displayed. .Pp If the file is a character special or block special file, -the major and minor device numbers for the file are displayed -in the size field. +the device number for the file is displayed in the size field. If the file is a symbolic link the pathname of the linked-to file is preceded by .Dq Li -> . @@ -530,7 +572,7 @@ variable is defined. .It Ev CLICOLOR_FORCE Color sequences are normally disabled if the output is not directed to a terminal. -This can be overridden by setting this flag. +This can be overridden by setting this variable. The .Ev TERM variable still needs to reference a color capable terminal however @@ -656,6 +698,14 @@ Not all columns have changeable widths. The fields are, in order: inode, block count, number of links, user name, group name, flags, file size, file name. +.It Ev LS_SAMESORT +If this variable is set, the +.Fl t +option sorts the names of files with the same modification timestamp in the same +sense as the time sort. +See the description of the +.Fl t +option for more details. .It Ev TERM The .Ev CLICOLOR @@ -679,6 +729,7 @@ specification. .Xr getfacl 1 , .Xr sort 1 , .Xr xterm 1 , +.Xr localeconv 3 , .Xr strftime 3 , .Xr strmode 3 , .Xr termcap 5 , @@ -717,3 +768,9 @@ option description might be a feature th based on the fact that single-column output usually goes to something other than a terminal. It is debatable whether this is a design bug. +.Pp +.St -p1003.2 +mandates opposite sort orders for files with the same timestamp when +sorting with the +.Fl t +option. Modified: stable/9/bin/ls/ls.c ============================================================================== --- stable/9/bin/ls/ls.c Mon Dec 10 02:44:47 2012 (r244074) +++ stable/9/bin/ls/ls.c Mon Dec 10 03:11:19 2012 (r244075) @@ -44,7 +44,7 @@ static char sccsid[] = "@(#)ls.c 8.5 (Be #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); -#include <sys/types.h> +#include <sys/param.h> #include <sys/stat.h> #include <sys/ioctl.h> #include <sys/mac.h> @@ -109,10 +109,11 @@ int termwidth = 80; /* default terminal int f_humanval; /* show human-readable file sizes */ int f_inode; /* print inode */ static int f_kblocks; /* print size in kilobytes */ + int f_label; /* show MAC label */ static int f_listdir; /* list actual directory, not contents */ static int f_listdot; /* list files beginning with . */ -static int f_noautodot; /* do not automatically enable -A for root */ int f_longform; /* long listing format */ +static int f_noautodot; /* do not automatically enable -A for root */ static int f_nofollow; /* don't follow symbolic link arguments */ int f_nonprint; /* show unprintables as ? */ static int f_nosort; /* don't sort output */ @@ -122,19 +123,21 @@ static int f_numericonly; /* don't conve int f_octal_escape; /* like f_octal but use C escapes if possible */ static int f_recursive; /* ls subdirectories also */ static int f_reversesort; /* reverse whatever sort is used */ - int f_sectime; /* print the real time for all files */ + int f_samesort; /* sort time and name in same direction */ + int f_sectime; /* print full time information */ static int f_singlecol; /* use single column output */ int f_size; /* list size in short listing */ +static int f_sizesort; int f_slash; /* similar to f_type, but only for dirs */ int f_sortacross; /* sort across rows, not down columns */ int f_statustime; /* use time of last mode change */ static int f_stream; /* stream the output, separate with commas */ -static int f_timesort; /* sort by time vice name */ + int f_thousands; /* show file sizes with thousands separators */ char *f_timeformat; /* user-specified time format */ -static int f_sizesort; +static int f_timesort; /* sort by time vice name */ int f_type; /* add type character for non-regular files */ static int f_whiteout; /* show whiteout entries */ - int f_label; /* show MAC label */ + #ifdef COLORLS int f_color; /* add type in color for non-regular files */ @@ -180,8 +183,10 @@ main(int argc, char *argv[]) } fts_options = FTS_PHYSICAL; - while ((ch = getopt(argc, argv, - "1ABCD:FGHILPRSTUWZabcdfghiklmnopqrstuwx")) != -1) { + if (getenv("LS_SAMESORT")) + f_samesort = 1; + while ((ch = getopt(argc, argv, + "1ABCD:FGHILPRSTUWXZabcdfghiklmnopqrstuwxy,")) != -1) { switch (ch) { /* * The -1, -C, -x and -l options all override each other so @@ -192,17 +197,9 @@ main(int argc, char *argv[]) f_longform = 0; f_stream = 0; break; - case 'B': - f_nonprint = 0; - f_octal = 1; - f_octal_escape = 0; - break; case 'C': f_sortacross = f_longform = f_singlecol = 0; break; - case 'D': - f_timeformat = optarg; - break; case 'l': f_longform = 1; f_singlecol = 0; @@ -229,16 +226,46 @@ main(int argc, char *argv[]) f_accesstime = 0; f_statustime = 0; break; + case 'a': + fts_options |= FTS_SEEDOT; + /* FALLTHROUGH */ + case 'A': + f_listdot = 1; + break; + /* The -t and -S options override each other. */ + case 'S': + f_sizesort = 1; + f_timesort = 0; + break; + case 't': + f_timesort = 1; + f_sizesort = 0; + break; + /* Other flags. Please keep alphabetic. */ + case ',': + f_thousands = 1; + break; + case 'B': + f_nonprint = 0; + f_octal = 1; + f_octal_escape = 0; + break; + case 'D': + f_timeformat = optarg; + break; case 'F': f_type = 1; f_slash = 0; break; + case 'G': + setenv("CLICOLOR", "", 1); + break; case 'H': fts_options |= FTS_COMFOLLOW; f_nofollow = 0; break; - case 'G': - setenv("CLICOLOR", "", 1); + case 'I': + f_noautodot = 1; break; case 'L': fts_options &= ~FTS_PHYSICAL; @@ -254,14 +281,19 @@ main(int argc, char *argv[]) case 'R': f_recursive = 1; break; - case 'a': - fts_options |= FTS_SEEDOT; - /* FALLTHROUGH */ - case 'A': - f_listdot = 1; + case 'T': + f_sectime = 1; break; - case 'I': - f_noautodot = 1; + case 'W': + f_whiteout = 1; + break; + case 'Z': + f_label = 1; + break; + case 'b': + f_nonprint = 0; + f_octal = 0; + f_octal_escape = 1; break; /* The -d option turns off the -R option. */ case 'd': @@ -309,33 +341,13 @@ main(int argc, char *argv[]) case 's': f_size = 1; break; - case 'T': - f_sectime = 1; - break; - /* The -t and -S options override each other. */ - case 't': - f_timesort = 1; - f_sizesort = 0; - break; - case 'S': - f_sizesort = 1; - f_timesort = 0; - break; - case 'W': - f_whiteout = 1; - break; - case 'b': - f_nonprint = 0; - f_octal = 0; - f_octal_escape = 1; - break; case 'w': f_nonprint = 0; f_octal = 0; f_octal_escape = 0; break; - case 'Z': - f_label = 1; + case 'y': + f_samesort = 1; break; default: case '?': @@ -414,8 +426,8 @@ main(int argc, char *argv[]) fts_options |= FTS_WHITEOUT; #endif - /* If -l or -s, figure out block size. */ - if (f_longform || f_size) { + /* If -i, -l or -s, figure out block size. */ + if (f_inode || f_longform || f_size) { if (f_kblocks) blocksize = 2; else { @@ -561,9 +573,10 @@ display(const FTSENT *p, FTSENT *list, i NAMES *np; off_t maxsize; long maxblock; - u_long btotal, labelstrlen, maxinode, maxlen, maxnlink; + uintmax_t maxinode; + u_long btotal, labelstrlen, maxlen, maxnlink; u_long maxlabelstr; - u_int devstrlen; + u_int sizelen; int maxflags; gid_t maxgroup; uid_t maxuser; @@ -572,7 +585,6 @@ display(const FTSENT *p, FTSENT *list, i int entries, needstats; const char *user, *group; char *flags, *labelstr = NULL; - char buf[STRBUF_SIZEOF(u_quad_t) + 1]; char ngroup[STRBUF_SIZEOF(uid_t) + 1]; char nuser[STRBUF_SIZEOF(gid_t) + 1]; @@ -581,8 +593,9 @@ display(const FTSENT *p, FTSENT *list, i btotal = 0; initmax = getenv("LS_COLWIDTHS"); /* Fields match -lios order. New ones should be added at the end. */ - maxlabelstr = maxblock = maxinode = maxlen = maxnlink = + maxlabelstr = maxblock = maxlen = maxnlink = 0; maxuser = maxgroup = maxflags = maxsize = 0; + maxinode = 0; if (initmax != NULL && *initmax != '\0') { char *initmax2, *jinitmax; int ninitmax; @@ -610,7 +623,7 @@ display(const FTSENT *p, FTSENT *list, i strcpy(initmax2, "0"); ninitmax = sscanf(jinitmax, - " %lu : %ld : %lu : %u : %u : %i : %jd : %lu : %lu ", + " %ju : %ld : %lu : %u : %u : %i : %jd : %lu : %lu ", &maxinode, &maxblock, &maxnlink, &maxuser, &maxgroup, &maxflags, &maxsize, &maxlen, &maxlabelstr); f_notabs = 1; @@ -656,7 +669,8 @@ display(const FTSENT *p, FTSENT *list, i MAKENINES(maxsize); free(jinitmax); } - devstrlen = 0; + d.s_size = 0; + sizelen = 0; flags = NULL; for (cur = list, entries = 0; cur; cur = cur->fts_link) { if (cur->fts_info == FTS_ERR || cur->fts_info == FTS_NS) { @@ -796,14 +810,12 @@ label_out: np->group = &np->data[ulen + 1]; (void)strcpy(np->group, group); - if ((S_ISCHR(sp->st_mode) || - S_ISBLK(sp->st_mode)) && - devstrlen < DEVSTR_HEX_LEN) { - if (minor(sp->st_rdev) > 255 || - minor(sp->st_rdev) < 0) - devstrlen = DEVSTR_HEX_LEN; - else - devstrlen = DEVSTR_LEN; + if (S_ISCHR(sp->st_mode) || + S_ISBLK(sp->st_mode)) { + sizelen = snprintf(NULL, 0, + "%#jx", (uintmax_t)sp->st_rdev); + if (d.s_size < sizelen) + d.s_size = sizelen; } if (f_flags) { @@ -837,25 +849,20 @@ label_out: d.maxlen = maxlen; if (needstats) { d.btotal = btotal; - (void)snprintf(buf, sizeof(buf), "%lu", maxblock); - d.s_block = strlen(buf); + d.s_block = snprintf(NULL, 0, "%lu", howmany(maxblock, blocksize)); d.s_flags = maxflags; d.s_label = maxlabelstr; d.s_group = maxgroup; - (void)snprintf(buf, sizeof(buf), "%lu", maxinode); - d.s_inode = strlen(buf); - (void)snprintf(buf, sizeof(buf), "%lu", maxnlink); - d.s_nlink = strlen(buf); - if (f_humanval) - d.s_size = HUMANVALSTR_LEN; - else { - (void)snprintf(buf, sizeof(buf), "%ju", maxsize); - d.s_size = strlen(buf); - } - if (d.s_size < devstrlen) - d.s_size = devstrlen; + d.s_inode = snprintf(NULL, 0, "%ju", maxinode); + d.s_nlink = snprintf(NULL, 0, "%lu", maxnlink); + sizelen = f_humanval ? HUMANVALSTR_LEN : + snprintf(NULL, 0, "%ju", maxsize); + if (d.s_size < sizelen) + d.s_size = sizelen; d.s_user = maxuser; } + if (f_thousands) /* make space for commas */ + d.s_size += (d.s_size - 1) / 3; printfcn(&d); output = 1; Modified: stable/9/bin/ls/ls.h ============================================================================== --- stable/9/bin/ls/ls.h Mon Dec 10 02:44:47 2012 (r244074) +++ stable/9/bin/ls/ls.h Mon Dec 10 03:11:19 2012 (r244075) @@ -36,8 +36,6 @@ #define NO_PRINT 1 #define HUMANVALSTR_LEN 5 -#define DEVSTR_LEN 8 -#define DEVSTR_HEX_LEN 15 extern long blocksize; /* block size units */ @@ -51,11 +49,13 @@ extern int f_longform; /* long listing extern int f_octal; /* print unprintables in octal */ extern int f_octal_escape; /* like f_octal but use C escapes if possible */ extern int f_nonprint; /* show unprintables as ? */ +extern int f_samesort; /* sort time and name in same direction */ extern int f_sectime; /* print the real time for all files */ extern int f_size; /* list size in short listing */ extern int f_slash; /* append a '/' if the file is a directory */ extern int f_sortacross; /* sort across rows, not down columns */ extern int f_statustime; /* use time of last mode change */ +extern int f_thousands; /* show file sizes with thousands separators */ extern char *f_timeformat; /* user-specified time format */ extern int f_notabs; /* don't use tab-separated multi-col output */ extern int f_type; /* add type character for non-regular files */ Modified: stable/9/bin/ls/print.c ============================================================================== --- stable/9/bin/ls/print.c Mon Dec 10 02:44:47 2012 (r244074) +++ stable/9/bin/ls/print.c Mon Dec 10 03:11:19 2012 (r244075) @@ -48,6 +48,7 @@ __FBSDID("$FreeBSD$"); #include <langinfo.h> #include <libutil.h> #include <stdio.h> +#include <stdint.h> #include <stdlib.h> #include <string.h> #include <time.h> @@ -151,7 +152,8 @@ printlong(const DISPLAY *dp) continue; sp = p->fts_statp; if (f_inode) - (void)printf("%*lu ", dp->s_inode, (u_long)sp->st_ino); + (void)printf("%*ju ", + dp->s_inode, (uintmax_t)sp->st_ino); if (f_size) (void)printf("%*jd ", dp->s_block, howmany(sp->st_blocks, blocksize)); @@ -327,7 +329,8 @@ printaname(const FTSENT *p, u_long inode sp = p->fts_statp; chcnt = 0; if (f_inode) - chcnt += printf("%*lu ", (int)inodefield, (u_long)sp->st_ino); + chcnt += printf("%*ju ", + (int)inodefield, (uintmax_t)sp->st_ino); if (f_size) chcnt += printf("%*jd ", (int)sizefield, howmany(sp->st_blocks, blocksize)); @@ -351,16 +354,8 @@ printaname(const FTSENT *p, u_long inode static void printdev(size_t width, dev_t dev) { - char buf[DEVSTR_HEX_LEN + 1]; - if (minor(dev) > 255 || minor(dev) < 0) - (void)snprintf(buf, sizeof(buf), "%3d, 0x%08x", - major(dev), (u_int)minor(dev)); - else - (void)snprintf(buf, sizeof(buf), "%3d, %3d", - major(dev), minor(dev)); - - (void)printf("%*s ", (u_int)width, buf); + (void)printf("%#*jx ", (u_int)width, (uintmax_t)dev); } static void @@ -611,6 +606,10 @@ printsize(size_t width, off_t bytes) humanize_number(buf, sizeof(buf), (int64_t)bytes, "", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); (void)printf("%*s ", (u_int)width, buf); + } else if (f_thousands) { /* with commas */ + /* This format assignment needed to work round gcc bug. */ + const char *format = "%*j'd "; + (void)printf(format, (u_int)width, bytes); } else (void)printf("%*jd ", (u_int)width, bytes); } Modified: stable/9/bin/ls/util.c ============================================================================== --- stable/9/bin/ls/util.c Mon Dec 10 02:44:47 2012 (r244074) +++ stable/9/bin/ls/util.c Mon Dec 10 03:11:19 2012 (r244075) @@ -222,9 +222,9 @@ usage(void) { (void)fprintf(stderr, #ifdef COLORLS - "usage: ls [-ABCFGHILPRSTUWZabcdfghiklmnopqrstuwx1] [-D format]" + "usage: ls [-ABCFGHILPRSTUWZabcdfghiklmnopqrstuwxy1,] [-D format]" #else - "usage: ls [-ABCFHILPRSTUWZabcdfghiklmnopqrstuwx1] [-D format]" + "usage: ls [-ABCFHILPRSTUWZabcdfghiklmnopqrstuwxy1,] [-D format]" #endif " [file ...]\n"); exit(1);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201212100311.qBA3BKL6004047>