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