1/*
2 * Copyright (c) 1997,2007 Andrew G. Morgan  <morgan@kernel.org>
3 *
4 * This displays the capabilities of a given file.
5 */
6
7#define _XOPEN_SOURCE 500
8
9#include <errno.h>
10#include <stdio.h>
11#include <string.h>
12#include <stdlib.h>
13#include <unistd.h>
14#include <dirent.h>
15#include <sys/stat.h>
16#include <sys/types.h>
17#include <sys/capability.h>
18
19#include <ftw.h>
20
21static int verbose = 0;
22static int recursive = 0;
23
24static void usage(void)
25{
26    fprintf(stderr,
27	    "usage: getcap [-v] [-r] [-h] <filename> [<filename> ...]\n"
28	    "\n"
29	    "\tdisplays the capabilities on the queried file(s).\n"
30	);
31    exit(1);
32}
33
34static int do_getcap(const char *fname, const struct stat *stbuf,
35		     int tflag, struct FTW* ftwbuf)
36{
37    cap_t cap_d;
38    char *result;
39
40    if (tflag != FTW_F) {
41	if (verbose) {
42	    printf("%s (Not a regular file)\n", fname);
43	}
44	return 0;
45    }
46
47    cap_d = cap_get_file(fname);
48    if (cap_d == NULL) {
49	if (errno != ENODATA) {
50	    fprintf(stderr, "Failed to get capabilities of file `%s' (%s)\n",
51		    fname, strerror(errno));
52	} else if (verbose) {
53	    printf("%s\n", fname);
54	}
55	return 0;
56    }
57
58    result = cap_to_text(cap_d, NULL);
59    if (!result) {
60	fprintf(stderr,
61		"Failed to get capabilities of human readable format at `%s' (%s)\n",
62		fname, strerror(errno));
63	cap_free(cap_d);
64	return 0;
65    }
66    printf("%s %s\n", fname, result);
67    cap_free(cap_d);
68    cap_free(result);
69
70    return 0;
71}
72
73int main(int argc, char **argv)
74{
75    int i, c;
76
77    while ((c = getopt(argc, argv, "rvh")) > 0) {
78	switch(c) {
79	case 'r':
80	    recursive = 1;
81	    break;
82	case 'v':
83	    verbose = 1;
84	    break;
85	default:
86	    usage();
87	}
88    }
89
90    if (!argv[optind])
91	usage();
92
93    for (i=optind; argv[i] != NULL; i++) {
94	struct stat stbuf;
95
96	if (lstat(argv[i], &stbuf) != 0) {
97	    fprintf(stderr, "%s (%s)\n", argv[i], strerror(errno));
98	} else if (recursive) {
99	    nftw(argv[i], do_getcap, 20, FTW_PHYS);
100	} else {
101	    int tflag = S_ISREG(stbuf.st_mode) ? FTW_F :
102		(S_ISLNK(stbuf.st_mode) ? FTW_SL : FTW_NS);
103	    do_getcap(argv[i], &stbuf, tflag, 0);
104	}
105    }
106
107    return 0;
108}
109