static __inline__ int print_volume_label(Stream_t *Dir, char drive) { Stream_t *Stream = GetFs(Dir); direntry_t entry; DeclareThis(FsPublic_t); char shortname[13]; char longname[VBUFSIZE]; int r; RootDir = OpenRoot(Stream); if(concise) return 0; /* find the volume label */ initializeDirentry(&entry, RootDir); if((r=vfat_lookup(&entry, 0, 0, ACCEPT_LABEL | MATCH_ANY, shortname, longname)) ) { if (r == -2) { /* I/O Error */ return -1; } printf(" Volume in drive %c has no label", drive); } else if (*longname) printf(" Volume in drive %c is %s (abbr=%s)", drive, longname, shortname); else printf(" Volume in drive %c is %s", drive, shortname); if(This->serialized) printf("\n Volume Serial Number is %04lX-%04lX", (This->serial_number >> 16) & 0xffff, This->serial_number & 0xffff); return 0; }
static int del_file(direntry_t *entry, MainParam_t *mp) { char shortname[13]; direntry_t subEntry; Stream_t *SubDir; Arg_t *arg = (Arg_t *) mp->arg; MainParam_t sonmp; int ret; int r; sonmp = *mp; sonmp.arg = mp->arg; r = 0; if (IS_DIR(entry)){ /* a directory */ SubDir = OpenFileByDirentry(entry); initializeDirentry(&subEntry, SubDir); ret = 0; while((r=vfat_lookup(&subEntry, "*", 1, ACCEPT_DIR | ACCEPT_PLAIN, shortname, NULL)) == 0 ){ if(shortname[0] != DELMARK && shortname[0] && shortname[0] != '.' ){ if(arg->deltype != 2){ fprintf(stderr, "Directory "); fprintPwd(stderr, entry,0); fprintf(stderr," non empty\n"); ret = ERROR_ONE; break; } if(got_signal) { ret = ERROR_ONE; break; } ret = del_file(&subEntry, &sonmp); if( ret & ERROR_ONE) break; ret = 0; } } FREE(&SubDir); if (r == -2) return ERROR_ONE; if(ret) return ret; } return del_entry(entry, mp); }
static Stream_t *subDir(Stream_t *parent, const char *filename) { direntry_t entry; initializeDirentry(&entry, parent); switch(vfat_lookup(&entry, filename, -1, ACCEPT_DIR, 0, 0)) { case 0: return OpenFileByDirentry(&entry); case -1: return NULL; default: /* IO Error */ return NULL; } }
/** * Wiped the given entry */ void wipeEntry(direntry_t *entry) { direntry_t longNameEntry; int i; initializeDirentry(&longNameEntry, entry->Dir); for(i=entry->beginSlot; i< entry->endSlot; i++) { int error; longNameEntry.entry=i; dir_read(&longNameEntry, &error); if(error) break; longNameEntry.dir.name[0] = (char) DELMARK; dir_write(&longNameEntry); } entry->dir.name[0] = (char) DELMARK; dir_write(entry); }
/* * Open the named file for read, create the cluster chain, return the * directory structure or NULL on error. */ int makeit(char *dosname, char *longname, void *arg0, direntry_t *targetEntry) { Stream_t *Target; CreateArg_t *arg = (CreateArg_t *) arg0; int fat; direntry_t subEntry; /* will it fit? At least one cluster must be free */ if (!getfreeMinClusters(targetEntry->Dir, 1)) return -1; mk_entry(dosname, ATTR_DIR, 1, 0, arg->mtime, &targetEntry->dir); Target = OpenFileByDirentry(targetEntry); if(!Target){ fprintf(stderr,"Could not open Target\n"); return -1; } /* this allocates the first cluster for our directory */ initializeDirentry(&subEntry, Target); subEntry.entry = 1; GET_DATA(targetEntry->Dir, 0, 0, 0, &fat); if (fat == fat32RootCluster(targetEntry->Dir)) { fat = 0; } mk_entry(".. ", ATTR_DIR, fat, 0, arg->mtime, &subEntry.dir); dir_write(&subEntry); FLUSH((Stream_t *) Target); subEntry.entry = 0; GET_DATA(Target, 0, 0, 0, &fat); mk_entry(". ", ATTR_DIR, fat, 0, arg->mtime, &subEntry.dir); dir_write(&subEntry); mk_entry(dosname, ATTR_DIR | arg->attr, fat, 0, arg->mtime, &targetEntry->dir); arg->NewDir = Target; return 0; }
static int _dos_loop(Stream_t *Dir, MainParam_t *mp, const char *filename) { Stream_t *MyFile=0; direntry_t entry; int ret; int r; ret = 0; r=0; initializeDirentry(&entry, Dir); while(!got_signal && (r=vfat_lookup(&entry, filename, -1, mp->lookupflags, mp->shortname, mp->longname)) == 0 ){ mp->File = NULL; if(!checkForDot(mp->lookupflags,entry.name)) { MyFile = 0; if((mp->lookupflags & DO_OPEN) || (IS_DIR(&entry) && (mp->lookupflags & DO_OPEN_DIRS))) { MyFile = mp->File = OpenFileByDirentry(&entry); } if(got_signal) break; mp->direntry = &entry; if(IS_DIR(&entry)) ret |= mp->dirCallback(&entry,mp); else ret |= mp->callback(&entry, mp); FREE(&MyFile); } if (fat_error(Dir)) ret |= ERROR_ONE; if(mp->fast_quit && (ret & ERROR_ONE)) break; } if (r == -2) return ERROR_ONE; if(got_signal) ret |= ERROR_ONE; return ret; }
void mlabel(int argc, char **argv, int type) { char *newLabel; int verbose, clear, interactive, show; direntry_t entry; int result=0; char longname[VBUFSIZE]; char shortname[45]; ClashHandling_t ch; struct MainParam_t mp; Stream_t *RootDir; int c; int mangled; enum { SER_NONE, SER_RANDOM, SER_SET } set_serial = SER_NONE; long serial = 0; int need_write_boot = 0; int have_boot = 0; char *eptr; union bootsector boot; Stream_t *Fs=0; int r; struct label_blk_t *labelBlock; int isRo=0; int *isRop=NULL; init_clash_handling(&ch); ch.name_converter = label_name; ch.ignore_entry = -2; verbose = 0; clear = 0; show = 0; if(helpFlag(argc, argv)) usage(0); while ((c = getopt(argc, argv, "i:vcsnN:h")) != EOF) { switch (c) { case 'i': set_cmd_line_image(optarg, 0); break; case 'v': verbose = 1; break; case 'c': clear = 1; break; case 's': show = 1; break; case 'n': set_serial = SER_RANDOM; srandom((long)time (0)); serial=random(); break; case 'N': set_serial = SER_SET; serial = strtol(optarg, &eptr, 16); if(*eptr) { fprintf(stderr, "%s not a valid serial number\n", optarg); exit(1); } break; case 'h': usage(0); default: usage(1); } } if (argc - optind != 1 || !argv[optind][0] || argv[optind][1] != ':') usage(1); init_mp(&mp); newLabel = argv[optind]+2; if(strlen(newLabel) > VBUFSIZE) { fprintf(stderr, "Label too long\n"); FREE(&RootDir); exit(1); } interactive = !show && !clear &&!newLabel[0] && (set_serial == SER_NONE); if(!clear && !newLabel[0]) { isRop = &isRo; } RootDir = open_root_dir(argv[optind][0], isRop ? 0 : O_RDWR, isRop); if(isRo) { show = 1; interactive = 0; } if(!RootDir) { fprintf(stderr, "%s: Cannot initialize drive\n", argv[0]); exit(1); } initializeDirentry(&entry, RootDir); r=vfat_lookup(&entry, 0, 0, ACCEPT_LABEL | MATCH_ANY, shortname, longname); if (r == -2) { FREE(&RootDir); exit(1); } if(show || interactive){ if(isNotFound(&entry)) printf(" Volume has no label\n"); else if (*longname) printf(" Volume label is %s (abbr=%s)\n", longname, shortname); else printf(" Volume label is %s\n", shortname); } /* ask for new label */ if(interactive){ newLabel = longname; fprintf(stderr,"Enter the new volume label : "); if(fgets(newLabel, VBUFSIZE, stdin) == NULL) { newLabel[0] = '\0'; fprintf(stderr, "\n"); } if(newLabel[0]) newLabel[strlen(newLabel)-1] = '\0'; } if((!show || newLabel[0]) && !isNotFound(&entry)){ /* if we have a label, wipe it out before putting new one */ if(interactive && newLabel[0] == '\0') if(ask_confirmation("Delete volume label (y/n): ")){ FREE(&RootDir); exit(0); } entry.dir.attr = 0; /* for old mlabel */ wipeEntry(&entry); } if (newLabel[0] != '\0') { ch.ignore_entry = 1; result = mwrite_one(RootDir,newLabel,0,labelit,NULL,&ch) ? 0 : 1; } have_boot = 0; if( (!show || newLabel[0]) || set_serial != SER_NONE) { Fs = GetFs(RootDir); have_boot = (force_read(Fs,boot.characters,0,sizeof(boot)) == sizeof(boot)); } if(WORD_S(fatlen)) { labelBlock = &boot.boot.ext.old.labelBlock; } else { labelBlock = &boot.boot.ext.fat32.labelBlock; } if(!show || newLabel[0]){ dos_name_t dosname; const char *shrtLabel; doscp_t *cp; if(!newLabel[0]) shrtLabel = "NO NAME "; else shrtLabel = newLabel; cp = GET_DOSCONVERT(Fs); label_name(cp, shrtLabel, verbose, &mangled, &dosname); if(have_boot && boot.boot.descr >= 0xf0 && labelBlock->dos4 == 0x29) { strncpy(labelBlock->label, dosname.base, 11); need_write_boot = 1; } } if((set_serial != SER_NONE) & have_boot) { if(have_boot && boot.boot.descr >= 0xf0 && labelBlock->dos4 == 0x29) { set_dword(labelBlock->serial, serial); need_write_boot = 1; } } if(need_write_boot) { force_write(Fs, (char *)&boot, 0, sizeof(boot)); } FREE(&RootDir); exit(result); }
int fatlabel_set_label(const char* device_name, const char* new_label) { if (strlen(new_label) > VBUFSIZE) return -1; /* * 1. Init clash handling */ struct ClashHandling_t ch; init_clash_handling(&ch); ch.name_converter = label_name; ch.ignore_entry = -2; /* * 2. Open root dir */ struct Stream_t* RootDir = fs_init(device_name, O_RDWR); if (RootDir) RootDir = OpenRoot(RootDir); if (!RootDir) { fprintf(stderr, "Opening root dir failed.\n"); return -2; } /* * 3. Init dir entry */ struct direntry_t entry; initializeDirentry(&entry, RootDir); /* * 4. Lookup vfat */ char longname[VBUFSIZE]; char shortname[45]; if (vfat_lookup(&entry, 0, 0, ACCEPT_LABEL | MATCH_ANY, shortname, longname) == -2) { fprintf(stderr, "Looking up vfat failed.\n"); free_stream(&RootDir); return -3; } /* * 5. Wipe existing entry. */ if (!isNotFound(&entry)) { /* if we have a label, wipe it out before putting new one */ entry.dir.attr = 0; /* for old mlabel */ wipeEntry(&entry); } /* * 6. Write new entry */ ch.ignore_entry = 1; /* don't try to write the label if it's empty */ int result = strlen(new_label) ? mwrite_one(RootDir, new_label, labelit, &ch) : 0; /* * 7. Load FAT boot record */ union bootsector boot; struct Stream_t* Fs = GetFs(RootDir); int have_boot = force_read(Fs, boot.characters, 0, sizeof(boot)) == sizeof(boot); struct label_blk_t* labelBlock = WORD_S(fatlen) ? &boot.boot.ext.old.labelBlock : &boot.boot.ext.fat32.labelBlock; /* * 8. Get "dosconvert" struct */ struct dos_name_t dosname; struct doscp_t* cp = GET_DOSCONVERT(Fs); /* * 9. Convert label */ int mangled = 0; label_name(cp, new_label, &mangled, &dosname); /* * 10. Overwrite FAT boot record */ if (have_boot && boot.boot.descr >= 0xf0 && labelBlock->dos4 == 0x29) { strncpy(labelBlock->label, dosname.base, 11); force_write(Fs, (char *)&boot, 0, sizeof(boot)); } free_stream(&RootDir); fs_close(Fs); return result; }
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; }