Imported Upstream version 4.0.43
[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 "mtools.h"
24 #include "mainloop.h"
25
26 typedef struct Arg_t {
27         int recursive;
28         int doPrintName;
29         unsigned char add;
30         unsigned char remove;
31 } Arg_t;
32
33 static int attrib_file(direntry_t *entry, MainParam_t *mp)
34 {
35         Arg_t *arg=(Arg_t *) mp->arg;
36
37         if(!isRootEntry(entry)) {
38                 /* if not root directory, change it */
39                 entry->dir.attr = (entry->dir.attr & arg->remove) | arg->add;
40                 dir_write(entry);
41         }
42         return GOT_ONE;
43 }
44
45 static int replay_attrib(direntry_t *entry, MainParam_t *mp UNUSEDP)
46 {
47         if ( (IS_ARCHIVE(entry) && IS_DIR(entry)) ||
48                  (!IS_ARCHIVE(entry) && !IS_DIR(entry)) ||
49                  IS_SYSTEM(entry) || IS_HIDDEN(entry)) {
50
51                 printf("mattrib ");
52
53                 if (IS_ARCHIVE(entry) && IS_DIR(entry)) {
54                         printf("+a ");
55                 }
56
57                 if (!IS_ARCHIVE(entry) && !IS_DIR(entry)) {
58                         printf("-a ");
59                 }
60
61                 if (IS_SYSTEM(entry)) {
62                         printf("+s ");
63                 }
64
65                 if (IS_HIDDEN(entry)) {
66                         printf("+h ");
67                 }
68
69                 fprintPwd(stdout, entry, 1);
70                 printf("\n");
71         }
72         return GOT_ONE;
73 }
74
75
76
77 static int view_attrib(direntry_t *entry, MainParam_t *mp UNUSEDP)
78 {
79         printf("  ");
80         if(IS_ARCHIVE(entry))
81                 putchar('A');
82         else
83                 putchar(' ');
84         fputs("  ",stdout);
85         if(IS_SYSTEM(entry))
86                 putchar('S');
87         else
88                 putchar(' ');
89         if(IS_HIDDEN(entry))
90                 putchar('H');
91         else
92                 putchar(' ');
93         if(IS_READONLY(entry))
94                 putchar('R');
95         else
96                 putchar(' ');
97         printf("     ");
98         fprintPwd(stdout, entry, 0);
99         printf("\n");
100         return GOT_ONE;
101 }
102
103
104 static int concise_view_attrib(direntry_t *entry, MainParam_t *mp)
105 {
106         Arg_t *arg=(Arg_t *) mp->arg;
107
108         if(IS_ARCHIVE(entry))
109                 putchar('A');
110         if(IS_DIR(entry))
111                 putchar('D');
112         if(IS_SYSTEM(entry))
113                 putchar('S');
114         if(IS_HIDDEN(entry))
115                 putchar('H');
116         if(IS_READONLY(entry))
117                 putchar('R');
118         if(arg->doPrintName) {
119                 putchar(' ');
120                 fprintPwd(stdout, entry, 0);
121         }
122         putchar('\n');
123         return GOT_ONE;
124 }
125
126 static int recursive_attrib(direntry_t *entry, MainParam_t *mp)
127 {
128         mp->callback(entry, mp);
129         return mp->loop(mp->File, mp, "*");
130 }
131
132
133 static void usage(int ret) NORETURN;
134 static void usage(int ret)
135 {
136         fprintf(stderr, "Mtools version %s, dated %s\n",
137                 mversion, mdate);
138         fprintf(stderr,
139                 "Usage: %s [-p] [-a|+a] [-h|+h] [-r|+r] [-s|+s] msdosfile [msdosfiles...]\n",
140                 progname);
141         exit(ret);
142 }
143
144 static int letterToCode(int letter)
145 {
146         switch (toupper(letter)) {
147                 case 'A':
148                         return ATTR_ARCHIVE;
149                 case 'H':
150                         return ATTR_HIDDEN;
151                 case 'R':
152                         return ATTR_READONLY;
153                 case 'S':
154                         return ATTR_SYSTEM;
155                 default:
156                         usage(1);
157         }
158 }
159
160 void mattrib(int argc, char **argv, int type UNUSEDP) NORETURN;
161 void mattrib(int argc, char **argv, int type UNUSEDP)
162 {
163         Arg_t arg;
164         struct MainParam_t mp;
165         int view;
166         int c;
167         int concise;
168         int replay;
169         char *ptr;
170         int wantUsage;
171
172         arg.add = 0;
173         arg.remove = 0xff;
174         arg.recursive = 0;
175         arg.doPrintName = 1;
176         view = 0;
177         concise = 0;
178         replay = 0;
179         wantUsage = 0;
180
181         if(helpFlag(argc, argv))
182                 usage(0);
183         while ((c = getopt(argc, argv, "i:/ahrsAHRSXp")) != EOF) {
184                 switch (c) {
185                         case 'h':
186                                 wantUsage = 1;
187                                 /* FALL THROUGH */
188                         default:
189                                 arg.remove &= ~letterToCode(c);
190                                 break;
191                         case 'i':
192                                 set_cmd_line_image(optarg);
193                                 break;
194                         case 'p':
195                                 replay = 1;
196                                 break;
197                         case '/':
198                                 arg.recursive = 1;
199                                 break;
200                         case 'X':
201                                 concise = 1;
202                                 break;
203                         case '?':
204                                 usage(1);
205                 }
206         }
207
208         if(optind == argc && wantUsage) {
209                 usage(0);
210         }
211
212         for(;optind < argc;optind++) {
213                 switch(argv[optind][0]) {
214                         case '+':
215                                 for(ptr = argv[optind] + 1; *ptr; ptr++)
216                                         arg.add |= letterToCode(*ptr);
217                                 continue;
218                         case '-':
219                                 for(ptr = argv[optind] + 1; *ptr; ptr++)
220                                         arg.remove &= ~letterToCode(*ptr);
221                                 continue;
222                 }
223                 break;
224         }
225
226         if(arg.remove == 0xff && !arg.add)
227                 view = 1;
228
229         if (optind >= argc)
230                 usage(1);
231
232         init_mp(&mp);
233         if(view){
234                 if(concise) {
235                         mp.callback = concise_view_attrib;
236                         arg.doPrintName = (argc - optind > 1 ||
237                                            arg.recursive ||
238                                            strpbrk(argv[optind], "*[?") != 0);
239                 } else if (replay) {
240                         mp.callback = replay_attrib;
241                 } else
242                         mp.callback = view_attrib;
243                 mp.openflags = O_RDONLY;
244         } else {
245                 mp.callback = attrib_file;
246                 mp.openflags = O_RDWR;
247         }
248
249         if(arg.recursive)
250                 mp.dirCallback = recursive_attrib;
251
252         mp.arg = (void *) &arg;
253         mp.lookupflags = ACCEPT_PLAIN | ACCEPT_DIR;
254         if(arg.recursive)
255                 mp.lookupflags |= DO_OPEN_DIRS | NO_DOTS;
256         exit(main_loop(&mp, argv + optind, argc - optind));
257 }