Print this page
12288 getfacl and setfacl could stand improvement
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/setfacl/setfacl.c
+++ new/usr/src/cmd/setfacl/setfacl.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved.
23 + * Copyright 2020 Peter Tribble.
23 24 */
24 25
25 26 /*
26 27 * setfacl [-r] -f aclfile file ...
27 28 * setfacl [-r] -d acl_entries file ...
28 29 * setfacl [-r] -m acl_entries file ...
29 30 * setfacl [-r] -s acl_entries file ...
30 31 * This command deletes/adds/modifies/sets discretionary information for a file
31 32 * or files.
32 33 */
33 34
↓ open down ↓ |
1 lines elided |
↑ open up ↑ |
34 35 #include <stdlib.h>
35 36 #include <stdio.h>
36 37 #include <pwd.h>
37 38 #include <grp.h>
38 39 #include <string.h>
39 40 #include <locale.h>
40 41 #include <sys/acl.h>
41 42 #include <sys/types.h>
42 43 #include <unistd.h>
43 44 #include <errno.h>
45 +#include <ctype.h>
44 46
45 47 #define ADD 1
46 48 #define MODIFY 2
47 49 #define DELETE 3
48 50 #define SET 4
49 51
50 52 static int get_acl_info(char *filep, aclent_t **aclpp);
51 53 static int mod_entries(aclent_t *, int, char *, char *, char *, int);
52 54 static int set_file_entries(char *, char *, int);
53 55 static int set_online_entries(char *, char *, int);
54 56 static void usage();
55 57 static int parse_entry_list(aclent_t **, int *, char *, int);
56 58 static int convert_to_aclent_t(char *, int *, aclent_t **, int);
57 59 static int parse_entry(char *, aclent_t *, int);
58 60 static void err_handle(int, aclent_t *);
59 61 static int conv_id(char *);
60 62
61 63 int
62 64 main(int argc, char *argv[])
↓ open down ↓ |
9 lines elided |
↑ open up ↑ |
63 65 {
64 66 int c;
65 67 int dflag = 0;
66 68 int mflag = 0;
67 69 int rflag = 0;
68 70 int sflag = 0;
69 71 int fflag = 0;
70 72 int errflag = 0;
71 73 int aclcnt; /* used by -m -d */
72 74 aclent_t *aclp; /* used by -m -d */
73 - char *aclfilep; /* acl file argument */
75 + char *aclfilep = NULL; /* acl file argument */
74 76 char *d_entryp = NULL; /* ptr to del entry list */
75 77 char *m_entryp = NULL; /* ptr to mod entry list */
76 78 char *s_entryp = NULL; /* ptr to set entry list */
77 79 char *work_dp = NULL; /* working ptrs for the above */
78 80 char *work_mp = NULL;
79 81 char *work_sp = NULL;
80 82
81 83 (void) setlocale(LC_ALL, "");
82 84 (void) textdomain(TEXT_DOMAIN);
83 85
84 86 if (argc < 3)
85 87 usage();
86 88
87 89 while ((c = getopt(argc, argv, "rm:d:s:f:")) != EOF) {
88 90 switch (c) {
89 91 case 'r':
90 92 rflag++;
91 93 break;
92 94 case 'd':
93 95 if (dflag || fflag || sflag)
94 96 usage();
95 97 dflag++;
96 98 d_entryp = optarg;
97 99 break;
98 100 case 'm':
99 101 if (mflag || fflag || sflag)
100 102 usage();
101 103 mflag++;
102 104 m_entryp = optarg;
103 105 break;
104 106 case 's':
105 107 if (fflag || sflag || mflag || dflag)
106 108 usage();
107 109 sflag++;
108 110 s_entryp = optarg;
109 111 break;
110 112 case 'f':
111 113 if (fflag || sflag || mflag || dflag)
112 114 usage();
113 115 fflag++;
114 116 aclfilep = optarg;
115 117 break;
116 118 case '?':
117 119 errflag++;
118 120 break;
119 121 }
120 122 }
121 123 if (errflag)
122 124 usage();
123 125
124 126 /* one of these flags should be set */
125 127 if (!fflag && !sflag && !mflag && !dflag)
126 128 usage();
127 129
128 130 /* no file arguments */
129 131 if (optind >= argc)
130 132 usage();
131 133
132 134 for (; optind < argc; optind++) {
133 135 register char *filep;
134 136
135 137 filep = argv[optind];
136 138
137 139 /* modify and delete: we need to get the ACL first */
138 140 if (mflag || dflag) {
139 141 if (m_entryp != NULL) {
140 142 free(work_mp);
141 143 work_mp = strdup(m_entryp);
142 144 if (work_mp == NULL) {
143 145 fprintf(stderr,
144 146 gettext("out of memory %s\n"),
145 147 m_entryp);
146 148 exit(1);
147 149 }
148 150 }
149 151
150 152 if (d_entryp != NULL) {
151 153 free(work_dp);
152 154 work_dp = strdup(d_entryp);
153 155 if (work_dp == NULL) {
154 156 fprintf(stderr,
155 157 gettext("out of memory %s\n"),
156 158 d_entryp);
157 159 exit(1);
158 160 }
159 161 }
160 162
161 163 aclcnt = get_acl_info(filep, &aclp);
162 164 if (aclcnt == -1)
163 165 exit(2);
164 166 if (mod_entries(aclp, aclcnt, work_mp,
165 167 work_dp, filep, rflag) == -1)
166 168 exit(2);
167 169 } else if (fflag) {
168 170 if (set_file_entries(aclfilep, filep, rflag) == -1)
169 171 exit(2);
170 172 } else if (sflag) {
171 173 if (s_entryp != NULL) {
172 174 free(work_sp);
173 175 work_sp = strdup(s_entryp);
174 176 if (work_sp == NULL) {
175 177 fprintf(stderr,
176 178 gettext("out of memory %s\n"),
177 179 s_entryp);
178 180 exit(1);
179 181 }
180 182 }
181 183 if (set_online_entries(work_sp, filep, rflag) == -1)
182 184 exit(2);
183 185 }
184 186 }
185 187 return (0);
186 188 }
187 189
188 190 /*
189 191 * For add, modify, and delete, we need to get the ACL of the file first.
190 192 */
191 193 static int
↓ open down ↓ |
108 lines elided |
↑ open up ↑ |
192 194 get_acl_info(char *filep, aclent_t **aclpp)
193 195 {
194 196 int aclcnt;
195 197
196 198 if ((aclcnt = acl(filep, GETACLCNT, 0, NULL)) < 0) {
197 199 if (errno == ENOSYS) {
198 200 (void) fprintf(stderr,
199 201 gettext("File system doesn't support aclent_t "
200 202 "style ACL's.\n"
201 203 "See acl(5) for more information on"
202 - " ACL styles support by Solaris.\n"));
204 + "POSIX-draft ACL support.\n"));
203 205 return (-1);
204 206 }
205 207 (void) fprintf(stderr,
206 208 gettext("%s: failed to get acl count\n"), filep);
207 209 perror("get acl count error");
208 210 return (-1);
209 211 }
210 212 if (aclcnt < MIN_ACL_ENTRIES) {
211 213 (void) fprintf(stderr,
212 214 gettext("%d: acl count is too small from %s\n"),
213 215 aclcnt, filep);
214 216 return (-1);
215 217 }
216 218
217 219 if ((*aclpp = (aclent_t *)malloc(sizeof (aclent_t) * aclcnt)) == NULL) {
218 220 (void) fprintf(stderr, gettext("out of memory\n"));
219 221 return (-1);
220 222 }
221 223 if (acl(filep, GETACL, aclcnt, *aclpp) < 0) {
222 224 (void) fprintf(stderr,
223 225 gettext("%s: failed to get acl entries\n"), filep);
224 226 perror("getacl error");
225 227 return (-1);
226 228 }
227 229 return (aclcnt);
228 230 }
229 231
↓ open down ↓ |
17 lines elided |
↑ open up ↑ |
230 232 /*
231 233 * mod_entries() handles add, delete, and modify ACL entries of a file.
232 234 * The real action is in convert_to_aclent_t() called by parse_entry_list().
233 235 * aclp: points ACL of a file and may be changed by lower level routine.
234 236 * modp: modify entry list in ascii format
235 237 * delp: delete entry list in ascii format
236 238 * fnamep: file of interest
237 239 */
238 240 static int
239 241 mod_entries(aclent_t *aclp, int cnt, char *modp, char *delp,
240 - char *fnamep, int rfg)
242 + char *fnamep, int rfg)
241 243 {
242 - int rc; /* return code */
243 -
244 244 /* modify and add: from -m option */
245 245 if (parse_entry_list(&aclp, &cnt, modp, MODIFY) == -1)
246 246 return (-1);
247 247
248 248 /* deletion: from -d option */
249 249 if (parse_entry_list(&aclp, &cnt, delp, DELETE) == -1)
250 250 return (-1);
251 251
252 252 if (aclsort(cnt, rfg, aclp) == -1) {
253 253 (void) err_handle(cnt, aclp);
254 254 (void) fprintf(stderr,
255 255 gettext("aclcnt %d, file %s\n"), cnt, fnamep);
256 256 return (-1);
257 257 }
258 258
259 259 if (acl(fnamep, SETACL, cnt, aclp) < 0) {
260 260 fprintf(stderr,
261 261 gettext("%s: failed to set acl entries\n"), fnamep);
262 262 perror("setacl error");
263 263 return (-1);
264 264 }
265 265 return (0);
266 266 }
267 267
268 268 /*
269 269 * set_file_entries() creates ACL entries from ACL file (acl_fnamep).
270 270 * It opens the file and converts every line (one line per acl entry)
271 271 * into aclent_t format. It then recalculates the mask according to rflag.
272 272 * Finally it sets ACL to the file (fnamep).
273 273 */
274 274 static int
275 275 set_file_entries(char *acl_fnamep, char *fnamep, int rflag)
276 276 {
277 277 int aclcnt = 0;
278 278 FILE *acl_fp;
279 279 aclent_t *aclp;
280 280 char buf[BUFSIZ];
281 281 char *tp;
282 282
283 283 if (strcmp(acl_fnamep, "-") == 0)
284 284 acl_fp = stdin;
285 285 else {
286 286 if ((acl_fp = fopen(acl_fnamep, "r")) == NULL) {
287 287 fprintf(stderr, gettext("Can't open acl file %s\n"),
288 288 acl_fnamep);
289 289 return (-1);
290 290 }
291 291 }
292 292 while (fgets(buf, BUFSIZ, acl_fp) != NULL) {
293 293 if (buf[0] == '#' || buf[0] == '\n')
294 294 continue;
295 295
296 296 /* check effective permission: add a null after real perm */
297 297 if ((tp = (char *)strchr(buf, '#')) != NULL) {
298 298 tp--;
299 299 while (*tp == ' ' || *tp == '\t') {
300 300 if (tp != buf)
301 301 tp--;
302 302 else {
303 303 fprintf(stderr,
304 304 gettext("entry format error %s\n"),
305 305 buf);
306 306 exit(1);
307 307 }
308 308 }
309 309 *(tp+1) = '\0';
310 310 }
311 311
312 312 /* remove <nl> at the end if there is one */
313 313 if ((tp = (char *)strchr(buf, '\n')) != NULL)
314 314 *tp = '\0';
315 315 aclcnt++;
316 316 if (convert_to_aclent_t(buf, &aclcnt, &aclp, SET) == -1)
317 317 return (-1);
318 318 }
319 319
320 320 if (aclsort(aclcnt, rflag, aclp) == -1) {
321 321 (void) err_handle(aclcnt, aclp);
322 322 (void) fprintf(stderr, gettext("aclcnt %d, aclfile %s\n"),
323 323 aclcnt, acl_fnamep);
324 324 return (-1);
325 325 }
326 326
327 327 if (acl(fnamep, SETACL, aclcnt, aclp) < 0) {
328 328 fprintf(stderr,
329 329 gettext("%s: failed to set acl entries\n"), fnamep);
330 330 perror("setacl error");
331 331 return (-1);
332 332 }
333 333 return (0);
334 334 }
↓ open down ↓ |
81 lines elided |
↑ open up ↑ |
335 335
336 336 /*
337 337 * set_online_entries() parses the acl entries from command line (setp).
338 338 * It converts the comma separated acl entries into aclent_t format.
339 339 * It then recalculates the mask according to rflag.
340 340 * Finally it sets ACL to the file (fnamep).
341 341 */
342 342 static int
343 343 set_online_entries(char *setp, char *fnamep, int rflag)
344 344 {
345 - char *commap;
346 345 aclent_t *aclp;
347 346 int aclcnt = 0;
348 347
349 348 if (parse_entry_list(&aclp, &aclcnt, setp, SET) == -1)
350 349 return (-1);
351 350
352 351 if (aclsort(aclcnt, rflag, aclp) == -1) {
353 352 (void) err_handle(aclcnt, aclp);
354 353 (void) fprintf(stderr,
355 354 gettext("aclcnt %d, file %s\n"), aclcnt, fnamep);
356 355 return (-1);
357 356 }
358 357
359 358 if (acl(fnamep, SETACL, aclcnt, aclp) < 0) {
360 359 fprintf(stderr,
361 360 gettext("%s: failed to set acl entries\n"), fnamep);
362 361 perror("setacl error");
363 362 return (-1);
364 363 }
365 364 return (0);
366 365 }
367 366
368 367 /*
369 368 * parse_entry_list() parses entry list (listp) separated by commas.
370 369 * Once it gets an ACL entry, it calls convert_to_aclent_t() to convert
371 370 * to internal format.
372 371 */
373 372 static int
374 373 parse_entry_list(aclent_t **aclpp, int *aclcntp, char *listp, int mode)
375 374 {
376 375 char *commap;
377 376
378 377 if (listp == NULL)
379 378 return (0);
380 379 while ((commap = (char *)strchr(listp, ',')) != NULL) {
381 380 *commap = '\0';
382 381 *aclcntp += 1;
383 382 /* aclcnt may be updated after the call: add or modify */
384 383 if (convert_to_aclent_t(listp, aclcntp, aclpp, mode) == -1)
385 384 return (-1);
386 385 listp = ++commap;
387 386 }
388 387 /* this is for only one entry or last entry */
389 388 if (*listp != '\0') {
390 389 *aclcntp += 1;
391 390 if (convert_to_aclent_t(listp, aclcntp, aclpp, mode) == -1)
392 391 return (-1);
393 392 }
394 393 return (0);
395 394 }
396 395
397 396 /*
398 397 * convert_to_aclent_t() converts an acl entry in ascii format (fields separated
399 398 * by colon) into aclent_t and appends it to the current ACL. It also handles
400 399 * memory allocation/deallocation for acl entries in aclent_t format.
401 400 * aclpp that contains acl entries in acl format will be returned.
402 401 * We don't check duplicates.
403 402 */
404 403 static int
405 404 convert_to_aclent_t(char *entryp, int *cntp, aclent_t **aclpp, int mode)
406 405 {
↓ open down ↓ |
51 lines elided |
↑ open up ↑ |
407 406 aclent_t *new_aclp;
408 407 aclent_t tmpacl;
409 408 aclent_t *taclp, *centry = NULL, *gentry = NULL;
410 409 int cur_cnt;
411 410 int found = 0;
412 411 int is_obj;
413 412
414 413 if (entryp == NULL)
415 414 return (0);
416 415
417 - if (*cntp > 1)
418 - new_aclp = (aclent_t *)realloc(*aclpp,
419 - sizeof (aclent_t) * (*cntp));
420 - else
421 - new_aclp = (aclent_t *) malloc(sizeof (aclent_t) * (*cntp));
422 - if (new_aclp == NULL) {
423 - fprintf(stderr,
424 - gettext("Insufficient memory for acl %d\n"), *cntp);
425 - return (-1);
426 - }
427 -
428 416 tmpacl.a_id = 0; /* id field needs to be initialized */
429 417 if (entryp[0] == 'u')
430 418 tmpacl.a_id = getuid(); /* id field for user */
431 419 if (entryp[0] == 'g')
432 420 tmpacl.a_id = getgid(); /* id field for group */
433 421
434 422 tmpacl.a_type = 0;
435 423 if (parse_entry(entryp, &tmpacl, mode) == -1)
436 424 return (-1);
437 425
438 426 is_obj = ((tmpacl.a_type == USER_OBJ) ||
439 427 (tmpacl.a_type == GROUP_OBJ) ||
440 428 (tmpacl.a_type == CLASS_OBJ) ||
441 429 (tmpacl.a_type == DEF_USER_OBJ) ||
442 430 (tmpacl.a_type == DEF_GROUP_OBJ) ||
443 431 (tmpacl.a_type == DEF_OTHER_OBJ));
444 432
433 + if (*cntp > 1)
434 + new_aclp = (aclent_t *)realloc(*aclpp,
435 + sizeof (aclent_t) * (*cntp));
436 + else
437 + new_aclp = (aclent_t *) malloc(sizeof (aclent_t) * (*cntp));
438 + if (new_aclp == NULL) {
439 + fprintf(stderr,
440 + gettext("Insufficient memory for acl %d\n"), *cntp);
441 + return (-1);
442 + }
443 +
445 444 cur_cnt = *cntp - 1;
446 445 switch (mode) {
447 446 case MODIFY: /* and add */
448 447 for (taclp = new_aclp; cur_cnt-- > 0; taclp++) {
449 448 if (taclp->a_type == tmpacl.a_type &&
450 449 ((taclp->a_id == tmpacl.a_id) || is_obj)) {
451 450 found++;
452 451 /* cnt is added before it's called */
453 452 *cntp -= 1;
454 453 taclp->a_perm = tmpacl.a_perm;
455 454 break;
456 455 }
457 456 }
458 457 if (!found) /* Add it to the end: no need to change cntp */
459 458 memcpy(new_aclp + *cntp -1, &tmpacl, sizeof (aclent_t));
460 459 break;
461 460
462 461 case DELETE:
463 462 for (taclp = new_aclp; cur_cnt-- > 0; taclp++) {
464 463 if (taclp->a_type == tmpacl.a_type &&
465 464 ((taclp->a_id == tmpacl.a_id) || is_obj)) {
466 465 found++;
467 466 /* move up the rest */
468 467 while (cur_cnt-- > 0) {
469 468 memcpy(taclp, taclp+1,
470 469 sizeof (aclent_t));
471 470 taclp++;
472 471 }
473 472 *cntp = *cntp - 2;
474 473 break;
475 474 }
476 475 }
477 476 if (!found)
478 477 *cntp -= 1;
479 478 break;
480 479
481 480 case SET:
482 481 /* we may check duplicate before copying over?? */
483 482 memcpy(new_aclp + *cntp -1, &tmpacl, sizeof (aclent_t));
484 483 break;
485 484
486 485 default:
487 486 fprintf(stderr,
488 487 gettext("Unrecognized mode: internal error\n"));
489 488 break;
490 489 }
491 490
492 491 /*
493 492 * If converting from non-trivial acl entry to trivial one,
494 493 * reset CLASS_OBJ's permission with that of GROUP_OBJ.
495 494 */
496 495
497 496 if (mode == DELETE) {
498 497 boolean_t trivial = B_TRUE; /* assumption */
499 498 cur_cnt = *cntp;
500 499 for (taclp = new_aclp; cur_cnt-- > 0; taclp++) {
501 500 switch (taclp->a_type) {
502 501 case USER_OBJ:
503 502 case OTHER_OBJ:
504 503 break;
505 504 case CLASS_OBJ:
506 505 centry = taclp;
507 506 break;
508 507 case GROUP_OBJ:
509 508 gentry = taclp;
510 509 break;
511 510 default:
512 511 /*
↓ open down ↓ |
58 lines elided |
↑ open up ↑ |
513 512 * Confirmed that the new acl set is
514 513 * still a non-trivial acl.
515 514 * Skip reset.
516 515 */
517 516 trivial = B_FALSE;
518 517 }
519 518 }
520 519 if (centry != NULL && gentry != NULL && trivial == B_TRUE)
521 520 centry->a_perm = gentry->a_perm;
522 521 }
523 - *aclpp = new_aclp; /* return new acl entries */
522 + *aclpp = new_aclp; /* return new acl entries */
524 523 return (0);
525 524 }
526 525
527 526 static void
528 527 usage()
529 528 {
530 529 (void) fprintf(stderr, gettext("usage:\n"));
531 530 (void) fprintf(stderr,
532 531 gettext("\tsetfacl [-r] -f aclfile file ...\n"));
533 532 (void) fprintf(stderr,
534 533 gettext("\tsetfacl [-r] -d acl_entries file ...\n"));
535 534 (void) fprintf(stderr,
536 535 gettext("\tsetfacl [-r] -m acl_entries file ...\n"));
537 536 (void) fprintf(stderr,
538 537 gettext("\tsetfacl [-r] -s acl_entries file ...\n"));
539 538 exit(1);
540 539 }
541 540
542 541 static void
543 542 err_handle(int cnt, aclent_t *aclentp)
544 543 {
545 544 int rc;
546 545 int which;
547 546
548 547 rc = aclcheck(aclentp, cnt, &which);
549 548 switch (rc) {
550 549 case USER_ERROR:
551 550 fprintf(stderr,
552 551 gettext("There is more than one user owner entry"));
553 552 fprintf(stderr,
554 553 gettext(" -- error found at entry index %d\n"), which);
555 554 break;
556 555 case GRP_ERROR:
557 556 fprintf(stderr,
558 557 gettext("There is more than one group owner entry"));
559 558 fprintf(stderr,
560 559 gettext(" -- error found at entry index %d\n"), which);
561 560 break;
562 561 case CLASS_ERROR:
563 562 fprintf(stderr,
564 563 gettext("There is more than one mask entry"));
565 564 fprintf(stderr,
566 565 gettext(" -- error found at entry index %d\n"), which);
567 566 break;
568 567 case OTHER_ERROR:
569 568 fprintf(stderr,
570 569 gettext("There is more than one other entry"));
571 570 fprintf(stderr,
572 571 gettext(" -- error found at entry index %d\n"), which);
573 572 break;
574 573 case DUPLICATE_ERROR:
575 574 fprintf(stderr,
576 575 gettext("Duplicate user or group entries"));
577 576 fprintf(stderr,
578 577 gettext(" -- error found at entry index %d\n"), which);
579 578 break;
580 579 case MISS_ERROR:
581 580 fprintf(stderr,
582 581 gettext("Missing user/group owner, other, mask entry\n"));
583 582 break;
584 583 case MEM_ERROR:
585 584 fprintf(stderr,
586 585 gettext("Insufficient memory\n"));
587 586 break;
588 587 case ENTRY_ERROR:
589 588 fprintf(stderr,
590 589 gettext("Unrecognized entry type"));
591 590 fprintf(stderr,
592 591 gettext(" -- error found at entry index %d\n"), which);
593 592 break;
594 593 default:
595 594 /* error is not from aclcheck */
596 595 fprintf(stderr,
597 596 gettext("aclsort error\n"));
598 597 break;
599 598 }
600 599 }
601 600
602 601 static int
603 602 parse_entry(char *fieldp, aclent_t *aclentp, int mode)
604 603 {
605 604 char *colonp;
606 605 int def_flag = 0, mo_flag = 0;
607 606 int id;
608 607 struct passwd *pwp;
609 608 struct group *grp;
610 609
611 610 colonp = (char *)strchr(fieldp, ':');
612 611 if (colonp == NULL) {
613 612 fprintf(stderr,
614 613 gettext("Can't find colon delimiter %s\n"), fieldp);
615 614 return (-1);
616 615 }
617 616 *colonp = '\0';
618 617 if ((strcmp(fieldp, "default") == 0) || (strcmp(fieldp, "d") == 0)) {
619 618 def_flag++;
620 619 fieldp = ++colonp;
621 620 colonp = (char *)strchr(fieldp, ':');
622 621 if (colonp == NULL) {
623 622 fprintf(stderr,
624 623 gettext("Can't find colon delimiter %s\n"), fieldp);
625 624 return (-1);
626 625 }
627 626 *colonp = '\0';
628 627 }
629 628
630 629 /* process entry type */
631 630 if ((strcmp(fieldp, "user") == 0) || (strcmp(fieldp, "u") == 0)) {
632 631 if (def_flag)
633 632 aclentp->a_type = DEF_USER;
634 633 else
635 634 aclentp->a_type = USER;
636 635 }
637 636 if ((strcmp(fieldp, "group") == 0) || (strcmp(fieldp, "g") == 0)) {
638 637 if (def_flag)
639 638 aclentp->a_type = DEF_GROUP;
640 639 else
641 640 aclentp->a_type = GROUP;
642 641 }
643 642 if ((strcmp(fieldp, "mask") == 0) || (strcmp(fieldp, "m") == 0)) {
644 643 if (def_flag)
645 644 aclentp->a_type = DEF_CLASS_OBJ;
646 645 else
647 646 aclentp->a_type = CLASS_OBJ;
648 647 }
649 648 if ((strcmp(fieldp, "other") == 0) || (strcmp(fieldp, "o") == 0)) {
650 649 if (def_flag)
651 650 aclentp->a_type = DEF_OTHER_OBJ;
652 651 else
653 652 aclentp->a_type = OTHER_OBJ;
654 653 }
655 654
656 655 /* still can't determine entry type */
657 656 if (aclentp->a_type == 0) {
658 657 fprintf(stderr,
659 658 gettext("Unrecognized entry type %s \n"), fieldp);
660 659 return (-1);
661 660 }
662 661
663 662 /* mask and other entries dont have id field */
664 663 if (aclentp->a_type != CLASS_OBJ && aclentp->a_type != OTHER_OBJ &&
665 664 aclentp->a_type != DEF_CLASS_OBJ &&
666 665 aclentp->a_type != DEF_OTHER_OBJ) {
667 666 /* process id: */
668 667 fieldp = ++colonp;
669 668 colonp = (char *)strchr(fieldp, ':');
670 669 if (colonp == NULL) {
671 670 if (mode != DELETE) {
672 671 fprintf(stderr,
673 672 gettext("Can't find colon delimiter %s\n"),
674 673 fieldp);
675 674 return (-1);
676 675 }
677 676 } else
678 677 *colonp = '\0';
679 678
680 679 if (*fieldp == '\0') {
681 680 /* empty uid */
682 681 if (aclentp->a_type == USER)
683 682 aclentp->a_type = USER_OBJ;
684 683 if (aclentp->a_type == DEF_USER)
685 684 aclentp->a_type = DEF_USER_OBJ;
686 685 if (aclentp->a_type == GROUP)
687 686 aclentp->a_type = GROUP_OBJ;
688 687 if (aclentp->a_type == DEF_GROUP)
689 688 aclentp->a_type = DEF_GROUP_OBJ;
690 689 } else {
691 690 /* see if it's a user/group name */
692 691 if (aclentp->a_type == USER ||
693 692 aclentp->a_type == USER_OBJ ||
694 693 aclentp->a_type == DEF_USER ||
695 694 aclentp->a_type == DEF_USER_OBJ) {
696 695 if ((pwp = getpwnam(fieldp)) != NULL)
697 696 aclentp->a_id = pwp->pw_uid;
698 697 else {
699 698 /* treat it as numeric id */
700 699 id = conv_id(fieldp);
701 700 if (id == -1)
702 701 return (-1);
703 702 aclentp->a_id = id;
704 703 }
705 704 } else {
706 705 /* group name */
707 706 if ((grp = getgrnam(fieldp)) != NULL)
708 707 aclentp->a_id = grp->gr_gid;
709 708 else {
710 709 id = conv_id(fieldp);
711 710 if (id == -1)
712 711 return (-1);
713 712 aclentp->a_id = id;
714 713 }
715 714 }
716 715 }
717 716 } else {
718 717 /* it is mask/other entry */
719 718 mo_flag = 1;
720 719 }
721 720
722 721 /* process permission: rwx and [0]n format */
723 722 if (mode == DELETE)
724 723 /* delete format: no permission field */
725 724 return (0);
726 725 fieldp = ++colonp;
727 726 colonp = (char *)strchr(fieldp, ':');
728 727 if (colonp != NULL) {
729 728 if (mo_flag == 1) {
730 729 /* Use only single : on mask/other entry */
731 730 (void) fprintf(stderr, gettext("use only 1 colon for "
732 731 "mask and other entries.\n"));
733 732 return (-1);
734 733 } else {
735 734 /* it's ok to have extra colon */
736 735 *colonp = '\0';
737 736 }
738 737 }
739 738
740 739 if ((int)strlen(fieldp) > 3) {
741 740 fprintf(stderr,
742 741 gettext("only rwx or [0]n format is allowed\n"));
743 742 return (-1);
744 743 }
745 744 if (strlen(fieldp) == 3) {
746 745 aclentp->a_perm = 0;
747 746 /* treat it as rwx */
748 747 if (*fieldp == 'r')
749 748 aclentp->a_perm += 4;
750 749 else
751 750 if (*fieldp != '-') {
752 751 fprintf(stderr,
753 752 gettext("Unrecognized character "));
754 753 fprintf(stderr,
755 754 gettext("found in mode field\n"));
756 755 return (-1);
757 756 }
758 757 fieldp++;
759 758 if (*fieldp == 'w')
760 759 aclentp->a_perm += 2;
761 760 else
762 761 if (*fieldp != '-') {
763 762 fprintf(stderr,
764 763 gettext("Unrecognized character "));
765 764 fprintf(stderr,
766 765 gettext("found in mode field\n"));
767 766 return (-1);
768 767 }
769 768 fieldp++;
770 769 if (*fieldp == 'x')
771 770 aclentp->a_perm += 1;
772 771 else
773 772 if (*fieldp != '-') {
774 773 fprintf(stderr,
775 774 gettext("Unrecognized character "));
776 775 fprintf(stderr,
777 776 gettext("found in mode field\n"));
778 777 return (-1);
779 778 }
780 779 return (0);
781 780 }
782 781
783 782 if (*fieldp == '\0')
784 783 return (0);
785 784
786 785 if (*fieldp >= '0' && *fieldp <= '7')
787 786 aclentp->a_perm = *fieldp - '0';
788 787 else {
789 788 fprintf(stderr, gettext("Unrecognized character "));
790 789 fprintf(stderr, gettext("found in mode field\n"));
791 790 return (-1);
792 791 }
793 792 if (aclentp->a_perm == 0 && *++fieldp != '\0') {
794 793 /* look at next char */
795 794 if (*fieldp >= '0' && *fieldp <= '7')
796 795 aclentp->a_perm = *fieldp - '0';
797 796 else {
798 797 fprintf(stderr, gettext("Unrecognized character "));
799 798 fprintf(stderr, gettext("found in mode field\n"));
800 799 fprintf(stderr,
801 800 gettext("Check also the number of fields "));
802 801 fprintf(stderr,
803 802 gettext("(default) mask and other entries\n"));
804 803 return (-1);
805 804 }
806 805 }
807 806 /* check for junk at the end ??? */
808 807 return (0);
809 808 }
810 809
811 810 /*
812 811 * This function is different from atoi() in that it checks for
813 812 * valid digit in the id field whereas atoi() won't report any
814 813 * error.
815 814 */
816 815 static int
817 816 conv_id(char *fieldp)
818 817 {
819 818 int a_id = 0;
820 819
821 820 for (; *fieldp != '\0'; fieldp++) {
822 821 if (!isdigit(*fieldp)) {
823 822 fprintf(stderr, gettext("non-digit in id field\n"));
824 823 return (-1);
825 824 }
826 825 a_id = a_id * 10 + (*fieldp - '0');
827 826 }
828 827 return (a_id);
829 828 }
↓ open down ↓ |
296 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX