source: trunk/minix/commands/i386/mtools-3.9.7/mmove.c@ 15

Last change on this file since 15 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 6.6 KB
Line 
1/*
2 * mmove.c
3 * Renames/moves an MSDOS file
4 *
5 */
6
7
8#define LOWERCASE
9
10#include "sysincludes.h"
11#include "msdos.h"
12#include "mtools.h"
13#include "vfat.h"
14#include "mainloop.h"
15#include "plain_io.h"
16#include "nameclash.h"
17#include "file.h"
18#include "fs.h"
19
20/*
21 * Preserve the file modification times after the fclose()
22 */
23
24typedef struct Arg_t {
25 const char *fromname;
26 int verbose;
27 MainParam_t mp;
28
29 direntry_t *entry;
30 ClashHandling_t ch;
31} Arg_t;
32
33
34/*
35 * Open the named file for read, create the cluster chain, return the
36 * directory structure or NULL on error.
37 */
38int renameit(char *dosname,
39 char *longname,
40 void *arg0,
41 direntry_t *targetEntry)
42{
43 Arg_t *arg = (Arg_t *) arg0;
44 int fat;
45
46 targetEntry->dir = arg->entry->dir;
47 strncpy(targetEntry->dir.name, dosname, 8);
48 strncpy(targetEntry->dir.ext, dosname + 8, 3);
49
50 if(IS_DIR(targetEntry)) {
51 direntry_t *movedEntry;
52
53 /* get old direntry. It is important that we do this
54 * on the actual direntry which is stored in the file,
55 * and not on a copy, because we will modify it, and the
56 * modification should be visible at file
57 * de-allocation time */
58 movedEntry = getDirentry(arg->mp.File);
59 if(movedEntry->Dir != targetEntry->Dir) {
60 /* we are indeed moving it to a new directory */
61 direntry_t subEntry;
62 Stream_t *oldDir;
63 /* we have a directory here. Change its parent link */
64
65 initializeDirentry(&subEntry, arg->mp.File);
66
67 switch(vfat_lookup(&subEntry, "..", 2, ACCEPT_DIR,
68 NULL, NULL)) {
69 case -1:
70 fprintf(stderr,
71 " Directory has no parent entry\n");
72 break;
73 case -2:
74 return ERROR_ONE;
75 case 0:
76 GET_DATA(targetEntry->Dir, 0, 0, 0, &fat);
77 if (fat == fat32RootCluster(targetEntry->Dir)) {
78 fat = 0;
79 }
80
81 subEntry.dir.start[1] = (fat >> 8) & 0xff;
82 subEntry.dir.start[0] = fat & 0xff;
83 dir_write(&subEntry);
84 if(arg->verbose){
85 fprintf(stderr,
86 "Easy, isn't it? I wonder why DOS can't do this.\n");
87 }
88 break;
89 }
90
91 /* wipe out original entry */
92 movedEntry->dir.name[0] = DELMARK;
93 dir_write(movedEntry);
94
95 /* free the old parent, allocate the new one. */
96 oldDir = movedEntry->Dir;
97 *movedEntry = *targetEntry;
98 COPY(targetEntry->Dir);
99 FREE(&oldDir);
100 return 0;
101 }
102 }
103
104 /* wipe out original entry */
105 arg->mp.direntry->dir.name[0] = DELMARK;
106 dir_write(arg->mp.direntry);
107 return 0;
108}
109
110
111
112static int rename_file(direntry_t *entry, MainParam_t *mp)
113/* rename a messy DOS file to another messy DOS file */
114{
115 int result;
116 Stream_t *targetDir;
117 char *shortname;
118 const char *longname;
119
120 Arg_t * arg = (Arg_t *) (mp->arg);
121
122 arg->entry = entry;
123 targetDir = mp->targetDir;
124
125 if (targetDir == entry->Dir){
126 arg->ch.ignore_entry = -1;
127 arg->ch.source = entry->entry;
128 arg->ch.source_entry = entry->entry;
129 } else {
130 arg->ch.ignore_entry = -1;
131 arg->ch.source = -2;
132 }
133
134 longname = mpPickTargetName(mp);
135 shortname = 0;
136 result = mwrite_one(targetDir, longname, shortname,
137 renameit, (void *)arg, &arg->ch);
138 if(result == 1)
139 return GOT_ONE;
140 else
141 return ERROR_ONE;
142}
143
144
145static int rename_directory(direntry_t *entry, MainParam_t *mp)
146{
147 int ret;
148
149 /* moves a DOS dir */
150 if(isSubdirOf(mp->targetDir, mp->File)) {
151 fprintf(stderr, "Cannot move directory ");
152 fprintPwd(stderr, entry,0);
153 fprintf(stderr, " into one of its own subdirectories (");
154 fprintPwd(stderr, getDirentry(mp->targetDir),0);
155 fprintf(stderr, ")\n");
156 return ERROR_ONE;
157 }
158
159 if(entry->entry == -3) {
160 fprintf(stderr, "Cannot move a root directory: ");
161 fprintPwd(stderr, entry,0);
162 return ERROR_ONE;
163 }
164
165 ret = rename_file(entry, mp);
166 if(ret & ERROR_ONE)
167 return ret;
168
169 return ret;
170}
171
172static int rename_oldsyntax(direntry_t *entry, MainParam_t *mp)
173{
174 int result;
175 Stream_t *targetDir;
176 const char *shortname, *longname;
177
178 Arg_t * arg = (Arg_t *) (mp->arg);
179 arg->entry = entry;
180 targetDir = entry->Dir;
181
182 arg->ch.ignore_entry = -1;
183 arg->ch.source = entry->entry;
184 arg->ch.source_entry = entry->entry;
185
186#if 0
187 if(!strcasecmp(mp->shortname, arg->fromname)){
188 longname = mp->longname;
189 shortname = mp->targetName;
190 } else {
191#endif
192 longname = mp->targetName;
193 shortname = 0;
194#if 0
195 }
196#endif
197 result = mwrite_one(targetDir, longname, shortname,
198 renameit, (void *)arg, &arg->ch);
199 if(result == 1)
200 return GOT_ONE;
201 else
202 return ERROR_ONE;
203}
204
205
206static void usage(void)
207{
208 fprintf(stderr,
209 "Mtools version %s, dated %s\n", mversion, mdate);
210 fprintf(stderr,
211 "Usage: %s [-vo] [-D clash_option] file targetfile\n", progname);
212 fprintf(stderr,
213 " %s [-vo] [-D clash_option] file [files...] target_directory\n",
214 progname);
215 fprintf(stderr, "\t-v Verbose\n");
216 exit(1);
217}
218
219void mmove(int argc, char **argv, int oldsyntax)
220{
221 Arg_t arg;
222 int c;
223 char shortname[13];
224 char longname[VBUFSIZE];
225 char *def_drive;
226 int i;
227
228 /* get command line options */
229
230 init_clash_handling(& arg.ch);
231
232 /* get command line options */
233 arg.verbose = 0;
234 while ((c = getopt(argc, argv, "vD:o")) != EOF) {
235 switch (c) {
236 case 'v': /* dummy option for mcopy */
237 arg.verbose = 1;
238 break;
239 case '?':
240 usage();
241 case 'o':
242 handle_clash_options(&arg.ch, c);
243 break;
244 case 'D':
245 if(handle_clash_options(&arg.ch, *optarg))
246 usage();
247 break;
248 default:
249 break;
250 }
251 }
252
253 if (argc - optind < 2)
254 usage();
255
256 init_mp(&arg.mp);
257 arg.mp.arg = (void *) &arg;
258 arg.mp.openflags = O_RDWR;
259
260 /* look for a default drive */
261 def_drive = NULL;
262 for(i=optind; i<argc; i++)
263 if(skip_drive(argv[i]) > argv[i]){
264 char *drive = get_drive(argv[i], NULL);
265 if(!def_drive)
266 def_drive = drive;
267 else if(strcmp(def_drive, drive) != 0){
268 fprintf(stderr,
269 "Cannot move files across different drives\n");
270 exit(1);
271 }
272 }
273
274 if(def_drive) {
275 char mcwd[MAXPATHLEN];
276
277 strcpy(mcwd, skip_drive(arg.mp.mcwd));
278 if(strlen(def_drive) + 1 + strlen(mcwd) + 1 > MAXPATHLEN){
279 fprintf(stderr,
280 "Path name to current directory too long\n");
281 exit(1);
282 }
283 strcpy(arg.mp.mcwd, def_drive);
284 strcat(arg.mp.mcwd, ":");
285 strcat(arg.mp.mcwd, mcwd);
286 }
287
288 if (oldsyntax && (argc - optind != 2 || strpbrk(":/", argv[argc-1])))
289 oldsyntax = 0;
290
291 arg.mp.lookupflags =
292 ACCEPT_PLAIN | ACCEPT_DIR | DO_OPEN_DIRS | NO_DOTS | NO_UNIX;
293
294 if (!oldsyntax){
295 target_lookup(&arg.mp, argv[argc-1]);
296 arg.mp.callback = rename_file;
297 arg.mp.dirCallback = rename_directory;
298 } else {
299 /* do not look up the target; it will be the same dir as the
300 * source */
301 arg.fromname = _basename(skip_drive(argv[optind]));
302 arg.mp.targetName = strdup(argv[argc-1]);
303 arg.mp.callback = rename_oldsyntax;
304 }
305
306
307 arg.mp.longname = longname;
308 longname[0]='\0';
309
310 arg.mp.shortname = shortname;
311 shortname[0]='\0';
312
313 exit(main_loop(&arg.mp, argv + optind, argc - optind - 1));
314}
Note: See TracBrowser for help on using the repository browser.