blob: 208bd6aaa98c02dad4bcc98558d682438ca79738 [file] [log] [blame]
Andrew Morgan2c9c0532007-07-10 20:50:21 -07001/*
Andrew G. Morgan0f0c1fe2020-12-26 17:35:40 -08002 * Copyright (c) 1997,2007 Andrew G. Morgan <morgan@kernel.org>
Andrew Morgan2c9c0532007-07-10 20:50:21 -07003 *
4 * This displays the capabilities of a given file.
5 */
6
Andrew G. Morgan0fe06e72020-06-04 21:44:09 -07007#undef _XOPEN_SOURCE
Lukas Kuklineka88ab3b2008-11-20 22:19:30 -08008#define _XOPEN_SOURCE 500
9
Andrew Morgan2c9c0532007-07-10 20:50:21 -070010#include <errno.h>
11#include <stdio.h>
12#include <string.h>
Andrew Morgane6033df2007-07-18 00:02:08 -070013#include <stdlib.h>
KaiGai Kohei7fc5f382007-11-16 20:54:06 -080014#include <unistd.h>
15#include <dirent.h>
16#include <sys/stat.h>
17#include <sys/types.h>
Andrew Morgan2c9c0532007-07-10 20:50:21 -070018#include <sys/capability.h>
19
Lukas Kuklineka88ab3b2008-11-20 22:19:30 -080020#include <ftw.h>
21
KaiGai Kohei7fc5f382007-11-16 20:54:06 -080022static int verbose = 0;
23static int recursive = 0;
Andrew G. Morgan5295c7d2018-09-09 17:52:06 -070024static int namespace = 0;
KaiGai Kohei7fc5f382007-11-16 20:54:06 -080025
Andrew G. Morganbdb10e72020-12-26 16:59:21 -080026static void usage(int code)
Andrew Morgan2c9c0532007-07-10 20:50:21 -070027{
28 fprintf(stderr,
Andrew G. Morgan0f0c1fe2020-12-26 17:35:40 -080029 "usage: getcap [-h] [-l] [-n] [-r] [-v] <filename> [<filename> ...]\n"
30 "\n"
31 "\tdisplays the capabilities on the queried file(s).\n"
Andrew Morgan2c9c0532007-07-10 20:50:21 -070032 );
Andrew G. Morganbdb10e72020-12-26 16:59:21 -080033 exit(code);
Andrew Morgan2c9c0532007-07-10 20:50:21 -070034}
35
Lukas Kuklineka88ab3b2008-11-20 22:19:30 -080036static int do_getcap(const char *fname, const struct stat *stbuf,
37 int tflag, struct FTW* ftwbuf)
KaiGai Kohei7fc5f382007-11-16 20:54:06 -080038{
39 cap_t cap_d;
40 char *result;
Andrew G. Morgan5295c7d2018-09-09 17:52:06 -070041 uid_t rootid;
KaiGai Kohei7fc5f382007-11-16 20:54:06 -080042
Lukas Kuklineka88ab3b2008-11-20 22:19:30 -080043 if (tflag != FTW_F) {
44 if (verbose) {
45 printf("%s (Not a regular file)\n", fname);
46 }
47 return 0;
48 }
49
KaiGai Kohei7fc5f382007-11-16 20:54:06 -080050 cap_d = cap_get_file(fname);
51 if (cap_d == NULL) {
52 if (errno != ENODATA) {
retornamefa5c222020-02-22 11:30:37 -080053 fprintf(stderr, "Failed to get capabilities of file '%s' (%s)\n",
KaiGai Kohei7fc5f382007-11-16 20:54:06 -080054 fname, strerror(errno));
55 } else if (verbose) {
56 printf("%s\n", fname);
57 }
Lukas Kuklineka88ab3b2008-11-20 22:19:30 -080058 return 0;
KaiGai Kohei7fc5f382007-11-16 20:54:06 -080059 }
60
61 result = cap_to_text(cap_d, NULL);
62 if (!result) {
63 fprintf(stderr,
retornamefa5c222020-02-22 11:30:37 -080064 "Failed to get capabilities of human readable format at '%s' (%s)\n",
KaiGai Kohei7fc5f382007-11-16 20:54:06 -080065 fname, strerror(errno));
66 cap_free(cap_d);
Lukas Kuklineka88ab3b2008-11-20 22:19:30 -080067 return 0;
KaiGai Kohei7fc5f382007-11-16 20:54:06 -080068 }
Andrew G. Morgan5295c7d2018-09-09 17:52:06 -070069 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 }
KaiGai Kohei7fc5f382007-11-16 20:54:06 -080075 cap_free(cap_d);
76 cap_free(result);
77
Lukas Kuklineka88ab3b2008-11-20 22:19:30 -080078 return 0;
KaiGai Kohei7fc5f382007-11-16 20:54:06 -080079}
80
Andrew Morgan2c9c0532007-07-10 20:50:21 -070081int main(int argc, char **argv)
82{
KaiGai Kohei7fc5f382007-11-16 20:54:06 -080083 int i, c;
Andrew Morgan2c9c0532007-07-10 20:50:21 -070084
Andrew G. Morgan0f0c1fe2020-12-26 17:35:40 -080085 while ((c = getopt(argc, argv, "rvhnl")) > 0) {
KaiGai Kohei7fc5f382007-11-16 20:54:06 -080086 switch(c) {
87 case 'r':
88 recursive = 1;
89 break;
90 case 'v':
91 verbose = 1;
92 break;
Andrew G. Morgan5295c7d2018-09-09 17:52:06 -070093 case 'n':
94 namespace = 1;
95 break;
Andrew G. Morgan0799b362020-12-15 22:09:39 -080096 case 'h':
Andrew G. Morgan0799b362020-12-15 22:09:39 -080097 usage(0);
Andrew G. Morgan0f0c1fe2020-12-26 17:35:40 -080098 case 'l':
99 printf("%s has a you choose license: BSD 3-clause or GPL2\n"
100 "Copyright (c) 1997,2007 Andrew G. Morgan"
101 " <morgan@kernel.org>\n", argv[0]);
102 exit(0);
Andrew G. Morganbdb10e72020-12-26 16:59:21 -0800103 default:
104 usage(1);
Andrew Morgan2c9c0532007-07-10 20:50:21 -0700105 }
Andrew Morgan2c9c0532007-07-10 20:50:21 -0700106 }
107
KaiGai Kohei7fc5f382007-11-16 20:54:06 -0800108 if (!argv[optind])
Andrew G. Morganbdb10e72020-12-26 16:59:21 -0800109 usage(1);
KaiGai Kohei7fc5f382007-11-16 20:54:06 -0800110
Lukas Kuklineka88ab3b2008-11-20 22:19:30 -0800111 for (i=optind; argv[i] != NULL; i++) {
112 struct stat stbuf;
113
114 if (lstat(argv[i], &stbuf) != 0) {
115 fprintf(stderr, "%s (%s)\n", argv[i], strerror(errno));
116 } else if (recursive) {
117 nftw(argv[i], 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 }
KaiGai Kohei7fc5f382007-11-16 20:54:06 -0800124
Andrew Morgan2c9c0532007-07-10 20:50:21 -0700125 return 0;
126}