1/* Copyright 1986-1992 Emmet P. Gray. 2 * Copyright 1996-2002,2005,2008,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 * mdel.c 19 * Delete an MSDOS file 20 * 21 */ 22 23#include "sysincludes.h" 24#include "msdos.h" 25#include "mtools.h" 26#include "stream.h" 27#include "mainloop.h" 28#include "fs.h" 29#include "file.h" 30#include "file_name.h" 31 32typedef struct Arg_t { 33 int deltype; 34 int verbose; 35} Arg_t; 36 37/** 38 * Wiped the given entry 39 */ 40void wipeEntry(direntry_t *entry) 41{ 42 direntry_t longNameEntry; 43 int i; 44 initializeDirentry(&longNameEntry, entry->Dir); 45 for(i=entry->beginSlot; i< entry->endSlot; i++) { 46 int error; 47 longNameEntry.entry=i; 48 dir_read(&longNameEntry, &error); 49 if(error) 50 break; 51 longNameEntry.dir.name[0] = (char) DELMARK; 52 dir_write(&longNameEntry); 53 } 54 entry->dir.name[0] = (char) DELMARK; 55 dir_write(entry); 56} 57 58static int del_entry(direntry_t *entry, MainParam_t *mp) 59{ 60 Arg_t *arg=(Arg_t *) mp->arg; 61 62 if(got_signal) 63 return ERROR_ONE; 64 65 if(entry->entry == -3) { 66 fprintf(stderr, "Cannot remove root directory\n"); 67 return ERROR_ONE; 68 } 69 70 if (arg->verbose) { 71 fprintf(stderr,"Removing "); 72 fprintPwd(stderr, entry,0); 73 fputc('\n', stderr); 74 } 75 76 if (entry->dir.attr & (ATTR_READONLY | ATTR_SYSTEM)) { 77 char tmp[4*MAX_VNAMELEN+1]; 78 wchar_to_native(entry->name,tmp,MAX_VNAMELEN); 79 if (ask_confirmation("%s: \"%s\" is read only, erase anyway (y/n) ? ", 80 progname, tmp)) 81 return ERROR_ONE; 82 } 83 if (fatFreeWithDirentry(entry)) 84 return ERROR_ONE; 85 86 wipeEntry(entry); 87 return GOT_ONE; 88} 89 90static int del_file(direntry_t *entry, MainParam_t *mp) 91{ 92 char shortname[13]; 93 direntry_t subEntry; 94 Stream_t *SubDir; 95 Arg_t *arg = (Arg_t *) mp->arg; 96 MainParam_t sonmp; 97 int ret; 98 int r; 99 100 sonmp = *mp; 101 sonmp.arg = mp->arg; 102 103 r = 0; 104 if (IS_DIR(entry)){ 105 /* a directory */ 106 SubDir = OpenFileByDirentry(entry); 107 initializeDirentry(&subEntry, SubDir); 108 ret = 0; 109 while((r=vfat_lookup(&subEntry, "*", 1, 110 ACCEPT_DIR | ACCEPT_PLAIN, 111 shortname, NULL)) == 0 ){ 112 if(shortname[0] != DELMARK && 113 shortname[0] && 114 shortname[0] != '.' ){ 115 if(arg->deltype != 2){ 116 fprintf(stderr, 117 "Directory "); 118 fprintPwd(stderr, entry,0); 119 fprintf(stderr," non empty\n"); 120 ret = ERROR_ONE; 121 break; 122 } 123 if(got_signal) { 124 ret = ERROR_ONE; 125 break; 126 } 127 ret = del_file(&subEntry, &sonmp); 128 if( ret & ERROR_ONE) 129 break; 130 ret = 0; 131 } 132 } 133 FREE(&SubDir); 134 if (r == -2) 135 return ERROR_ONE; 136 if(ret) 137 return ret; 138 } 139 return del_entry(entry, mp); 140} 141 142static void usage(int ret) NORETURN; 143static void usage(int ret) 144{ 145 fprintf(stderr, 146 "Mtools version %s, dated %s\n", mversion, mdate); 147 fprintf(stderr, 148 "Usage: %s [-v] msdosfile [msdosfiles...]\n", progname); 149 exit(ret); 150} 151 152void mdel(int argc, char **argv, int deltype) 153{ 154 Arg_t arg; 155 MainParam_t mp; 156 int c,i; 157 158 arg.verbose = 0; 159 if(helpFlag(argc, argv)) 160 usage(0); 161 while ((c = getopt(argc, argv, "i:vh")) != EOF) { 162 switch (c) { 163 case 'i': 164 set_cmd_line_image(optarg, 0); 165 break; 166 case 'v': 167 arg.verbose = 1; 168 break; 169 case 'h': 170 usage(0); 171 default: 172 usage(1); 173 } 174 } 175 176 if(argc == optind) 177 usage(1); 178 179 init_mp(&mp); 180 mp.callback = del_file; 181 mp.arg = (void *) &arg; 182 mp.openflags = O_RDWR; 183 arg.deltype = deltype; 184 switch(deltype){ 185 case 0: 186 mp.lookupflags = ACCEPT_PLAIN; /* mdel */ 187 break; 188 case 1: 189 mp.lookupflags = ACCEPT_DIR; /* mrd */ 190 break; 191 case 2: 192 mp.lookupflags = ACCEPT_DIR | ACCEPT_PLAIN; /* mdeltree */ 193 break; 194 } 195 mp.lookupflags |= NO_DOTS; 196 for(i=optind;i<argc;i++) { 197 int b,l; 198 if(argv[i][0] && argv[i][1] == ':') 199 b = 2; 200 else 201 b = 0; 202 l = strlen(argv[i]+b); 203 if(l > 1 && argv[i][b+l-1] == '/') 204 argv[i][b+l-1] = '\0'; 205 } 206 207 exit(main_loop(&mp, argv + optind, argc - optind)); 208} 209