summaryrefslogtreecommitdiff
path: root/src/ls.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ls.c')
-rw-r--r--src/ls.c200
1 files changed, 132 insertions, 68 deletions
diff --git a/src/ls.c b/src/ls.c
index f1ed43bd..cd5996eb 100644
--- a/src/ls.c
+++ b/src/ls.c
@@ -1,5 +1,5 @@
/* 'dir', 'vdir' and 'ls' directory listing programs for GNU.
- Copyright (C) 1985-2013 Free Software Foundation, Inc.
+ Copyright (C) 1985-2014 Free Software Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -101,12 +101,14 @@
#include "obstack.h"
#include "quote.h"
#include "quotearg.h"
+#include "smack.h"
#include "stat-size.h"
#include "stat-time.h"
#include "strftime.h"
#include "xstrtol.h"
#include "areadlink.h"
#include "mbsalign.h"
+#include "dircolors.h"
/* Include <sys/capability.h> last to avoid a clash of <sys/types.h>
include guards with some premature versions of libcap.
@@ -185,7 +187,7 @@ verify (sizeof filetype_letter - 1 == arg_directory + 1);
enum acl_type
{
ACL_T_NONE,
- ACL_T_SELINUX_ONLY,
+ ACL_T_LSM_CONTEXT_ONLY,
ACL_T_YES
};
@@ -205,8 +207,8 @@ struct fileinfo
zero. */
mode_t linkmode;
- /* SELinux security context. */
- security_context_t scontext;
+ /* security context. */
+ char *scontext;
bool stat_ok;
@@ -215,7 +217,7 @@ struct fileinfo
bool linkok;
/* For long listings, true if the file has an access control list,
- or an SELinux security context. */
+ or a security context. */
enum acl_type acl_type;
/* For color listings, true if a regular file has capability info. */
@@ -962,25 +964,33 @@ static struct obstack subdired_obstack;
static struct obstack dev_ino_obstack;
/* Push a pair onto the device/inode stack. */
-#define DEV_INO_PUSH(Dev, Ino) \
- do \
- { \
- struct dev_ino *di; \
- obstack_blank (&dev_ino_obstack, sizeof (struct dev_ino)); \
- di = -1 + (struct dev_ino *) obstack_next_free (&dev_ino_obstack); \
- di->st_dev = (Dev); \
- di->st_ino = (Ino); \
- } \
- while (0)
+static void
+dev_ino_push (dev_t dev, ino_t ino)
+{
+ void *vdi;
+ struct dev_ino *di;
+ int dev_ino_size = sizeof *di;
+ obstack_blank (&dev_ino_obstack, dev_ino_size);
+ vdi = obstack_next_free (&dev_ino_obstack);
+ di = vdi;
+ di--;
+ di->st_dev = dev;
+ di->st_ino = ino;
+}
/* Pop a dev/ino struct off the global dev_ino_obstack
and return that struct. */
static struct dev_ino
dev_ino_pop (void)
{
- assert (sizeof (struct dev_ino) <= obstack_object_size (&dev_ino_obstack));
- obstack_blank (&dev_ino_obstack, -(int) (sizeof (struct dev_ino)));
- return *(struct dev_ino *) obstack_next_free (&dev_ino_obstack);
+ void *vdi;
+ struct dev_ino *di;
+ int dev_ino_size = sizeof *di;
+ assert (dev_ino_size <= obstack_object_size (&dev_ino_obstack));
+ obstack_blank (&dev_ino_obstack, -dev_ino_size);
+ vdi = obstack_next_free (&dev_ino_obstack);
+ di = vdi;
+ return *di;
}
/* Note the use commented out below:
@@ -1978,7 +1988,7 @@ decode_switches (int argc, char **argv)
if (file_type <= indicator_style)
{
char const *p;
- for (p = "*=>@|" + indicator_style - file_type; *p; p++)
+ for (p = &"*=>@|"[indicator_style - file_type]; *p; p++)
set_char_quoting (filename_quoting_options, *p, 1);
}
@@ -2317,6 +2327,30 @@ enum parse_state
PS_FAIL
};
+
+/* Check if the content of TERM is a valid name in dircolors. */
+
+static bool
+known_term_type (void)
+{
+ char const *term = getenv ("TERM");
+ if (! term || ! *term)
+ return false;
+
+ char const *line = G_line;
+ while (line - G_line < sizeof (G_line))
+ {
+ if (STRNCMP_LIT (line, "TERM ") == 0)
+ {
+ if (STREQ (term, line + 5))
+ return true;
+ }
+ line += strlen (line) + 1;
+ }
+
+ return false;
+}
+
static void
parse_ls_color (void)
{
@@ -2327,7 +2361,16 @@ parse_ls_color (void)
struct color_ext_type *ext; /* Extension we are working on */
if ((p = getenv ("LS_COLORS")) == NULL || *p == '\0')
- return;
+ {
+ /* LS_COLORS takes precedence, but if that's not set then
+ honor the COLORTERM and TERM env variables so that
+ we only go with the internal ANSI color codes if the
+ former is non empty or the latter is set to a known value. */
+ char const *colorterm = getenv ("COLORTERM");
+ if (! (colorterm && *colorterm) && ! known_term_type ())
+ print_with_color = false;
+ return;
+ }
ext = NULL;
strcpy (label, "??");
@@ -2542,7 +2585,7 @@ print_dir (char const *name, char const *realname, bool command_line_arg)
return;
}
- DEV_INO_PUSH (dir_stat.st_dev, dir_stat.st_ino);
+ dev_ino_push (dir_stat.st_dev, dir_stat.st_ino);
}
if (recursive || print_dir_name)
@@ -2638,7 +2681,7 @@ print_dir (char const *name, char const *realname, bool command_line_arg)
contents listed rather than being mentioned here as files. */
if (recursive)
- extract_dirs_from_files (name, command_line_arg);
+ extract_dirs_from_files (name, false);
if (format == long_format || print_block_size)
{
@@ -2734,7 +2777,7 @@ has_capability (char const *name)
}
#else
static bool
-has_capability (char const *name ATTRIBUTE_UNUSED)
+has_capability (char const *name _GL_UNUSED)
{
errno = ENOTSUP;
return false;
@@ -2749,7 +2792,12 @@ free_ent (struct fileinfo *f)
free (f->name);
free (f->linkname);
if (f->scontext != UNKNOWN_SECURITY_CONTEXT)
- freecon (f->scontext);
+ {
+ if (is_smack_enabled ())
+ free (f->scontext);
+ else
+ freecon (f->scontext);
+ }
}
/* Empty the table of files. */
@@ -2790,8 +2838,8 @@ errno_unsupported (int err)
}
/* Cache *getfilecon failure, when it's trivial to do so.
- Like getfilecon/lgetfilecon, but when F's st_dev says it's on a known-
- SELinux-challenged file system, fail with ENOTSUP immediately. */
+ Like getfilecon/lgetfilecon, but when F's st_dev says it's doesn't
+ support getting the security context, fail with ENOTSUP immediately. */
static int
getfilecon_cache (char const *file, struct fileinfo *f, bool deref)
{
@@ -2804,9 +2852,16 @@ getfilecon_cache (char const *file, struct fileinfo *f, bool deref)
errno = ENOTSUP;
return -1;
}
- int r = (deref
- ? getfilecon (file, &f->scontext)
- : lgetfilecon (file, &f->scontext));
+ int r = 0;
+#ifdef HAVE_SMACK
+ if (is_smack_enabled ())
+ r = smack_new_label_from_path (file, "security.SMACK64", deref,
+ &f->scontext);
+ else
+#endif
+ r = (deref
+ ? getfilecon (file, &f->scontext)
+ : lgetfilecon (file, &f->scontext));
if (r < 0 && errno_unsupported (errno))
unsupported_device = f->stat.st_dev;
return r;
@@ -2997,13 +3052,18 @@ gobble_file (char const *name, enum filetype type, ino_t inode,
if (format == long_format || print_scontext)
{
- bool have_selinux = false;
+ bool have_scontext = false;
bool have_acl = false;
int attr_len = getfilecon_cache (absolute_name, f, do_deref);
err = (attr_len < 0);
if (err == 0)
- have_selinux = ! STREQ ("unlabeled", f->scontext);
+ {
+ if (is_smack_enabled ())
+ have_scontext = ! STREQ ("_", f->scontext);
+ else
+ have_scontext = ! STREQ ("unlabeled", f->scontext);
+ }
else
{
f->scontext = UNKNOWN_SECURITY_CONTEXT;
@@ -3023,10 +3083,10 @@ gobble_file (char const *name, enum filetype type, ino_t inode,
have_acl = (0 < n);
}
- f->acl_type = (!have_selinux && !have_acl
+ f->acl_type = (!have_scontext && !have_acl
? ACL_T_NONE
- : (have_selinux && !have_acl
- ? ACL_T_SELINUX_ONLY
+ : (have_scontext && !have_acl
+ ? ACL_T_LSM_CONTEXT_ONLY
: ACL_T_YES));
any_has_acl |= f->acl_type != ACL_T_NONE;
@@ -3773,7 +3833,7 @@ print_long_format (const struct fileinfo *f)
struct tm *when_local;
/* Compute the mode string, except remove the trailing space if no
- file in this directory has an ACL or SELinux security context. */
+ file in this directory has an ACL or security context. */
if (f->stat_ok)
filemodestring (&f->stat, modebuf);
else
@@ -3784,7 +3844,7 @@ print_long_format (const struct fileinfo *f)
}
if (! any_has_acl)
modebuf[10] = '\0';
- else if (f->acl_type == ACL_T_SELINUX_ONLY)
+ else if (f->acl_type == ACL_T_LSM_CONTEXT_ONLY)
modebuf[10] = '.';
else if (f->acl_type == ACL_T_YES)
modebuf[10] = '+';
@@ -4732,21 +4792,21 @@ Sort entries alphabetically if none of -cftuvSUX nor --sort is specified.\n\
-b, --escape print C-style escapes for nongraphic characters\n\
"), stdout);
fputs (_("\
- --block-size=SIZE scale sizes by SIZE before printing them. E.g.,\n\
+ --block-size=SIZE scale sizes by SIZE before printing them; e.g.,\n\
'--block-size=M' prints sizes in units of\n\
- 1,048,576 bytes. See SIZE format below.\n\
+ 1,048,576 bytes; see SIZE format below\n\
-B, --ignore-backups do not list implied entries ending with ~\n\
-c with -lt: sort by, and show, ctime (time of last\n\
- modification of file status information)\n\
- with -l: show ctime and sort by name\n\
+ modification of file status information);\n\
+ with -l: show ctime and sort by name;\n\
otherwise: sort by ctime, newest first\n\
"), stdout);
fputs (_("\
-C list entries by columns\n\
- --color[=WHEN] colorize the output. WHEN defaults to 'always'\n\
- or can be 'never' or 'auto'. More info below\n\
- -d, --directory list directory entries instead of contents,\n\
- and do not dereference symbolic links\n\
+ --color[=WHEN] colorize the output; WHEN can be 'never', 'auto',\
+\n\
+ or 'always' (the default); more info below\n\
+ -d, --directory list directories themselves, not their contents\n\
-D, --dired generate output designed for Emacs' dired mode\n\
"), stdout);
fputs (_("\
@@ -4762,13 +4822,13 @@ Sort entries alphabetically if none of -cftuvSUX nor --sort is specified.\n\
"), stdout);
fputs (_("\
--group-directories-first\n\
- group directories before files.\n\
- augment with a --sort option, but any\n\
+ group directories before files;\n\
+ can be augmented with a --sort option, but any\n\
use of --sort=none (-U) disables grouping\n\
"), stdout);
fputs (_("\
-G, --no-group in a long listing, don't print group names\n\
- -h, --human-readable with -l, print sizes in human readable format\n\
+ -h, --human-readable with -l and/or -s, print human readable sizes\n\
(e.g., 1K 234M 2G)\n\
--si likewise, but use powers of 1000 not 1024\n\
"), stdout);
@@ -4777,7 +4837,7 @@ Sort entries alphabetically if none of -cftuvSUX nor --sort is specified.\n\
follow symbolic links listed on the command line\n\
--dereference-command-line-symlink-to-dir\n\
follow each command line symbolic link\n\
- that points to a directory\n\
+ that points to a directory\n\
--hide=PATTERN do not list implied entries matching shell PATTERN\
\n\
(overridden by -a or -A)\n\
@@ -4790,7 +4850,7 @@ Sort entries alphabetically if none of -cftuvSUX nor --sort is specified.\n\
-i, --inode print the index number of each file\n\
-I, --ignore=PATTERN do not list implied entries matching shell PATTERN\
\n\
- -k, --kibibytes use 1024-byte blocks\n\
+ -k, --kibibytes default to 1024-byte blocks for disk usage\n\
"), stdout);
fputs (_("\
-l use a long listing format\n\
@@ -4809,9 +4869,10 @@ Sort entries alphabetically if none of -cftuvSUX nor --sort is specified.\n\
append / indicator to directories\n\
"), stdout);
fputs (_("\
- -q, --hide-control-chars print ? instead of non graphic characters\n\
- --show-control-chars show non graphic characters as-is (default\n\
- unless program is 'ls' and output is a terminal)\n\
+ -q, --hide-control-chars print ? instead of nongraphic characters\n\
+ --show-control-chars show nongraphic characters as-is (the default,\n\
+ unless program is 'ls' and output is a terminal)\
+\n\
-Q, --quote-name enclose entry names in double quotes\n\
--quoting-style=WORD use quoting style WORD for entry names:\n\
literal, locale, shell, shell-always, c, escape\
@@ -4824,30 +4885,33 @@ Sort entries alphabetically if none of -cftuvSUX nor --sort is specified.\n\
"), stdout);
fputs (_("\
-S sort by file size\n\
- --sort=WORD sort by WORD instead of name: none -U,\n\
- extension -X, size -S, time -t, version -v\n\
- --time=WORD with -l, show time as WORD instead of modification\
-\n\
- time: atime -u, access -u, use -u, ctime -c,\n\
- or status -c; use specified time as sort key\n\
- if --sort=time\n\
+ --sort=WORD sort by WORD instead of name: none (-U), size (-S)\
+,\n\
+ time (-t), version (-v), extension (-X)\n\
+ --time=WORD with -l, show time as WORD instead of default\n\
+ modification time: atime or access or use (-u)\n\
+ ctime or status (-c); also use specified time\n\
+ as sort key if --sort=time\n\
"), stdout);
fputs (_("\
--time-style=STYLE with -l, show times using style STYLE:\n\
- full-iso, long-iso, iso, locale, +FORMAT.\n\
- FORMAT is interpreted like 'date'; if FORMAT is\n\
- FORMAT1<newline>FORMAT2, FORMAT1 applies to\n\
- non-recent files and FORMAT2 to recent files;\n\
- if STYLE is prefixed with 'posix-', STYLE\n\
- takes effect only outside the POSIX locale\n\
+ full-iso, long-iso, iso, locale, or +FORMAT;\n\
+ FORMAT is interpreted like in 'date'; if FORMAT\
+\n\
+ is FORMAT1<newline>FORMAT2, then FORMAT1 applies\
+\n\
+ to non-recent files and FORMAT2 to recent files;\
+\n\
+ if STYLE is prefixed with 'posix-', STYLE\n\
+ takes effect only outside the POSIX locale\n\
"), stdout);
fputs (_("\
-t sort by modification time, newest first\n\
-T, --tabsize=COLS assume tab stops at each COLS instead of 8\n\
"), stdout);
fputs (_("\
- -u with -lt: sort by, and show, access time\n\
- with -l: show access time and sort by name\n\
+ -u with -lt: sort by, and show, access time;\n\
+ with -l: show access time and sort by name;\n\
otherwise: sort by access time\n\
-U do not sort; list entries in directory order\n\
-v natural sort of (version) numbers within text\n\
@@ -4856,7 +4920,7 @@ Sort entries alphabetically if none of -cftuvSUX nor --sort is specified.\n\
-w, --width=COLS assume screen width instead of current value\n\
-x list entries by lines instead of by columns\n\
-X sort alphabetically by entry extension\n\
- -Z, --context print any SELinux security context of each file\n\
+ -Z, --context print any security context of each file\n\
-1 list one file per line\n\
"), stdout);
fputs (HELP_OPTION_DESCRIPTION, stdout);