mmove.c

Go to the documentation of this file.
00001 /*
00002  * mmove.c
00003  * Renames/moves an MSDOS file
00004  *
00005  */
00006 
00007 
00008 #define LOWERCASE
00009 
00010 #include "sysincludes.h"
00011 #include "msdos.h"
00012 #include "mtools.h"
00013 #include "vfat.h"
00014 #include "mainloop.h"
00015 #include "plain_io.h"
00016 #include "nameclash.h"
00017 #include "file.h"
00018 #include "fs.h"
00019 
00020 /*
00021  * Preserve the file modification times after the fclose()
00022  */
00023 
00024 typedef struct Arg_t {
00025         const char *fromname;
00026         int verbose;
00027         MainParam_t mp;
00028 
00029         direntry_t *entry;
00030         ClashHandling_t ch;
00031 } Arg_t;
00032 
00033 
00034 /*
00035  * Open the named file for read, create the cluster chain, return the
00036  * directory structure or NULL on error.
00037  */
00038 int renameit(char *dosname,
00039              char *longname,
00040              void *arg0,
00041              direntry_t *targetEntry)
00042 {
00043         Arg_t *arg = (Arg_t *) arg0;
00044         int fat;
00045 
00046         targetEntry->dir = arg->entry->dir;
00047         strncpy(targetEntry->dir.name, dosname, 8);
00048         strncpy(targetEntry->dir.ext, dosname + 8, 3);
00049 
00050         if(IS_DIR(targetEntry)) {
00051                 direntry_t *movedEntry;
00052 
00053                 /* get old direntry. It is important that we do this
00054                  * on the actual direntry which is stored in the file,
00055                  * and not on a copy, because we will modify it, and the
00056                  * modification should be visible at file 
00057                  * de-allocation time */
00058                 movedEntry = getDirentry(arg->mp.File);
00059                 if(movedEntry->Dir != targetEntry->Dir) {
00060                         /* we are indeed moving it to a new directory */
00061                         direntry_t subEntry;
00062                         Stream_t *oldDir;
00063                         /* we have a directory here. Change its parent link */
00064                         
00065                         initializeDirentry(&subEntry, arg->mp.File);
00066 
00067                         switch(vfat_lookup(&subEntry, "..", 2, ACCEPT_DIR,
00068                                            NULL, NULL)) {
00069                             case -1:
00070                                 fprintf(stderr,
00071                                         " Directory has no parent entry\n");
00072                                 break;
00073                             case -2:
00074                                 return ERROR_ONE;
00075                             case 0:
00076                                 GET_DATA(targetEntry->Dir, 0, 0, 0, &fat);
00077                                 if (fat == fat32RootCluster(targetEntry->Dir)) {
00078                                     fat = 0;
00079                                 }
00080 
00081                                 subEntry.dir.start[1] = (fat >> 8) & 0xff;
00082                                 subEntry.dir.start[0] = fat & 0xff;
00083                                 dir_write(&subEntry);
00084                                 if(arg->verbose){
00085                                         fprintf(stderr,
00086                                                 "Easy, isn't it? I wonder why DOS can't do this.\n");
00087                                 }
00088                                 break;
00089                         }
00090                         
00091                         /* wipe out original entry */                   
00092                         movedEntry->dir.name[0] = DELMARK;
00093                         dir_write(movedEntry);
00094                         
00095                         /* free the old parent, allocate the new one. */
00096                         oldDir = movedEntry->Dir;
00097                         *movedEntry = *targetEntry;
00098                         COPY(targetEntry->Dir);
00099                         FREE(&oldDir);
00100                         return 0;
00101                 }
00102         }
00103 
00104         /* wipe out original entry */
00105         arg->mp.direntry->dir.name[0] = DELMARK;
00106         dir_write(arg->mp.direntry);
00107         return 0;
00108 }
00109 
00110 
00111 
00112 static int rename_file(direntry_t *entry, MainParam_t *mp)
00113 /* rename a messy DOS file to another messy DOS file */
00114 {
00115         int result;
00116         Stream_t *targetDir;
00117         char *shortname;
00118         const char *longname;
00119 
00120         Arg_t * arg = (Arg_t *) (mp->arg);
00121 
00122         arg->entry = entry;
00123         targetDir = mp->targetDir;
00124 
00125         if (targetDir == entry->Dir){
00126                 arg->ch.ignore_entry = -1;
00127                 arg->ch.source = entry->entry;
00128                 arg->ch.source_entry = entry->entry;
00129         } else {
00130                 arg->ch.ignore_entry = -1;
00131                 arg->ch.source = -2;
00132         }
00133 
00134         longname = mpPickTargetName(mp);
00135         shortname = 0;
00136         result = mwrite_one(targetDir, longname, shortname,
00137                             renameit, (void *)arg, &arg->ch);
00138         if(result == 1)
00139                 return GOT_ONE;
00140         else
00141                 return ERROR_ONE;
00142 }
00143 
00144 
00145 static int rename_directory(direntry_t *entry, MainParam_t *mp)
00146 {
00147         int ret;
00148 
00149         /* moves a DOS dir */
00150         if(isSubdirOf(mp->targetDir, mp->File)) {
00151                 fprintf(stderr, "Cannot move directory ");
00152                 fprintPwd(stderr, entry,0);
00153                 fprintf(stderr, " into one of its own subdirectories (");
00154                 fprintPwd(stderr, getDirentry(mp->targetDir),0);
00155                 fprintf(stderr, ")\n");
00156                 return ERROR_ONE;
00157         }
00158 
00159         if(entry->entry == -3) {
00160                 fprintf(stderr, "Cannot move a root directory: ");
00161                 fprintPwd(stderr, entry,0);
00162                 return ERROR_ONE;
00163         }
00164 
00165         ret = rename_file(entry, mp);
00166         if(ret & ERROR_ONE)
00167                 return ret;
00168         
00169         return ret;
00170 }
00171 
00172 static int rename_oldsyntax(direntry_t *entry, MainParam_t *mp)
00173 {
00174         int result;
00175         Stream_t *targetDir;
00176         const char *shortname, *longname;
00177 
00178         Arg_t * arg = (Arg_t *) (mp->arg);
00179         arg->entry = entry;
00180         targetDir = entry->Dir;
00181 
00182         arg->ch.ignore_entry = -1;
00183         arg->ch.source = entry->entry;
00184         arg->ch.source_entry = entry->entry;
00185 
00186 #if 0
00187         if(!strcasecmp(mp->shortname, arg->fromname)){
00188                 longname = mp->longname;
00189                 shortname = mp->targetName;
00190         } else {
00191 #endif
00192                 longname = mp->targetName;
00193                 shortname = 0;
00194 #if 0
00195         }
00196 #endif
00197         result = mwrite_one(targetDir, longname, shortname,
00198                             renameit, (void *)arg, &arg->ch);
00199         if(result == 1)
00200                 return GOT_ONE;
00201         else
00202                 return ERROR_ONE;
00203 }
00204 
00205 
00206 static void usage(void)
00207 {
00208         fprintf(stderr,
00209                 "Mtools version %s, dated %s\n", mversion, mdate);
00210         fprintf(stderr,
00211                 "Usage: %s [-vo] [-D clash_option] file targetfile\n", progname);
00212         fprintf(stderr,
00213                 "       %s [-vo] [-D clash_option] file [files...] target_directory\n", 
00214                 progname);
00215         fprintf(stderr, "\t-v Verbose\n");
00216         exit(1);
00217 }
00218 
00219 void mmove(int argc, char **argv, int oldsyntax)
00220 {
00221         Arg_t arg;
00222         int c;
00223         char shortname[13];
00224         char longname[VBUFSIZE];
00225         char *def_drive;
00226         int i;
00227 
00228         /* get command line options */
00229 
00230         init_clash_handling(& arg.ch);
00231 
00232         /* get command line options */
00233         arg.verbose = 0;
00234         while ((c = getopt(argc, argv, "vD:o")) != EOF) {
00235                 switch (c) {
00236                         case 'v':       /* dummy option for mcopy */
00237                                 arg.verbose = 1;
00238                                 break;
00239                         case '?':
00240                                 usage();
00241                         case 'o':
00242                                 handle_clash_options(&arg.ch, c);
00243                                 break;
00244                         case 'D':
00245                                 if(handle_clash_options(&arg.ch, *optarg))
00246                                         usage();
00247                                 break;
00248                         default:
00249                                 break;
00250                 }
00251         }
00252 
00253         if (argc - optind < 2)
00254                 usage();
00255 
00256         init_mp(&arg.mp);               
00257         arg.mp.arg = (void *) &arg;
00258         arg.mp.openflags = O_RDWR;
00259 
00260         /* look for a default drive */
00261         def_drive = NULL;
00262         for(i=optind; i<argc; i++)
00263                 if(skip_drive(argv[i]) > argv[i]){
00264                         char *drive = get_drive(argv[i], NULL);
00265                         if(!def_drive)
00266                                 def_drive = drive;
00267                         else if(strcmp(def_drive, drive) != 0){
00268                                 fprintf(stderr,
00269                                         "Cannot move files across different drives\n");
00270                                 exit(1);
00271                         }
00272                 }
00273 
00274         if(def_drive) {
00275                 char mcwd[MAXPATHLEN];
00276 
00277                 strcpy(mcwd, skip_drive(arg.mp.mcwd));
00278                 if(strlen(def_drive) + 1 + strlen(mcwd) + 1 > MAXPATHLEN){
00279                         fprintf(stderr,
00280                                 "Path name to current directory too long\n");
00281                         exit(1);
00282                 }
00283                 strcpy(arg.mp.mcwd, def_drive);
00284                 strcat(arg.mp.mcwd, ":");
00285                 strcat(arg.mp.mcwd, mcwd);
00286         }
00287 
00288         if (oldsyntax && (argc - optind != 2 || strpbrk(":/", argv[argc-1])))
00289                 oldsyntax = 0;
00290 
00291         arg.mp.lookupflags = 
00292           ACCEPT_PLAIN | ACCEPT_DIR | DO_OPEN_DIRS | NO_DOTS | NO_UNIX;
00293 
00294         if (!oldsyntax){
00295                 target_lookup(&arg.mp, argv[argc-1]);
00296                 arg.mp.callback = rename_file;
00297                 arg.mp.dirCallback = rename_directory;
00298         } else {
00299                 /* do not look up the target; it will be the same dir as the
00300                  * source */
00301                 arg.fromname = _basename(skip_drive(argv[optind]));
00302                 arg.mp.targetName = strdup(argv[argc-1]);
00303                 arg.mp.callback = rename_oldsyntax;
00304         }
00305 
00306 
00307         arg.mp.longname = longname;
00308         longname[0]='\0';
00309 
00310         arg.mp.shortname = shortname;
00311         shortname[0]='\0';
00312 
00313         exit(main_loop(&arg.mp, argv + optind, argc - optind - 1));
00314 }

Generated on Fri Apr 14 22:56:56 2006 for minix by  doxygen 1.4.6