xref: /aosp_15_r20/external/mtools/mattrib.c (revision d5c9a868b113e0ec0db2f27bc2ce8a253e77c4b0)
1 /*  Copyright 1986-1992 Emmet P. Gray.
2  *  Copyright 1996-1998,2000-2002,2007,2009 Alain Knaff.
3  *  This file is part of mtools.
4  *
5  *  Mtools is free software: you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation, either version 3 of the License, or
8  *  (at your option) any later version.
9  *
10  *  Mtools is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with Mtools.  If not, see <http://www.gnu.org/licenses/>.
17  *
18  * mattrib.c
19  * Change MSDOS file attribute flags
20  */
21 
22 #include "sysincludes.h"
23 #include "msdos.h"
24 #include "mtools.h"
25 #include "mainloop.h"
26 
27 typedef struct Arg_t {
28 	int recursive;
29 	int doPrintName;
30 	unsigned char add;
31 	unsigned char remove;
32 } Arg_t;
33 
attrib_file(direntry_t * entry,MainParam_t * mp)34 static int attrib_file(direntry_t *entry, MainParam_t *mp)
35 {
36 	Arg_t *arg=(Arg_t *) mp->arg;
37 
38 	if(entry->entry != -3) {
39 		/* if not root directory, change it */
40 		entry->dir.attr = (entry->dir.attr & arg->remove) | arg->add;
41 		dir_write(entry);
42 	}
43 	return GOT_ONE;
44 }
45 
replay_attrib(direntry_t * entry,MainParam_t * mp UNUSEDP)46 static int replay_attrib(direntry_t *entry, MainParam_t *mp UNUSEDP)
47 {
48 	if ( (IS_ARCHIVE(entry) && IS_DIR(entry)) ||
49 		 (!IS_ARCHIVE(entry) && !IS_DIR(entry)) ||
50 		 IS_SYSTEM(entry) || IS_HIDDEN(entry)) {
51 
52 		printf("mattrib ");
53 
54 		if (IS_ARCHIVE(entry) && IS_DIR(entry)) {
55 			printf("+a ");
56 		}
57 
58 		if (!IS_ARCHIVE(entry) && !IS_DIR(entry)) {
59 			printf("-a ");
60 		}
61 
62 		if (IS_SYSTEM(entry)) {
63 			printf("+s ");
64 		}
65 
66 		if (IS_HIDDEN(entry)) {
67 			printf("+h ");
68 		}
69 
70 		fprintPwd(stdout, entry, 1);
71 		printf("\n");
72 	}
73 	return GOT_ONE;
74 }
75 
76 
77 
view_attrib(direntry_t * entry,MainParam_t * mp UNUSEDP)78 static int view_attrib(direntry_t *entry, MainParam_t *mp UNUSEDP)
79 {
80 	printf("  ");
81 	if(IS_ARCHIVE(entry))
82 		putchar('A');
83 	else
84 		putchar(' ');
85 	fputs("  ",stdout);
86 	if(IS_SYSTEM(entry))
87 		putchar('S');
88 	else
89 		putchar(' ');
90 	if(IS_HIDDEN(entry))
91 		putchar('H');
92 	else
93 		putchar(' ');
94 	if(IS_READONLY(entry))
95 		putchar('R');
96 	else
97 		putchar(' ');
98 	printf("     ");
99 	fprintPwd(stdout, entry, 0);
100 	printf("\n");
101 	return GOT_ONE;
102 }
103 
104 
concise_view_attrib(direntry_t * entry,MainParam_t * mp)105 static int concise_view_attrib(direntry_t *entry, MainParam_t *mp)
106 {
107 	Arg_t *arg=(Arg_t *) mp->arg;
108 
109 	if(IS_ARCHIVE(entry))
110 		putchar('A');
111 	if(IS_DIR(entry))
112 		putchar('D');
113 	if(IS_SYSTEM(entry))
114 		putchar('S');
115 	if(IS_HIDDEN(entry))
116 		putchar('H');
117 	if(IS_READONLY(entry))
118 		putchar('R');
119 	if(arg->doPrintName) {
120 		putchar(' ');
121 		fprintPwd(stdout, entry, 0);
122 	}
123 	putchar('\n');
124 	return GOT_ONE;
125 }
126 
recursive_attrib(direntry_t * entry,MainParam_t * mp)127 static int recursive_attrib(direntry_t *entry, MainParam_t *mp)
128 {
129 	mp->callback(entry, mp);
130 	return mp->loop(mp->File, mp, "*");
131 }
132 
133 
134 static void usage(int ret) NORETURN;
usage(int ret)135 static void usage(int ret)
136 {
137 	fprintf(stderr, "Mtools version %s, dated %s\n",
138 		mversion, mdate);
139 	fprintf(stderr,
140 		"Usage: %s [-p] [-a|+a] [-h|+h] [-r|+r] [-s|+s] msdosfile [msdosfiles...]\n",
141 		progname);
142 	exit(ret);
143 }
144 
letterToCode(int letter)145 static int letterToCode(int letter)
146 {
147 	switch (toupper(letter)) {
148 		case 'A':
149 			return ATTR_ARCHIVE;
150 		case 'H':
151 			return ATTR_HIDDEN;
152 		case 'R':
153 			return ATTR_READONLY;
154 		case 'S':
155 			return ATTR_SYSTEM;
156 		default:
157 			usage(1);
158 	}
159 }
160 
161 void mattrib(int argc, char **argv, int type UNUSEDP) NORETURN;
mattrib(int argc,char ** argv,int type UNUSEDP)162 void mattrib(int argc, char **argv, int type UNUSEDP)
163 {
164 	Arg_t arg;
165 	struct MainParam_t mp;
166 	int view;
167 	int c;
168 	int concise;
169 	int replay;
170 	char *ptr;
171 	int wantUsage;
172 
173 	arg.add = 0;
174 	arg.remove = 0xff;
175 	arg.recursive = 0;
176 	arg.doPrintName = 1;
177 	view = 0;
178 	concise = 0;
179 	replay = 0;
180 	wantUsage = 0;
181 
182 	if(helpFlag(argc, argv))
183 		usage(0);
184 	while ((c = getopt(argc, argv, "i:/ahrsAHRSXp")) != EOF) {
185 		switch (c) {
186 			case 'h':
187 				wantUsage = 1;
188 				/* FALL THROUGH */
189 			default:
190 				arg.remove &= ~letterToCode(c);
191 				break;
192 			case 'i':
193 				set_cmd_line_image(optarg);
194 				break;
195 			case 'p':
196 				replay = 1;
197 				break;
198 			case '/':
199 				arg.recursive = 1;
200 				break;
201 			case 'X':
202 				concise = 1;
203 				break;
204 			case '?':
205 				usage(1);
206 		}
207 	}
208 
209 	if(optind == argc && wantUsage) {
210 		usage(0);
211 	}
212 
213 	for(;optind < argc;optind++) {
214 		switch(argv[optind][0]) {
215 			case '+':
216 				for(ptr = argv[optind] + 1; *ptr; ptr++)
217 					arg.add |= letterToCode(*ptr);
218 				continue;
219 			case '-':
220 				for(ptr = argv[optind] + 1; *ptr; ptr++)
221 					arg.remove &= ~letterToCode(*ptr);
222 				continue;
223 		}
224 		break;
225 	}
226 
227 	if(arg.remove == 0xff && !arg.add)
228 		view = 1;
229 
230 	if (optind >= argc)
231 		usage(1);
232 
233 	init_mp(&mp);
234 	if(view){
235 		if(concise) {
236 			mp.callback = concise_view_attrib;
237 			arg.doPrintName = (argc - optind > 1 ||
238 					   arg.recursive ||
239 					   strpbrk(argv[optind], "*[?") != 0);
240 		} else if (replay) {
241 			mp.callback = replay_attrib;
242 		} else
243 			mp.callback = view_attrib;
244 		mp.openflags = O_RDONLY;
245 	} else {
246 		mp.callback = attrib_file;
247 		mp.openflags = O_RDWR;
248 	}
249 
250 	if(arg.recursive)
251 		mp.dirCallback = recursive_attrib;
252 
253 	mp.arg = (void *) &arg;
254 	mp.lookupflags = ACCEPT_PLAIN | ACCEPT_DIR;
255 	if(arg.recursive)
256 		mp.lookupflags |= DO_OPEN_DIRS | NO_DOTS;
257 	exit(main_loop(&mp, argv + optind, argc - optind));
258 }
259