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 27typedef 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 35static 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 47static int replay_attrib(direntry_t *entry, MainParam_t *mp) 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 79static int view_attrib(direntry_t *entry, MainParam_t *mp) 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 106static 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 128static 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 135static void usage(int ret) NORETURN; 136static 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 146static 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 163void mattrib(int argc, char **argv, int type) 164{ 165 Arg_t arg; 166 int view; 167 int c; 168 int concise; 169 int replay; 170 char *ptr; 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 180 if(helpFlag(argc, argv)) 181 usage(0); 182 while ((c = getopt(argc, argv, "i:/ahrsAHRSXph")) != EOF) { 183 switch (c) { 184 default: 185 arg.remove &= ~letterToCode(c); 186 break; 187 case 'i': 188 set_cmd_line_image(optarg, 0); 189 break; 190 case 'p': 191 replay = 1; 192 break; 193 case '/': 194 arg.recursive = 1; 195 break; 196 case 'X': 197 concise = 1; 198 break; 199 case 'h': 200 usage(0); 201 case '?': 202 usage(1); 203 } 204 } 205 206 for(;optind < argc;optind++) { 207 switch(argv[optind][0]) { 208 case '+': 209 for(ptr = argv[optind] + 1; *ptr; ptr++) 210 arg.add |= letterToCode(*ptr); 211 continue; 212 case '-': 213 for(ptr = argv[optind] + 1; *ptr; ptr++) 214 arg.remove &= ~letterToCode(*ptr); 215 continue; 216 } 217 break; 218 } 219 220 if(arg.remove == 0xff && !arg.add) 221 view = 1; 222 223 if (optind >= argc) 224 usage(1); 225 226 init_mp(&arg.mp); 227 if(view){ 228 if(concise) { 229 arg.mp.callback = concise_view_attrib; 230 arg.doPrintName = (argc - optind > 1 || 231 arg.recursive || 232 strpbrk(argv[optind], "*[?") != 0); 233 } else if (replay) { 234 arg.mp.callback = replay_attrib; 235 } else 236 arg.mp.callback = view_attrib; 237 arg.mp.openflags = O_RDONLY; 238 } else { 239 arg.mp.callback = attrib_file; 240 arg.mp.openflags = O_RDWR; 241 } 242 243 if(arg.recursive) 244 arg.mp.dirCallback = recursive_attrib; 245 246 arg.mp.arg = (void *) &arg; 247 arg.mp.lookupflags = ACCEPT_PLAIN | ACCEPT_DIR; 248 if(arg.recursive) 249 arg.mp.lookupflags |= DO_OPEN_DIRS | NO_DOTS; 250 exit(main_loop(&arg.mp, argv + optind, argc - optind)); 251} 252