Andrew Morgan | 2c9c053 | 2007-07-10 20:50:21 -0700 | [diff] [blame] | 1 | /* |
Andrew G. Morgan | 0f0c1fe | 2020-12-26 17:35:40 -0800 | [diff] [blame] | 2 | * Copyright (c) 1997,2007 Andrew G. Morgan <morgan@kernel.org> |
Andrew Morgan | 2c9c053 | 2007-07-10 20:50:21 -0700 | [diff] [blame] | 3 | * |
| 4 | * This displays the capabilities of a given file. |
| 5 | */ |
| 6 | |
Andrew G. Morgan | 0fe06e7 | 2020-06-04 21:44:09 -0700 | [diff] [blame] | 7 | #undef _XOPEN_SOURCE |
Lukas Kuklinek | a88ab3b | 2008-11-20 22:19:30 -0800 | [diff] [blame] | 8 | #define _XOPEN_SOURCE 500 |
| 9 | |
Andrew Morgan | 2c9c053 | 2007-07-10 20:50:21 -0700 | [diff] [blame] | 10 | #include <errno.h> |
| 11 | #include <stdio.h> |
| 12 | #include <string.h> |
Andrew Morgan | e6033df | 2007-07-18 00:02:08 -0700 | [diff] [blame] | 13 | #include <stdlib.h> |
KaiGai Kohei | 7fc5f38 | 2007-11-16 20:54:06 -0800 | [diff] [blame] | 14 | #include <unistd.h> |
| 15 | #include <dirent.h> |
| 16 | #include <sys/stat.h> |
| 17 | #include <sys/types.h> |
Andrew Morgan | 2c9c053 | 2007-07-10 20:50:21 -0700 | [diff] [blame] | 18 | #include <sys/capability.h> |
| 19 | |
Lukas Kuklinek | a88ab3b | 2008-11-20 22:19:30 -0800 | [diff] [blame] | 20 | #include <ftw.h> |
| 21 | |
KaiGai Kohei | 7fc5f38 | 2007-11-16 20:54:06 -0800 | [diff] [blame] | 22 | static int verbose = 0; |
| 23 | static int recursive = 0; |
Andrew G. Morgan | 5295c7d | 2018-09-09 17:52:06 -0700 | [diff] [blame] | 24 | static int namespace = 0; |
KaiGai Kohei | 7fc5f38 | 2007-11-16 20:54:06 -0800 | [diff] [blame] | 25 | |
Andrew G. Morgan | bdb10e7 | 2020-12-26 16:59:21 -0800 | [diff] [blame] | 26 | static void usage(int code) |
Andrew Morgan | 2c9c053 | 2007-07-10 20:50:21 -0700 | [diff] [blame] | 27 | { |
| 28 | fprintf(stderr, |
Andrew G. Morgan | 0f0c1fe | 2020-12-26 17:35:40 -0800 | [diff] [blame] | 29 | "usage: getcap [-h] [-l] [-n] [-r] [-v] <filename> [<filename> ...]\n" |
| 30 | "\n" |
| 31 | "\tdisplays the capabilities on the queried file(s).\n" |
Andrew Morgan | 2c9c053 | 2007-07-10 20:50:21 -0700 | [diff] [blame] | 32 | ); |
Andrew G. Morgan | bdb10e7 | 2020-12-26 16:59:21 -0800 | [diff] [blame] | 33 | exit(code); |
Andrew Morgan | 2c9c053 | 2007-07-10 20:50:21 -0700 | [diff] [blame] | 34 | } |
| 35 | |
Lukas Kuklinek | a88ab3b | 2008-11-20 22:19:30 -0800 | [diff] [blame] | 36 | static int do_getcap(const char *fname, const struct stat *stbuf, |
| 37 | int tflag, struct FTW* ftwbuf) |
KaiGai Kohei | 7fc5f38 | 2007-11-16 20:54:06 -0800 | [diff] [blame] | 38 | { |
| 39 | cap_t cap_d; |
| 40 | char *result; |
Andrew G. Morgan | 5295c7d | 2018-09-09 17:52:06 -0700 | [diff] [blame] | 41 | uid_t rootid; |
KaiGai Kohei | 7fc5f38 | 2007-11-16 20:54:06 -0800 | [diff] [blame] | 42 | |
Lukas Kuklinek | a88ab3b | 2008-11-20 22:19:30 -0800 | [diff] [blame] | 43 | if (tflag != FTW_F) { |
| 44 | if (verbose) { |
| 45 | printf("%s (Not a regular file)\n", fname); |
| 46 | } |
| 47 | return 0; |
| 48 | } |
| 49 | |
KaiGai Kohei | 7fc5f38 | 2007-11-16 20:54:06 -0800 | [diff] [blame] | 50 | cap_d = cap_get_file(fname); |
| 51 | if (cap_d == NULL) { |
| 52 | if (errno != ENODATA) { |
retornam | efa5c22 | 2020-02-22 11:30:37 -0800 | [diff] [blame] | 53 | fprintf(stderr, "Failed to get capabilities of file '%s' (%s)\n", |
KaiGai Kohei | 7fc5f38 | 2007-11-16 20:54:06 -0800 | [diff] [blame] | 54 | fname, strerror(errno)); |
| 55 | } else if (verbose) { |
| 56 | printf("%s\n", fname); |
| 57 | } |
Lukas Kuklinek | a88ab3b | 2008-11-20 22:19:30 -0800 | [diff] [blame] | 58 | return 0; |
KaiGai Kohei | 7fc5f38 | 2007-11-16 20:54:06 -0800 | [diff] [blame] | 59 | } |
| 60 | |
| 61 | result = cap_to_text(cap_d, NULL); |
| 62 | if (!result) { |
| 63 | fprintf(stderr, |
retornam | efa5c22 | 2020-02-22 11:30:37 -0800 | [diff] [blame] | 64 | "Failed to get capabilities of human readable format at '%s' (%s)\n", |
KaiGai Kohei | 7fc5f38 | 2007-11-16 20:54:06 -0800 | [diff] [blame] | 65 | fname, strerror(errno)); |
| 66 | cap_free(cap_d); |
Lukas Kuklinek | a88ab3b | 2008-11-20 22:19:30 -0800 | [diff] [blame] | 67 | return 0; |
KaiGai Kohei | 7fc5f38 | 2007-11-16 20:54:06 -0800 | [diff] [blame] | 68 | } |
Andrew G. Morgan | 5295c7d | 2018-09-09 17:52:06 -0700 | [diff] [blame] | 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 | } |
KaiGai Kohei | 7fc5f38 | 2007-11-16 20:54:06 -0800 | [diff] [blame] | 75 | cap_free(cap_d); |
| 76 | cap_free(result); |
| 77 | |
Lukas Kuklinek | a88ab3b | 2008-11-20 22:19:30 -0800 | [diff] [blame] | 78 | return 0; |
KaiGai Kohei | 7fc5f38 | 2007-11-16 20:54:06 -0800 | [diff] [blame] | 79 | } |
| 80 | |
Andrew Morgan | 2c9c053 | 2007-07-10 20:50:21 -0700 | [diff] [blame] | 81 | int main(int argc, char **argv) |
| 82 | { |
KaiGai Kohei | 7fc5f38 | 2007-11-16 20:54:06 -0800 | [diff] [blame] | 83 | int i, c; |
Andrew Morgan | 2c9c053 | 2007-07-10 20:50:21 -0700 | [diff] [blame] | 84 | |
Andrew G. Morgan | 0f0c1fe | 2020-12-26 17:35:40 -0800 | [diff] [blame] | 85 | while ((c = getopt(argc, argv, "rvhnl")) > 0) { |
KaiGai Kohei | 7fc5f38 | 2007-11-16 20:54:06 -0800 | [diff] [blame] | 86 | switch(c) { |
| 87 | case 'r': |
| 88 | recursive = 1; |
| 89 | break; |
| 90 | case 'v': |
| 91 | verbose = 1; |
| 92 | break; |
Andrew G. Morgan | 5295c7d | 2018-09-09 17:52:06 -0700 | [diff] [blame] | 93 | case 'n': |
| 94 | namespace = 1; |
| 95 | break; |
Andrew G. Morgan | 0799b36 | 2020-12-15 22:09:39 -0800 | [diff] [blame] | 96 | case 'h': |
Andrew G. Morgan | 0799b36 | 2020-12-15 22:09:39 -0800 | [diff] [blame] | 97 | usage(0); |
Andrew G. Morgan | 0f0c1fe | 2020-12-26 17:35:40 -0800 | [diff] [blame] | 98 | 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. Morgan | bdb10e7 | 2020-12-26 16:59:21 -0800 | [diff] [blame] | 103 | default: |
| 104 | usage(1); |
Andrew Morgan | 2c9c053 | 2007-07-10 20:50:21 -0700 | [diff] [blame] | 105 | } |
Andrew Morgan | 2c9c053 | 2007-07-10 20:50:21 -0700 | [diff] [blame] | 106 | } |
| 107 | |
KaiGai Kohei | 7fc5f38 | 2007-11-16 20:54:06 -0800 | [diff] [blame] | 108 | if (!argv[optind]) |
Andrew G. Morgan | bdb10e7 | 2020-12-26 16:59:21 -0800 | [diff] [blame] | 109 | usage(1); |
KaiGai Kohei | 7fc5f38 | 2007-11-16 20:54:06 -0800 | [diff] [blame] | 110 | |
Lukas Kuklinek | a88ab3b | 2008-11-20 22:19:30 -0800 | [diff] [blame] | 111 | 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 Kohei | 7fc5f38 | 2007-11-16 20:54:06 -0800 | [diff] [blame] | 124 | |
Andrew Morgan | 2c9c053 | 2007-07-10 20:50:21 -0700 | [diff] [blame] | 125 | return 0; |
| 126 | } |