chattr.c revision b705640ae162093d40fc9f77e716bec891561ffe
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
21fff18b4e76d3757a78e5583010bbce3772461f4dTheodore Ts'o#define _LARGEFILE64_SOURCE
22fff18b4e76d3757a78e5583010bbce3772461f4dTheodore Ts'o
23a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#include <sys/types.h>
243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <dirent.h>
253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <fcntl.h>
263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <stdio.h>
273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <stdlib.h>
283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <unistd.h>
2919c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o#include <string.h>
30a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#ifdef HAVE_ERRNO_H
31a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#include <errno.h>
32a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#endif
333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <sys/param.h>
343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <sys/stat.h>
3554c637d4d29af3e6365779f8b12976abe95a4753Theodore Ts'o#include "ext2fs/ext2_fs.h"
363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
3736caf25f8d61eb8ffddc9895463bce5807e96808Theodore Ts'o#ifndef S_ISLNK			/* So we can compile even with gcc-warn */
3836caf25f8d61eb8ffddc9895463bce5807e96808Theodore Ts'o# ifdef __S_IFLNK
3936caf25f8d61eb8ffddc9895463bce5807e96808Theodore Ts'o#  define S_ISLNK(mode)	 __S_ISTYPE((mode), __S_IFLNK)
4036caf25f8d61eb8ffddc9895463bce5807e96808Theodore Ts'o# else
4136caf25f8d61eb8ffddc9895463bce5807e96808Theodore Ts'o#  define S_ISLNK(mode)  0
4236caf25f8d61eb8ffddc9895463bce5807e96808Theodore Ts'o# endif
4336caf25f8d61eb8ffddc9895463bce5807e96808Theodore Ts'o#endif
4436caf25f8d61eb8ffddc9895463bce5807e96808Theodore Ts'o
453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include "et/com_err.h"
463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include "e2p/e2p.h"
473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include "../version.h"
49d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o#include "nls-enable.h"
503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
51e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'ostatic const char * program_name = "chattr";
523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
539a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'ostatic int add;
549a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'ostatic int rem;
559a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'ostatic int set;
569a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'ostatic int set_version;
573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
58e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'ostatic unsigned long version;
593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
609a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'ostatic int recursive;
619a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'ostatic int verbose;
623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
63e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'ostatic unsigned long af;
64e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'ostatic unsigned long rf;
65e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'ostatic unsigned long sf;
663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
67b705640ae162093d40fc9f77e716bec891561ffeTheodore Ts'o#ifdef _LFS64_LARGEFILE
68b705640ae162093d40fc9f77e716bec891561ffeTheodore Ts'o#define LSTAT		lstat64
69b705640ae162093d40fc9f77e716bec891561ffeTheodore Ts'o#define STRUCT_STAT	struct stat64
70b705640ae162093d40fc9f77e716bec891561ffeTheodore Ts'o#else
71b705640ae162093d40fc9f77e716bec891561ffeTheodore Ts'o#define LSTAT		lstat
72b705640ae162093d40fc9f77e716bec891561ffeTheodore Ts'o#define STRUCT_STAT	struct stat
73b705640ae162093d40fc9f77e716bec891561ffeTheodore Ts'o#endif
74b705640ae162093d40fc9f77e716bec891561ffeTheodore Ts'o
75818180cdfcff84b9048ecdc5dc86323f0fefba24Theodore Ts'ostatic void fatal_error(const char * fmt_string, int errcode)
763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	fprintf (stderr, fmt_string, program_name);
783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	exit (errcode);
793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
803839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
819a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o#define usage() fatal_error(_("usage: %s [-RV] [-+=AacdijsSu] [-v version] files...\n"), \
823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			     1)
833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
849a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'ostruct flags_char {
859a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o	unsigned long	flag;
869a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o	char 		optchar;
879a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o};
889a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o
899a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'ostatic const struct flags_char flags_array[] = {
909a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o	{ EXT2_NOATIME_FL, 'A' },
919a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o	{ EXT2_SYNC_FL, 'S' },
929a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o	{ EXT2_APPEND_FL, 'a' },
939a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o	{ EXT2_COMPR_FL, 'c' },
949a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o	{ EXT2_NODUMP_FL, 'd' },
959a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o	{ EXT2_IMMUTABLE_FL, 'i' },
969a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o	{ EXT3_JOURNAL_DATA_FL, 'j' },
979a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o	{ EXT2_SECRM_FL, 's' },
989a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o	{ EXT2_UNRM_FL, 'u' },
999a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o	{ 0, 0 }
1009a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o};
1019a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o
1029a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'ostatic unsigned long get_flag(char c)
1039a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o{
1049a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o	const struct flags_char *fp;
1059a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o
1069a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o	for (fp = flags_array; fp->flag != 0; fp++) {
1079a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o		if (fp->optchar == c)
1089a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o			return fp->flag;
1099a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o	}
1109a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o	return 0;
1119a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o}
1129a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o
1139a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o
1143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic int decode_arg (int * i, int argc, char ** argv)
1153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
1163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	char * p;
1173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	char * tmp;
1189a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o	unsigned long fl;
1193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
1203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	switch (argv[*i][0])
1213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	{
1223839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	case '-':
1239a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o		for (p = &argv[*i][1]; *p; p++) {
1249a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o			if (*p == 'R') {
1253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				recursive = 1;
1269a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o				continue;
1279a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o			}
1289a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o			if (*p == 'V') {
1293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				verbose = 1;
1309a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o				continue;
1319a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o			}
1329a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o			if (*p == 'v') {
1331e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o				(*i)++;
1343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				if (*i >= argc)
1353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o					usage ();
1363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				version = strtol (argv[*i], &tmp, 0);
1379a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o				if (*tmp) {
1383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o					com_err (program_name, 0,
1399a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o						 _("bad version - %s\n"),
1409a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o						 argv[*i]);
1413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o					usage ();
1423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				}
1433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				set_version = 1;
1449a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o				continue;
1453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			}
1469a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o			if ((fl = get_flag(*p)) == 0)
1479a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o				usage();
1489a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o			rf |= fl;
1499a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o			rem = 1;
1509a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o		}
1513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		break;
1523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	case '+':
1533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		add = 1;
1549a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o		for (p = &argv[*i][1]; *p; p++) {
1559a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o			if ((fl = get_flag(*p)) == 0)
1569a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o				usage();
1579a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o			af |= fl;
1589a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o		}
1593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		break;
1603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	case '=':
1613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		set = 1;
1629a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o		for (p = &argv[*i][1]; *p; p++) {
1639a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o			if ((fl = get_flag(*p)) == 0)
1649a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o				usage();
1659a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o			sf |= fl;
1669a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o		}
1673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		break;
1683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	default:
1693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		return EOF;
1703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		break;
1713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
1723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	return 1;
1733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
1743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
1753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic int chattr_dir_proc (const char *, struct dirent *, void *);
1763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
1773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic void change_attributes (const char * name)
1783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
1793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	unsigned long flags;
180b705640ae162093d40fc9f77e716bec891561ffeTheodore Ts'o	STRUCT_STAT	st;
1813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
182b705640ae162093d40fc9f77e716bec891561ffeTheodore Ts'o	if (LSTAT (name, &st) == -1) {
183e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o		com_err (program_name, errno, _("while trying to stat %s"),
184e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o			 name);
1853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		return;
1863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
187a88fa0c0135307288562d4922438ae52fdbad855Theodore Ts'o	if (S_ISLNK(st.st_mode) && recursive)
188a88fa0c0135307288562d4922438ae52fdbad855Theodore Ts'o		return;
189e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o
190e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o	/* Don't try to open device files, fifos etc.  We probably
191e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o           ought to display an error if the file was explicitly given
192e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o           on the command line (whether or not recursive was
193e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o           requested).  */
194e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o	if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode) &&
195e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o	    !S_ISDIR(st.st_mode))
196e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o		return;
197e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o
198e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o	if (set) {
199e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o		if (verbose) {
200d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o			printf (_("Flags of %s set as "), name);
201f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o			print_flags (stdout, sf, 0);
2023839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			printf ("\n");
2033839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		}
2043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		if (fsetflags (name, sf) == -1)
2053839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			perror (name);
206e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o	} else {
2073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		if (fgetflags (name, &flags) == -1)
2083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			com_err (program_name, errno,
209d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o			         _("while reading flags on %s"), name);
210e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o		else {
2113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			if (rem)
2123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				flags &= ~rf;
2133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			if (add)
2143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				flags |= af;
215e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o			if (verbose) {
216d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o				printf (_("Flags of %s set as "), name);
217f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o				print_flags (stdout, flags, 0);
2183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				printf ("\n");
2193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			}
2203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			if (fsetflags (name, flags) == -1)
2213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				com_err (program_name, errno,
222d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o				         _("while setting flags on %s"), name);
2233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		}
2243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
225e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o	if (set_version) {
2263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		if (verbose)
227d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o			printf (_("Version of %s set as %lu\n"), name, version);
2283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		if (fsetversion (name, version) == -1)
2293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			com_err (program_name, errno,
230d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o			         _("while setting version on %s"), name);
2313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
2323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	if (S_ISDIR(st.st_mode) && recursive)
233e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o		iterate_on_dir (name, chattr_dir_proc, NULL);
2343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
2353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
236e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'ostatic int chattr_dir_proc (const char * dir_name, struct dirent * de,
237e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o			    void * unused_private)
2383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
239e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o	if (strcmp (de->d_name, ".") && strcmp (de->d_name, "..")) {
240a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o	        char *path;
241a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o
242a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o		path = malloc(strlen (dir_name) + 1 + strlen (de->d_name) + 1);
243a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o		if (!path)
244d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o			fatal_error(_("Couldn't allocate path variable "
245d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o				    "in chattr_dir_proc"), 1);
2463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		sprintf (path, "%s/%s", dir_name, de->d_name);
2473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		change_attributes (path);
248a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o		free(path);
2493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
2503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	return 0;
2513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
2523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
25300e5433eb5e9f70f485968b809fdcf297d7fe7b9Theodore Ts'oint main (int argc, char ** argv)
2543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
2553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	int i, j;
2563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	int end_arg = 0;
2573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
258d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o#ifdef ENABLE_NLS
259d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o	setlocale(LC_MESSAGES, "");
260d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o	bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
261d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o	textdomain(NLS_CAT_NAME);
262d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o#endif
2633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	if (argc && *argv)
2643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		program_name = *argv;
2653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	i = 1;
266e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o	while (i < argc && !end_arg) {
2673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		if (decode_arg (&i, argc, argv) == EOF)
2683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			end_arg = 1;
2693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		else
2703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			i++;
2713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
2723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	if (i >= argc)
2733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		usage ();
274e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o	if (set && (add || rem)) {
275d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o		fprintf (stderr, _("= is incompatible with - and +\n"));
2763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		exit (1);
2773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
278e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o	if ((rf & af) != 0) {
279e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o		fprintf (stderr, "Can't both set and unset same flag.\n");
280e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o		exit (1);
281e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o	}
282e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o	if (!(add || rem || set || set_version)) {
283d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o		fprintf (stderr, _("Must use '-v', =, - or +\n"));
2843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		exit (1);
2853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
286a88fa0c0135307288562d4922438ae52fdbad855Theodore Ts'o	if (verbose)
287d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o		fprintf (stderr, _("chattr %s, %s for EXT2 FS %s, %s\n"),
288a88fa0c0135307288562d4922438ae52fdbad855Theodore Ts'o			 E2FSPROGS_VERSION, E2FSPROGS_DATE,
289a88fa0c0135307288562d4922438ae52fdbad855Theodore Ts'o			 EXT2FS_VERSION, EXT2FS_DATE);
2903839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	for (j = i; j < argc; j++)
2913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		change_attributes (argv[j]);
29200e5433eb5e9f70f485968b809fdcf297d7fe7b9Theodore Ts'o	exit(0);
2933839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
294