1139969Simp/*- 21590Srgrimes * Copyright (c) 1992, 1993, 1994 31590Srgrimes * The Regents of the University of California. All rights reserved. 41590Srgrimes * 51590Srgrimes * Redistribution and use in source and binary forms, with or without 61590Srgrimes * modification, are permitted provided that the following conditions 71590Srgrimes * are met: 81590Srgrimes * 1. Redistributions of source code must retain the above copyright 91590Srgrimes * notice, this list of conditions and the following disclaimer. 101590Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111590Srgrimes * notice, this list of conditions and the following disclaimer in the 121590Srgrimes * documentation and/or other materials provided with the distribution. 131590Srgrimes * 4. Neither the name of the University nor the names of its contributors 141590Srgrimes * may be used to endorse or promote products derived from this software 151590Srgrimes * without specific prior written permission. 161590Srgrimes * 171590Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181590Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191590Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201590Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211590Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221590Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231590Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241590Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251590Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261590Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271590Srgrimes * SUCH DAMAGE. 281590Srgrimes */ 291590Srgrimes 30114423Sobrien#if 0 311590Srgrimes#ifndef lint 3241568Sarchiestatic const char copyright[] = 331590Srgrimes"@(#) Copyright (c) 1992, 1993, 1994\n\ 341590Srgrimes The Regents of the University of California. All rights reserved.\n"; 3587237Smarkm#endif 361590Srgrimes 371590Srgrimes#ifndef lint 3887628Sdwmalonestatic char sccsid[] = "@(#)chflags.c 8.5 (Berkeley) 4/1/94"; 3953507Scharnier#endif 4087628Sdwmalone#endif 411590Srgrimes 4287628Sdwmalone#include <sys/cdefs.h> 4387628Sdwmalone__FBSDID("$FreeBSD$"); 4487628Sdwmalone 451590Srgrimes#include <sys/types.h> 461590Srgrimes#include <sys/stat.h> 471590Srgrimes 481590Srgrimes#include <err.h> 491590Srgrimes#include <errno.h> 50283875Ssmh#include <fcntl.h> 511590Srgrimes#include <fts.h> 521590Srgrimes#include <stdio.h> 531590Srgrimes#include <stdlib.h> 541590Srgrimes#include <string.h> 551590Srgrimes#include <unistd.h> 561590Srgrimes 57194795Sdelphijstatic void usage(void); 581590Srgrimes 591590Srgrimesint 60102944Sdwmalonemain(int argc, char *argv[]) 611590Srgrimes{ 621590Srgrimes FTS *ftsp; 631590Srgrimes FTSENT *p; 64176976Srwatson u_long clear, newflags, set; 651590Srgrimes long val; 66176976Srwatson int Hflag, Lflag, Rflag, fflag, hflag, vflag; 67176976Srwatson int ch, fts_options, oct, rval; 681590Srgrimes char *flags, *ep; 691590Srgrimes 70176976Srwatson Hflag = Lflag = Rflag = fflag = hflag = vflag = 0; 71176976Srwatson while ((ch = getopt(argc, argv, "HLPRfhv")) != -1) 721590Srgrimes switch (ch) { 731590Srgrimes case 'H': 741590Srgrimes Hflag = 1; 75136088Sstefanf Lflag = 0; 761590Srgrimes break; 771590Srgrimes case 'L': 781590Srgrimes Lflag = 1; 79136088Sstefanf Hflag = 0; 801590Srgrimes break; 811590Srgrimes case 'P': 821590Srgrimes Hflag = Lflag = 0; 831590Srgrimes break; 841590Srgrimes case 'R': 851590Srgrimes Rflag = 1; 861590Srgrimes break; 87176976Srwatson case 'f': 88176976Srwatson fflag = 1; 89176976Srwatson break; 90146224Sdd case 'h': 91146224Sdd hflag = 1; 92146224Sdd break; 93176976Srwatson case 'v': 94176976Srwatson vflag++; 95176976Srwatson break; 961590Srgrimes case '?': 971590Srgrimes default: 981590Srgrimes usage(); 991590Srgrimes } 1001590Srgrimes argv += optind; 1011590Srgrimes argc -= optind; 1021590Srgrimes 1031590Srgrimes if (argc < 2) 1041590Srgrimes usage(); 1051590Srgrimes 1061590Srgrimes if (Rflag) { 107146224Sdd if (hflag) 108283875Ssmh errx(1, "the -R and -h options may not be " 109283875Ssmh "specified together."); 1101590Srgrimes if (Lflag) { 111283875Ssmh fts_options = FTS_LOGICAL; 112283875Ssmh } else { 113283875Ssmh fts_options = FTS_PHYSICAL; 114283875Ssmh 115283875Ssmh if (Hflag) { 116283875Ssmh fts_options |= FTS_COMFOLLOW; 117283875Ssmh } 1181590Srgrimes } 119283875Ssmh } else if (hflag) { 120283875Ssmh fts_options = FTS_PHYSICAL; 121283875Ssmh } else { 122283875Ssmh fts_options = FTS_LOGICAL; 123283875Ssmh } 1241590Srgrimes 1251590Srgrimes flags = *argv; 1261590Srgrimes if (*flags >= '0' && *flags <= '7') { 1271590Srgrimes errno = 0; 1281590Srgrimes val = strtol(flags, &ep, 8); 1291590Srgrimes if (val < 0) 1301590Srgrimes errno = ERANGE; 1311590Srgrimes if (errno) 1321590Srgrimes err(1, "invalid flags: %s", flags); 1331590Srgrimes if (*ep) 1341590Srgrimes errx(1, "invalid flags: %s", flags); 1351590Srgrimes set = val; 1361590Srgrimes oct = 1; 1371590Srgrimes } else { 13861749Sjoe if (strtofflags(&flags, &set, &clear)) 1391590Srgrimes errx(1, "invalid flag: %s", flags); 1401590Srgrimes clear = ~clear; 1411590Srgrimes oct = 0; 1421590Srgrimes } 1431590Srgrimes 1441590Srgrimes if ((ftsp = fts_open(++argv, fts_options , 0)) == NULL) 1458874Srgrimes err(1, NULL); 1461590Srgrimes 1471590Srgrimes for (rval = 0; (p = fts_read(ftsp)) != NULL;) { 148283875Ssmh int atflag; 149283875Ssmh 150283875Ssmh if ((fts_options & FTS_LOGICAL) || 151283875Ssmh ((fts_options & FTS_COMFOLLOW) && 152283875Ssmh p->fts_level == FTS_ROOTLEVEL)) 153283875Ssmh atflag = 0; 154283875Ssmh else 155283875Ssmh atflag = AT_SYMLINK_NOFOLLOW; 156283875Ssmh 1571590Srgrimes switch (p->fts_info) { 158125972Sceri case FTS_D: /* Change it at FTS_DP if we're recursive. */ 159125972Sceri if (!Rflag) 160125972Sceri fts_set(ftsp, p, FTS_SKIP); 161125972Sceri continue; 162283875Ssmh case FTS_DNR: /* Warn, chflags. */ 1631590Srgrimes warnx("%s: %s", p->fts_path, strerror(p->fts_errno)); 1641590Srgrimes rval = 1; 1651590Srgrimes break; 1661590Srgrimes case FTS_ERR: /* Warn, continue. */ 1671590Srgrimes case FTS_NS: 1681590Srgrimes warnx("%s: %s", p->fts_path, strerror(p->fts_errno)); 1691590Srgrimes rval = 1; 1701590Srgrimes continue; 1711590Srgrimes default: 1721590Srgrimes break; 1731590Srgrimes } 174176976Srwatson if (oct) 175176976Srwatson newflags = set; 176176976Srwatson else 177176976Srwatson newflags = (p->fts_statp->st_flags | set) & clear; 178176976Srwatson if (newflags == p->fts_statp->st_flags) 179176976Srwatson continue; 180283875Ssmh if (chflagsat(AT_FDCWD, p->fts_accpath, newflags, 181283875Ssmh atflag) == -1 && !fflag) { 182176976Srwatson warn("%s", p->fts_path); 183176976Srwatson rval = 1; 184176976Srwatson } else if (vflag) { 185176976Srwatson (void)printf("%s", p->fts_path); 186176976Srwatson if (vflag > 1) 187176976Srwatson (void)printf(": 0%lo -> 0%lo", 188176976Srwatson (u_long)p->fts_statp->st_flags, 189176976Srwatson newflags); 190176976Srwatson (void)printf("\n"); 1911590Srgrimes } 1921590Srgrimes } 1931590Srgrimes if (errno) 1941590Srgrimes err(1, "fts_read"); 1951590Srgrimes exit(rval); 1961590Srgrimes} 1971590Srgrimes 198194795Sdelphijstatic void 199102944Sdwmaloneusage(void) 2001590Srgrimes{ 2011590Srgrimes (void)fprintf(stderr, 202176976Srwatson "usage: chflags [-fhv] [-R [-H | -L | -P]] flags file ...\n"); 2031590Srgrimes exit(1); 2041590Srgrimes} 205