00001
00002
00003
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
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
00036
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
00054
00055
00056
00057
00058 movedEntry = getDirentry(arg->mp.File);
00059 if(movedEntry->Dir != targetEntry->Dir) {
00060
00061 direntry_t subEntry;
00062 Stream_t *oldDir;
00063
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
00092 movedEntry->dir.name[0] = DELMARK;
00093 dir_write(movedEntry);
00094
00095
00096 oldDir = movedEntry->Dir;
00097 *movedEntry = *targetEntry;
00098 COPY(targetEntry->Dir);
00099 FREE(&oldDir);
00100 return 0;
00101 }
00102 }
00103
00104
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
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
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
00229
00230 init_clash_handling(& arg.ch);
00231
00232
00233 arg.verbose = 0;
00234 while ((c = getopt(argc, argv, "vD:o")) != EOF) {
00235 switch (c) {
00236 case 'v':
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
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
00300
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 }