1 /*
2 * Copyright (c) 2000-2002,2004 Silicon Graphics, Inc.
3 * All Rights Reserved.
4 *
5 * This program is free software: you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include "config.h"
20
21 #include <sys/types.h>
22 #include <sys/param.h>
23 #include <sys/stat.h>
24 #include <stdio.h>
25 #include <fcntl.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <errno.h>
29 #include <string.h>
30 #include <locale.h>
31
32 #include <attr/attributes.h>
33
34 #include "misc.h"
35
36 #define SETOP 1 /* do a SET operation */
37 #define GETOP 2 /* do a GET operation */
38 #define REMOVEOP 3 /* do a REMOVE operation */
39 #define LISTOP 4 /* do a LIST operation */
40
41 #define BUFSIZE (60*1024) /* buffer size for LIST operations */
42
43 static char *progname;
44
45 void
46 usage(void)
47 {
48 fprintf(stderr, _(
49 "Usage: %s [-LRSq] -s attrname [-V attrvalue] pathname # set value\n"
50 " %s [-LRSq] -g attrname pathname # get value\n"
51 " %s [-LRSq] -r attrname pathname # remove attr\n"
52 " %s [-LRq] -l pathname # list attrs \n"
53 " -s reads a value from stdin and -g writes a value to stdout\n"),
54 progname, progname, progname, progname);
55 exit(1);
56 }
57
58 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
59 int
60 main(int argc, char **argv)
61 {
62 char *attrname, *attrvalue, *filename, *buffer;
63 int attrlength, attrflags;
64 int opflag, i, ch, error, follow, verbose, rootflag, secureflag;
65 attrlist_t *alist;
66 attrlist_ent_t *aep;
67 attrlist_cursor_t cursor;
68
69 progname = basename(argv[0]);
70
71 setlocale(LC_CTYPE, "");
72 setlocale(LC_MESSAGES, "");
73 bindtextdomain(PACKAGE, LOCALEDIR);
74 textdomain(PACKAGE);
75
76 /*
77 * Pick up and validate the arguments.
78 */
79 verbose = 1;
80 follow = opflag = rootflag = secureflag = 0;
81 attrname = attrvalue = NULL;
82 while ((ch = getopt(argc, argv, "s:V:g:r:lqLRS")) != EOF) {
83 switch (ch) {
84 case 's':
85 if ((opflag != 0) && (opflag != SETOP)) {
86 fprintf(stderr,
87 _("Only one of -s, -g, -r, or -l allowed\n"));
88 usage();
89 }
90 opflag = SETOP;
91 attrname = optarg;
92 break;
93 case 'V':
94 if ((opflag != 0) && (opflag != SETOP)) {
95 fprintf(stderr, _("-V only allowed with -s\n"));
96 usage();
97 }
98 opflag = SETOP;
99 attrvalue = optarg;
100 break;
101 case 'g':
102 if (opflag) {
103 fprintf(stderr,
104 _("Only one of -s, -g, -r, or -l allowed\n"));
105 usage();
106 }
107 opflag = GETOP;
108 attrname = optarg;
109 break;
110 case 'r':
111 if (opflag) {
112 fprintf(stderr,
113 _("Only one of -s, -g, -r, or -l allowed\n"));
114 usage();
115 }
116 opflag = REMOVEOP;
117 attrname = optarg;
118 break;
119 case 'l':
120 if (opflag) {
121 fprintf(stderr,
122 _("Only one of -s, -g, -r, or -l allowed\n"));
123 usage();
124 }
125 opflag = LISTOP;
126 break;
127 case 'L':
128 follow++;
129 break;
130 case 'R':
131 rootflag++;
132 break;
133 case 'S':
134 secureflag++;
135 break;
136 case 'q':
137 verbose = 0;
138 break;
139 default:
140 fprintf(stderr, _("Unrecognized option: %c\n"),
141 (char)ch);
142 usage();
143 break;
144 }
145 }
146 if (optind != argc-1) {
147 fprintf(stderr, _("A filename to operate on is required\n"));
148 usage();
149 }
150 filename = argv[optind];
151
152 attrflags = ((!follow ? ATTR_DONTFOLLOW : 0) |
153 (secureflag ? ATTR_SECURE : 0) |
154 (rootflag ? ATTR_ROOT : 0));
155 /*
156 * Break out into option-specific processing.
157 */
158 switch (opflag) {
159 case SETOP:
160 if (!attrname) {
161 fprintf(stderr, _("-V only allowed with -s\n"));
162 usage();
163 }
164 if (attrvalue == NULL) {
165 attrvalue = malloc(ATTR_MAX_VALUELEN);
166 if (attrvalue == NULL) {
167 perror("malloc");
168 exit(1);
169 }
170 attrlength =
171 fread(attrvalue, 1, ATTR_MAX_VALUELEN, stdin);
172 } else {
173 attrlength = strlen(attrvalue);
174 }
175 error = attr_set(filename, attrname, attrvalue,
176 attrlength, attrflags);
177 if (error) {
178 perror("attr_set");
179 fprintf(stderr, _("Could not set \"%s\" for %s\n"),
180 attrname, filename);
181 exit(1);
182 }
183 if (verbose) {
184 printf(_("Attribute \"%s\" set to a %d byte value "
185 "for %s:\n"), attrname, attrlength, filename);
186 fwrite(attrvalue, 1, attrlength, stdout);
187 printf("\n");
188 }
189 break;
190
191 case GETOP:
192 attrvalue = malloc(ATTR_MAX_VALUELEN);
193 if (attrvalue == NULL) {
194 perror("malloc");
195 exit(1);
196 }
197 attrlength = ATTR_MAX_VALUELEN;
198 error = attr_get(filename, attrname, attrvalue,
199 &attrlength, attrflags);
200 if (error) {
201 perror("attr_get");
202 fprintf(stderr, _("Could not get \"%s\" for %s\n"),
203 attrname, filename);
204 exit(1);
205 }
206 if (verbose) {
207 printf(_("Attribute \"%s\" had a %d byte value "
208 "for %s:\n"), attrname, attrlength, filename);
209 }
210 fwrite(attrvalue, 1, attrlength, stdout);
211 if (verbose) {
212 printf("\n");
213 }
214 break;
215
216 case REMOVEOP:
217 error = attr_remove(filename, attrname, attrflags);
218 if (error) {
219 perror("attr_remove");
220 fprintf(stderr, _("Could not remove \"%s\" for %s\n"),
221 attrname, filename);
222 exit(1);
223 }
224 break;
225
226 case LISTOP:
227 if ((buffer = malloc(BUFSIZE)) == NULL) {
228 perror("malloc");
229 exit(1);
230 }
231 memset(&cursor, 0, sizeof(cursor));
232 do {
233 error = attr_list(filename, buffer, BUFSIZE,
234 attrflags, &cursor);
235 if (error) {
236 perror("attr_list");
237 fprintf(stderr,
238 _("Could not list %s\n"),
239 filename);
240 exit(1);
241 }
242
243 alist = (attrlist_t *)buffer;
244 for (i = 0; i < alist->al_count; i++) {
245 aep = (attrlist_ent_t *)&buffer[ alist->al_offset[i] ];
246 if (verbose) {
247 printf(
248 _("Attribute \"%s\" has a %d byte value for %s\n"),
249 aep->a_name, aep->a_valuelen,
250 filename);
251 } else {
252 printf("%s\n", aep->a_name);
253 }
254 }
255 } while (alist->al_more);
256 break;
257
258 default:
259 fprintf(stderr,
260 _("At least one of -s, -g, -r, or -l is required\n"));
261 usage();
262 break;
263 }
264
265 return(0);
266 }
267 #pragma GCC diagnostic warning "-Wdeprecated-declarations"