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