Kamil Dudka c7a6ab
From 7634188624dc7f48c047b29fab3715dc7a468059 Mon Sep 17 00:00:00 2001
Kamil Dudka c7a6ab
From: Kamil Dudka <kdudka@redhat.com>
Kamil Dudka c7a6ab
Date: Wed, 23 Jul 2008 09:52:05 +0200
Kamil Dudka c7a6ab
Subject: [PATCH] ls: --color now highlights files with capabilities, too
Kamil Dudka c7a6ab
* configure.ac: New option: --disable-libcap.  Check for libcap usability.
Kamil Dudka c7a6ab
* src/Makefile.am (dir_LDADD, ls_LDADD, ...): Append $(LIB_CAP).
Kamil Dudka c7a6ab
* src/ls.c: [HAVE_CAP] Include <sys/capability.h>.
Kamil Dudka c7a6ab
(has_capability): New function for capability detection.
Kamil Dudka c7a6ab
(print_color_indicator): Colorize file with capability.
Kamil Dudka c7a6ab
* src/dircolors.c: Update color lists.
Kamil Dudka c7a6ab
* src/dircolors.hin: Mention new CAPABILITY color attribute.
Kamil Dudka c7a6ab
* tests/ls/capability: Test for ls - colorize file with capability.
Kamil Dudka c7a6ab
* tests/Makefile.am (TESTS): Add ls/capability.
Kamil Dudka c7a6ab
* NEWS: Mention the change.
Kamil Dudka c7a6ab
Kamil Dudka c7a6ab
---
Kamil Dudka c7a6ab
 NEWS                |    2 ++
Kamil Dudka c7a6ab
 configure.ac        |   13 +++++++++++++
Kamil Dudka c7a6ab
 src/Makefile.am     |    6 +++---
Kamil Dudka c7a6ab
 src/dircolors.c     |    4 ++--
Kamil Dudka c7a6ab
 src/dircolors.hin   |    1 +
Kamil Dudka c7a6ab
 src/ls.c            |   43 +++++++++++++++++++++++++++++++++++++++++--
Kamil Dudka c7a6ab
 tests/Makefile.am   |    1 +
Kamil Dudka c7a6ab
 tests/ls/capability |   43 +++++++++++++++++++++++++++++++++++++++++++
Kamil Dudka c7a6ab
 8 files changed, 106 insertions(+), 7 deletions(-)
Kamil Dudka c7a6ab
 create mode 100755 tests/ls/capability
Kamil Dudka c7a6ab
Kamil Dudka c7a6ab
diff -ruN coreutils-6.12.old/configure.ac coreutils-6.12/configure.ac
Kamil Dudka c7a6ab
--- coreutils-6.12.old/configure.ac	2008-07-24 14:16:32.000000000 +0200
Kamil Dudka c7a6ab
+++ coreutils-6.12/configure.ac	2008-07-24 14:18:51.000000000 +0200
Kamil Dudka c7a6ab
@@ -58,6 +58,19 @@
Kamil Dudka c7a6ab
 LIB_SELINUX="-lselinux"
Kamil Dudka c7a6ab
 AC_SUBST(LIB_SELINUX)])
Kamil Dudka c7a6ab
 
Kamil Dudka c7a6ab
+dnl Check whether libcap is usable
Kamil Dudka c7a6ab
+AC_ARG_ENABLE([libcap],
Kamil Dudka c7a6ab
+  AC_HELP_STRING([--disable-libcap], [disable libcap support]),
Kamil Dudka c7a6ab
+  AC_MSG_WARN([libcap support disabled by user]),
Kamil Dudka c7a6ab
+  [AC_CHECK_LIB([cap], [cap_get_file],
Kamil Dudka c7a6ab
+    [AC_CHECK_HEADER([sys/capability.h],
Kamil Dudka c7a6ab
+      [LIB_CAP="-lcap" AC_DEFINE(HAVE_CAP, 1, [libcap usability])],
Kamil Dudka c7a6ab
+      [AC_MSG_WARN([header sys/capability.h was not found, support for libcap will not be built])]
Kamil Dudka c7a6ab
+      )],
Kamil Dudka c7a6ab
+    [AC_MSG_WARN([libcap library was not found or not usable, support for libcap will not be built])])
Kamil Dudka c7a6ab
+    ])
Kamil Dudka c7a6ab
+AC_SUBST([LIB_CAP])
Kamil Dudka c7a6ab
+
Kamil Dudka c7a6ab
 AC_FUNC_FORK
Kamil Dudka c7a6ab
 
Kamil Dudka c7a6ab
 optional_bin_progs=
Kamil Dudka c7a6ab
diff -ruN coreutils-6.12.orig/src/Makefile.am coreutils-6.12/src/Makefile.am
Kamil Dudka c7a6ab
--- coreutils-6.12.orig/src/Makefile.am	2008-07-10 12:30:03.000000000 +0200
Kamil Dudka c7a6ab
+++ coreutils-6.12/src/Makefile.am	2008-07-24 13:18:43.000000000 +0200
Kamil Dudka c7a6ab
@@ -98,15 +98,15 @@
Kamil Dudka c7a6ab
 
Kamil Dudka c7a6ab
 # for clock_gettime and fdatasync
Kamil Dudka c7a6ab
 dd_LDADD = $(LDADD) $(LIB_GETHRXTIME) $(LIB_FDATASYNC)
Kamil Dudka c7a6ab
-dir_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME) $(LIB_SELINUX)
Kamil Dudka c7a6ab
+dir_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME) $(LIB_SELINUX) $(LIB_CAP)
Kamil Dudka c7a6ab
 id_LDADD = $(LDADD) $(LIB_SELINUX)
Kamil Dudka c7a6ab
-ls_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME) $(LIB_SELINUX)
Kamil Dudka c7a6ab
+ls_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME) $(LIB_SELINUX) $(LIB_CAP)
Kamil Dudka c7a6ab
 mktemp_LDADD = $(LDADD) $(LIB_GETHRXTIME)
Kamil Dudka c7a6ab
 pr_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME)
Kamil Dudka c7a6ab
 shred_LDADD = $(LDADD) $(LIB_GETHRXTIME) $(LIB_FDATASYNC)
Kamil Dudka c7a6ab
 shuf_LDADD = $(LDADD) $(LIB_GETHRXTIME)
Kamil Dudka c7a6ab
 tac_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME)
Kamil Dudka c7a6ab
-vdir_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME) $(LIB_SELINUX)
Kamil Dudka c7a6ab
+vdir_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME) $(LIB_SELINUX) $(LIB_CAP)
Kamil Dudka c7a6ab
 tac_LDADD = $(LDADD) $(LIB_CLOCK_GETTIME)
Kamil Dudka c7a6ab
 
Kamil Dudka c7a6ab
 ## If necessary, add -lm to resolve use of pow in lib/strtod.c.
Kamil Dudka c7a6ab
diff --git a/src/dircolors.c b/src/dircolors.c
Kamil Dudka c7a6ab
index 56194f7..79109b9 100644
Kamil Dudka c7a6ab
--- a/src/dircolors.c
Kamil Dudka c7a6ab
+++ b/src/dircolors.c
Kamil Dudka c7a6ab
@@ -63,14 +63,14 @@ static const char *const slack_codes[] =
Kamil Dudka c7a6ab
   "SYMLINK", "ORPHAN", "MISSING", "FIFO", "PIPE", "SOCK", "BLK", "BLOCK",
Kamil Dudka c7a6ab
   "CHR", "CHAR", "DOOR", "EXEC", "LEFT", "LEFTCODE", "RIGHT", "RIGHTCODE",
Kamil Dudka c7a6ab
   "END", "ENDCODE", "SUID", "SETUID", "SGID", "SETGID", "STICKY",
Kamil Dudka c7a6ab
-  "OTHER_WRITABLE", "OWR", "STICKY_OTHER_WRITABLE", "OWT", NULL
Kamil Dudka c7a6ab
+  "OTHER_WRITABLE", "OWR", "STICKY_OTHER_WRITABLE", "OWT", "CAPABILITY", NULL
Kamil Dudka c7a6ab
 };
Kamil Dudka c7a6ab
 
Kamil Dudka c7a6ab
 static const char *const ls_codes[] =
Kamil Dudka c7a6ab
 {
Kamil Dudka c7a6ab
   "no", "no", "fi", "rs", "di", "ln", "ln", "ln", "or", "mi", "pi", "pi",
Kamil Dudka c7a6ab
   "so", "bd", "bd", "cd", "cd", "do", "ex", "lc", "lc", "rc", "rc", "ec", "ec",
Kamil Dudka c7a6ab
-  "su", "su", "sg", "sg", "st", "ow", "ow", "tw", "tw", NULL
Kamil Dudka c7a6ab
+  "su", "su", "sg", "sg", "st", "ow", "ow", "tw", "tw", "ca", NULL
Kamil Dudka c7a6ab
 };
Kamil Dudka c7a6ab
 #define array_len(Array) (sizeof (Array) / sizeof *(Array))
Kamil Dudka c7a6ab
 verify (array_len (slack_codes) == array_len (ls_codes));
Kamil Dudka c7a6ab
diff --git a/src/dircolors.hin b/src/dircolors.hin
Kamil Dudka c7a6ab
index 38914c8..5137cc6 100644
Kamil Dudka c7a6ab
--- a/src/dircolors.hin
Kamil Dudka c7a6ab
+++ b/src/dircolors.hin
Kamil Dudka c7a6ab
@@ -77,6 +77,7 @@ CHR 40;33;01	# character device driver
Kamil Dudka c7a6ab
 ORPHAN 40;31;01 # symlink to nonexistent file, or non-stat'able file
Kamil Dudka c7a6ab
 SETUID 37;41	# file that is setuid (u+s)
Kamil Dudka c7a6ab
 SETGID 30;43	# file that is setgid (g+s)
Kamil Dudka c7a6ab
+CAPABILITY 30;41	# file with capability
Kamil Dudka c7a6ab
 STICKY_OTHER_WRITABLE 30;42 # dir that is sticky and other-writable (+t,o+w)
Kamil Dudka c7a6ab
 OTHER_WRITABLE 34;42 # dir that is other-writable (o+w) and not sticky
Kamil Dudka c7a6ab
 STICKY 37;44	# dir with the sticky bit set (+t) and not other-writable
Kamil Dudka c7a6ab
diff --git a/src/ls.c b/src/ls.c
Kamil Dudka c7a6ab
index 4b69f7d..9bc66a1 100644
Kamil Dudka c7a6ab
--- a/src/ls.c
Kamil Dudka c7a6ab
+++ b/src/ls.c
Kamil Dudka c7a6ab
@@ -38,6 +38,10 @@
Kamil Dudka c7a6ab
 #include <config.h>
Kamil Dudka c7a6ab
 #include <sys/types.h>
Kamil Dudka c7a6ab
 
Kamil Dudka c7a6ab
+#ifdef HAVE_CAP
Kamil Dudka c7a6ab
+# include <sys/capability.h>
Kamil Dudka c7a6ab
+#endif
Kamil Dudka c7a6ab
+
Kamil Dudka c7a6ab
 #if HAVE_TERMIOS_H
Kamil Dudka c7a6ab
 # include <termios.h>
Kamil Dudka c7a6ab
 #endif
Kamil Dudka c7a6ab
@@ -513,14 +517,14 @@ enum indicator_no
Kamil Dudka c7a6ab
     C_LEFT, C_RIGHT, C_END, C_RESET, C_NORM, C_FILE, C_DIR, C_LINK,
Kamil Dudka c7a6ab
     C_FIFO, C_SOCK,
Kamil Dudka c7a6ab
     C_BLK, C_CHR, C_MISSING, C_ORPHAN, C_EXEC, C_DOOR, C_SETUID, C_SETGID,
Kamil Dudka c7a6ab
-    C_STICKY, C_OTHER_WRITABLE, C_STICKY_OTHER_WRITABLE
Kamil Dudka c7a6ab
+    C_STICKY, C_OTHER_WRITABLE, C_STICKY_OTHER_WRITABLE, C_CAP
Kamil Dudka c7a6ab
   };
Kamil Dudka c7a6ab
 
Kamil Dudka c7a6ab
 static const char *const indicator_name[]=
Kamil Dudka c7a6ab
   {
Kamil Dudka c7a6ab
     "lc", "rc", "ec", "rs", "no", "fi", "di", "ln", "pi", "so",
Kamil Dudka c7a6ab
     "bd", "cd", "mi", "or", "ex", "do", "su", "sg", "st",
Kamil Dudka c7a6ab
-    "ow", "tw", NULL
Kamil Dudka c7a6ab
+    "ow", "tw", "ca", NULL
Kamil Dudka c7a6ab
   };
Kamil Dudka c7a6ab
 
Kamil Dudka c7a6ab
 struct color_ext_type
Kamil Dudka c7a6ab
@@ -553,6 +557,7 @@ static struct bin_str color_indicator[] =
Kamil Dudka c7a6ab
     { LEN_STR_PAIR ("37;44") },		/* st: sticky: black on blue */
Kamil Dudka c7a6ab
     { LEN_STR_PAIR ("34;42") },		/* ow: other-writable: blue on green */
Kamil Dudka c7a6ab
     { LEN_STR_PAIR ("30;42") },		/* tw: ow w/ sticky: black on green */
Ondrej Vasik 893c38
+    { LEN_STR_PAIR ("30;41") },		/* ca: black on red */
Kamil Dudka c7a6ab
   };
Kamil Dudka c7a6ab
 
Kamil Dudka c7a6ab
 /* FIXME: comment  */
Kamil Dudka c7a6ab
@@ -3896,6 +3901,38 @@ print_type_indicator (bool stat_ok, mode_t mode, enum filetype type)
Kamil Dudka c7a6ab
     DIRED_PUTCHAR (c);
Kamil Dudka c7a6ab
 }
Kamil Dudka c7a6ab
 
Kamil Dudka c7a6ab
+#ifdef HAVE_CAP
Kamil Dudka c7a6ab
+static bool
Kamil Dudka c7a6ab
+/* Return true if NAME has a capability (see linux/capability.h) */
Kamil Dudka c7a6ab
+has_capability (const char *name)
Kamil Dudka c7a6ab
+{
Kamil Dudka c7a6ab
+  cap_t cap_d;
Kamil Dudka c7a6ab
+  char *result;
Kamil Dudka c7a6ab
+  bool has_cap;
Kamil Dudka c7a6ab
+
Kamil Dudka c7a6ab
+  cap_d = cap_get_file (name);
Kamil Dudka c7a6ab
+  if (cap_d == NULL)
Kamil Dudka c7a6ab
+    return false;
Kamil Dudka c7a6ab
+
Kamil Dudka c7a6ab
+  result = cap_to_text (cap_d, NULL);
Kamil Dudka c7a6ab
+  cap_free (cap_d);
Kamil Dudka c7a6ab
+  if (!result)
Kamil Dudka c7a6ab
+    return false;
Kamil Dudka c7a6ab
+
Kamil Dudka c7a6ab
+  /* check if human-readable capability string is empty */
Kamil Dudka c7a6ab
+  has_cap = !!*result;
Kamil Dudka c7a6ab
+
Kamil Dudka c7a6ab
+  cap_free (result);
Kamil Dudka c7a6ab
+  return has_cap;
Kamil Dudka c7a6ab
+}
Kamil Dudka c7a6ab
+#else
Kamil Dudka c7a6ab
+static bool
Kamil Dudka c7a6ab
+has_capability (const char *name)
Kamil Dudka c7a6ab
+{
Kamil Dudka c7a6ab
+  return false;
Kamil Dudka c7a6ab
+}
Kamil Dudka c7a6ab
+#endif
Kamil Dudka c7a6ab
+
Kamil Dudka c7a6ab
 /* Returns whether any color sequence was printed. */
Kamil Dudka c7a6ab
 static bool
Kamil Dudka c7a6ab
 print_color_indicator (const char *name, mode_t mode, int linkok,
Kamil Dudka c7a6ab
@@ -3923,6 +3960,8 @@ print_color_indicator (const char *name, mode_t mode, int linkok,
Kamil Dudka c7a6ab
 	    type = C_SETUID;
Kamil Dudka c7a6ab
 	  else if ((mode & S_ISGID) != 0)
Kamil Dudka c7a6ab
 	    type = C_SETGID;
Ondrej Vasik 893c38
+	  else if (is_colored (C_CAP) && has_capability (name))
Kamil Dudka c7a6ab
+	    type = C_CAP;
Kamil Dudka c7a6ab
 	  else if ((mode & S_IXUGO) != 0)
Kamil Dudka c7a6ab
 	    type = C_EXEC;
Kamil Dudka c7a6ab
 	}
Kamil Dudka c7a6ab
diff --git a/tests/Makefile.am b/tests/Makefile.am
Kamil Dudka c7a6ab
index c2da630..309d174 100644
Kamil Dudka c7a6ab
--- a/tests/Makefile.am
Kamil Dudka c7a6ab
+++ b/tests/Makefile.am
Kamil Dudka c7a6ab
@@ -313,6 +313,7 @@ TESTS =						\
Kamil Dudka c7a6ab
   ln/misc					\
Kamil Dudka c7a6ab
   ln/sf-1					\
Kamil Dudka c7a6ab
   ln/target-1					\
Kamil Dudka c7a6ab
+  ls/capability					\
Kamil Dudka c7a6ab
   ls/color-dtype-dir				\
Kamil Dudka c7a6ab
   ls/dangle					\
Kamil Dudka c7a6ab
   ls/dired					\
Kamil Dudka c7a6ab
diff --git a/tests/ls/capability b/tests/ls/capability
Kamil Dudka c7a6ab
new file mode 100755
Kamil Dudka c7a6ab
index 0000000..549e06b
Kamil Dudka c7a6ab
--- /dev/null
Kamil Dudka c7a6ab
+++ b/tests/ls/capability
Kamil Dudka c7a6ab
@@ -0,0 +1,43 @@
Kamil Dudka c7a6ab
+#!/bin/sh
Kamil Dudka c7a6ab
+# Ensure "ls --color" properly colorizes file with capability.
Kamil Dudka c7a6ab
+
Kamil Dudka c7a6ab
+# Copyright (C) 2008 Free Software Foundation, Inc.
Kamil Dudka c7a6ab
+
Kamil Dudka c7a6ab
+# This program is free software: you can redistribute it and/or modify
Kamil Dudka c7a6ab
+# it under the terms of the GNU General Public License as published by
Kamil Dudka c7a6ab
+# the Free Software Foundation, either version 3 of the License, or
Kamil Dudka c7a6ab
+# (at your option) any later version.
Kamil Dudka c7a6ab
+
Kamil Dudka c7a6ab
+# This program is distributed in the hope that it will be useful,
Kamil Dudka c7a6ab
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
Kamil Dudka c7a6ab
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Kamil Dudka c7a6ab
+# GNU General Public License for more details.
Kamil Dudka c7a6ab
+
Kamil Dudka c7a6ab
+# You should have received a copy of the GNU General Public License
Kamil Dudka c7a6ab
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
Kamil Dudka c7a6ab
+
Kamil Dudka c7a6ab
+if test "$VERBOSE" = yes; then
Kamil Dudka c7a6ab
+  set -x
Kamil Dudka c7a6ab
+  ls --version
Kamil Dudka c7a6ab
+fi
Kamil Dudka c7a6ab
+
Kamil Dudka c7a6ab
+. $srcdir/test-lib.sh
Kamil Dudka c7a6ab
+require_root_
Kamil Dudka c7a6ab
+
Kamil Dudka c7a6ab
+(setcap --help) 2>&1 |grep 'usage: setcap' > /dev/null \
Kamil Dudka c7a6ab
+  || skip_test_ "setcap utility not found"
Kamil Dudka c7a6ab
+fail=0
Kamil Dudka c7a6ab
+
Kamil Dudka c7a6ab
+# Don't let a different umask perturb the results.
Kamil Dudka c7a6ab
+umask 22
Kamil Dudka c7a6ab
+
Kamil Dudka c7a6ab
+touch test
Kamil Dudka c7a6ab
+setcap cap_net_bind_service=ep test \
Kamil Dudka c7a6ab
+  || framework_failure
Kamil Dudka c7a6ab
+code='30;41'
Kamil Dudka c7a6ab
+LS_COLORS="ca=$code" \
Kamil Dudka c7a6ab
+  ls --color=always test > out || fail=1
Kamil Dudka c7a6ab
+printf "\033[0m\033[${code}mtest\033[0m\n\033[m" > out_ok || fail=1
Kamil Dudka c7a6ab
+compare out out_ok || fail=1
Kamil Dudka c7a6ab
+
Kamil Dudka c7a6ab
+(exit $fail); exit $fail
Kamil Dudka c7a6ab
-- 
Kamil Dudka c7a6ab
1.5.4.1
Kamil Dudka c7a6ab