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
23d1154eb460efe588eaed3d439c1caaca149fa362Theodore Ts'o#include "config.h"
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
38544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o#ifdef __GNUC__
39544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o#define EXT2FS_ATTR(x) __attribute__(x)
40544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o#else
41544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o#define EXT2FS_ATTR(x)
42544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o#endif
43544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o
4436caf25f8d61eb8ffddc9895463bce5807e96808Theodore Ts'o#ifndef S_ISLNK			/* So we can compile even with gcc-warn */
4536caf25f8d61eb8ffddc9895463bce5807e96808Theodore Ts'o# ifdef __S_IFLNK
4636caf25f8d61eb8ffddc9895463bce5807e96808Theodore Ts'o#  define S_ISLNK(mode)	 __S_ISTYPE((mode), __S_IFLNK)
4736caf25f8d61eb8ffddc9895463bce5807e96808Theodore Ts'o# else
4836caf25f8d61eb8ffddc9895463bce5807e96808Theodore Ts'o#  define S_ISLNK(mode)  0
4936caf25f8d61eb8ffddc9895463bce5807e96808Theodore Ts'o# endif
5036caf25f8d61eb8ffddc9895463bce5807e96808Theodore Ts'o#endif
5136caf25f8d61eb8ffddc9895463bce5807e96808Theodore Ts'o
523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include "et/com_err.h"
533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include "e2p/e2p.h"
5499ceb8ec1acd7f38da289966b9984b3ffa1914a9Theodore Ts'o#include "support/nls-enable.h"
553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include "../version.h"
573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
58e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'ostatic const char * program_name = "chattr";
593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
609a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'ostatic int add;
619a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'ostatic int rem;
629a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'ostatic int set;
639a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'ostatic int set_version;
643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
65e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'ostatic unsigned long version;
663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
673627e83830995a8d3c00b391241909f7b6b44a76Li Xistatic int set_project;
683627e83830995a8d3c00b391241909f7b6b44a76Li Xistatic unsigned long project;
693627e83830995a8d3c00b391241909f7b6b44a76Li Xi
709a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'ostatic int recursive;
719a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'ostatic int verbose;
72e68594d2376afd10e03b440b4bc288508ad13aa2Theodore Ts'ostatic int silent;
733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
74e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'ostatic unsigned long af;
75e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'ostatic unsigned long rf;
76e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'ostatic unsigned long sf;
773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
78b705640ae162093d40fc9f77e716bec891561ffeTheodore Ts'o#ifdef _LFS64_LARGEFILE
79b705640ae162093d40fc9f77e716bec891561ffeTheodore Ts'o#define LSTAT		lstat64
80b705640ae162093d40fc9f77e716bec891561ffeTheodore Ts'o#define STRUCT_STAT	struct stat64
81b705640ae162093d40fc9f77e716bec891561ffeTheodore Ts'o#else
82b705640ae162093d40fc9f77e716bec891561ffeTheodore Ts'o#define LSTAT		lstat
83b705640ae162093d40fc9f77e716bec891561ffeTheodore Ts'o#define STRUCT_STAT	struct stat
84b705640ae162093d40fc9f77e716bec891561ffeTheodore Ts'o#endif
85b705640ae162093d40fc9f77e716bec891561ffeTheodore Ts'o
86642935c082ca22e1186fc9926fe06e4207d5ab56Theodore Ts'ostatic void usage(void)
873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
88e68594d2376afd10e03b440b4bc288508ad13aa2Theodore Ts'o	fprintf(stderr,
893627e83830995a8d3c00b391241909f7b6b44a76Li Xi		_("Usage: %s [-pRVf] [-+=aAcCdDeijPsStTu] [-v version] files...\n"),
90642935c082ca22e1186fc9926fe06e4207d5ab56Theodore Ts'o		program_name);
91642935c082ca22e1186fc9926fe06e4207d5ab56Theodore Ts'o	exit(1);
923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
933839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
949a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'ostruct flags_char {
959a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o	unsigned long	flag;
969a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o	char 		optchar;
979a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o};
989a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o
999a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'ostatic const struct flags_char flags_array[] = {
1009a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o	{ EXT2_NOATIME_FL, 'A' },
1019a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o	{ EXT2_SYNC_FL, 'S' },
10288372d5c4b2ebd0405446b42de65bf2b0ebb2408Theodore Ts'o	{ EXT2_DIRSYNC_FL, 'D' },
1039a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o	{ EXT2_APPEND_FL, 'a' },
1049a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o	{ EXT2_COMPR_FL, 'c' },
1059a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o	{ EXT2_NODUMP_FL, 'd' },
1067c8da6e3768bc7cc7ffde72b4f87fd2ec3c7c7e7Aneesh Kumar K.V	{ EXT4_EXTENTS_FL, 'e'},
1079a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o	{ EXT2_IMMUTABLE_FL, 'i' },
1089a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o	{ EXT3_JOURNAL_DATA_FL, 'j' },
109e1cec4464bdaf93ea609de43c5cdeb6a1f553483Li Xi	{ EXT4_PROJINHERIT_FL, 'P' },
1109a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o	{ EXT2_SECRM_FL, 's' },
1119a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o	{ EXT2_UNRM_FL, 'u' },
112b3f5b4c22939daba86465d05842bce76053bc3cfTheodore Ts'o	{ EXT2_NOTAIL_FL, 't' },
11315f9011add4013d32ea2f7ca7dbf860f95b8ec53Theodore Ts'o	{ EXT2_TOPDIR_FL, 'T' },
1140796e660859724f304155e094b6cf5739a610ae4Theodore Ts'o	{ FS_NOCOW_FL, 'C' },
1159a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o	{ 0, 0 }
1169a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o};
1179a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o
1189a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'ostatic unsigned long get_flag(char c)
1199a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o{
1209a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o	const struct flags_char *fp;
121efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
1229a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o	for (fp = flags_array; fp->flag != 0; fp++) {
1239a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o		if (fp->optchar == c)
1249a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o			return fp->flag;
1259a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o	}
1269a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o	return 0;
1279a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o}
1289a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o
1299a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o
1303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic int decode_arg (int * i, int argc, char ** argv)
1313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
1323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	char * p;
1333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	char * tmp;
1349a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o	unsigned long fl;
1353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
1363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	switch (argv[*i][0])
1373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	{
1383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	case '-':
1399a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o		for (p = &argv[*i][1]; *p; p++) {
1409a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o			if (*p == 'R') {
1413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				recursive = 1;
1429a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o				continue;
1439a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o			}
1449a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o			if (*p == 'V') {
1453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				verbose = 1;
1469a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o				continue;
1479a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o			}
148e68594d2376afd10e03b440b4bc288508ad13aa2Theodore Ts'o			if (*p == 'f') {
149e68594d2376afd10e03b440b4bc288508ad13aa2Theodore Ts'o				silent = 1;
150e68594d2376afd10e03b440b4bc288508ad13aa2Theodore Ts'o				continue;
151e68594d2376afd10e03b440b4bc288508ad13aa2Theodore Ts'o			}
1523627e83830995a8d3c00b391241909f7b6b44a76Li Xi			if (*p == 'p') {
1533627e83830995a8d3c00b391241909f7b6b44a76Li Xi				(*i)++;
1543627e83830995a8d3c00b391241909f7b6b44a76Li Xi				if (*i >= argc)
1553627e83830995a8d3c00b391241909f7b6b44a76Li Xi					usage ();
1563627e83830995a8d3c00b391241909f7b6b44a76Li Xi				project = strtol (argv[*i], &tmp, 0);
1573627e83830995a8d3c00b391241909f7b6b44a76Li Xi				if (*tmp) {
1583627e83830995a8d3c00b391241909f7b6b44a76Li Xi					com_err (program_name, 0,
1593627e83830995a8d3c00b391241909f7b6b44a76Li Xi						 _("bad project - %s\n"),
1603627e83830995a8d3c00b391241909f7b6b44a76Li Xi						 argv[*i]);
1613627e83830995a8d3c00b391241909f7b6b44a76Li Xi					usage ();
1623627e83830995a8d3c00b391241909f7b6b44a76Li Xi				}
1633627e83830995a8d3c00b391241909f7b6b44a76Li Xi				set_project = 1;
1643627e83830995a8d3c00b391241909f7b6b44a76Li Xi				continue;
1653627e83830995a8d3c00b391241909f7b6b44a76Li Xi			}
1669a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o			if (*p == 'v') {
1671e3472c5f37ca3686dd69b079d4d02a302f5798dTheodore Ts'o				(*i)++;
1683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				if (*i >= argc)
1693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o					usage ();
1703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				version = strtol (argv[*i], &tmp, 0);
1719a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o				if (*tmp) {
1723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o					com_err (program_name, 0,
173e68594d2376afd10e03b440b4bc288508ad13aa2Theodore Ts'o						 _("bad version - %s\n"),
1749a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o						 argv[*i]);
1753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o					usage ();
1763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				}
1773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o				set_version = 1;
1789a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o				continue;
1793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			}
1809a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o			if ((fl = get_flag(*p)) == 0)
1819a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o				usage();
1829a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o			rf |= fl;
1839a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o			rem = 1;
1849a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o		}
1853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		break;
1863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	case '+':
1873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		add = 1;
1889a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o		for (p = &argv[*i][1]; *p; p++) {
1899a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o			if ((fl = get_flag(*p)) == 0)
1909a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o				usage();
1919a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o			af |= fl;
1929a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o		}
1933839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		break;
1943839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	case '=':
1953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		set = 1;
1969a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o		for (p = &argv[*i][1]; *p; p++) {
1979a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o			if ((fl = get_flag(*p)) == 0)
1989a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o				usage();
1999a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o			sf |= fl;
2009a7188496851014f62592077b2ec603cc2c300a6Theodore Ts'o		}
2013839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		break;
2023839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	default:
2033839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		return EOF;
2043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		break;
2053839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
2063839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	return 1;
2073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
2083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
2092d328bb76d2d63bdfdba923b54c28bd686bd8fecTheodore Ts'ostatic int chattr_dir_proc(const char *, struct dirent *, void *);
2103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
2112d328bb76d2d63bdfdba923b54c28bd686bd8fecTheodore Ts'ostatic int change_attributes(const char * name)
2123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
2133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	unsigned long flags;
214b705640ae162093d40fc9f77e716bec891561ffeTheodore Ts'o	STRUCT_STAT	st;
2153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
216b705640ae162093d40fc9f77e716bec891561ffeTheodore Ts'o	if (LSTAT (name, &st) == -1) {
217e68594d2376afd10e03b440b4bc288508ad13aa2Theodore Ts'o		if (!silent)
218e68594d2376afd10e03b440b4bc288508ad13aa2Theodore Ts'o			com_err (program_name, errno,
219e68594d2376afd10e03b440b4bc288508ad13aa2Theodore Ts'o				 _("while trying to stat %s"), name);
220e68594d2376afd10e03b440b4bc288508ad13aa2Theodore Ts'o		return -1;
2213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
222e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o
2237c8da6e3768bc7cc7ffde72b4f87fd2ec3c7c7e7Aneesh Kumar K.V	if (fgetflags(name, &flags) == -1) {
2247c8da6e3768bc7cc7ffde72b4f87fd2ec3c7c7e7Aneesh Kumar K.V		if (!silent)
2257c8da6e3768bc7cc7ffde72b4f87fd2ec3c7c7e7Aneesh Kumar K.V			com_err(program_name, errno,
2267c8da6e3768bc7cc7ffde72b4f87fd2ec3c7c7e7Aneesh Kumar K.V					_("while reading flags on %s"), name);
2277c8da6e3768bc7cc7ffde72b4f87fd2ec3c7c7e7Aneesh Kumar K.V		return -1;
2287c8da6e3768bc7cc7ffde72b4f87fd2ec3c7c7e7Aneesh Kumar K.V	}
229e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o	if (set) {
230e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o		if (verbose) {
231d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o			printf (_("Flags of %s set as "), name);
232f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o			print_flags (stdout, sf, 0);
2333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			printf ("\n");
2343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		}
2353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		if (fsetflags (name, sf) == -1)
2363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			perror (name);
237e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o	} else {
2387c8da6e3768bc7cc7ffde72b4f87fd2ec3c7c7e7Aneesh Kumar K.V		if (rem)
2397c8da6e3768bc7cc7ffde72b4f87fd2ec3c7c7e7Aneesh Kumar K.V			flags &= ~rf;
2407c8da6e3768bc7cc7ffde72b4f87fd2ec3c7c7e7Aneesh Kumar K.V		if (add)
2417c8da6e3768bc7cc7ffde72b4f87fd2ec3c7c7e7Aneesh Kumar K.V			flags |= af;
2427c8da6e3768bc7cc7ffde72b4f87fd2ec3c7c7e7Aneesh Kumar K.V		if (verbose) {
2437c8da6e3768bc7cc7ffde72b4f87fd2ec3c7c7e7Aneesh Kumar K.V			printf(_("Flags of %s set as "), name);
2447c8da6e3768bc7cc7ffde72b4f87fd2ec3c7c7e7Aneesh Kumar K.V			print_flags(stdout, flags, 0);
2457c8da6e3768bc7cc7ffde72b4f87fd2ec3c7c7e7Aneesh Kumar K.V			printf("\n");
2467c8da6e3768bc7cc7ffde72b4f87fd2ec3c7c7e7Aneesh Kumar K.V		}
2477c8da6e3768bc7cc7ffde72b4f87fd2ec3c7c7e7Aneesh Kumar K.V		if (!S_ISDIR(st.st_mode))
2487c8da6e3768bc7cc7ffde72b4f87fd2ec3c7c7e7Aneesh Kumar K.V			flags &= ~EXT2_DIRSYNC_FL;
2497c8da6e3768bc7cc7ffde72b4f87fd2ec3c7c7e7Aneesh Kumar K.V		if (fsetflags(name, flags) == -1) {
2507c8da6e3768bc7cc7ffde72b4f87fd2ec3c7c7e7Aneesh Kumar K.V			if (!silent) {
2517c8da6e3768bc7cc7ffde72b4f87fd2ec3c7c7e7Aneesh Kumar K.V				com_err(program_name, errno,
252e68594d2376afd10e03b440b4bc288508ad13aa2Theodore Ts'o						_("while setting flags on %s"),
253e68594d2376afd10e03b440b4bc288508ad13aa2Theodore Ts'o						name);
254e68594d2376afd10e03b440b4bc288508ad13aa2Theodore Ts'o			}
2557c8da6e3768bc7cc7ffde72b4f87fd2ec3c7c7e7Aneesh Kumar K.V			return -1;
2563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		}
2573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
258e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o	if (set_version) {
2593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		if (verbose)
260d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o			printf (_("Version of %s set as %lu\n"), name, version);
261e68594d2376afd10e03b440b4bc288508ad13aa2Theodore Ts'o		if (fsetversion (name, version) == -1) {
262e68594d2376afd10e03b440b4bc288508ad13aa2Theodore Ts'o			if (!silent)
263e68594d2376afd10e03b440b4bc288508ad13aa2Theodore Ts'o				com_err (program_name, errno,
264e68594d2376afd10e03b440b4bc288508ad13aa2Theodore Ts'o					 _("while setting version on %s"),
265e68594d2376afd10e03b440b4bc288508ad13aa2Theodore Ts'o					 name);
266e68594d2376afd10e03b440b4bc288508ad13aa2Theodore Ts'o			return -1;
267e68594d2376afd10e03b440b4bc288508ad13aa2Theodore Ts'o		}
2683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
2693627e83830995a8d3c00b391241909f7b6b44a76Li Xi	if (set_project) {
2703627e83830995a8d3c00b391241909f7b6b44a76Li Xi		if (verbose)
27125040c0431e4f8508f643bc731e4b4034fdd9b82Theodore Ts'o			printf (_("Project of %s set as %lu\n"), name, project);
2723627e83830995a8d3c00b391241909f7b6b44a76Li Xi		if (fsetproject (name, project) == -1) {
2733627e83830995a8d3c00b391241909f7b6b44a76Li Xi			if (!silent)
2743627e83830995a8d3c00b391241909f7b6b44a76Li Xi				com_err (program_name, errno,
2753627e83830995a8d3c00b391241909f7b6b44a76Li Xi					 _("while setting project on %s"),
2763627e83830995a8d3c00b391241909f7b6b44a76Li Xi					 name);
2773627e83830995a8d3c00b391241909f7b6b44a76Li Xi			return -1;
2783627e83830995a8d3c00b391241909f7b6b44a76Li Xi		}
2793627e83830995a8d3c00b391241909f7b6b44a76Li Xi
2803627e83830995a8d3c00b391241909f7b6b44a76Li Xi	}
2813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	if (S_ISDIR(st.st_mode) && recursive)
282e68594d2376afd10e03b440b4bc288508ad13aa2Theodore Ts'o		return iterate_on_dir (name, chattr_dir_proc, NULL);
283e68594d2376afd10e03b440b4bc288508ad13aa2Theodore Ts'o	return 0;
2843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
2853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
286e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'ostatic int chattr_dir_proc (const char * dir_name, struct dirent * de,
287544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o			    void * private EXT2FS_ATTR((unused)))
2883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
289e68594d2376afd10e03b440b4bc288508ad13aa2Theodore Ts'o	int ret = 0;
290e68594d2376afd10e03b440b4bc288508ad13aa2Theodore Ts'o
291e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o	if (strcmp (de->d_name, ".") && strcmp (de->d_name, "..")) {
292a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o	        char *path;
293a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o
294a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o		path = malloc(strlen (dir_name) + 1 + strlen (de->d_name) + 1);
295642935c082ca22e1186fc9926fe06e4207d5ab56Theodore Ts'o		if (!path) {
29645ff69ffeb700012a7c052f5e45882557a40be7eAndreas Dilger			fprintf(stderr, "%s",
29745ff69ffeb700012a7c052f5e45882557a40be7eAndreas Dilger				_("Couldn't allocate path variable "
29845ff69ffeb700012a7c052f5e45882557a40be7eAndreas Dilger				  "in chattr_dir_proc"));
299e68594d2376afd10e03b440b4bc288508ad13aa2Theodore Ts'o			return -1;
300642935c082ca22e1186fc9926fe06e4207d5ab56Theodore Ts'o		}
301e68594d2376afd10e03b440b4bc288508ad13aa2Theodore Ts'o		sprintf(path, "%s/%s", dir_name, de->d_name);
3022d328bb76d2d63bdfdba923b54c28bd686bd8fecTheodore Ts'o		ret = change_attributes(path);
303a418d3ad819323f871005d253f7f9ac378e78ba5Theodore Ts'o		free(path);
3043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
305e68594d2376afd10e03b440b4bc288508ad13aa2Theodore Ts'o	return ret;
3063839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
3073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
30800e5433eb5e9f70f485968b809fdcf297d7fe7b9Theodore Ts'oint main (int argc, char ** argv)
3093839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
3103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	int i, j;
3113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	int end_arg = 0;
312e68594d2376afd10e03b440b4bc288508ad13aa2Theodore Ts'o	int err, retval = 0;
3133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
314d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o#ifdef ENABLE_NLS
315d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o	setlocale(LC_MESSAGES, "");
31614308a5398984842e808faa3ff2dd6a1c52d90bdTheodore Ts'o	setlocale(LC_CTYPE, "");
317d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o	bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
318d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o	textdomain(NLS_CAT_NAME);
3199d4507c5b61007df968638623aa1b4c47dae6cf9Theodore Ts'o	set_com_err_gettext(gettext);
320d9c56d3ca0bee11e3446ff7e12e3124d28e298a7Theodore Ts'o#endif
3213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	if (argc && *argv)
3223839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		program_name = *argv;
3233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	i = 1;
324e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o	while (i < argc && !end_arg) {
3252293a4d5deb30b02d90c4d0aee516e8280092a58Theodore Ts'o		/* '--' arg should end option processing */
3262293a4d5deb30b02d90c4d0aee516e8280092a58Theodore Ts'o		if (strcmp(argv[i], "--") == 0) {
3272293a4d5deb30b02d90c4d0aee516e8280092a58Theodore Ts'o			i++;
3282293a4d5deb30b02d90c4d0aee516e8280092a58Theodore Ts'o			end_arg = 1;
3292293a4d5deb30b02d90c4d0aee516e8280092a58Theodore Ts'o		} else if (decode_arg (&i, argc, argv) == EOF)
3303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			end_arg = 1;
3313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		else
3323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			i++;
3333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
3343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	if (i >= argc)
3353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		usage ();
336e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o	if (set && (add || rem)) {
337544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o		fputs(_("= is incompatible with - and +\n"), stderr);
3383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		exit (1);
3393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
340e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o	if ((rf & af) != 0) {
341544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o		fputs("Can't both set and unset same flag.\n", stderr);
342e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o		exit (1);
343e1a0a3e304229a625c37f0e845c0c9fff117c8c1Theodore Ts'o	}
3443627e83830995a8d3c00b391241909f7b6b44a76Li Xi	if (!(add || rem || set || set_version || set_project )) {
345544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o		fputs(_("Must use '-v', =, - or +\n"), stderr);
3463839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		exit (1);
3473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
348a88fa0c0135307288562d4922438ae52fdbad855Theodore Ts'o	if (verbose)
3490f8973fb092a40fd0a11b7ec95c09128c9fb8f0cTheodore Ts'o		fprintf (stderr, "chattr %s (%s)\n",
3500f8973fb092a40fd0a11b7ec95c09128c9fb8f0cTheodore Ts'o			 E2FSPROGS_VERSION, E2FSPROGS_DATE);
351e68594d2376afd10e03b440b4bc288508ad13aa2Theodore Ts'o	for (j = i; j < argc; j++) {
3522d328bb76d2d63bdfdba923b54c28bd686bd8fecTheodore Ts'o		err = change_attributes (argv[j]);
353e68594d2376afd10e03b440b4bc288508ad13aa2Theodore Ts'o		if (err)
354e68594d2376afd10e03b440b4bc288508ad13aa2Theodore Ts'o			retval = 1;
355e68594d2376afd10e03b440b4bc288508ad13aa2Theodore Ts'o	}
356e68594d2376afd10e03b440b4bc288508ad13aa2Theodore Ts'o	exit(retval);
3573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
358