* 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"
#define NAMEI_MNTS (1 << 3)
#define NAMEI_OWNERS (1 << 4)
#define NAMEI_VERTICAL (1 << 5)
+#define NAMEI_CONTEXT (1 << 6)
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;
{
while (nm) {
struct namei *next = nm->next;
+#ifdef HAVE_LIBSELINUX
+ free(nm->context);
+#endif
free(nm->name);
free(nm->abslink);
free(nm);
}
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) = '/';
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);
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;
}
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);
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);
{ "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 },
};
{
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;
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);
}
return rc;
}
-