chattr.c revision 54c637d4d29af3e6365779f8b12976abe95a4753
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#define _FILE_OFFSET_BITS 64
23fff18b4e76d3757a78e5583010bbce3772461f4dTheodore Ts'o
24a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#include <sys/types.h>
253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <dirent.h>
263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <fcntl.h>
273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <stdio.h>
283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <stdlib.h>
293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <unistd.h>
3019c78dc07fce2d6f39b5e541562afc3ca1ea38ffTheodore Ts'o#include <string.h>
31a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#ifdef HAVE_ERRNO_H
32a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#include <errno.h>
33a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o#endif
343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <sys/param.h>
353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <sys/stat.h>
3654c637d4d29af3e6365779f8b12976abe95a4753Theodore Ts'o#include "ext2fs/ext2_fs.h"
373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
3836caf25f8d61eb8ffddc9895463bce5807e96808Theodore Ts'o#ifndef S_ISLNK			/* So we can compile even with gcc-warn */
3936caf25f8d61eb8ffddc9895463bce5807e96808Theodore Ts'o# ifdef __S_IFLNK
4036caf25f8d61eb8ffddc9895463bce5807e96808Theodore Ts'o#  define S_ISLNK(mode)	 __S_ISTYPE((mode), __S_IFLNK)
4136caf25f8d61eb8ffddc9895463bce5807e96808Theodore Ts'o# else
4236caf25f8d61eb8ffddc9895463bce5807e96808Theodore Ts'o#  define S_ISLNK(mode)  0
4336caf25f8d61eb8ffddc9895463bce5807e96808Theodore Ts'o# endif
4436caf25f8d61eb8ffddc9895463bce5807e96808Theodore Ts'o#endif
4536caf25f8d61eb8ffddc9895463bce5807e96808Theodore Ts'o
463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include "et/com_err.h"
473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include "e2p/e2p.h"
483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include "../version.h"
50d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o#include "nls-enable.h"
513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
52e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'ostatic const char * program_name = "chattr";
533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
549a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'ostatic int add;
559a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'ostatic int rem;
569a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'ostatic int set;
579a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'ostatic int set_version;
583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
59e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'ostatic unsigned long version;
603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
619a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'ostatic int recursive;
629a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'ostatic int verbose;
633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
64e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'ostatic unsigned long af;
65e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'ostatic unsigned long rf;
66e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'ostatic unsigned long sf;
673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
68818180cdfcff84b9048ecdc5dc86323f0fefba24Theodore Ts'ostatic void fatal_error(const char * fmt_string, int errcode)
693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	fprintf (stderr, fmt_string, program_name);
713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	exit (errcode);
723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
749a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o#define usage() fatal_error(_("usage: %s [-RV] [-+=AacdijsSu] [-v version] files...\n"), \
753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			     1)
763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
779a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'ostruct flags_char {
789a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o	unsigned long	flag;
799a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o	char 		optchar;
809a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o};
819a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o
829a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'ostatic const struct flags_char flags_array[] = {
839a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o	{ EXT2_NOATIME_FL, 'A' },
849a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o	{ EXT2_SYNC_FL, 'S' },
859a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o	{ EXT2_APPEND_FL, 'a' },
869a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o	{ EXT2_COMPR_FL, 'c' },
879a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o	{ EXT2_NODUMP_FL, 'd' },
889a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o	{ EXT2_IMMUTABLE_FL, 'i' },
899a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o	{ EXT3_JOURNAL_DATA_FL, 'j' },
909a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o	{ EXT2_SECRM_FL, 's' },
919a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o	{ EXT2_UNRM_FL, 'u' },
929a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o	{ 0, 0 }
939a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o};
949a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o
959a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'ostatic unsigned long get_flag(char c)
969a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o{
979a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o	const struct flags_char *fp;
989a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o
999a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o	for (fp = flags_array; fp->flag != 0; fp++) {
1009a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o		if (fp->optchar == c)
1019a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o			return fp->flag;
1029a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o	}
1039a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o	return 0;
1049a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o}
1059a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o
1069a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o
1073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic int decode_arg (int * i, int argc, char ** argv)
1083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
1093839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	char * p;
1103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	char * tmp;
1119a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o	unsigned long fl;
1123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
1133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	switch (argv[*i][0])
1143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	{
1153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	case '-':
1169a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o		for (p = &argv[*i][1]; *p; p++) {
1179a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o			if (*p == 'R') {
1183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				recursive = 1;
1199a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o				continue;
1209a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o			}
1219a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o			if (*p == 'V') {
1223839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				verbose = 1;
1239a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o				continue;
1249a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o			}
1259a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o			if (*p == 'v') {
1261e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o				(*i)++;
1273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				if (*i >= argc)
1283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o					usage ();
1293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				version = strtol (argv[*i], &tmp, 0);
1309a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o				if (*tmp) {
1313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o					com_err (program_name, 0,
1329a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o						 _("bad version - %s\n"),
1339a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o						 argv[*i]);
1343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o					usage ();
1353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				}
1363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				set_version = 1;
1379a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o				continue;
1383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			}
1399a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o			if ((fl = get_flag(*p)) == 0)
1409a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o				usage();
1419a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o			rf |= fl;
1429a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o			rem = 1;
1439a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o		}
1443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		break;
1453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	case '+':
1463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		add = 1;
1479a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o		for (p = &argv[*i][1]; *p; p++) {
1489a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o			if ((fl = get_flag(*p)) == 0)
1499a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o				usage();
1509a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o			af |= fl;
1519a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o		}
1523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		break;
1533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	case '=':
1543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		set = 1;
1559a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o		for (p = &argv[*i][1]; *p; p++) {
1569a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o			if ((fl = get_flag(*p)) == 0)
1579a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o				usage();
1589a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o			sf |= fl;
1599a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o		}
1603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		break;
1613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	default:
1623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		return EOF;
1633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		break;
1643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
1653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	return 1;
1663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
1673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
1683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic int chattr_dir_proc (const char *, struct dirent *, void *);
1693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
1703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic void change_attributes (const char * name)
1713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
1723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	unsigned long flags;
1733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	struct stat st;
1743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
175e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o	if (lstat (name, &st) == -1) {
176e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o		com_err (program_name, errno, _("while trying to stat %s"),
177e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o			 name);
1783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		return;
1793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
180a88fa0c0135307288562d4922438ae52fdbad855Theodore Ts'o	if (S_ISLNK(st.st_mode) && recursive)
181a88fa0c0135307288562d4922438ae52fdbad855Theodore Ts'o		return;
182e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o
183e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o	/* Don't try to open device files, fifos etc.  We probably
184e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o           ought to display an error if the file was explicitly given
185e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o           on the command line (whether or not recursive was
186e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o           requested).  */
187e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o	if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode) &&
188e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o	    !S_ISDIR(st.st_mode))
189e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o		return;
190e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o
191e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o	if (set) {
192e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o		if (verbose) {
193d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o			printf (_("Flags of %s set as "), name);
194f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o			print_flags (stdout, sf, 0);
1953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			printf ("\n");
1963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		}
1973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		if (fsetflags (name, sf) == -1)
1983839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			perror (name);
199e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o	} else {
2003839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		if (fgetflags (name, &flags) == -1)
2013839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			com_err (program_name, errno,
202d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o			         _("while reading flags on %s"), name);
203e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o		else {
2043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			if (rem)
2053839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				flags &= ~rf;
2063839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			if (add)
2073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				flags |= af;
208e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o			if (verbose) {
209d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o				printf (_("Flags of %s set as "), name);
210f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o				print_flags (stdout, flags, 0);
2113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				printf ("\n");
2123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			}
2133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			if (fsetflags (name, flags) == -1)
2143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				com_err (program_name, errno,
215d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o				         _("while setting flags on %s"), name);
2163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		}
2173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
218e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o	if (set_version) {
2193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		if (verbose)
220d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o			printf (_("Version of %s set as %lu\n"), name, version);
2213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		if (fsetversion (name, version) == -1)
2223839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			com_err (program_name, errno,
223d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o			         _("while setting version on %s"), name);
2243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
2253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	if (S_ISDIR(st.st_mode) && recursive)
226e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o		iterate_on_dir (name, chattr_dir_proc, NULL);
2273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
2283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
229e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'ostatic int chattr_dir_proc (const char * dir_name, struct dirent * de,
230e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o			    void * unused_private)
2313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
232e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o	if (strcmp (de->d_name, ".") && strcmp (de->d_name, "..")) {
233a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o	        char *path;
234a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o
235a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o		path = malloc(strlen (dir_name) + 1 + strlen (de->d_name) + 1);
236a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o		if (!path)
237d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o			fatal_error(_("Couldn't allocate path variable "
238d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o				    "in chattr_dir_proc"), 1);
2393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		sprintf (path, "%s/%s", dir_name, de->d_name);
2403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		change_attributes (path);
241a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o		free(path);
2423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
2433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	return 0;
2443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
2453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
24600e5433eb5e9f70f485968b809fdcf297d7fe7b9Theodore Ts'oint main (int argc, char ** argv)
2473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
2483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	int i, j;
2493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	int end_arg = 0;
2503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
251d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o#ifdef ENABLE_NLS
252d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o	setlocale(LC_MESSAGES, "");
253d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o	bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
254d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o	textdomain(NLS_CAT_NAME);
255d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o#endif
2563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	if (argc && *argv)
2573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		program_name = *argv;
2583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	i = 1;
259e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o	while (i < argc && !end_arg) {
2603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		if (decode_arg (&i, argc, argv) == EOF)
2613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			end_arg = 1;
2623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		else
2633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			i++;
2643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
2653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	if (i >= argc)
2663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		usage ();
267e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o	if (set && (add || rem)) {
268d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o		fprintf (stderr, _("= is incompatible with - and +\n"));
2693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		exit (1);
2703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
271e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o	if ((rf & af) != 0) {
272e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o		fprintf (stderr, "Can't both set and unset same flag.\n");
273e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o		exit (1);
274e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o	}
275e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o	if (!(add || rem || set || set_version)) {
276d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o		fprintf (stderr, _("Must use '-v', =, - or +\n"));
2773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		exit (1);
2783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
279a88fa0c0135307288562d4922438ae52fdbad855Theodore Ts'o	if (verbose)
280d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o		fprintf (stderr, _("chattr %s, %s for EXT2 FS %s, %s\n"),
281a88fa0c0135307288562d4922438ae52fdbad855Theodore Ts'o			 E2FSPROGS_VERSION, E2FSPROGS_DATE,
282a88fa0c0135307288562d4922438ae52fdbad855Theodore Ts'o			 EXT2FS_VERSION, EXT2FS_DATE);
2833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	for (j = i; j < argc; j++)
2843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		change_attributes (argv[j]);
28500e5433eb5e9f70f485968b809fdcf297d7fe7b9Theodore Ts'o	exit(0);
2863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
287