• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*  Copyright 1986-1992 Emmet P. Gray.
2  *  Copyright 1996-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  * mmd.c
19  * Makes an MSDOS directory
20  */
21 
22 
23 #include "sysincludes.h"
24 #include "msdos.h"
25 #include "mtools.h"
26 #include "vfat.h"
27 #include "mainloop.h"
28 #include "plain_io.h"
29 #include "nameclash.h"
30 #include "file.h"
31 #include "fs.h"
32 
33 /*
34  * Preserve the file modification times after the fclose()
35  */
36 
37 typedef struct Arg_t {
38 	char *target;
39 	MainParam_t mp;
40 
41 	Stream_t *SrcDir;
42 	int entry;
43 	ClashHandling_t ch;
44 	Stream_t *targetDir;
45 } Arg_t;
46 
47 
48 typedef struct CreateArg_t {
49 	Stream_t *Dir;
50 	Stream_t *NewDir;
51 	unsigned char attr;
52 	time_t mtime;
53 } CreateArg_t;
54 
55 /*
56  * Open the named file for read, create the cluster chain, return the
57  * directory structure or NULL on error.
58  */
makeit(dos_name_t * dosname,char * longname UNUSEDP,void * arg0,direntry_t * targetEntry)59 static int makeit(dos_name_t *dosname,
60 		  char *longname UNUSEDP,
61 		  void *arg0,
62 		  direntry_t *targetEntry)
63 {
64 	Stream_t *Target;
65 	CreateArg_t *arg = (CreateArg_t *) arg0;
66 	int fat;
67 	direntry_t subEntry;
68 
69 	/* will it fit? At least one cluster must be free */
70 	if (!getfreeMinClusters(targetEntry->Dir, 1))
71 		return -1;
72 
73 	mk_entry(dosname, ATTR_DIR, 1, 0, arg->mtime, &targetEntry->dir);
74 	Target = OpenFileByDirentry(targetEntry);
75 	if(!Target){
76 		fprintf(stderr,"Could not open Target\n");
77 		return -1;
78 	}
79 
80 	/* this allocates the first cluster for our directory */
81 
82 	initializeDirentry(&subEntry, Target);
83 
84 	subEntry.entry = 1;
85 	GET_DATA(targetEntry->Dir, 0, 0, 0, &fat);
86 	if (fat == fat32RootCluster(targetEntry->Dir)) {
87 	    fat = 0;
88 	}
89 	mk_entry_from_base("..      ", ATTR_DIR, fat, 0, arg->mtime, &subEntry.dir);
90 	dir_write(&subEntry);
91 
92 	FLUSH((Stream_t *) Target);
93 	subEntry.entry = 0;
94 	GET_DATA(Target, 0, 0, 0, &fat);
95 	mk_entry_from_base(".       ", ATTR_DIR, fat, 0, arg->mtime, &subEntry.dir);
96 	dir_write(&subEntry);
97 
98 	mk_entry(dosname, ATTR_DIR | arg->attr, fat, 0, arg->mtime,
99 		 &targetEntry->dir);
100 	arg->NewDir = Target;
101 	return 0;
102 }
103 
104 
105 static void usage(int ret) NORETURN;
usage(int ret)106 static void usage(int ret)
107 {
108 	fprintf(stderr,
109 		"Mtools version %s, dated %s\n", mversion, mdate);
110 	fprintf(stderr,
111 		"Usage: %s [-D clash_option] file targetfile\n", progname);
112 	fprintf(stderr,
113 		"       %s [-D clash_option] file [files...] target_directory\n",
114 		progname);
115 	exit(ret);
116 }
117 
createDir(Stream_t * Dir,const char * filename,ClashHandling_t * ch,unsigned char attr,time_t mtime)118 Stream_t *createDir(Stream_t *Dir, const char *filename, ClashHandling_t *ch,
119 					unsigned char attr, time_t mtime)
120 {
121 	CreateArg_t arg;
122 	int ret;
123 
124 	arg.Dir = Dir;
125 	arg.attr = attr;
126 	arg.mtime = mtime;
127 
128 	if (!getfreeMinClusters(Dir, 1))
129 		return NULL;
130 
131 	ret = mwrite_one(Dir, filename, 0, makeit, &arg, ch);
132 	if(ret < 1)
133 		return NULL;
134 	else
135 		return arg.NewDir;
136 }
137 
createDirCallback(direntry_t * entry UNUSEDP,MainParam_t * mp)138 static int createDirCallback(direntry_t *entry UNUSEDP, MainParam_t *mp)
139 {
140 	Stream_t *ret;
141 	time_t now;
142 
143 	ret = createDir(mp->File, mp->targetName, &((Arg_t *)(mp->arg))->ch,
144 					ATTR_DIR, getTimeNow(&now));
145 	if(ret == NULL)
146 		return ERROR_ONE;
147 	else {
148 		FREE(&ret);
149 		return GOT_ONE;
150 	}
151 
152 }
153 
154 void mmd(int argc, char **argv, int type UNUSEDP) NORETURN;
mmd(int argc,char ** argv,int type UNUSEDP)155 void mmd(int argc, char **argv, int type UNUSEDP)
156 {
157 	Arg_t arg;
158 	int c;
159 
160 	/* get command line options */
161 
162 	init_clash_handling(& arg.ch);
163 
164 	/* get command line options */
165 	if(helpFlag(argc, argv))
166 		usage(0);
167 	while ((c = getopt(argc, argv, "i:D:oh")) != EOF) {
168 		switch (c) {
169 			case 'i':
170 				set_cmd_line_image(optarg);
171 				break;
172 			case '?':
173 				usage(1);
174 			case 'o':
175 				handle_clash_options(&arg.ch, (char) c);
176 				break;
177 			case 'D':
178 				if(handle_clash_options(&arg.ch, *optarg))
179 					usage(1);
180 				break;
181 			case 'h':
182 				usage(0);
183 			default:
184 				usage(1);
185 		}
186 	}
187 
188 	if (argc - optind < 1)
189 		usage(1);
190 
191 	init_mp(&arg.mp);
192 	arg.mp.arg = (void *) &arg;
193 	arg.mp.openflags = O_RDWR;
194 	arg.mp.callback = createDirCallback;
195 	arg.mp.lookupflags = OPEN_PARENT | DO_OPEN_DIRS;
196 	exit(main_loop(&arg.mp, argv + optind, argc - optind));
197 }
198