chattr.c revision 36caf25f8d61eb8ffddc9895463bce5807e96808
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
17a88fa0c0135307288562d4922438ae52fdbad855Theodore Ts'o * 98/12/29	- Ignore symlinks when working recursively (G M Sipe)
18a88fa0c0135307288562d4922438ae52fdbad855Theodore Ts'o * 98/12/29	- Display version info only when -V specified (G M Sipe)
193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */
203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
21a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#include <sys/types.h>
223839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <dirent.h>
233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <fcntl.h>
243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <stdio.h>
253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <stdlib.h>
263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <unistd.h>
2719c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o#include <string.h>
28a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#ifdef HAVE_ERRNO_H
29a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#include <errno.h>
30a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#endif
313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <sys/param.h>
323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <sys/stat.h>
333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <linux/ext2_fs.h>
343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
3536caf25f8d61eb8ffddc9895463bce5807e96808Theodore Ts'o#ifndef S_ISLNK			/* So we can compile even with gcc-warn */
3636caf25f8d61eb8ffddc9895463bce5807e96808Theodore Ts'o# ifdef __S_IFLNK
3736caf25f8d61eb8ffddc9895463bce5807e96808Theodore Ts'o#  define S_ISLNK(mode)	 __S_ISTYPE((mode), __S_IFLNK)
3836caf25f8d61eb8ffddc9895463bce5807e96808Theodore Ts'o# else
3936caf25f8d61eb8ffddc9895463bce5807e96808Theodore Ts'o#  define S_ISLNK(mode)  0
4036caf25f8d61eb8ffddc9895463bce5807e96808Theodore Ts'o# endif
4136caf25f8d61eb8ffddc9895463bce5807e96808Theodore Ts'o#endif
4236caf25f8d61eb8ffddc9895463bce5807e96808Theodore Ts'o
433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include "et/com_err.h"
443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include "e2p/e2p.h"
453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include "../version.h"
473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'oconst char * program_name = "chattr";
493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'oint add = 0;
513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'oint rem = 0;
523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'oint set = 0;
533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'oint set_version = 0;
543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ounsigned long version;
563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'oint recursive = 0;
583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'oint verbose = 0;
593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ounsigned long af;
613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ounsigned long rf;
623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ounsigned long sf;
633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
64818180cdfcff84b9048ecdc5dc86323f0fefba24Theodore Ts'ostatic void fatal_error(const char * fmt_string, int errcode)
653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	fprintf (stderr, fmt_string, program_name);
673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	exit (errcode);
683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
70818180cdfcff84b9048ecdc5dc86323f0fefba24Theodore Ts'o#define usage() fatal_error("usage: %s [-RV] [-+=AacdisSu] [-v version] files...\n", \
713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			     1)
723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic int decode_arg (int * i, int argc, char ** argv)
743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	char * p;
763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	char * tmp;
773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	switch (argv[*i][0])
793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	{
803839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	case '-':
813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		for (p = &argv[*i][1]; *p; p++)
823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			switch (*p)
833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			{
843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			case 'R':
853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				recursive = 1;
863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				break;
873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			case 'S':
883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				rf |= EXT2_SYNC_FL;
893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				rem = 1;
903839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				break;
913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			case 'V':
923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				verbose = 1;
933839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				break;
94f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#ifdef	EXT2_APPEND_FL
95f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o			case 'a':
96f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o				rf |= EXT2_APPEND_FL;
97f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o				rem = 1;
98f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o				break;
99f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#endif
1005c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o#ifdef EXT2_NOATIME_FL
1015c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o			case 'A':
1025c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o				rf |= EXT2_NOATIME_FL;
1035c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o				rem = 1;
1045c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o				break;
1055c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o#endif
1063839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			case 'c':
1073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				rf |= EXT2_COMPR_FL;
1083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				rem = 1;
1093839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				break;
110f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#ifdef	EXT2_NODUMP_FL
111f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o			case 'd':
112f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o				rf |= EXT2_NODUMP_FL;
113f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o				rem = 1;
114f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o				break;
115f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#endif
116f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#ifdef	EXT2_IMMUTABLE_FL
117f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o			case 'i':
118f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o				rf |= EXT2_IMMUTABLE_FL;
119f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o				rem = 1;
120f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o				break;
121f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#endif
1223839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			case 's':
1233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				rf |= EXT2_SECRM_FL;
1243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				rem = 1;
1253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				break;
1263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			case 'u':
1273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				rf |= EXT2_UNRM_FL;
1283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				rem = 1;
1293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				break;
1303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			case 'v':
1311e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o				(*i)++;
1323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				if (*i >= argc)
1333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o					usage ();
1343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				version = strtol (argv[*i], &tmp, 0);
1353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				if (*tmp)
1363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				{
1373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o					com_err (program_name, 0,
1383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o						 "bad version - %s\n", argv[*i]);
1393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o					usage ();
1403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				}
1413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				set_version = 1;
1423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				break;
1433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			default:
1443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				fprintf (stderr, "%s: Unrecognized argument: %c\n",
1453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o					 program_name, *p);
1463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				usage ();
1473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			}
1483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		break;
1493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	case '+':
1503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		add = 1;
1513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		for (p = &argv[*i][1]; *p; p++)
1523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			switch (*p)
1533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			{
1543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			case 'S':
1553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				af |= EXT2_SYNC_FL;
1563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				break;
157f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#ifdef	EXT2_APPEND_FL
158f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o			case 'a':
159f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o				af |= EXT2_APPEND_FL;
160f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o				break;
161f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#endif
1625c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o#ifdef EXT2_NOATIME_FL
1635c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o			case 'A':
1645c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o				af |= EXT2_NOATIME_FL;
1655c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o				break;
1665c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o#endif
1673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			case 'c':
1683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				af |= EXT2_COMPR_FL;
1693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				break;
170f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#ifdef	EXT2_NODUMP_FL
171f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o			case 'd':
172f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o				af |= EXT2_NODUMP_FL;
173f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o				break;
174f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#endif
175f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#ifdef	EXT2_IMMUTABLE_FL
176f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o			case 'i':
177f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o				af |= EXT2_IMMUTABLE_FL;
178f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o				break;
179f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#endif
1803839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			case 's':
1813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				af |= EXT2_SECRM_FL;
1823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				break;
1833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			case 'u':
1843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				af |= EXT2_UNRM_FL;
1853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				break;
1863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			default:
1873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				usage ();
1883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			}
1893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		break;
1903839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	case '=':
1913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		set = 1;
1923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		for (p = &argv[*i][1]; *p; p++)
1933839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			switch (*p)
1943839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			{
1953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			case 'S':
1963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				sf |= EXT2_SYNC_FL;
1973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				break;
198f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#ifdef	EXT2_APPEND_FL
199f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o			case 'a':
200f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o				sf |= EXT2_APPEND_FL;
201f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o				break;
202f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#endif
2035c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o#ifdef EXT2_NOATIME_FL
2045c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o			case 'A':
2055c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o				sf |= EXT2_NOATIME_FL;
2065c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o				break;
2075c576477ccb2f0ca8c5d5af2e2354fd8eeff1589Theodore Ts'o#endif
2083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			case 'c':
2093839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				sf |= EXT2_COMPR_FL;
2103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				break;
211f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#ifdef	EXT2_NODUMP_FL
212f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o			case 'd':
213f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o				sf |= EXT2_NODUMP_FL;
214f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o				break;
215f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#endif
216f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#ifdef	EXT2_IMMUTABLE_FL
217f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o			case 'i':
218f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o				sf |= EXT2_IMMUTABLE_FL;
219f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o				break;
220f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o#endif
2213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			case 's':
2223839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				sf |= EXT2_SECRM_FL;
2233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				break;
2243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			case 'u':
2253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				sf |= EXT2_UNRM_FL;
2263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				break;
2273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			default:
2283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				usage ();
2293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			}
2303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		break;
2313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	default:
2323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		return EOF;
2333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		break;
2343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
2353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	return 1;
2363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
2373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
2383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic int chattr_dir_proc (const char *, struct dirent *, void *);
2393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
2403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic void change_attributes (const char * name)
2413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
2423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	unsigned long flags;
2433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	struct stat st;
2443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
2453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	if (lstat (name, &st) == -1)
2463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	{
2473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		com_err (program_name, errno, "while stating %s", name);
2483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		return;
2493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
250a88fa0c0135307288562d4922438ae52fdbad855Theodore Ts'o	if (S_ISLNK(st.st_mode) && recursive)
251a88fa0c0135307288562d4922438ae52fdbad855Theodore Ts'o		return;
2523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	if (set)
2533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	{
2543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		if (verbose)
2553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		{
2563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			printf ("Flags of %s set as ", name);
257f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o			print_flags (stdout, sf, 0);
2583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			printf ("\n");
2593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		}
2603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		if (fsetflags (name, sf) == -1)
2613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			perror (name);
2623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
2633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	else
2643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	{
2653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		if (fgetflags (name, &flags) == -1)
2663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			com_err (program_name, errno,
2673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			         "while reading flags on %s", name);
2683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		else
2693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		{
2703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			if (rem)
2713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				flags &= ~rf;
2723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			if (add)
2733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				flags |= af;
2743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			if (verbose)
2753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			{
2763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				printf ("Flags of %s set as ", name);
277f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o				print_flags (stdout, flags, 0);
2783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				printf ("\n");
2793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			}
2803839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			if (fsetflags (name, flags) == -1)
2813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				com_err (program_name, errno,
2823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				         "while setting flags on %s", name);
2833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		}
2843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
2853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	if (set_version)
2863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	{
2873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		if (verbose)
2883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			printf ("Version of %s set as %lu\n", name, version);
2893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		if (fsetversion (name, version) == -1)
2903839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			com_err (program_name, errno,
2913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			         "while setting version on %s", name);
2923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
2933839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	if (S_ISDIR(st.st_mode) && recursive)
2943839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		iterate_on_dir (name, chattr_dir_proc, (void *) NULL);
2953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
2963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
2973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic int chattr_dir_proc (const char * dir_name, struct dirent * de, void * private)
2983839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
2993839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	if (strcmp (de->d_name, ".") && strcmp (de->d_name, ".."))
3003839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	{
301a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o	        char *path;
302a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o
303a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o		path = malloc(strlen (dir_name) + 1 + strlen (de->d_name) + 1);
304a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o		if (!path)
305a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o			fatal_error("Couldn't allocate path variable "
306a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o				    "in chattr_dir_proc", 1);
3073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		sprintf (path, "%s/%s", dir_name, de->d_name);
3083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		change_attributes (path);
309a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o		free(path);
3103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
3113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	return 0;
3123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
3133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
31400e5433eb5e9f70f485968b809fdcf297d7fe7b9Theodore Ts'oint main (int argc, char ** argv)
3153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
3163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	int i, j;
3173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	int end_arg = 0;
3183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
3193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	if (argc && *argv)
3203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		program_name = *argv;
3213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	i = 1;
3223839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	while (i < argc && !end_arg)
3233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	{
3243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		if (decode_arg (&i, argc, argv) == EOF)
3253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			end_arg = 1;
3263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		else
3273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			i++;
3283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
3293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	if (i >= argc)
3303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		usage ();
3313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	if (set && (add || rem))
3323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	{
3333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		fprintf (stderr, "= is incompatible with - and +\n");
3343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		exit (1);
3353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
3361e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o	if (!(add || rem || set || set_version))
3373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	{
3381e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o		fprintf (stderr, "Must use '-v', =, - or +\n");
3393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		exit (1);
3403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
341a88fa0c0135307288562d4922438ae52fdbad855Theodore Ts'o	if (verbose)
342a88fa0c0135307288562d4922438ae52fdbad855Theodore Ts'o		fprintf (stderr, "chattr %s, %s for EXT2 FS %s, %s\n",
343a88fa0c0135307288562d4922438ae52fdbad855Theodore Ts'o			 E2FSPROGS_VERSION, E2FSPROGS_DATE,
344a88fa0c0135307288562d4922438ae52fdbad855Theodore Ts'o			 EXT2FS_VERSION, EXT2FS_DATE);
3453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	for (j = i; j < argc; j++)
3463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		change_attributes (argv[j]);
34700e5433eb5e9f70f485968b809fdcf297d7fe7b9Theodore Ts'o	exit(0);
3483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
349