xref: /aosp_15_r20/external/mtools/mmd.c (revision d5c9a868b113e0ec0db2f27bc2ce8a253e77c4b0)
1*d5c9a868SElliott Hughes /*  Copyright 1986-1992 Emmet P. Gray.
2*d5c9a868SElliott Hughes  *  Copyright 1996-2002,2007-2009 Alain Knaff.
3*d5c9a868SElliott Hughes  *  This file is part of mtools.
4*d5c9a868SElliott Hughes  *
5*d5c9a868SElliott Hughes  *  Mtools is free software: you can redistribute it and/or modify
6*d5c9a868SElliott Hughes  *  it under the terms of the GNU General Public License as published by
7*d5c9a868SElliott Hughes  *  the Free Software Foundation, either version 3 of the License, or
8*d5c9a868SElliott Hughes  *  (at your option) any later version.
9*d5c9a868SElliott Hughes  *
10*d5c9a868SElliott Hughes  *  Mtools is distributed in the hope that it will be useful,
11*d5c9a868SElliott Hughes  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12*d5c9a868SElliott Hughes  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13*d5c9a868SElliott Hughes  *  GNU General Public License for more details.
14*d5c9a868SElliott Hughes  *
15*d5c9a868SElliott Hughes  *  You should have received a copy of the GNU General Public License
16*d5c9a868SElliott Hughes  *  along with Mtools.  If not, see <http://www.gnu.org/licenses/>.
17*d5c9a868SElliott Hughes  *
18*d5c9a868SElliott Hughes  * mmd.c
19*d5c9a868SElliott Hughes  * Makes an MSDOS directory
20*d5c9a868SElliott Hughes  */
21*d5c9a868SElliott Hughes 
22*d5c9a868SElliott Hughes 
23*d5c9a868SElliott Hughes #include "sysincludes.h"
24*d5c9a868SElliott Hughes #include "msdos.h"
25*d5c9a868SElliott Hughes #include "mtools.h"
26*d5c9a868SElliott Hughes #include "vfat.h"
27*d5c9a868SElliott Hughes #include "mainloop.h"
28*d5c9a868SElliott Hughes #include "plain_io.h"
29*d5c9a868SElliott Hughes #include "nameclash.h"
30*d5c9a868SElliott Hughes #include "file.h"
31*d5c9a868SElliott Hughes #include "fs.h"
32*d5c9a868SElliott Hughes 
33*d5c9a868SElliott Hughes /*
34*d5c9a868SElliott Hughes  * Preserve the file modification times after the fclose()
35*d5c9a868SElliott Hughes  */
36*d5c9a868SElliott Hughes 
37*d5c9a868SElliott Hughes typedef struct Arg_t {
38*d5c9a868SElliott Hughes 	char *target;
39*d5c9a868SElliott Hughes 	MainParam_t mp;
40*d5c9a868SElliott Hughes 
41*d5c9a868SElliott Hughes 	Stream_t *SrcDir;
42*d5c9a868SElliott Hughes 	int entry;
43*d5c9a868SElliott Hughes 	ClashHandling_t ch;
44*d5c9a868SElliott Hughes 	Stream_t *targetDir;
45*d5c9a868SElliott Hughes } Arg_t;
46*d5c9a868SElliott Hughes 
47*d5c9a868SElliott Hughes 
48*d5c9a868SElliott Hughes typedef struct CreateArg_t {
49*d5c9a868SElliott Hughes 	Stream_t *Dir;
50*d5c9a868SElliott Hughes 	Stream_t *NewDir;
51*d5c9a868SElliott Hughes 	unsigned char attr;
52*d5c9a868SElliott Hughes 	time_t mtime;
53*d5c9a868SElliott Hughes } CreateArg_t;
54*d5c9a868SElliott Hughes 
55*d5c9a868SElliott Hughes /*
56*d5c9a868SElliott Hughes  * Open the named file for read, create the cluster chain, return the
57*d5c9a868SElliott Hughes  * directory structure or NULL on error.
58*d5c9a868SElliott Hughes  */
makeit(dos_name_t * dosname,char * longname UNUSEDP,void * arg0,direntry_t * targetEntry)59*d5c9a868SElliott Hughes static int makeit(dos_name_t *dosname,
60*d5c9a868SElliott Hughes 		  char *longname UNUSEDP,
61*d5c9a868SElliott Hughes 		  void *arg0,
62*d5c9a868SElliott Hughes 		  direntry_t *targetEntry)
63*d5c9a868SElliott Hughes {
64*d5c9a868SElliott Hughes 	Stream_t *Target;
65*d5c9a868SElliott Hughes 	CreateArg_t *arg = (CreateArg_t *) arg0;
66*d5c9a868SElliott Hughes 	uint32_t fat;
67*d5c9a868SElliott Hughes 	direntry_t subEntry;
68*d5c9a868SElliott Hughes 
69*d5c9a868SElliott Hughes 	/* will it fit? At least one cluster must be free */
70*d5c9a868SElliott Hughes 	if (!getfreeMinClusters(targetEntry->Dir, 1))
71*d5c9a868SElliott Hughes 		return -1;
72*d5c9a868SElliott Hughes 
73*d5c9a868SElliott Hughes 	mk_entry(dosname, ATTR_DIR, 1, 0, arg->mtime, &targetEntry->dir);
74*d5c9a868SElliott Hughes 	Target = OpenFileByDirentry(targetEntry);
75*d5c9a868SElliott Hughes 	if(!Target){
76*d5c9a868SElliott Hughes 		fprintf(stderr,"Could not open Target\n");
77*d5c9a868SElliott Hughes 		return -1;
78*d5c9a868SElliott Hughes 	}
79*d5c9a868SElliott Hughes 
80*d5c9a868SElliott Hughes 	/* this allocates the first cluster for our directory */
81*d5c9a868SElliott Hughes 
82*d5c9a868SElliott Hughes 	initializeDirentry(&subEntry, Target);
83*d5c9a868SElliott Hughes 
84*d5c9a868SElliott Hughes 	subEntry.entry = 1;
85*d5c9a868SElliott Hughes 	GET_DATA(targetEntry->Dir, 0, 0, 0, &fat);
86*d5c9a868SElliott Hughes 	if (fat == fat32RootCluster(targetEntry->Dir)) {
87*d5c9a868SElliott Hughes 	    fat = 0;
88*d5c9a868SElliott Hughes 	}
89*d5c9a868SElliott Hughes 	mk_entry_from_base("..      ", ATTR_DIR, fat, 0, arg->mtime, &subEntry.dir);
90*d5c9a868SElliott Hughes 	dir_write(&subEntry);
91*d5c9a868SElliott Hughes 
92*d5c9a868SElliott Hughes 	FLUSH(Target);
93*d5c9a868SElliott Hughes 	subEntry.entry = 0;
94*d5c9a868SElliott Hughes 	GET_DATA(Target, 0, 0, 0, &fat);
95*d5c9a868SElliott Hughes 	mk_entry_from_base(".       ", ATTR_DIR, fat, 0, arg->mtime, &subEntry.dir);
96*d5c9a868SElliott Hughes 	dir_write(&subEntry);
97*d5c9a868SElliott Hughes 
98*d5c9a868SElliott Hughes 	mk_entry(dosname, ATTR_DIR | arg->attr, fat, 0, arg->mtime,
99*d5c9a868SElliott Hughes 		 &targetEntry->dir);
100*d5c9a868SElliott Hughes 	arg->NewDir = Target;
101*d5c9a868SElliott Hughes 	return 0;
102*d5c9a868SElliott Hughes }
103*d5c9a868SElliott Hughes 
104*d5c9a868SElliott Hughes 
105*d5c9a868SElliott Hughes static void usage(int ret) NORETURN;
usage(int ret)106*d5c9a868SElliott Hughes static void usage(int ret)
107*d5c9a868SElliott Hughes {
108*d5c9a868SElliott Hughes 	fprintf(stderr,
109*d5c9a868SElliott Hughes 		"Mtools version %s, dated %s\n", mversion, mdate);
110*d5c9a868SElliott Hughes 	fprintf(stderr,
111*d5c9a868SElliott Hughes 		"Usage: %s [-D clash_option] file targetfile\n", progname);
112*d5c9a868SElliott Hughes 	fprintf(stderr,
113*d5c9a868SElliott Hughes 		"       %s [-D clash_option] file [files...] target_directory\n",
114*d5c9a868SElliott Hughes 		progname);
115*d5c9a868SElliott Hughes 	exit(ret);
116*d5c9a868SElliott Hughes }
117*d5c9a868SElliott Hughes 
createDir(Stream_t * Dir,const char * filename,ClashHandling_t * ch,unsigned char attr,time_t mtime)118*d5c9a868SElliott Hughes Stream_t *createDir(Stream_t *Dir, const char *filename, ClashHandling_t *ch,
119*d5c9a868SElliott Hughes 					unsigned char attr, time_t mtime)
120*d5c9a868SElliott Hughes {
121*d5c9a868SElliott Hughes 	CreateArg_t arg;
122*d5c9a868SElliott Hughes 	int ret;
123*d5c9a868SElliott Hughes 
124*d5c9a868SElliott Hughes 	arg.Dir = Dir;
125*d5c9a868SElliott Hughes 	arg.attr = attr;
126*d5c9a868SElliott Hughes 	arg.mtime = mtime;
127*d5c9a868SElliott Hughes 
128*d5c9a868SElliott Hughes 	if (!getfreeMinClusters(Dir, 1))
129*d5c9a868SElliott Hughes 		return NULL;
130*d5c9a868SElliott Hughes 
131*d5c9a868SElliott Hughes 	ret = mwrite_one(Dir, filename, 0, makeit, &arg, ch);
132*d5c9a868SElliott Hughes 	if(ret < 1)
133*d5c9a868SElliott Hughes 		return NULL;
134*d5c9a868SElliott Hughes 	else
135*d5c9a868SElliott Hughes 		return arg.NewDir;
136*d5c9a868SElliott Hughes }
137*d5c9a868SElliott Hughes 
createDirCallback(direntry_t * entry UNUSEDP,MainParam_t * mp)138*d5c9a868SElliott Hughes static int createDirCallback(direntry_t *entry UNUSEDP, MainParam_t *mp)
139*d5c9a868SElliott Hughes {
140*d5c9a868SElliott Hughes 	Stream_t *ret;
141*d5c9a868SElliott Hughes 	time_t now;
142*d5c9a868SElliott Hughes 
143*d5c9a868SElliott Hughes 	ret = createDir(mp->File, mp->targetName, &((Arg_t *)(mp->arg))->ch,
144*d5c9a868SElliott Hughes 					ATTR_DIR, getTimeNow(&now));
145*d5c9a868SElliott Hughes 	if(ret == NULL)
146*d5c9a868SElliott Hughes 		return ERROR_ONE;
147*d5c9a868SElliott Hughes 	else {
148*d5c9a868SElliott Hughes 		FREE(&ret);
149*d5c9a868SElliott Hughes 		return GOT_ONE;
150*d5c9a868SElliott Hughes 	}
151*d5c9a868SElliott Hughes 
152*d5c9a868SElliott Hughes }
153*d5c9a868SElliott Hughes 
154*d5c9a868SElliott Hughes void mmd(int argc, char **argv, int type UNUSEDP) NORETURN;
mmd(int argc,char ** argv,int type UNUSEDP)155*d5c9a868SElliott Hughes void mmd(int argc, char **argv, int type UNUSEDP)
156*d5c9a868SElliott Hughes {
157*d5c9a868SElliott Hughes 	Arg_t arg;
158*d5c9a868SElliott Hughes 	int c;
159*d5c9a868SElliott Hughes 
160*d5c9a868SElliott Hughes 	/* get command line options */
161*d5c9a868SElliott Hughes 
162*d5c9a868SElliott Hughes 	init_clash_handling(& arg.ch);
163*d5c9a868SElliott Hughes 
164*d5c9a868SElliott Hughes 	/* get command line options */
165*d5c9a868SElliott Hughes 	if(helpFlag(argc, argv))
166*d5c9a868SElliott Hughes 		usage(0);
167*d5c9a868SElliott Hughes 	while ((c = getopt(argc, argv, "i:D:oh")) != EOF) {
168*d5c9a868SElliott Hughes 		switch (c) {
169*d5c9a868SElliott Hughes 			case 'i':
170*d5c9a868SElliott Hughes 				set_cmd_line_image(optarg);
171*d5c9a868SElliott Hughes 				break;
172*d5c9a868SElliott Hughes 			case '?':
173*d5c9a868SElliott Hughes 				usage(1);
174*d5c9a868SElliott Hughes 			case 'o':
175*d5c9a868SElliott Hughes 				handle_clash_options(&arg.ch, (char) c);
176*d5c9a868SElliott Hughes 				break;
177*d5c9a868SElliott Hughes 			case 'D':
178*d5c9a868SElliott Hughes 				if(handle_clash_options(&arg.ch, *optarg))
179*d5c9a868SElliott Hughes 					usage(1);
180*d5c9a868SElliott Hughes 				break;
181*d5c9a868SElliott Hughes 			case 'h':
182*d5c9a868SElliott Hughes 				usage(0);
183*d5c9a868SElliott Hughes 			default:
184*d5c9a868SElliott Hughes 				usage(1);
185*d5c9a868SElliott Hughes 		}
186*d5c9a868SElliott Hughes 	}
187*d5c9a868SElliott Hughes 
188*d5c9a868SElliott Hughes 	if (argc - optind < 1)
189*d5c9a868SElliott Hughes 		usage(1);
190*d5c9a868SElliott Hughes 
191*d5c9a868SElliott Hughes 	init_mp(&arg.mp);
192*d5c9a868SElliott Hughes 	arg.mp.arg = (void *) &arg;
193*d5c9a868SElliott Hughes 	arg.mp.openflags = O_RDWR;
194*d5c9a868SElliott Hughes 	arg.mp.callback = createDirCallback;
195*d5c9a868SElliott Hughes 	arg.mp.lookupflags = OPEN_PARENT | DO_OPEN_DIRS;
196*d5c9a868SElliott Hughes 	exit(main_loop(&arg.mp, argv + optind, argc - optind));
197*d5c9a868SElliott Hughes }
198