aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--coreutils/ls.c238
1 files changed, 138 insertions, 100 deletions
diff --git a/coreutils/ls.c b/coreutils/ls.c
index 8aa05507d..edb6300ba 100644
--- a/coreutils/ls.c
+++ b/coreutils/ls.c
@@ -118,6 +118,103 @@ SPLIT_SUBDIR = 2,
#define ATTR(mode) ("\00\00\01\00\01\00\01\00"\
"\00\00\01\00\01\00\00\01" [TYPEINDEX(mode)])
+/* "[-]Cadil1", POSIX mandated options, busybox always supports */
+/* "[-]gnsx", POSIX non-mandated options, busybox always supports */
+/* "[-]Q" GNU option? busybox always supports */
+/* "[-]Ak" GNU options, busybox always supports */
+/* "[-]FLRctur", POSIX mandated options, busybox optionally supports */
+/* "[-]p", POSIX non-mandated options, busybox optionally supports */
+/* "[-]SXvThw", GNU options, busybox optionally supports */
+/* "[-]K", SELinux mandated options, busybox optionally supports */
+/* "[-]e", I think we made this one up */
+static const char ls_options[] ALIGN1 =
+ "Cadil1gnsxQAk" /* 13 opts, total 13 */
+ USE_FEATURE_LS_TIMESTAMPS("cetu") /* 4, 17 */
+ USE_FEATURE_LS_SORTFILES("SXrv") /* 4, 21 */
+ USE_FEATURE_LS_FILETYPES("Fp") /* 2, 23 */
+ USE_FEATURE_LS_FOLLOWLINKS("L") /* 1, 24 */
+ USE_FEATURE_LS_RECURSIVE("R") /* 1, 25 */
+ USE_FEATURE_HUMAN_READABLE("h") /* 1, 26 */
+ USE_SELINUX("K") /* 1, 27 */
+ USE_SELINUX("Z") /* 1, 28 */
+ USE_FEATURE_AUTOWIDTH("T:w:") /* 2, 30 */
+ ;
+enum {
+ //OPT_C = (1 << 0),
+ //OPT_a = (1 << 1),
+ //OPT_d = (1 << 2),
+ //OPT_i = (1 << 3),
+ //OPT_l = (1 << 4),
+ //OPT_1 = (1 << 5),
+ OPT_g = (1 << 6),
+ //OPT_n = (1 << 7),
+ //OPT_s = (1 << 8),
+ //OPT_x = (1 << 9),
+ OPT_Q = (1 << 10),
+ //OPT_A = (1 << 11),
+ //OPT_k = (1 << 12),
+};
+
+enum {
+ LIST_MASK_TRIGGER = 0,
+ STYLE_MASK_TRIGGER = STYLE_MASK,
+ DISP_MASK_TRIGGER = DISP_ROWS,
+ SORT_MASK_TRIGGER = SORT_MASK,
+};
+
+/* TODO: simple toggles may be stored as OPT_xxx bits instead */
+static const unsigned opt_flags[] = {
+ LIST_SHORT | STYLE_COLUMNS, /* C */
+ DISP_HIDDEN | DISP_DOT, /* a */
+ DISP_NOLIST, /* d */
+ LIST_INO, /* i */
+ LIST_LONG | STYLE_LONG, /* l - remember LS_DISP_HR in mask! */
+ LIST_SHORT | STYLE_SINGLE, /* 1 */
+ 0, /* g (don't show group) - handled via OPT_g */
+ LIST_ID_NUMERIC, /* n */
+ LIST_BLOCKS, /* s */
+ DISP_ROWS, /* x */
+ 0, /* Q (quote filename) - handled via OPT_Q */
+ DISP_HIDDEN, /* A */
+ ENABLE_SELINUX * LIST_CONTEXT, /* k (ignored if !SELINUX) */
+#if ENABLE_FEATURE_LS_TIMESTAMPS
+ TIME_CHANGE | (ENABLE_FEATURE_LS_SORTFILES * SORT_CTIME), /* c */
+ LIST_FULLTIME, /* e */
+ ENABLE_FEATURE_LS_SORTFILES * SORT_MTIME, /* t */
+ TIME_ACCESS | (ENABLE_FEATURE_LS_SORTFILES * SORT_ATIME), /* u */
+#endif
+#if ENABLE_FEATURE_LS_SORTFILES
+ SORT_SIZE, /* S */
+ SORT_EXT, /* X */
+ SORT_REVERSE, /* r */
+ SORT_VERSION, /* v */
+#endif
+#if ENABLE_FEATURE_LS_FILETYPES
+ LIST_FILETYPE | LIST_EXEC, /* F */
+ LIST_FILETYPE, /* p */
+#endif
+#if ENABLE_FEATURE_LS_FOLLOWLINKS
+ FOLLOW_LINKS, /* L */
+#endif
+#if ENABLE_FEATURE_LS_RECURSIVE
+ DISP_RECURSIVE, /* R */
+#endif
+#if ENABLE_FEATURE_HUMAN_READABLE
+ LS_DISP_HR, /* h */
+#endif
+#if ENABLE_SELINUX
+ LIST_MODEBITS|LIST_NLINKS|LIST_CONTEXT|LIST_SIZE|LIST_DATE_TIME, /* K */
+#endif
+#if ENABLE_SELINUX
+ LIST_MODEBITS|LIST_ID_NAME|LIST_CONTEXT, /* Z */
+#endif
+ (1U<<31)
+ /* options after Z are not processed through opt_flags:
+ * T, w - ignored
+ */
+};
+
+
/*
* a directory entry and its stat info are stored here
*/
@@ -573,6 +670,37 @@ static struct dnode **list_dir(const char *path)
}
+static int print_name(const char *name)
+{
+ if (option_mask32 & OPT_Q) {
+#if ENABLE_FEATURE_ASSUME_UNICODE
+ int len = 2 + mbstrlen(name);
+#else
+ int len = 2;
+#endif
+ putchar('"');
+ while (*name) {
+ if (*name == '"') {
+ putchar('\\');
+ len++;
+ }
+ putchar(*name++);
+ if (!ENABLE_FEATURE_ASSUME_UNICODE)
+ len++;
+ }
+ putchar('"');
+ return len;
+ }
+ /* No -Q: */
+#if ENABLE_FEATURE_ASSUME_UNICODE
+ fputs(name, stdout);
+ return mbstrlen(name);
+#else
+ return printf("%s", name);
+#endif
+}
+
+
static int list_single(const struct dnode *dn)
{
int i, column = 0;
@@ -617,6 +745,12 @@ static int list_single(const struct dnode *dn)
break;
case LIST_ID_NAME:
#if ENABLE_FEATURE_LS_USERNAME
+ if (option_mask32 & OPT_g) {
+ printf("%-8.8s",
+ get_cached_username(dn->dstat.st_uid));
+ column += 9;
+ break;
+ }
printf("%-8.8s %-8.8s",
get_cached_username(dn->dstat.st_uid),
get_cached_groupname(dn->dstat.st_gid));
@@ -662,21 +796,8 @@ static int list_single(const struct dnode *dn)
#endif
#if ENABLE_SELINUX
case LIST_CONTEXT:
- {
- char context[80];
- int len = 0;
-
- if (dn->sid) {
- /* I assume sid initilized with NULL */
- len = strlen(dn->sid) + 1;
- safe_strncpy(context, dn->sid, len);
- freecon(dn->sid);
- } else {
- safe_strncpy(context, "unknown", 8);
- }
- printf("%-32s ", context);
- column += MAX(33, len);
- }
+ column += printf("%-32s ", dn->sid ? dn->sid : "unknown");
+ freecon(dn->sid);
break;
#endif
case LIST_FILENAME:
@@ -687,12 +808,7 @@ static int list_single(const struct dnode *dn)
fgcolor(info.st_mode));
}
#endif
-#if ENABLE_FEATURE_ASSUME_UNICODE
- printf("%s", dn->name);
- column += mbstrlen(dn->name);
-#else
- column += printf("%s", dn->name);
-#endif
+ column += print_name(dn->name);
if (show_color) {
printf("\033[0m");
}
@@ -714,7 +830,7 @@ static int list_single(const struct dnode *dn)
fgcolor(info.st_mode));
}
#endif
- column += printf("%s", lpath) + 4;
+ column += print_name(lpath) + 4;
if (show_color) {
printf("\033[0m");
}
@@ -736,84 +852,6 @@ static int list_single(const struct dnode *dn)
}
-/* "[-]Cadil1", POSIX mandated options, busybox always supports */
-/* "[-]gnsx", POSIX non-mandated options, busybox always supports */
-/* "[-]Ak" GNU options, busybox always supports */
-/* "[-]FLRctur", POSIX mandated options, busybox optionally supports */
-/* "[-]p", POSIX non-mandated options, busybox optionally supports */
-/* "[-]SXvThw", GNU options, busybox optionally supports */
-/* "[-]K", SELinux mandated options, busybox optionally supports */
-/* "[-]e", I think we made this one up */
-static const char ls_options[] ALIGN1 =
- "Cadil1gnsxAk"
- USE_FEATURE_LS_TIMESTAMPS("cetu")
- USE_FEATURE_LS_SORTFILES("SXrv")
- USE_FEATURE_LS_FILETYPES("Fp")
- USE_FEATURE_LS_FOLLOWLINKS("L")
- USE_FEATURE_LS_RECURSIVE("R")
- USE_FEATURE_HUMAN_READABLE("h")
- USE_SELINUX("K")
- USE_FEATURE_AUTOWIDTH("T:w:")
- USE_SELINUX("Z");
-
-enum {
- LIST_MASK_TRIGGER = 0,
- STYLE_MASK_TRIGGER = STYLE_MASK,
- DISP_MASK_TRIGGER = DISP_ROWS,
- SORT_MASK_TRIGGER = SORT_MASK,
-};
-
-static const unsigned opt_flags[] = {
- LIST_SHORT | STYLE_COLUMNS, /* C */
- DISP_HIDDEN | DISP_DOT, /* a */
- DISP_NOLIST, /* d */
- LIST_INO, /* i */
- LIST_LONG | STYLE_LONG, /* l - remember LS_DISP_HR in mask! */
- LIST_SHORT | STYLE_SINGLE, /* 1 */
- 0, /* g - ingored */
- LIST_ID_NUMERIC, /* n */
- LIST_BLOCKS, /* s */
- DISP_ROWS, /* x */
- DISP_HIDDEN, /* A */
- ENABLE_SELINUX * LIST_CONTEXT, /* k (ignored if !SELINUX) */
-#if ENABLE_FEATURE_LS_TIMESTAMPS
- TIME_CHANGE | (ENABLE_FEATURE_LS_SORTFILES * SORT_CTIME), /* c */
- LIST_FULLTIME, /* e */
- ENABLE_FEATURE_LS_SORTFILES * SORT_MTIME, /* t */
- TIME_ACCESS | (ENABLE_FEATURE_LS_SORTFILES * SORT_ATIME), /* u */
-#endif
-#if ENABLE_FEATURE_LS_SORTFILES
- SORT_SIZE, /* S */
- SORT_EXT, /* X */
- SORT_REVERSE, /* r */
- SORT_VERSION, /* v */
-#endif
-#if ENABLE_FEATURE_LS_FILETYPES
- LIST_FILETYPE | LIST_EXEC, /* F */
- LIST_FILETYPE, /* p */
-#endif
-#if ENABLE_FEATURE_LS_FOLLOWLINKS
- FOLLOW_LINKS, /* L */
-#endif
-#if ENABLE_FEATURE_LS_RECURSIVE
- DISP_RECURSIVE, /* R */
-#endif
-#if ENABLE_FEATURE_HUMAN_READABLE
- LS_DISP_HR, /* h */
-#endif
-#if ENABLE_SELINUX
- LIST_MODEBITS|LIST_NLINKS|LIST_CONTEXT|LIST_SIZE|LIST_DATE_TIME, /* K */
-#endif
-#if ENABLE_FEATURE_AUTOWIDTH
- 0, 0, /* T, w - ignored */
-#endif
-#if ENABLE_SELINUX
- LIST_MODEBITS|LIST_ID_NAME|LIST_CONTEXT, /* Z */
-#endif
- (1U<<31)
-};
-
-
/* colored LS support by JaWi, janwillem.janssen@lxtreme.nl */
#if ENABLE_FEATURE_LS_COLOR
/* long option entry used only for --color, which has no short option