1 /* 2 * Copyright (c) 1992, 1993, 1994 3 * The Regents of the University of California. All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 static char copyright[] = 10 "@(#) Copyright (c) 1992, 1993, 1994\n\ 11 The Regents of the University of California. All rights reserved.\n"; 12 #endif /* not lint */ 13 14 #ifndef lint 15 static char sccsid[] = "@(#)chflags.c 8.5 (Berkeley) 04/01/94"; 16 #endif /* not lint */ 17 18 #include <sys/types.h> 19 #include <sys/stat.h> 20 21 #include <err.h> 22 #include <errno.h> 23 #include <fts.h> 24 #include <stdio.h> 25 #include <stdlib.h> 26 #include <string.h> 27 #include <unistd.h> 28 29 u_long string_to_flags __P((char **, u_long *, u_long *)); 30 void usage __P((void)); 31 32 int 33 main(argc, argv) 34 int argc; 35 char *argv[]; 36 { 37 FTS *ftsp; 38 FTSENT *p; 39 u_long clear, set; 40 long val; 41 int Hflag, Lflag, Pflag, Rflag, ch, fts_options, oct, rval; 42 char *flags, *ep; 43 44 Hflag = Lflag = Pflag = Rflag = 0; 45 while ((ch = getopt(argc, argv, "HLPR")) != EOF) 46 switch (ch) { 47 case 'H': 48 Hflag = 1; 49 Lflag = Pflag = 0; 50 break; 51 case 'L': 52 Lflag = 1; 53 Hflag = Pflag = 0; 54 break; 55 case 'P': 56 Pflag = 1; 57 Hflag = Lflag = 0; 58 break; 59 case 'R': 60 Rflag = 1; 61 break; 62 case '?': 63 default: 64 usage(); 65 } 66 argv += optind; 67 argc -= optind; 68 69 if (argc < 2) 70 usage(); 71 72 fts_options = FTS_PHYSICAL; 73 if (Rflag) { 74 if (Hflag) 75 fts_options |= FTS_COMFOLLOW; 76 if (Lflag) { 77 fts_options &= ~FTS_PHYSICAL; 78 fts_options |= FTS_LOGICAL; 79 } 80 } 81 82 flags = *argv; 83 if (*flags >= '0' && *flags <= '7') { 84 errno = 0; 85 val = strtol(flags, &ep, 8); 86 if (val < 0) 87 errno = ERANGE; 88 if (errno) 89 err(1, "invalid flags: %s", flags); 90 if (*ep) 91 errx(1, "invalid flags: %s", flags); 92 set = val; 93 oct = 1; 94 } else { 95 if (string_to_flags(&flags, &set, &clear)) 96 errx(1, "invalid flag: %s", flags); 97 clear = ~clear; 98 oct = 0; 99 } 100 101 if ((ftsp = fts_open(++argv, fts_options , 0)) == NULL) 102 err(1, NULL); 103 104 for (rval = 0; (p = fts_read(ftsp)) != NULL;) { 105 switch (p->fts_info) { 106 case FTS_D: 107 if (Rflag) /* Change it at FTS_DP. */ 108 continue; 109 fts_set(ftsp, p, FTS_SKIP); 110 break; 111 case FTS_DNR: /* Warn, chflag, continue. */ 112 warnx("%s: %s", p->fts_path, strerror(p->fts_errno)); 113 rval = 1; 114 break; 115 case FTS_ERR: /* Warn, continue. */ 116 case FTS_NS: 117 warnx("%s: %s", p->fts_path, strerror(p->fts_errno)); 118 rval = 1; 119 continue; 120 case FTS_SL: /* Ignore. */ 121 case FTS_SLNONE: 122 /* 123 * The only symlinks that end up here are ones that 124 * don't point to anything and ones that we found 125 * doing a physical walk. 126 */ 127 continue; 128 default: 129 break; 130 } 131 if (oct) { 132 if (!chflags(p->fts_accpath, set)) 133 continue; 134 } else { 135 p->fts_statp->st_flags |= set; 136 p->fts_statp->st_flags &= clear; 137 if (!chflags(p->fts_accpath, p->fts_statp->st_flags)) 138 continue; 139 } 140 warn("%s", p->fts_path); 141 rval = 1; 142 } 143 if (errno) 144 err(1, "fts_read"); 145 exit(rval); 146 } 147 148 void 149 usage() 150 { 151 (void)fprintf(stderr, 152 "usage: chflags [-R [-H | -L | -P]] flags file ...\n"); 153 exit(1); 154 } 155