xref: /aosp_15_r20/external/mtools/mk_direntry.c (revision d5c9a868b113e0ec0db2f27bc2ce8a253e77c4b0)
1*d5c9a868SElliott Hughes /*  Copyright 1995-1998,2000-2003,2005,2007-2009 Alain Knaff.
2*d5c9a868SElliott Hughes  *  This file is part of mtools.
3*d5c9a868SElliott Hughes  *
4*d5c9a868SElliott Hughes  *  Mtools is free software: you can redistribute it and/or modify
5*d5c9a868SElliott Hughes  *  it under the terms of the GNU General Public License as published by
6*d5c9a868SElliott Hughes  *  the Free Software Foundation, either version 3 of the License, or
7*d5c9a868SElliott Hughes  *  (at your option) any later version.
8*d5c9a868SElliott Hughes  *
9*d5c9a868SElliott Hughes  *  Mtools is distributed in the hope that it will be useful,
10*d5c9a868SElliott Hughes  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11*d5c9a868SElliott Hughes  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12*d5c9a868SElliott Hughes  *  GNU General Public License for more details.
13*d5c9a868SElliott Hughes  *
14*d5c9a868SElliott Hughes  *  You should have received a copy of the GNU General Public License
15*d5c9a868SElliott Hughes  *  along with Mtools.  If not, see <http://www.gnu.org/licenses/>.
16*d5c9a868SElliott Hughes  *
17*d5c9a868SElliott Hughes  * mk_direntry.c
18*d5c9a868SElliott Hughes  * Make new directory entries, and handles name clashes
19*d5c9a868SElliott Hughes  *
20*d5c9a868SElliott Hughes  */
21*d5c9a868SElliott Hughes 
22*d5c9a868SElliott Hughes /*
23*d5c9a868SElliott Hughes  * This file is used by those commands that need to create new directory entries
24*d5c9a868SElliott Hughes  */
25*d5c9a868SElliott Hughes 
26*d5c9a868SElliott Hughes #include "sysincludes.h"
27*d5c9a868SElliott Hughes #include "msdos.h"
28*d5c9a868SElliott Hughes #include "mtools.h"
29*d5c9a868SElliott Hughes #include "vfat.h"
30*d5c9a868SElliott Hughes #include "nameclash.h"
31*d5c9a868SElliott Hughes #include "fs.h"
32*d5c9a868SElliott Hughes #include "stream.h"
33*d5c9a868SElliott Hughes #include "mainloop.h"
34*d5c9a868SElliott Hughes #include "file_name.h"
35*d5c9a868SElliott Hughes 
36*d5c9a868SElliott Hughes /**
37*d5c9a868SElliott Hughes  * Converts input to shortname
38*d5c9a868SElliott Hughes  * @param un unix name (in Unix charset)
39*d5c9a868SElliott Hughes  *
40*d5c9a868SElliott Hughes  * @return 1 if name had to be mangled
41*d5c9a868SElliott Hughes  */
convert_to_shortname(doscp_t * cp,ClashHandling_t * ch,const char * un,dos_name_t * dn)42*d5c9a868SElliott Hughes static __inline__ int convert_to_shortname(doscp_t *cp, ClashHandling_t *ch,
43*d5c9a868SElliott Hughes 					   const char *un, dos_name_t *dn)
44*d5c9a868SElliott Hughes {
45*d5c9a868SElliott Hughes 	int mangled;
46*d5c9a868SElliott Hughes 
47*d5c9a868SElliott Hughes 	/* Then do conversion to dn */
48*d5c9a868SElliott Hughes 	ch->name_converter(cp, un, 0, &mangled, dn);
49*d5c9a868SElliott Hughes 	dn->sentinel = '\0';
50*d5c9a868SElliott Hughes 	if (dn->base[0] == '\xE5')
51*d5c9a868SElliott Hughes 		dn->base[0] = '\x05';
52*d5c9a868SElliott Hughes 	return mangled;
53*d5c9a868SElliott Hughes }
54*d5c9a868SElliott Hughes 
chomp(char * line)55*d5c9a868SElliott Hughes static __inline__ void chomp(char *line)
56*d5c9a868SElliott Hughes {
57*d5c9a868SElliott Hughes 	size_t l = strlen(line);
58*d5c9a868SElliott Hughes 	while(l > 0 && (line[l-1] == '\n' || line[l-1] == '\r')) {
59*d5c9a868SElliott Hughes 		line[--l] = '\0';
60*d5c9a868SElliott Hughes 	}
61*d5c9a868SElliott Hughes }
62*d5c9a868SElliott Hughes 
63*d5c9a868SElliott Hughes /**
64*d5c9a868SElliott Hughes  * Asks for an alternative new name for a file, in case of a clash
65*d5c9a868SElliott Hughes  */
ask_rename(doscp_t * cp,ClashHandling_t * ch,dos_name_t * shortname,char * longname,int isprimary)66*d5c9a868SElliott Hughes static __inline__ int ask_rename(doscp_t *cp, ClashHandling_t *ch,
67*d5c9a868SElliott Hughes 				 dos_name_t *shortname,
68*d5c9a868SElliott Hughes 				 char *longname,
69*d5c9a868SElliott Hughes 				 int isprimary)
70*d5c9a868SElliott Hughes {
71*d5c9a868SElliott Hughes 	int mangled;
72*d5c9a868SElliott Hughes 
73*d5c9a868SElliott Hughes 	/* TODO: Would be nice to suggest "autorenamed" version of name, press
74*d5c9a868SElliott Hughes 	 * <Return> to get it.
75*d5c9a868SElliott Hughes 	 */
76*d5c9a868SElliott Hughes #if 0
77*d5c9a868SElliott Hughes 	fprintf(stderr,"Entering ask_rename, isprimary=%d.\n", isprimary);
78*d5c9a868SElliott Hughes #endif
79*d5c9a868SElliott Hughes 
80*d5c9a868SElliott Hughes 	if(!opentty(0))
81*d5c9a868SElliott Hughes 		return 0;
82*d5c9a868SElliott Hughes 
83*d5c9a868SElliott Hughes 	mangled = 0;
84*d5c9a868SElliott Hughes 	do {
85*d5c9a868SElliott Hughes 		char tname[4*MAX_VNAMELEN+1];
86*d5c9a868SElliott Hughes 		fprintf(stderr, "New %s name for \"%s\": ",
87*d5c9a868SElliott Hughes 			isprimary ? "primary" : "secondary", longname);
88*d5c9a868SElliott Hughes 		fflush(stderr);
89*d5c9a868SElliott Hughes 		if (! fgets(tname, 4*MAX_VNAMELEN+1, opentty(0)))
90*d5c9a868SElliott Hughes 			return 0;
91*d5c9a868SElliott Hughes 		chomp(tname);
92*d5c9a868SElliott Hughes 		if (isprimary)
93*d5c9a868SElliott Hughes 			strcpy(longname, tname);
94*d5c9a868SElliott Hughes 		else
95*d5c9a868SElliott Hughes 			mangled = convert_to_shortname(cp,
96*d5c9a868SElliott Hughes 						       ch, tname, shortname);
97*d5c9a868SElliott Hughes 	} while (mangled & 1);
98*d5c9a868SElliott Hughes 	return 1;
99*d5c9a868SElliott Hughes }
100*d5c9a868SElliott Hughes 
101*d5c9a868SElliott Hughes /**
102*d5c9a868SElliott Hughes  * This function determines the action to be taken in case there is a problem
103*d5c9a868SElliott Hughes  * with target name (clash, illegal characters, or reserved)
104*d5c9a868SElliott Hughes  * The decision either comes from the default (ch), or the user will be
105*d5c9a868SElliott Hughes  * prompted if there is no default
106*d5c9a868SElliott Hughes  */
ask_namematch(doscp_t * cp,dos_name_t * dosname,char * longname,int isprimary,ClashHandling_t * ch,int no_overwrite,int reason)107*d5c9a868SElliott Hughes static __inline__ clash_action ask_namematch(doscp_t *cp,
108*d5c9a868SElliott Hughes 					     dos_name_t *dosname,
109*d5c9a868SElliott Hughes 					     char *longname,
110*d5c9a868SElliott Hughes 					     int isprimary,
111*d5c9a868SElliott Hughes 					     ClashHandling_t *ch,
112*d5c9a868SElliott Hughes 					     int no_overwrite,
113*d5c9a868SElliott Hughes 					     int reason)
114*d5c9a868SElliott Hughes {
115*d5c9a868SElliott Hughes 	/* User's answer letter (from keyboard). Only first letter is used,
116*d5c9a868SElliott Hughes 	 * but we allocate space for 10 in order to account for extra garbage
117*d5c9a868SElliott Hughes 	 * that user may enter
118*d5c9a868SElliott Hughes 	 */
119*d5c9a868SElliott Hughes 	char ans[10];
120*d5c9a868SElliott Hughes 
121*d5c9a868SElliott Hughes 	/**
122*d5c9a868SElliott Hughes 	 * Return value: action to be taken
123*d5c9a868SElliott Hughes 	 */
124*d5c9a868SElliott Hughes 	clash_action a;
125*d5c9a868SElliott Hughes 
126*d5c9a868SElliott Hughes 	/**
127*d5c9a868SElliott Hughes 	 * Should this decision be made permanent (do no longer ask same
128*d5c9a868SElliott Hughes 	 * question)
129*d5c9a868SElliott Hughes 	 */
130*d5c9a868SElliott Hughes 	int perm;
131*d5c9a868SElliott Hughes 
132*d5c9a868SElliott Hughes 	/**
133*d5c9a868SElliott Hughes 	 * Buffer for shortname
134*d5c9a868SElliott Hughes 	 */
135*d5c9a868SElliott Hughes 	char name_buffer[4*13];
136*d5c9a868SElliott Hughes 
137*d5c9a868SElliott Hughes 	/**
138*d5c9a868SElliott Hughes 	 * Name to be printed
139*d5c9a868SElliott Hughes 	 */
140*d5c9a868SElliott Hughes 	char *name;
141*d5c9a868SElliott Hughes 
142*d5c9a868SElliott Hughes #define EXISTS 0
143*d5c9a868SElliott Hughes #define RESERVED 1
144*d5c9a868SElliott Hughes #define ILLEGALS 2
145*d5c9a868SElliott Hughes 
146*d5c9a868SElliott Hughes 	static const char *reasons[]= {
147*d5c9a868SElliott Hughes 		"already exists",
148*d5c9a868SElliott Hughes 		"is reserved",
149*d5c9a868SElliott Hughes 		"contains illegal character(s)"};
150*d5c9a868SElliott Hughes 
151*d5c9a868SElliott Hughes 	a = ch->action[isprimary];
152*d5c9a868SElliott Hughes 
153*d5c9a868SElliott Hughes 	if(a == NAMEMATCH_NONE && !opentty(1)) {
154*d5c9a868SElliott Hughes 		/* no default, and no tty either . Skip the troublesome file */
155*d5c9a868SElliott Hughes 		return NAMEMATCH_SKIP;
156*d5c9a868SElliott Hughes 	}
157*d5c9a868SElliott Hughes 
158*d5c9a868SElliott Hughes 	if (!isprimary)
159*d5c9a868SElliott Hughes 		name = unix_normalize(cp, name_buffer,
160*d5c9a868SElliott Hughes 				      dosname, sizeof(*dosname));
161*d5c9a868SElliott Hughes 	else
162*d5c9a868SElliott Hughes 		name = longname;
163*d5c9a868SElliott Hughes 
164*d5c9a868SElliott Hughes 	perm = 0;
165*d5c9a868SElliott Hughes 	while (a == NAMEMATCH_NONE) {
166*d5c9a868SElliott Hughes 		fprintf(stderr, "%s file name \"%s\" %s.\n",
167*d5c9a868SElliott Hughes 			isprimary ? "Long" : "Short", name, reasons[reason]);
168*d5c9a868SElliott Hughes 		fprintf(stderr,
169*d5c9a868SElliott Hughes 			"a)utorename A)utorename-all r)ename R)ename-all ");
170*d5c9a868SElliott Hughes 		if(!no_overwrite)
171*d5c9a868SElliott Hughes 			fprintf(stderr,"o)verwrite O)verwrite-all");
172*d5c9a868SElliott Hughes 		fprintf(stderr,
173*d5c9a868SElliott Hughes 			"\ns)kip S)kip-all q)uit (aArR");
174*d5c9a868SElliott Hughes 		if(!no_overwrite)
175*d5c9a868SElliott Hughes 			fprintf(stderr,"oO");
176*d5c9a868SElliott Hughes 		fprintf(stderr,"sSq): ");
177*d5c9a868SElliott Hughes 		fflush(stderr);
178*d5c9a868SElliott Hughes 		fflush(opentty(1));
179*d5c9a868SElliott Hughes 		if (mtools_raw_tty) {
180*d5c9a868SElliott Hughes 			int rep;
181*d5c9a868SElliott Hughes 			rep = fgetc(opentty(1));
182*d5c9a868SElliott Hughes 			fputs("\n", stderr);
183*d5c9a868SElliott Hughes 			if(rep == EOF)
184*d5c9a868SElliott Hughes 				ans[0] = 'q';
185*d5c9a868SElliott Hughes 			else
186*d5c9a868SElliott Hughes 				ans[0] = (char) rep;
187*d5c9a868SElliott Hughes 		} else {
188*d5c9a868SElliott Hughes 			if(fgets(ans, 9, opentty(0)) == NULL)
189*d5c9a868SElliott Hughes 				ans[0] = 'q';
190*d5c9a868SElliott Hughes 		}
191*d5c9a868SElliott Hughes 		perm = isupper((unsigned char)ans[0]);
192*d5c9a868SElliott Hughes 		switch(tolower((unsigned char)ans[0])) {
193*d5c9a868SElliott Hughes 			case 'a':
194*d5c9a868SElliott Hughes 				a = NAMEMATCH_AUTORENAME;
195*d5c9a868SElliott Hughes 				break;
196*d5c9a868SElliott Hughes 			case 'r':
197*d5c9a868SElliott Hughes 				if(isprimary)
198*d5c9a868SElliott Hughes 					a = NAMEMATCH_PRENAME;
199*d5c9a868SElliott Hughes 				else
200*d5c9a868SElliott Hughes 					a = NAMEMATCH_RENAME;
201*d5c9a868SElliott Hughes 				break;
202*d5c9a868SElliott Hughes 			case 'o':
203*d5c9a868SElliott Hughes 				if(no_overwrite)
204*d5c9a868SElliott Hughes 					continue;
205*d5c9a868SElliott Hughes 				a = NAMEMATCH_OVERWRITE;
206*d5c9a868SElliott Hughes 				break;
207*d5c9a868SElliott Hughes 			case 's':
208*d5c9a868SElliott Hughes 				a = NAMEMATCH_SKIP;
209*d5c9a868SElliott Hughes 				break;
210*d5c9a868SElliott Hughes 			case 'q':
211*d5c9a868SElliott Hughes 				perm = 0;
212*d5c9a868SElliott Hughes 				a = NAMEMATCH_QUIT;
213*d5c9a868SElliott Hughes 				break;
214*d5c9a868SElliott Hughes 			default:
215*d5c9a868SElliott Hughes 				perm = 0;
216*d5c9a868SElliott Hughes 		}
217*d5c9a868SElliott Hughes 	}
218*d5c9a868SElliott Hughes 
219*d5c9a868SElliott Hughes 	/* Keep track of this action in case this file collides again */
220*d5c9a868SElliott Hughes 	ch->action[isprimary]  = a;
221*d5c9a868SElliott Hughes 	if (perm)
222*d5c9a868SElliott Hughes 		ch->namematch_default[isprimary] = a;
223*d5c9a868SElliott Hughes 
224*d5c9a868SElliott Hughes 	/* if we were asked to overwrite be careful. We can't set the action
225*d5c9a868SElliott Hughes 	 * to overwrite, else we get won't get a chance to specify another
226*d5c9a868SElliott Hughes 	 * action, should overwrite fail. Indeed, we'll be caught in an
227*d5c9a868SElliott Hughes 	 * infinite loop because overwrite will fail the same way for the
228*d5c9a868SElliott Hughes 	 * second time */
229*d5c9a868SElliott Hughes 	if(a == NAMEMATCH_OVERWRITE)
230*d5c9a868SElliott Hughes 		ch->action[isprimary] = NAMEMATCH_NONE;
231*d5c9a868SElliott Hughes 	return a;
232*d5c9a868SElliott Hughes }
233*d5c9a868SElliott Hughes 
234*d5c9a868SElliott Hughes /*
235*d5c9a868SElliott Hughes  * Processes a name match
236*d5c9a868SElliott Hughes  *  dosname short dosname (ignored if is_primary)
237*d5c9a868SElliott Hughes  *
238*d5c9a868SElliott Hughes  *
239*d5c9a868SElliott Hughes  * Returns:
240*d5c9a868SElliott Hughes  * 2 if file is to be overwritten
241*d5c9a868SElliott Hughes  * 1 if file was renamed
242*d5c9a868SElliott Hughes  * 0 if it was skipped
243*d5c9a868SElliott Hughes  *
244*d5c9a868SElliott Hughes  * If a short name is involved, handle conversion between the 11-character
245*d5c9a868SElliott Hughes  * fixed-length record DOS name and a literal null-terminated name (e.g.
246*d5c9a868SElliott Hughes  * "COMMAND  COM" (no null) <-> "COMMAND.COM" (null terminated)).
247*d5c9a868SElliott Hughes  *
248*d5c9a868SElliott Hughes  * Also, immediately copy the original name so that messages can use it.
249*d5c9a868SElliott Hughes  */
process_namematch(doscp_t * cp,dos_name_t * dosname,char * longname,int isprimary,ClashHandling_t * ch,int no_overwrite,int reason)250*d5c9a868SElliott Hughes static __inline__ clash_action process_namematch(doscp_t *cp,
251*d5c9a868SElliott Hughes 						 dos_name_t *dosname,
252*d5c9a868SElliott Hughes 						 char *longname,
253*d5c9a868SElliott Hughes 						 int isprimary,
254*d5c9a868SElliott Hughes 						 ClashHandling_t *ch,
255*d5c9a868SElliott Hughes 						 int no_overwrite,
256*d5c9a868SElliott Hughes 						 int reason)
257*d5c9a868SElliott Hughes {
258*d5c9a868SElliott Hughes 	clash_action action;
259*d5c9a868SElliott Hughes 
260*d5c9a868SElliott Hughes #if 0
261*d5c9a868SElliott Hughes 	fprintf(stderr,
262*d5c9a868SElliott Hughes 		"process_namematch: name=%s, default_action=%d, ask=%d.\n",
263*d5c9a868SElliott Hughes 		name, default_action, ch->ask);
264*d5c9a868SElliott Hughes #endif
265*d5c9a868SElliott Hughes 
266*d5c9a868SElliott Hughes 	action = ask_namematch(cp, dosname, longname,
267*d5c9a868SElliott Hughes 			       isprimary, ch, no_overwrite, reason);
268*d5c9a868SElliott Hughes 
269*d5c9a868SElliott Hughes 	switch(action){
270*d5c9a868SElliott Hughes 	case NAMEMATCH_QUIT:
271*d5c9a868SElliott Hughes 		got_signal = 1;
272*d5c9a868SElliott Hughes 		return NAMEMATCH_SKIP;
273*d5c9a868SElliott Hughes 	case NAMEMATCH_SKIP:
274*d5c9a868SElliott Hughes 		return NAMEMATCH_SKIP;
275*d5c9a868SElliott Hughes 	case NAMEMATCH_RENAME:
276*d5c9a868SElliott Hughes 	case NAMEMATCH_PRENAME:
277*d5c9a868SElliott Hughes 		/* We need to rename the file now.  This means we must pass
278*d5c9a868SElliott Hughes 		 * back through the loop, a) ensuring there isn't a potential
279*d5c9a868SElliott Hughes 		 * new name collision, and b) finding a big enough VSE.
280*d5c9a868SElliott Hughes 		 * Change the name, so that it won't collide again.
281*d5c9a868SElliott Hughes 		 */
282*d5c9a868SElliott Hughes 		ask_rename(cp, ch, dosname, longname, isprimary);
283*d5c9a868SElliott Hughes 		return action;
284*d5c9a868SElliott Hughes 	case NAMEMATCH_AUTORENAME:
285*d5c9a868SElliott Hughes 		/* Very similar to NAMEMATCH_RENAME, except that we need to
286*d5c9a868SElliott Hughes 		 * first generate the name.
287*d5c9a868SElliott Hughes 		 * TODO: Remember previous name so we don't
288*d5c9a868SElliott Hughes 		 * keep trying the same one.
289*d5c9a868SElliott Hughes 		 */
290*d5c9a868SElliott Hughes 		if (isprimary) {
291*d5c9a868SElliott Hughes 			autorename_long(longname, 1);
292*d5c9a868SElliott Hughes 			return NAMEMATCH_PRENAME;
293*d5c9a868SElliott Hughes 		} else {
294*d5c9a868SElliott Hughes 			autorename_short(dosname, 1);
295*d5c9a868SElliott Hughes 			return NAMEMATCH_RENAME;
296*d5c9a868SElliott Hughes 		}
297*d5c9a868SElliott Hughes 	case NAMEMATCH_OVERWRITE:
298*d5c9a868SElliott Hughes 		if(no_overwrite)
299*d5c9a868SElliott Hughes 			return NAMEMATCH_SKIP;
300*d5c9a868SElliott Hughes 		else
301*d5c9a868SElliott Hughes 			return NAMEMATCH_OVERWRITE;
302*d5c9a868SElliott Hughes 	case NAMEMATCH_NONE:
303*d5c9a868SElliott Hughes 	case NAMEMATCH_ERROR:
304*d5c9a868SElliott Hughes 	case NAMEMATCH_SUCCESS:
305*d5c9a868SElliott Hughes 	case NAMEMATCH_GREW:
306*d5c9a868SElliott Hughes 		return NAMEMATCH_NONE;
307*d5c9a868SElliott Hughes 	}
308*d5c9a868SElliott Hughes 	return action;
309*d5c9a868SElliott Hughes }
310*d5c9a868SElliott Hughes 
contains_illegals(const char * string,const char * illegals,int len)311*d5c9a868SElliott Hughes static int contains_illegals(const char *string, const char *illegals,
312*d5c9a868SElliott Hughes 			     int len)
313*d5c9a868SElliott Hughes {
314*d5c9a868SElliott Hughes 	for(; *string && len--; string++)
315*d5c9a868SElliott Hughes 		if((*string < ' ' && *string != '\005' && !(*string & 0x80)) ||
316*d5c9a868SElliott Hughes 		   strchr(illegals, *string))
317*d5c9a868SElliott Hughes 			return 1;
318*d5c9a868SElliott Hughes 	return 0;
319*d5c9a868SElliott Hughes }
320*d5c9a868SElliott Hughes 
is_reserved(char * ans,int islong)321*d5c9a868SElliott Hughes static int is_reserved(char *ans, int islong)
322*d5c9a868SElliott Hughes {
323*d5c9a868SElliott Hughes 	unsigned int i;
324*d5c9a868SElliott Hughes 	static const char *dev3[] = {"CON", "AUX", "PRN", "NUL", "   "};
325*d5c9a868SElliott Hughes 	static const char *dev4[] = {"COM", "LPT" };
326*d5c9a868SElliott Hughes 
327*d5c9a868SElliott Hughes 	for (i = 0; i < sizeof(dev3)/sizeof(*dev3); i++)
328*d5c9a868SElliott Hughes 		if (!strncasecmp(ans, dev3[i], 3) &&
329*d5c9a868SElliott Hughes 		    ((islong && !ans[3]) ||
330*d5c9a868SElliott Hughes 		     (!islong && !strncmp(ans+3,"     ",5))))
331*d5c9a868SElliott Hughes 			return 1;
332*d5c9a868SElliott Hughes 
333*d5c9a868SElliott Hughes 	for (i = 0; i < sizeof(dev4)/sizeof(*dev4); i++)
334*d5c9a868SElliott Hughes 		if (!strncasecmp(ans, dev4[i], 3) &&
335*d5c9a868SElliott Hughes 		    (ans[3] >= '1' && ans[3] <= '4') &&
336*d5c9a868SElliott Hughes 		    ((islong && !ans[4]) ||
337*d5c9a868SElliott Hughes 		     (!islong && !strncmp(ans+4,"    ",4))))
338*d5c9a868SElliott Hughes 			return 1;
339*d5c9a868SElliott Hughes 
340*d5c9a868SElliott Hughes 	return 0;
341*d5c9a868SElliott Hughes }
342*d5c9a868SElliott Hughes 
get_slots(Stream_t * Dir,dos_name_t * dosname,char * longname,struct scan_state * ssp,ClashHandling_t * ch)343*d5c9a868SElliott Hughes static __inline__ clash_action get_slots(Stream_t *Dir,
344*d5c9a868SElliott Hughes 					 dos_name_t *dosname,
345*d5c9a868SElliott Hughes 					 char *longname,
346*d5c9a868SElliott Hughes 					 struct scan_state *ssp,
347*d5c9a868SElliott Hughes 					 ClashHandling_t *ch)
348*d5c9a868SElliott Hughes {
349*d5c9a868SElliott Hughes 	int error;
350*d5c9a868SElliott Hughes 	clash_action ret;
351*d5c9a868SElliott Hughes 	int match_pos=0;
352*d5c9a868SElliott Hughes 	direntry_t entry;
353*d5c9a868SElliott Hughes 	int isprimary;
354*d5c9a868SElliott Hughes 	int no_overwrite;
355*d5c9a868SElliott Hughes 	int reason;
356*d5c9a868SElliott Hughes 	int pessimisticShortRename;
357*d5c9a868SElliott Hughes 	doscp_t *cp = GET_DOSCONVERT(Dir);
358*d5c9a868SElliott Hughes 
359*d5c9a868SElliott Hughes 	pessimisticShortRename = (ch->action[0] == NAMEMATCH_AUTORENAME);
360*d5c9a868SElliott Hughes 
361*d5c9a868SElliott Hughes 	entry.Dir = Dir;
362*d5c9a868SElliott Hughes 	no_overwrite = 1;
363*d5c9a868SElliott Hughes 	if((is_reserved(longname,1)) ||
364*d5c9a868SElliott Hughes 	   longname[strspn(longname,". ")] == '\0'){
365*d5c9a868SElliott Hughes 		reason = RESERVED;
366*d5c9a868SElliott Hughes 		isprimary = 1;
367*d5c9a868SElliott Hughes 	} else if(contains_illegals(longname,long_illegals,1024)) {
368*d5c9a868SElliott Hughes 		reason = ILLEGALS;
369*d5c9a868SElliott Hughes 		isprimary = 1;
370*d5c9a868SElliott Hughes 	} else if(is_reserved(dosname->base,0)) {
371*d5c9a868SElliott Hughes 		reason = RESERVED;
372*d5c9a868SElliott Hughes 		ch->use_longname = 1;
373*d5c9a868SElliott Hughes 		isprimary = 0;
374*d5c9a868SElliott Hughes 	} else if(!ch->is_label &&
375*d5c9a868SElliott Hughes 		  contains_illegals(dosname->base,short_illegals,11)) {
376*d5c9a868SElliott Hughes 		reason = ILLEGALS;
377*d5c9a868SElliott Hughes 		ch->use_longname = 1;
378*d5c9a868SElliott Hughes 		isprimary = 0;
379*d5c9a868SElliott Hughes 	} else {
380*d5c9a868SElliott Hughes 		reason = EXISTS;
381*d5c9a868SElliott Hughes 		switch (lookupForInsert(Dir,
382*d5c9a868SElliott Hughes 					&entry,
383*d5c9a868SElliott Hughes 					dosname, longname, ssp,
384*d5c9a868SElliott Hughes 					ch->ignore_entry,
385*d5c9a868SElliott Hughes 					ch->source_entry,
386*d5c9a868SElliott Hughes 					pessimisticShortRename &&
387*d5c9a868SElliott Hughes 					ch->use_longname,
388*d5c9a868SElliott Hughes 					ch->use_longname)) {
389*d5c9a868SElliott Hughes 			case -1:
390*d5c9a868SElliott Hughes 				return NAMEMATCH_ERROR;
391*d5c9a868SElliott Hughes 
392*d5c9a868SElliott Hughes 			case 0:
393*d5c9a868SElliott Hughes 				return NAMEMATCH_SKIP;
394*d5c9a868SElliott Hughes 				/* Single-file error error or skip request */
395*d5c9a868SElliott Hughes 
396*d5c9a868SElliott Hughes 			case 5:
397*d5c9a868SElliott Hughes 				return NAMEMATCH_GREW;
398*d5c9a868SElliott Hughes 				/* Grew directory, try again */
399*d5c9a868SElliott Hughes 
400*d5c9a868SElliott Hughes 			case 6:
401*d5c9a868SElliott Hughes 				return NAMEMATCH_SUCCESS; /* Success */
402*d5c9a868SElliott Hughes 		}
403*d5c9a868SElliott Hughes 		match_pos = -2;
404*d5c9a868SElliott Hughes 		if (ssp->longmatch > -1) {
405*d5c9a868SElliott Hughes 			/* Primary Long Name Match */
406*d5c9a868SElliott Hughes #ifdef debug
407*d5c9a868SElliott Hughes 			fprintf(stderr,
408*d5c9a868SElliott Hughes 				"Got longmatch=%d for name %s.\n",
409*d5c9a868SElliott Hughes 				longmatch, longname);
410*d5c9a868SElliott Hughes #endif
411*d5c9a868SElliott Hughes 			match_pos = ssp->longmatch;
412*d5c9a868SElliott Hughes 			isprimary = 1;
413*d5c9a868SElliott Hughes 		} else if ((ch->use_longname & 1) && (ssp->shortmatch != -1)) {
414*d5c9a868SElliott Hughes 			/* Secondary Short Name Match */
415*d5c9a868SElliott Hughes #ifdef debug
416*d5c9a868SElliott Hughes 			fprintf(stderr,
417*d5c9a868SElliott Hughes 				"Got secondary short name match for name %s.\n",
418*d5c9a868SElliott Hughes 				longname);
419*d5c9a868SElliott Hughes #endif
420*d5c9a868SElliott Hughes 
421*d5c9a868SElliott Hughes 			match_pos = ssp->shortmatch;
422*d5c9a868SElliott Hughes 			isprimary = 0;
423*d5c9a868SElliott Hughes 		} else if (ssp->shortmatch >= 0) {
424*d5c9a868SElliott Hughes 			/* Primary Short Name Match */
425*d5c9a868SElliott Hughes #ifdef debug
426*d5c9a868SElliott Hughes 			fprintf(stderr,
427*d5c9a868SElliott Hughes 				"Got primary short name match for name %s.\n",
428*d5c9a868SElliott Hughes 				longname);
429*d5c9a868SElliott Hughes #endif
430*d5c9a868SElliott Hughes 			match_pos = ssp->shortmatch;
431*d5c9a868SElliott Hughes 			isprimary = 1;
432*d5c9a868SElliott Hughes 		} else
433*d5c9a868SElliott Hughes 			return NAMEMATCH_RENAME;
434*d5c9a868SElliott Hughes 
435*d5c9a868SElliott Hughes 		if(match_pos > -1) {
436*d5c9a868SElliott Hughes 			entry.entry = match_pos;
437*d5c9a868SElliott Hughes 			dir_read(&entry, &error);
438*d5c9a868SElliott Hughes 			if (error)
439*d5c9a868SElliott Hughes 			    return NAMEMATCH_ERROR;
440*d5c9a868SElliott Hughes 			/* if we can't overwrite, don't propose it */
441*d5c9a868SElliott Hughes 			no_overwrite = (match_pos == ch->source || IS_DIR(&entry));
442*d5c9a868SElliott Hughes 		}
443*d5c9a868SElliott Hughes 	}
444*d5c9a868SElliott Hughes 	ret = process_namematch(cp, dosname, longname,
445*d5c9a868SElliott Hughes 				isprimary, ch, no_overwrite, reason);
446*d5c9a868SElliott Hughes 
447*d5c9a868SElliott Hughes 	if (ret == NAMEMATCH_OVERWRITE && match_pos > -1){
448*d5c9a868SElliott Hughes 		if((entry.dir.attr & 0x5) &&
449*d5c9a868SElliott Hughes 		   (ask_confirmation("file is read only, overwrite anyway (y/n) ? ")))
450*d5c9a868SElliott Hughes 			return NAMEMATCH_RENAME;
451*d5c9a868SElliott Hughes 		/* Free up the file to be overwritten */
452*d5c9a868SElliott Hughes 		if(fatFreeWithDirentry(&entry))
453*d5c9a868SElliott Hughes 			return NAMEMATCH_ERROR;
454*d5c9a868SElliott Hughes 
455*d5c9a868SElliott Hughes #if 0
456*d5c9a868SElliott Hughes 		if(isprimary &&
457*d5c9a868SElliott Hughes 		   match_pos - ssp->match_free + 1 >= ssp->size_needed){
458*d5c9a868SElliott Hughes 			/* reuse old entry and old short name for overwrite */
459*d5c9a868SElliott Hughes 			ssp->free_start = match_pos - ssp->size_needed + 1;
460*d5c9a868SElliott Hughes 			ssp->free_size = ssp->size_needed;
461*d5c9a868SElliott Hughes 			ssp->slot = match_pos;
462*d5c9a868SElliott Hughes 			ssp->got_slots = 1;
463*d5c9a868SElliott Hughes 			strncpy(dosname, dir.name, 3);
464*d5c9a868SElliott Hughes 			strncpy(dosname + 8, dir.ext, 3);
465*d5c9a868SElliott Hughes 			return ret;
466*d5c9a868SElliott Hughes 		} else
467*d5c9a868SElliott Hughes #endif
468*d5c9a868SElliott Hughes 			{
469*d5c9a868SElliott Hughes 			wipeEntry(&entry);
470*d5c9a868SElliott Hughes 			return NAMEMATCH_RENAME;
471*d5c9a868SElliott Hughes 		}
472*d5c9a868SElliott Hughes 	}
473*d5c9a868SElliott Hughes 
474*d5c9a868SElliott Hughes 	return ret;
475*d5c9a868SElliott Hughes }
476*d5c9a868SElliott Hughes 
477*d5c9a868SElliott Hughes 
write_slots(Stream_t * Dir,dos_name_t * dosname,char * longname,struct scan_state * ssp,write_data_callback * cb,void * arg,int Case)478*d5c9a868SElliott Hughes static __inline__ int write_slots(Stream_t *Dir,
479*d5c9a868SElliott Hughes 				  dos_name_t *dosname,
480*d5c9a868SElliott Hughes 				  char *longname,
481*d5c9a868SElliott Hughes 				  struct scan_state *ssp,
482*d5c9a868SElliott Hughes 				  write_data_callback *cb,
483*d5c9a868SElliott Hughes 				  void *arg,
484*d5c9a868SElliott Hughes 				  int Case)
485*d5c9a868SElliott Hughes {
486*d5c9a868SElliott Hughes 	direntry_t entry;
487*d5c9a868SElliott Hughes 
488*d5c9a868SElliott Hughes 	/* write the file */
489*d5c9a868SElliott Hughes 	if (fat_error(Dir))
490*d5c9a868SElliott Hughes 		return 0;
491*d5c9a868SElliott Hughes 
492*d5c9a868SElliott Hughes 	entry.Dir = Dir;
493*d5c9a868SElliott Hughes 	entry.entry = ssp->slot;
494*d5c9a868SElliott Hughes 	native_to_wchar(longname, entry.name, MAX_VNAMELEN, 0, 0);
495*d5c9a868SElliott Hughes 	entry.name[MAX_VNAMELEN]='\0';
496*d5c9a868SElliott Hughes 	entry.dir.Case = Case & (EXTCASE | BASECASE);
497*d5c9a868SElliott Hughes 	if (cb(dosname, longname, arg, &entry) >= 0) {
498*d5c9a868SElliott Hughes 		if ((ssp->size_needed > 1) &&
499*d5c9a868SElliott Hughes 		    (ssp->free_end - ssp->free_start >= ssp->size_needed)) {
500*d5c9a868SElliott Hughes 			ssp->slot = write_vfat(Dir, dosname, longname,
501*d5c9a868SElliott Hughes 					       ssp->free_start, &entry);
502*d5c9a868SElliott Hughes 		} else {
503*d5c9a868SElliott Hughes 			ssp->size_needed = 1;
504*d5c9a868SElliott Hughes 			write_vfat(Dir, dosname, 0,
505*d5c9a868SElliott Hughes 				   ssp->free_start, &entry);
506*d5c9a868SElliott Hughes 		}
507*d5c9a868SElliott Hughes 		/* clear_vses(Dir, ssp->free_start + ssp->size_needed,
508*d5c9a868SElliott Hughes 		   ssp->free_end); */
509*d5c9a868SElliott Hughes 	} else
510*d5c9a868SElliott Hughes 		return 0;
511*d5c9a868SElliott Hughes 
512*d5c9a868SElliott Hughes 	return 1;	/* Successfully wrote the file */
513*d5c9a868SElliott Hughes }
514*d5c9a868SElliott Hughes 
stripspaces(char * name)515*d5c9a868SElliott Hughes static void stripspaces(char *name)
516*d5c9a868SElliott Hughes {
517*d5c9a868SElliott Hughes 	char *p,*non_space;
518*d5c9a868SElliott Hughes 
519*d5c9a868SElliott Hughes 	non_space = name;
520*d5c9a868SElliott Hughes 	for(p=name; *p; p++)
521*d5c9a868SElliott Hughes 		if (*p != ' ')
522*d5c9a868SElliott Hughes 			non_space = p;
523*d5c9a868SElliott Hughes 	if(name[0])
524*d5c9a868SElliott Hughes 		non_space[1] = '\0';
525*d5c9a868SElliott Hughes }
526*d5c9a868SElliott Hughes 
527*d5c9a868SElliott Hughes 
_mwrite_one(Stream_t * Dir,char * argname,char * shortname,write_data_callback * cb,void * arg,ClashHandling_t * ch)528*d5c9a868SElliott Hughes static int _mwrite_one(Stream_t *Dir,
529*d5c9a868SElliott Hughes 		       char *argname,
530*d5c9a868SElliott Hughes 		       char *shortname,
531*d5c9a868SElliott Hughes 		       write_data_callback *cb,
532*d5c9a868SElliott Hughes 		       void *arg,
533*d5c9a868SElliott Hughes 		       ClashHandling_t *ch)
534*d5c9a868SElliott Hughes {
535*d5c9a868SElliott Hughes 	char longname[VBUFSIZE];
536*d5c9a868SElliott Hughes 	const char *dstname;
537*d5c9a868SElliott Hughes 	dos_name_t dosname;
538*d5c9a868SElliott Hughes 	int expanded;
539*d5c9a868SElliott Hughes 	struct scan_state scan;
540*d5c9a868SElliott Hughes 	clash_action ret;
541*d5c9a868SElliott Hughes 	doscp_t *cp = GET_DOSCONVERT(Dir);
542*d5c9a868SElliott Hughes 
543*d5c9a868SElliott Hughes 	expanded = 0;
544*d5c9a868SElliott Hughes 
545*d5c9a868SElliott Hughes 	if(isSpecial(argname)) {
546*d5c9a868SElliott Hughes 		fprintf(stderr, "Cannot create entry named . or ..\n");
547*d5c9a868SElliott Hughes 		return -1;
548*d5c9a868SElliott Hughes 	}
549*d5c9a868SElliott Hughes 
550*d5c9a868SElliott Hughes 	if(ch->name_converter == dos_name) {
551*d5c9a868SElliott Hughes 		if(shortname)
552*d5c9a868SElliott Hughes 			stripspaces(shortname);
553*d5c9a868SElliott Hughes 		if(argname)
554*d5c9a868SElliott Hughes 			stripspaces(argname);
555*d5c9a868SElliott Hughes 	}
556*d5c9a868SElliott Hughes 
557*d5c9a868SElliott Hughes 	if(shortname){
558*d5c9a868SElliott Hughes 		convert_to_shortname(cp, ch, shortname, &dosname);
559*d5c9a868SElliott Hughes 		if(ch->use_longname & 1){
560*d5c9a868SElliott Hughes 			/* short name mangled, treat it as a long name */
561*d5c9a868SElliott Hughes 			argname = shortname;
562*d5c9a868SElliott Hughes 			shortname = 0;
563*d5c9a868SElliott Hughes 		}
564*d5c9a868SElliott Hughes 	}
565*d5c9a868SElliott Hughes 
566*d5c9a868SElliott Hughes 	if (argname[0] && (argname[1] == ':')) {
567*d5c9a868SElliott Hughes 		/* Skip drive letter */
568*d5c9a868SElliott Hughes 		dstname = argname + 2;
569*d5c9a868SElliott Hughes 	} else {
570*d5c9a868SElliott Hughes 		dstname = argname;
571*d5c9a868SElliott Hughes 	}
572*d5c9a868SElliott Hughes 
573*d5c9a868SElliott Hughes 	/* Copy original argument dstname to working value longname */
574*d5c9a868SElliott Hughes 	strncpy(longname, dstname, VBUFSIZE-1);
575*d5c9a868SElliott Hughes 
576*d5c9a868SElliott Hughes 	if(shortname) {
577*d5c9a868SElliott Hughes 		ch->use_longname =
578*d5c9a868SElliott Hughes 			convert_to_shortname(cp, ch, shortname, &dosname);
579*d5c9a868SElliott Hughes 		if(strcmp(shortname, longname))
580*d5c9a868SElliott Hughes 			ch->use_longname |= 1;
581*d5c9a868SElliott Hughes 	} else {
582*d5c9a868SElliott Hughes 		ch->use_longname =
583*d5c9a868SElliott Hughes 			convert_to_shortname(cp, ch, longname, &dosname);
584*d5c9a868SElliott Hughes 	}
585*d5c9a868SElliott Hughes 
586*d5c9a868SElliott Hughes 	ch->action[0] = ch->namematch_default[0];
587*d5c9a868SElliott Hughes 	ch->action[1] = ch->namematch_default[1];
588*d5c9a868SElliott Hughes 
589*d5c9a868SElliott Hughes 	while (1) {
590*d5c9a868SElliott Hughes 		switch((ret=get_slots(Dir, &dosname, longname, &scan, ch))){
591*d5c9a868SElliott Hughes 			case NAMEMATCH_ERROR:
592*d5c9a868SElliott Hughes 				return -1;	/* Non-file-specific error,
593*d5c9a868SElliott Hughes 						 * quit */
594*d5c9a868SElliott Hughes 
595*d5c9a868SElliott Hughes 			case NAMEMATCH_SKIP:
596*d5c9a868SElliott Hughes 				return -1;	/* Skip file (user request or
597*d5c9a868SElliott Hughes 						 * error) */
598*d5c9a868SElliott Hughes 
599*d5c9a868SElliott Hughes 			case NAMEMATCH_PRENAME:
600*d5c9a868SElliott Hughes 				ch->use_longname =
601*d5c9a868SElliott Hughes 					convert_to_shortname(cp, ch,
602*d5c9a868SElliott Hughes 							     longname,
603*d5c9a868SElliott Hughes 							     &dosname);
604*d5c9a868SElliott Hughes 				continue;
605*d5c9a868SElliott Hughes 			case NAMEMATCH_RENAME:
606*d5c9a868SElliott Hughes 				continue;	/* Renamed file, loop again */
607*d5c9a868SElliott Hughes 
608*d5c9a868SElliott Hughes 			case NAMEMATCH_GREW:
609*d5c9a868SElliott Hughes 				/* No collision, and not enough slots.
610*d5c9a868SElliott Hughes 				 * Try to grow the directory
611*d5c9a868SElliott Hughes 				 */
612*d5c9a868SElliott Hughes 				if (expanded) {	/* Already tried this
613*d5c9a868SElliott Hughes 						 * once, no good */
614*d5c9a868SElliott Hughes 					fprintf(stderr,
615*d5c9a868SElliott Hughes 						"%s: No directory slots\n",
616*d5c9a868SElliott Hughes 						progname);
617*d5c9a868SElliott Hughes 					return -1;
618*d5c9a868SElliott Hughes 				}
619*d5c9a868SElliott Hughes 				expanded = 1;
620*d5c9a868SElliott Hughes 
621*d5c9a868SElliott Hughes 				if (dir_grow(Dir, scan.max_entry))
622*d5c9a868SElliott Hughes 					return -1;
623*d5c9a868SElliott Hughes 				continue;
624*d5c9a868SElliott Hughes 			case NAMEMATCH_OVERWRITE:
625*d5c9a868SElliott Hughes 			case NAMEMATCH_SUCCESS:
626*d5c9a868SElliott Hughes 				return write_slots(Dir, &dosname, longname,
627*d5c9a868SElliott Hughes 						   &scan, cb, arg,
628*d5c9a868SElliott Hughes 						   ch->use_longname);
629*d5c9a868SElliott Hughes 			case NAMEMATCH_NONE:
630*d5c9a868SElliott Hughes 			case NAMEMATCH_AUTORENAME:
631*d5c9a868SElliott Hughes 			case NAMEMATCH_QUIT:
632*d5c9a868SElliott Hughes 				fprintf(stderr,
633*d5c9a868SElliott Hughes 					"Internal error: clash_action=%d\n",
634*d5c9a868SElliott Hughes 					ret);
635*d5c9a868SElliott Hughes 				return -1;
636*d5c9a868SElliott Hughes 		}
637*d5c9a868SElliott Hughes 
638*d5c9a868SElliott Hughes 	}
639*d5c9a868SElliott Hughes }
640*d5c9a868SElliott Hughes 
mwrite_one(Stream_t * Dir,const char * _argname,const char * _shortname,write_data_callback * cb,void * arg,ClashHandling_t * ch)641*d5c9a868SElliott Hughes int mwrite_one(Stream_t *Dir,
642*d5c9a868SElliott Hughes 	       const char *_argname,
643*d5c9a868SElliott Hughes 	       const char *_shortname,
644*d5c9a868SElliott Hughes 	       write_data_callback *cb,
645*d5c9a868SElliott Hughes 	       void *arg,
646*d5c9a868SElliott Hughes 	       ClashHandling_t *ch)
647*d5c9a868SElliott Hughes {
648*d5c9a868SElliott Hughes 	char *argname;
649*d5c9a868SElliott Hughes 	char *shortname;
650*d5c9a868SElliott Hughes 	int ret;
651*d5c9a868SElliott Hughes 
652*d5c9a868SElliott Hughes 	if(_argname)
653*d5c9a868SElliott Hughes 		argname = strdup(_argname);
654*d5c9a868SElliott Hughes 	else
655*d5c9a868SElliott Hughes 		argname = 0;
656*d5c9a868SElliott Hughes 	if(_shortname)
657*d5c9a868SElliott Hughes 		shortname = strdup(_shortname);
658*d5c9a868SElliott Hughes 	else
659*d5c9a868SElliott Hughes 		shortname = 0;
660*d5c9a868SElliott Hughes 	ret = _mwrite_one(Dir, argname, shortname, cb, arg, ch);
661*d5c9a868SElliott Hughes 	if(argname)
662*d5c9a868SElliott Hughes 		free(argname);
663*d5c9a868SElliott Hughes 	if(shortname)
664*d5c9a868SElliott Hughes 		free(shortname);
665*d5c9a868SElliott Hughes 	return ret;
666*d5c9a868SElliott Hughes }
667*d5c9a868SElliott Hughes 
init_clash_handling(ClashHandling_t * ch)668*d5c9a868SElliott Hughes void init_clash_handling(ClashHandling_t *ch)
669*d5c9a868SElliott Hughes {
670*d5c9a868SElliott Hughes 	ch->ignore_entry = -1;
671*d5c9a868SElliott Hughes 	ch->source_entry = -2;
672*d5c9a868SElliott Hughes 	ch->nowarn = 0;	/*Don't ask, just do default action if name collision */
673*d5c9a868SElliott Hughes 	ch->namematch_default[0] = NAMEMATCH_AUTORENAME;
674*d5c9a868SElliott Hughes 	ch->namematch_default[1] = NAMEMATCH_NONE;
675*d5c9a868SElliott Hughes 	ch->name_converter = dos_name; /* changed by mlabel */
676*d5c9a868SElliott Hughes 	ch->source = -2;
677*d5c9a868SElliott Hughes 	ch->is_label = 0;
678*d5c9a868SElliott Hughes }
679*d5c9a868SElliott Hughes 
handle_clash_options(ClashHandling_t * ch,char c)680*d5c9a868SElliott Hughes int handle_clash_options(ClashHandling_t *ch, char c)
681*d5c9a868SElliott Hughes {
682*d5c9a868SElliott Hughes 	int isprimary;
683*d5c9a868SElliott Hughes 	if(isupper(c))
684*d5c9a868SElliott Hughes 		isprimary = 0;
685*d5c9a868SElliott Hughes 	else
686*d5c9a868SElliott Hughes 		isprimary = 1;
687*d5c9a868SElliott Hughes 	c = ch_tolower(c);
688*d5c9a868SElliott Hughes 	switch(c) {
689*d5c9a868SElliott Hughes 		case 'o':
690*d5c9a868SElliott Hughes 			/* Overwrite if primary name matches */
691*d5c9a868SElliott Hughes 			ch->namematch_default[isprimary] = NAMEMATCH_OVERWRITE;
692*d5c9a868SElliott Hughes 			return 0;
693*d5c9a868SElliott Hughes 		case 'r':
694*d5c9a868SElliott Hughes 				/* Rename primary name interactively */
695*d5c9a868SElliott Hughes 			ch->namematch_default[isprimary] = NAMEMATCH_RENAME;
696*d5c9a868SElliott Hughes 			return 0;
697*d5c9a868SElliott Hughes 		case 's':
698*d5c9a868SElliott Hughes 			/* Skip file if primary name collides */
699*d5c9a868SElliott Hughes 			ch->namematch_default[isprimary] = NAMEMATCH_SKIP;
700*d5c9a868SElliott Hughes 			return 0;
701*d5c9a868SElliott Hughes 		case 'm':
702*d5c9a868SElliott Hughes 			ch->namematch_default[isprimary] = NAMEMATCH_NONE;
703*d5c9a868SElliott Hughes 			return 0;
704*d5c9a868SElliott Hughes 		case 'a':
705*d5c9a868SElliott Hughes 			ch->namematch_default[isprimary] = NAMEMATCH_AUTORENAME;
706*d5c9a868SElliott Hughes 			return 0;
707*d5c9a868SElliott Hughes 		default:
708*d5c9a868SElliott Hughes 			return -1;
709*d5c9a868SElliott Hughes 	}
710*d5c9a868SElliott Hughes }
711*d5c9a868SElliott Hughes 
dosnameToDirentry(const struct dos_name_t * dn,struct directory * dir)712*d5c9a868SElliott Hughes void dosnameToDirentry(const struct dos_name_t *dn, struct directory *dir) {
713*d5c9a868SElliott Hughes 	strncpy(dir->name, dn->base, 8);
714*d5c9a868SElliott Hughes 	strncpy(dir->ext, dn->ext, 3);
715*d5c9a868SElliott Hughes }
716