]> git.ipfire.org Git - thirdparty/util-linux.git/blobdiff - misc-utils/namei.c
hwclock: free temporary variable before return
[thirdparty/util-linux.git] / misc-utils / namei.c
index dcaf5d2ebb49bf2ce3f4336d0b0b63bd3adc83c0..0a9ed8df80eb50bdb8613bfe19e1aa60386fcc4e 100644 (file)
@@ -19,7 +19,6 @@
  *     Arkadiusz Miƛkiewicz (1999-02-22)
  *     Li Zefan (2007-09-10).
  */
-
 #include <stdio.h>
 #include <unistd.h>
 #include <getopt.h>
 #include <pwd.h>
 #include <grp.h>
 
+#ifdef HAVE_LIBSELINUX
+# include <selinux/selinux.h>
+#endif
+
 #include "c.h"
 #include "xalloc.h"
 #include "nls.h"
@@ -49,6 +52,7 @@
 #define NAMEI_MNTS     (1 << 3)
 #define NAMEI_OWNERS   (1 << 4)
 #define NAMEI_VERTICAL (1 << 5)
+#define NAMEI_CONTEXT  (1 << 6)
 
 
 struct namei {
@@ -59,7 +63,11 @@ struct namei {
        struct namei    *next;          /* next item */
        int             level;
        int             mountpoint;     /* is mount point */
-       int             noent;          /* is this item not existing */
+       int             noent;          /* this item not existing (stores errno from stat()) */
+#ifdef HAVE_LIBSELINUX
+       int             context_len;    /* length of selinux contexts, as returned by lgetfilecon(3) */
+       char            *context;       /* selinux contexts, as set by lgetfilecon(3) */
+#endif
 };
 
 static int flags;
@@ -71,6 +79,9 @@ free_namei(struct namei *nm)
 {
        while (nm) {
                struct namei *next = nm->next;
+#ifdef HAVE_LIBSELINUX
+               free(nm->context);
+#endif
                free(nm->name);
                free(nm->abslink);
                free(nm);
@@ -99,7 +110,7 @@ readlink_to_namei(struct namei *nm, const char *path)
        }
        nm->abslink = xmalloc(sz + 1);
 
-       if (*sym != '/' && isrel) {
+       if (isrel) {
                /* create the absolute path from the relative symlink */
                memcpy(nm->abslink, path, nm->relstart);
                *(nm->abslink + nm->relstart) = '/';
@@ -151,9 +162,15 @@ new_namei(struct namei *parent, const char *path, const char *fname, int lev)
        nm->level = lev;
        nm->name = xstrdup(fname);
 
-       nm->noent = (lstat(path, &nm->st) == -1);
-       if (nm->noent)
+#ifdef HAVE_LIBSELINUX
+       /* Don't use is_selinux_enabled() here. We need info about a context
+        * also on systems where SELinux is (temporary) disabled */
+       nm->context_len = lgetfilecon(path, &nm->context);
+#endif
+       if (lstat(path, &nm->st) != 0) {
+               nm->noent = errno;
                return nm;
+       }
 
        if (S_ISLNK(nm->st.st_mode))
                readlink_to_namei(nm, path);
@@ -278,9 +295,11 @@ print_namei(struct namei *nm, char *path)
                                blanks += ucache->width + gcache->width + 2;
                        if (!(flags & NAMEI_VERTICAL))
                                blanks += 1;
+                       if (!(flags & NAMEI_CONTEXT))
+                               blanks += 1;
                        blanks += nm->level * 2;
                        printf("%*s ", blanks, "");
-                       printf(_("%s - No such file or directory\n"), nm->name);
+                       printf("%s - %s\n", nm->name, strerror(nm->noent));
                        return -1;
                }
 
@@ -306,7 +325,14 @@ print_namei(struct namei *nm, char *path)
                        printf(" %-*s", gcache->width,
                                get_id(gcache, nm->st.st_gid)->name);
                }
-
+#ifdef HAVE_LIBSELINUX
+               if (flags & NAMEI_CONTEXT) {
+                       if (nm->context)
+                               printf(" %-*s", nm->context_len, nm->context);
+                       else
+                               printf(" ?");
+               }
+#endif
                if (flags & NAMEI_VERTICAL)
                        for (i = 0; i < nm->level; i++)
                                fputs("  ", stdout);
@@ -336,14 +362,18 @@ static void __attribute__((__noreturn__)) usage(void)
        fputs(_("Follow a pathname until a terminal point is found.\n"), out);
 
        fputs(USAGE_OPTIONS, out);
-       fputs(_(" -h, --help          displays this help text\n"
-               " -V, --version       output version information and exit\n"
+       fputs(_(
                " -x, --mountpoints   show mount point directories with a 'D'\n"
                " -m, --modes         show the mode bits of each file\n"
                " -o, --owners        show owner and group name of each file\n"
                " -l, --long          use a long listing format (-m -o -v) \n"
                " -n, --nosymlinks    don't follow symlinks\n"
                " -v, --vertical      vertical align of modes and owners\n"), out);
+#ifdef HAVE_LIBSELINUX
+       fputs(_( " -Z, --context       print any security context of each file \n"), out);
+#endif
+
+       fprintf(out, USAGE_HELP_OPTIONS(21));
 
        fprintf(out, USAGE_MAN_TAIL("namei(1)"));
        exit(EXIT_SUCCESS);
@@ -359,6 +389,9 @@ static const struct option longopts[] =
        { "long",        no_argument, NULL, 'l' },
        { "nolinks",     no_argument, NULL, 'n' },
        { "vertical",    no_argument, NULL, 'v' },
+#ifdef HAVE_LIBSELINUX
+       { "context",     no_argument, NULL, 'Z' },
+#endif
        { NULL, 0, NULL, 0 },
 };
 
@@ -367,20 +400,19 @@ main(int argc, char **argv)
 {
        int c;
        int rc = EXIT_SUCCESS;
+       static const char *shortopts =
+#ifdef HAVE_LIBSELINUX
+               "Z"
+#endif
+               "hVlmnovx";
 
        setlocale(LC_ALL, "");
        bindtextdomain(PACKAGE, LOCALEDIR);
        textdomain(PACKAGE);
-       atexit(close_stdout);
+       close_stdout_atexit();
 
-       while ((c = getopt_long(argc, argv, "hVlmnovx", longopts, NULL)) != -1) {
+       while ((c = getopt_long(argc, argv, shortopts, longopts, NULL)) != -1) {
                switch(c) {
-               case 'h':
-                       usage();
-                       break;
-               case 'V':
-                       printf(UTIL_LINUX_VERSION);
-                       return EXIT_SUCCESS;
                case 'l':
                        flags |= (NAMEI_OWNERS | NAMEI_MODES | NAMEI_VERTICAL);
                        break;
@@ -399,6 +431,15 @@ main(int argc, char **argv)
                case 'v':
                        flags |= NAMEI_VERTICAL;
                        break;
+#ifdef HAVE_LIBSELINUX
+               case 'Z':
+                       flags |= NAMEI_CONTEXT;
+                       break;
+#endif
+               case 'h':
+                       usage();
+               case 'V':
+                       print_version(EXIT_SUCCESS);
                default:
                        errtryhelp(EXIT_FAILURE);
                }
@@ -447,4 +488,3 @@ main(int argc, char **argv)
 
        return rc;
 }
-