int isSubdirOf(Stream_t *inside, Stream_t *outside) { while(1) { if(inside == outside) /* both are the same */ return 1; if(getDirentry(inside)->entry == -3) /* root directory */ return 0; /* look further up */ inside = getDirentry(inside)->Dir; } }
static int getPathLen(direntry_t *entry) { int length=0; while(1) { if(entry->entry == -3) /* rootDir */ return strlen(getDrive(entry->Dir)) + 1 + length + 1; length += 1 + strlen(entry->name); entry = getDirentry(entry->Dir); } }
static char *sprintPwd(direntry_t *entry, char *ptr) { if(entry->entry == -3) { strcpy(ptr, getDrive(entry->Dir)); strcat(ptr, ":/"); ptr = strchr(ptr, 0); } else { ptr = sprintPwd(getDirentry(entry->Dir), ptr); if(ptr[-1] != '/') *ptr++ = '/'; strcpy(ptr, entry->name); ptr += strlen(entry->name); } return ptr; }
static void _fprintPwd(FILE *f, direntry_t *entry, int recurs, int escape) { if(entry->entry == -3) { fputs(getDrive(entry->Dir), f); putc(':', f); if(!recurs) putc('/', f); } else { _fprintPwd(f, getDirentry(entry->Dir), 1, escape); if (escape && strpbrk(entry->name, NEED_ESCAPE)) { char *ptr; for(ptr = entry->name; *ptr; ptr++) { if (strchr(NEED_ESCAPE, *ptr)) putc('\\', f); putc(*ptr, f); } } else { fprintf(f, "/%s", entry->name); } } }
static int enterDirectory(Stream_t *Dir) { int r; char drive; if(currentDir == Dir) return 0; /* still the same directory */ leaveDirectory(0); drive = getDrive(Dir); r=enterDrive(Dir, drive); if(r) return r; currentDir = COPY(Dir); dynDirPath = getPwd(getDirentry(Dir)); if(!dynDirPath) dirPath=emptyString; else { if(!dynDirPath[3] && concise) dynDirPath[2]='\0'; dirPath=dynDirPath; } /* print directory title */ if(!concise) printf("\nDirectory for %s\n", dirPath); if(!wide && !concise) printf("\n"); dirsOnDrive++; bytesInDir = 0; filesInDir = 0; return 0; }
static int enterDirectory(Stream_t *Dir) { int r; char *drive; char *slash; if(currentDir == Dir) return 0; /* still the same directory */ leaveDirectory(0); drive = getDrive(Dir); r=enterDrive(Dir, drive); if(r) return r; currentDir = COPY(Dir); dirPath = getPwd(getDirentry(Dir)); if(!dirPath) dirPath=emptyString; if(concise && (slash = strrchr(dirPath, '/')) != NULL && slash[1] == '\0') *slash = '\0'; /* print directory title */ if(!concise) printf("\nDirectory for %s\n", dirPath); if(!wide && !concise) printf("\n"); dirsOnDrive++; bytesInDir = 0; filesInDir = 0; return 0; }
static int dos_copydir(direntry_t *entry, MainParam_t *mp) /* copyes a directory to Dos */ { Arg_t * arg = (Arg_t *) (mp->arg); Arg_t newArg; time_t now; time_t date; int ret; const char *targetName = mpPickTargetName(mp); if (!arg->recursive && mp->basenameHasWildcard) return 0; if(entry && isSubdirOf(mp->targetDir, mp->File)) { fprintf(stderr, "Cannot recursively copy directory "); fprintPwd(stderr, entry,0); fprintf(stderr, " into one of its own subdirectories "); fprintPwd(stderr, getDirentry(mp->targetDir),0); fprintf(stderr, "\n"); return ERROR_ONE; } if (arg->mp.File->Class->get_data(arg->mp.File, & date, 0, 0, 0) < 0 ){ fprintf(stderr, "Can't stat source file\n"); return ERROR_ONE; } if(!arg->type && arg->verbose) fprintf(stderr,"Copying %s\n", mpGetBasename(mp)); if(entry && arg->preserveAttributes) arg->attr = entry->dir.attr; else arg->attr = 0; if (entry && (mp->targetDir == entry->Dir)){ arg->ch.ignore_entry = -1; arg->ch.source = entry->entry; } else { arg->ch.ignore_entry = -1; arg->ch.source = -2; } /* preserve mod time? */ if (arg->preserveTime) now = date; else getTimeNow(&now); newArg = *arg; newArg.mp.arg = &newArg; newArg.mp.targetName = 0; newArg.mp.basenameHasWildcard = 1; if(*targetName) { /* maybe the directory already exist. Use it */ newArg.mp.targetDir = subDir(mp->targetDir, targetName); if(!newArg.mp.targetDir) newArg.mp.targetDir = createDir(mp->targetDir, targetName, &arg->ch, arg->attr, now); } else newArg.mp.targetDir = mp->targetDir; if(!newArg.mp.targetDir) return ERROR_ONE; ret = mp->loop(mp->File, &newArg.mp, "*"); if(*targetName) FREE(&newArg.mp.targetDir); return ret | GOT_ONE; }
direntry_t *getParent(direntry_t *entry) { return getDirentry(entry->Dir); }
static int recurs_dos_loop(MainParam_t *mp, const char *filename0, const char *filename1, lookupState_t *lookupState) { /* Dir is de-allocated by the same entity which allocated it */ const char *ptr; direntry_t entry; int length; int lookupflags; int ret; int have_one; int doing_mcwd; int r; while(1) { /* strip dots and // */ if(!strncmp(filename0,"./", 2)) { filename0 += 2; continue; } if(!strcmp(filename0,".") && filename1) { filename0 ++; continue; } if(filename0[0] == '/') { filename0++; continue; } if(!filename0[0]) { if(!filename1) break; filename0 = filename1; filename1 = 0; continue; } break; } if(!strncmp(filename0,"../", 3) || (!strcmp(filename0, "..") && filename1)) { /* up one level */ mp->File = getDirentry(mp->File)->Dir; return recurs_dos_loop(mp, filename0+2, filename1, lookupState); } doing_mcwd = !!filename1; ptr = strchr(filename0, '/'); if(!ptr) { length = strlen(filename0); ptr = filename1; filename1 = 0; } else { length = ptr - filename0; ptr++; } if(!ptr) { if(mp->lookupflags & OPEN_PARENT) { mp->targetName = filename0; ret = handle_leaf(getDirentry(mp->File), mp, lookupState); mp->targetName = 0; return ret; } if(!strcmp(filename0, ".") || !filename0[0]) { return handle_leaf(getDirentry(mp->File), mp, lookupState); } if(!strcmp(filename0, "..")) { return handle_leaf(getParent(getDirentry(mp->File)), mp, lookupState); } lookupflags = mp->lookupflags; if(lookupState) { lookupState->filename = filename0; if(lookupState->nbContainers + lookupState->nbDirs > 0){ /* we have already one target, don't bother * with this one. */ FREE(&lookupState->container); } else { /* no match yet. Remember this container for * later use */ lookupState->container = COPY(mp->File); } lookupState->nbContainers++; } } else lookupflags = ACCEPT_DIR | DO_OPEN | NO_DOTS; ret = 0; r = 0; have_one = 0; initializeDirentry(&entry, mp->File); while(!(ret & STOP_NOW) && !got_signal && (r=vfat_lookup(&entry, filename0, length, lookupflags | NO_MSG, mp->shortname, mp->longname)) == 0 ){ if(checkForDot(lookupflags, entry.name)) /* while following the path, ignore the * special entries if they were not * explicitly given */ continue; have_one = 1; if(ptr) { Stream_t *SubDir; SubDir = mp->File = OpenFileByDirentry(&entry); ret |= recurs_dos_loop(mp, ptr, filename1, lookupState); FREE(&SubDir); } else { ret |= handle_leaf(&entry, mp, lookupState); if(isUniqueTarget(mp->targetName)) return ret | STOP_NOW; } if(doing_mcwd) break; } if (r == -2) return ERROR_ONE; if(got_signal) return ret | ERROR_ONE; if(doing_mcwd & !have_one) return NO_CWD; return ret; }