Imported Upstream version 4.0.18
[platform/upstream/mtools.git] / mattrib.c
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         char add;
29         unsigned char remove;
30         struct MainParam_t mp;
31         int recursive;
32         int doPrintName;
33 } Arg_t;
34
35 static int attrib_file(direntry_t *entry, MainParam_t *mp)
36 {
37         Arg_t *arg=(Arg_t *) mp->arg;
38
39         if(entry->entry != -3) {
40                 /* if not root directory, change it */
41                 entry->dir.attr = (entry->dir.attr & arg->remove) | arg->add;
42                 dir_write(entry);
43         }
44         return GOT_ONE;
45 }
46
47 static int replay_attrib(direntry_t *entry, MainParam_t *mp UNUSEDP)
48 {
49         if ( (IS_ARCHIVE(entry) && IS_DIR(entry)) ||
50                  (!IS_ARCHIVE(entry) && !IS_DIR(entry)) ||
51                  IS_SYSTEM(entry) || IS_HIDDEN(entry)) {
52
53                 printf("mattrib ");
54
55                 if (IS_ARCHIVE(entry) && IS_DIR(entry)) {
56                         printf("+a ");
57                 }
58
59                 if (!IS_ARCHIVE(entry) && !IS_DIR(entry)) {
60                         printf("-a ");
61                 }
62
63                 if (IS_SYSTEM(entry)) {
64                         printf("+s ");
65                 }
66
67                 if (IS_HIDDEN(entry)) {
68                         printf("+h ");
69                 }
70
71                 fprintPwd(stdout, entry, 1);
72                 printf("\n");
73         }
74         return GOT_ONE;
75 }
76
77
78
79 static int view_attrib(direntry_t *entry, MainParam_t *mp UNUSEDP)
80 {
81         printf("  ");
82         if(IS_ARCHIVE(entry))
83                 putchar('A');
84         else
85                 putchar(' ');
86         fputs("  ",stdout);
87         if(IS_SYSTEM(entry))
88                 putchar('S');
89         else
90                 putchar(' ');
91         if(IS_HIDDEN(entry))
92                 putchar('H');
93         else
94                 putchar(' ');
95         if(IS_READONLY(entry))
96                 putchar('R');
97         else
98                 putchar(' ');
99         printf("     ");
100         fprintPwd(stdout, entry, 0);
101         printf("\n");
102         return GOT_ONE;
103 }
104
105
106 static int concise_view_attrib(direntry_t *entry, MainParam_t *mp)
107 {
108         Arg_t *arg=(Arg_t *) mp->arg;
109
110         if(IS_ARCHIVE(entry))
111                 putchar('A');
112         if(IS_DIR(entry))
113                 putchar('D');   
114         if(IS_SYSTEM(entry))
115                 putchar('S');
116         if(IS_HIDDEN(entry))
117                 putchar('H');
118         if(IS_READONLY(entry))
119                 putchar('R');
120         if(arg->doPrintName) {
121                 putchar(' ');
122                 fprintPwd(stdout, entry, 0);
123         }
124         putchar('\n');
125         return GOT_ONE;
126 }
127
128 static int recursive_attrib(direntry_t *entry, MainParam_t *mp)
129 {
130         mp->callback(entry, mp);
131         return mp->loop(mp->File, mp, "*");
132 }
133
134
135 static void usage(int ret) NORETURN;
136 static void usage(int ret)
137 {
138         fprintf(stderr, "Mtools version %s, dated %s\n", 
139                 mversion, mdate);
140         fprintf(stderr, 
141                 "Usage: %s [-p] [-a|+a] [-h|+h] [-r|+r] [-s|+s] msdosfile [msdosfiles...]\n",
142                 progname);
143         exit(ret);
144 }
145
146 static int letterToCode(int letter)
147 {
148         switch (toupper(letter)) {
149                 case 'A':
150                         return ATTR_ARCHIVE;
151                 case 'H':
152                         return ATTR_HIDDEN;
153                 case 'R':
154                         return ATTR_READONLY;
155                 case 'S':
156                         return ATTR_SYSTEM;
157                 default:
158                         usage(1);
159         }
160 }
161
162
163 void mattrib(int argc, char **argv, int type UNUSEDP)
164 {
165         Arg_t arg;
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(&arg.mp);
234         if(view){
235                 if(concise) {
236                         arg.mp.callback = concise_view_attrib;
237                         arg.doPrintName = (argc - optind > 1 ||
238                                            arg.recursive ||
239                                            strpbrk(argv[optind], "*[?") != 0);
240                 } else if (replay) {
241                         arg.mp.callback = replay_attrib;
242                 } else
243                         arg.mp.callback = view_attrib;
244                 arg.mp.openflags = O_RDONLY;
245         } else {
246                 arg.mp.callback = attrib_file;
247                 arg.mp.openflags = O_RDWR;
248         }
249
250         if(arg.recursive)
251                 arg.mp.dirCallback = recursive_attrib;
252
253         arg.mp.arg = (void *) &arg;
254         arg.mp.lookupflags = ACCEPT_PLAIN | ACCEPT_DIR;
255         if(arg.recursive)
256                 arg.mp.lookupflags |= DO_OPEN_DIRS | NO_DOTS;
257         exit(main_loop(&arg.mp, argv + optind, argc - optind));
258 }