xref: /aosp_15_r20/external/mtools/mdel.c (revision d5c9a868b113e0ec0db2f27bc2ce8a253e77c4b0)
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 
32 typedef struct Arg_t {
33 	int deltype;
34 	int verbose;
35 } Arg_t;
36 
37 /**
38  * Wiped the given entry
39  */
wipeEntry(direntry_t * entry)40 void 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 
del_entry(direntry_t * entry,MainParam_t * mp)58 static 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 
del_file(direntry_t * entry,MainParam_t * mp)90 static 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, sizeof(shortname),
112 				     NULL, 0)) == 0 ){
113 			if(shortname[0] != DELMARK &&
114 			   shortname[0] &&
115 			   shortname[0] != '.' ){
116 				if(arg->deltype != 2){
117 					fprintf(stderr,
118 						"Directory ");
119 					fprintPwd(stderr, entry,0);
120 					fprintf(stderr," non empty\n");
121 					ret = ERROR_ONE;
122 					break;
123 				}
124 				if(got_signal) {
125 					ret = ERROR_ONE;
126 					break;
127 				}
128 				ret = del_file(&subEntry, &sonmp);
129 				if( ret & ERROR_ONE)
130 					break;
131 				ret = 0;
132 			}
133 		}
134 		FREE(&SubDir);
135 		if (r == -2)
136 			return ERROR_ONE;
137 		if(ret)
138 			return ret;
139 	}
140 	return del_entry(entry, mp);
141 }
142 
143 static void usage(int ret) NORETURN;
usage(int ret)144 static void usage(int ret)
145 {
146 	fprintf(stderr,
147 		"Mtools version %s, dated %s\n", mversion, mdate);
148 	fprintf(stderr,
149 		"Usage: %s [-v] msdosfile [msdosfiles...]\n", progname);
150 	exit(ret);
151 }
152 
153 void mdel(int argc, char **argv, int deltype) NORETURN;
mdel(int argc,char ** argv,int deltype)154 void mdel(int argc, char **argv, int deltype)
155 {
156 	Arg_t arg;
157 	MainParam_t mp;
158 	int c,i;
159 
160 	arg.verbose = 0;
161 	if(helpFlag(argc, argv))
162 		usage(0);
163 	while ((c = getopt(argc, argv, "i:vh")) != EOF) {
164 		switch (c) {
165 			case 'i':
166 				set_cmd_line_image(optarg);
167 				break;
168 			case 'v':
169 				arg.verbose = 1;
170 				break;
171 			case 'h':
172 				usage(0);
173 			default:
174 				usage(1);
175 		}
176 	}
177 
178 	if(argc == optind)
179 		usage(1);
180 
181 	init_mp(&mp);
182 	mp.callback = del_file;
183 	mp.arg = (void *) &arg;
184 	mp.openflags = O_RDWR;
185 	arg.deltype = deltype;
186 	switch(deltype){
187 	case 0:
188 		mp.lookupflags = ACCEPT_PLAIN; /* mdel */
189 		break;
190 	case 1:
191 		mp.lookupflags = ACCEPT_DIR; /* mrd */
192 		break;
193 	case 2:
194 		mp.lookupflags = ACCEPT_DIR | ACCEPT_PLAIN; /* mdeltree */
195 		break;
196 	}
197 	mp.lookupflags |= NO_DOTS;
198 	for(i=optind;i<argc;i++) {
199 		size_t b, l;
200 		if(argv[i][0] && argv[i][1] == ':')
201 			b = 2;
202 		else
203 			b = 0;
204 		l = strlen(argv[i]+b);
205 		if(l > 1 && argv[i][b+l-1] == '/')
206 			argv[i][b+l-1] = '\0';
207 	}
208 
209 	exit(main_loop(&mp, argv + optind, argc - optind));
210 }
211