blob: 0fa3e101dbbcac526677e501fe0fd7c18329707f [file] [log] [blame]
Alistair Delvabeaee832021-02-24 11:27:23 -08001/* 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
27typedef struct Arg_t {
Alistair Delvabeaee832021-02-24 11:27:23 -080028 int recursive;
29 int doPrintName;
Yi Kong39bbd962022-01-09 19:41:38 +080030 unsigned char add;
31 unsigned char remove;
Alistair Delvabeaee832021-02-24 11:27:23 -080032} Arg_t;
33
34static 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
46static 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
78static 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
105static 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))
Yi Kong39bbd962022-01-09 19:41:38 +0800112 putchar('D');
Alistair Delvabeaee832021-02-24 11:27:23 -0800113 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
127static 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
134static void usage(int ret) NORETURN;
135static void usage(int ret)
136{
Yi Kong39bbd962022-01-09 19:41:38 +0800137 fprintf(stderr, "Mtools version %s, dated %s\n",
Alistair Delvabeaee832021-02-24 11:27:23 -0800138 mversion, mdate);
Yi Kong39bbd962022-01-09 19:41:38 +0800139 fprintf(stderr,
Alistair Delvabeaee832021-02-24 11:27:23 -0800140 "Usage: %s [-p] [-a|+a] [-h|+h] [-r|+r] [-s|+s] msdosfile [msdosfiles...]\n",
141 progname);
142 exit(ret);
143}
144
145static 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
161void mattrib(int argc, char **argv, int type UNUSEDP) NORETURN;
162void mattrib(int argc, char **argv, int type UNUSEDP)
163{
164 Arg_t arg;
Yi Kong39bbd962022-01-09 19:41:38 +0800165 struct MainParam_t mp;
Alistair Delvabeaee832021-02-24 11:27:23 -0800166 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
Yi Kong39bbd962022-01-09 19:41:38 +0800233 init_mp(&mp);
Alistair Delvabeaee832021-02-24 11:27:23 -0800234 if(view){
235 if(concise) {
Yi Kong39bbd962022-01-09 19:41:38 +0800236 mp.callback = concise_view_attrib;
Alistair Delvabeaee832021-02-24 11:27:23 -0800237 arg.doPrintName = (argc - optind > 1 ||
238 arg.recursive ||
239 strpbrk(argv[optind], "*[?") != 0);
240 } else if (replay) {
Yi Kong39bbd962022-01-09 19:41:38 +0800241 mp.callback = replay_attrib;
Alistair Delvabeaee832021-02-24 11:27:23 -0800242 } else
Yi Kong39bbd962022-01-09 19:41:38 +0800243 mp.callback = view_attrib;
244 mp.openflags = O_RDONLY;
Alistair Delvabeaee832021-02-24 11:27:23 -0800245 } else {
Yi Kong39bbd962022-01-09 19:41:38 +0800246 mp.callback = attrib_file;
247 mp.openflags = O_RDWR;
Alistair Delvabeaee832021-02-24 11:27:23 -0800248 }
249
250 if(arg.recursive)
Yi Kong39bbd962022-01-09 19:41:38 +0800251 mp.dirCallback = recursive_attrib;
Alistair Delvabeaee832021-02-24 11:27:23 -0800252
Yi Kong39bbd962022-01-09 19:41:38 +0800253 mp.arg = (void *) &arg;
254 mp.lookupflags = ACCEPT_PLAIN | ACCEPT_DIR;
Alistair Delvabeaee832021-02-24 11:27:23 -0800255 if(arg.recursive)
Yi Kong39bbd962022-01-09 19:41:38 +0800256 mp.lookupflags |= DO_OPEN_DIRS | NO_DOTS;
257 exit(main_loop(&mp, argv + optind, argc - optind));
Alistair Delvabeaee832021-02-24 11:27:23 -0800258}