chattr.c revision 3839e65723771b85975f4263102dd3ceec4523c
13839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/*
23839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * chattr.c		- Change file attributes on an ext2 file system
33839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o *
43839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Copyright (C) 1993, 1994  Remy Card <card@masi.ibp.fr>
53839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o *                           Laboratoire MASI, Institut Blaise Pascal
63839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o *                           Universite Pierre et Marie Curie (Paris VI)
73839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o *
83839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * This file can be redistributed under the terms of the GNU General
93839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Public License
103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */
113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/*
133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * History:
143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 93/10/30	- Creation
153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 93/11/13	- Replace stat() calls by lstat() to avoid loops
163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 94/02/27	- Integrated in Ted's distribution
173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */
183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <dirent.h>
203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <fcntl.h>
213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <getopt.h>
223839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <stdio.h>
233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <stdlib.h>
243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <unistd.h>
253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <sys/param.h>
263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <sys/stat.h>
273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <linux/ext2_fs.h>
283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include "et/com_err.h"
303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include "e2p/e2p.h"
313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include "../version.h"
333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'oconst char * program_name = "chattr";
353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'oint add = 0;
373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'oint rem = 0;
383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'oint set = 0;
393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'oint set_version = 0;
403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ounsigned long version;
423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'oint recursive = 0;
443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'oint verbose = 0;
453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ounsigned long af;
473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ounsigned long rf;
483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ounsigned long sf;
493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic void volatile fatal_error (const char * fmt_string, int errcode)
513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	fprintf (stderr, fmt_string, program_name);
533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	exit (errcode);
543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#define usage() fatal_error ("usage: %s [-RV] [-+=csu] [-v version] files...\n", \
573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			     1)
583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic int decode_arg (int * i, int argc, char ** argv)
603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	char * p;
623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	char * tmp;
633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	switch (argv[*i][0])
653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	{
663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	case '-':
673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		for (p = &argv[*i][1]; *p; p++)
683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			switch (*p)
693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			{
703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			case 'R':
713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				recursive = 1;
723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				break;
733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			case 'S':
743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				rf |= EXT2_SYNC_FL;
753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				rem = 1;
763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				break;
773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			case 'V':
783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				verbose = 1;
793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				break;
803839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			case 'c':
813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				rf |= EXT2_COMPR_FL;
823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				rem = 1;
833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				break;
843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			case 's':
853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				rf |= EXT2_SECRM_FL;
863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				rem = 1;
873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				break;
883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			case 'u':
893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				rf |= EXT2_UNRM_FL;
903839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				rem = 1;
913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				break;
923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			case 'v':
933839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				if (*i >= argc)
943839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o					usage ();
953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				(*i)++;
963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				version = strtol (argv[*i], &tmp, 0);
973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				if (*tmp)
983839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				{
993839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o					com_err (program_name, 0,
1003839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o						 "bad version - %s\n", argv[*i]);
1013839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o					usage ();
1023839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				}
1033839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				set_version = 1;
1043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				break;
1053839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			default:
1063839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				fprintf (stderr, "%s: Unrecognized argument: %c\n",
1073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o					 program_name, *p);
1083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				usage ();
1093839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			}
1103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		break;
1113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	case '+':
1123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		add = 1;
1133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		for (p = &argv[*i][1]; *p; p++)
1143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			switch (*p)
1153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			{
1163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			case 'S':
1173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				af |= EXT2_SYNC_FL;
1183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				break;
1193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			case 'c':
1203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				af |= EXT2_COMPR_FL;
1213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				break;
1223839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			case 's':
1233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				af |= EXT2_SECRM_FL;
1243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				break;
1253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			case 'u':
1263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				af |= EXT2_UNRM_FL;
1273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				break;
1283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			default:
1293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				usage ();
1303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			}
1313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		break;
1323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	case '=':
1333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		set = 1;
1343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		for (p = &argv[*i][1]; *p; p++)
1353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			switch (*p)
1363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			{
1373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			case 'S':
1383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				sf |= EXT2_SYNC_FL;
1393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				break;
1403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			case 'c':
1413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				sf |= EXT2_COMPR_FL;
1423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				break;
1433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			case 's':
1443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				sf |= EXT2_SECRM_FL;
1453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				break;
1463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			case 'u':
1473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				sf |= EXT2_UNRM_FL;
1483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				break;
1493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			default:
1503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				usage ();
1513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			}
1523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		break;
1533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	default:
1543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		return EOF;
1553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		break;
1563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
1573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	return 1;
1583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
1593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
1603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic int chattr_dir_proc (const char *, struct dirent *, void *);
1613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
1623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic void change_attributes (const char * name)
1633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
1643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	unsigned long flags;
1653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	struct stat st;
1663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
1673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	if (lstat (name, &st) == -1)
1683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	{
1693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		com_err (program_name, errno, "while stating %s", name);
1703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		return;
1713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
1723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	if (set)
1733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	{
1743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		if (verbose)
1753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		{
1763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			printf ("Flags of %s set as ", name);
1773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			print_flags (stdout, sf);
1783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			printf ("\n");
1793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		}
1803839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		if (fsetflags (name, sf) == -1)
1813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			perror (name);
1823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
1833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	else
1843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	{
1853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		if (fgetflags (name, &flags) == -1)
1863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			com_err (program_name, errno,
1873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			         "while reading flags on %s", name);
1883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		else
1893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		{
1903839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			if (rem)
1913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				flags &= ~rf;
1923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			if (add)
1933839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				flags |= af;
1943839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			if (verbose)
1953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			{
1963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				printf ("Flags of %s set as ", name);
1973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				print_flags (stdout, flags);
1983839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				printf ("\n");
1993839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			}
2003839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			if (fsetflags (name, flags) == -1)
2013839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				com_err (program_name, errno,
2023839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				         "while setting flags on %s", name);
2033839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		}
2043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
2053839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	if (set_version)
2063839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	{
2073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		if (verbose)
2083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			printf ("Version of %s set as %lu\n", name, version);
2093839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		if (fsetversion (name, version) == -1)
2103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			com_err (program_name, errno,
2113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			         "while setting version on %s", name);
2123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
2133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	if (S_ISDIR(st.st_mode) && recursive)
2143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		iterate_on_dir (name, chattr_dir_proc, (void *) NULL);
2153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
2163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
2173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic int chattr_dir_proc (const char * dir_name, struct dirent * de, void * private)
2183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
2193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	char path[MAXPATHLEN];
2203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
2213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	if (strcmp (de->d_name, ".") && strcmp (de->d_name, ".."))
2223839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	{
2233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		sprintf (path, "%s/%s", dir_name, de->d_name);
2243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		change_attributes (path);
2253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
2263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	return 0;
2273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
2283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
2293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ovoid main (int argc, char ** argv)
2303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
2313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	int i, j;
2323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	int end_arg = 0;
2333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
2343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	fprintf (stderr, "chattr %s, %s for EXT2 FS %s, %s\n",
2353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		 E2FSPROGS_VERSION, E2FSPROGS_DATE,
2363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		 EXT2FS_VERSION, EXT2FS_DATE);
2373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	if (argc && *argv)
2383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		program_name = *argv;
2393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	i = 1;
2403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	while (i < argc && !end_arg)
2413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	{
2423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		if (decode_arg (&i, argc, argv) == EOF)
2433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			end_arg = 1;
2443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		else
2453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			i++;
2463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
2473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	if (i >= argc)
2483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		usage ();
2493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	if (set && (add || rem))
2503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	{
2513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		fprintf (stderr, "= is incompatible with - and +\n");
2523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		exit (1);
2533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
2543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	if (!(add || rem || set))
2553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	{
2563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		fprintf (stderr, "Must use =, - or +\n");
2573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		exit (1);
2583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
2593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	for (j = i; j < argc; j++)
2603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		change_attributes (argv[j]);
2613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
262