upload tizen1.0 source
[external/libcap.git] / progs / setcap.c
1 /*
2  * Copyright (c) 1997,2007-8 Andrew G. Morgan  <morgan@kernel.org>
3  *
4  * This sets/verifies the capabilities of a given file.
5  */
6
7 #include <errno.h>
8 #include <stdio.h>
9 #include <string.h>
10 #include <stdlib.h>
11 #include <sys/capability.h>
12 #include <unistd.h>
13
14 static void usage(void)
15 {
16     fprintf(stderr,
17             "usage: setcap [-q] [-v] (-r|-|<caps>) <filename> "
18             "[ ... (-r|-|<capsN>) <filenameN> ]\n"
19             "\n"
20             " Note <filename> must be a regular (non-symlink) file.\n"
21         );
22     exit(1);
23 }
24
25 #define MAXCAP  2048
26
27 static int read_caps(int quiet, const char *filename, char *buffer)
28 {
29     int i=MAXCAP;
30
31     if (!quiet) {
32         fprintf(stderr, "Please enter caps for file [empty line to end]:\n");
33     }
34     while (i > 0) {
35         int j = read(STDIN_FILENO, buffer, i);
36
37         if (j < 0) {
38             fprintf(stderr, "\n[Error - aborting]\n");
39             exit(1);
40         }
41
42         if (j==0 || buffer[0] == '\n') {
43             /* we're done */
44             break;
45         }
46
47         /* move on... */
48
49         i -= j;
50         buffer += j;
51     }
52
53     /* <NUL> terminate */
54     buffer[0] = '\0';
55
56     return (i < MAXCAP ? 0:-1);
57 }
58
59 int main(int argc, char **argv)
60 {
61     int tried_to_cap_setfcap = 0;
62     char buffer[MAXCAP+1];
63     int retval, quiet=0, verify=0;
64     cap_t mycaps;
65     cap_value_t capflag;
66
67     if (argc < 3) {
68         usage();
69     }
70
71     mycaps = cap_get_proc();
72     if (mycaps == NULL) {
73         fprintf(stderr, "warning - unable to get process capabilities"
74                 " (old libcap?)\n");
75     }
76
77     while (--argc > 0) {
78         const char *text;
79         cap_t cap_d;
80
81         if (!strcmp(*++argv, "-q")) {
82             quiet = 1;
83             continue;
84         }
85         if (!strcmp(*argv, "-v")) {
86             verify = 1;
87             continue;
88         }
89
90         if (!strcmp(*argv, "-r")) {
91             cap_d = NULL;
92         } else {
93             if (!strcmp(*argv,"-")) {
94                 retval = read_caps(quiet, *argv, buffer);
95                 if (retval)
96                     usage();
97                 text = buffer;
98             } else {
99                 text = *argv;
100             }
101
102             cap_d = cap_from_text(text);
103             if (cap_d == NULL) {
104                 perror("fatal error");
105                 usage();
106             }
107 #ifdef DEBUG
108             {
109                 ssize_t length;
110                 const char *result;
111
112                 result = cap_to_text(cap_d, &length);
113                 fprintf(stderr, "caps set to: [%s]\n", result);
114             }
115 #endif
116         }
117
118         if (--argc <= 0)
119             usage();
120         /*
121          * Set the filesystem capability for this file.
122          */
123         if (verify) {
124             cap_t cap_on_file;
125             int cmp;
126
127             if (cap_d == NULL) {
128                 cap_d = cap_from_text("=");
129             }
130
131             cap_on_file = cap_get_file(*++argv);
132
133             if (cap_on_file == NULL) {
134                 cap_on_file = cap_from_text("=");
135             }
136
137             cmp = cap_compare(cap_on_file, cap_d);
138             cap_free(cap_on_file);
139
140             if (cmp != 0) {
141                 if (!quiet) {
142                     printf("%s differs in [%s%s%s]\n", *argv,
143                            CAP_DIFFERS(cmp, CAP_PERMITTED) ? "p" : "",
144                            CAP_DIFFERS(cmp, CAP_INHERITABLE) ? "i" : "",
145                            CAP_DIFFERS(cmp, CAP_EFFECTIVE) ? "e" : "");
146                 }
147                 exit(1);
148             }
149             if (!quiet) {
150                 printf("%s: OK\n", *argv);
151             }
152         } else {
153             if (!tried_to_cap_setfcap) {
154                 capflag = CAP_SETFCAP;
155
156                 /*
157                  * Raise the effective CAP_SETFCAP.
158                  */
159                 if (cap_set_flag(mycaps, CAP_EFFECTIVE, 1, &capflag, CAP_SET)
160                     != 0) {
161                     perror("unable to manipulate CAP_SETFCAP - "
162                            "try a newer libcap?");
163                     exit(1);
164                 }
165                 if (cap_set_proc(mycaps) != 0) {
166                     perror("unable to set CAP_SETFCAP effective capability");
167                     exit(1);
168                 }
169                 tried_to_cap_setfcap = 1;
170             }
171             retval = cap_set_file(*++argv, cap_d);
172             if (retval != 0) {
173                 fprintf(stderr,
174                         "Failed to set capabilities on file `%s' (%s)\n",
175                         argv[0], strerror(errno));
176                 usage();
177             }
178         }
179         if (cap_d) {
180             cap_free(cap_d);
181         }
182     }
183
184     exit(0);
185 }