void LaosFileSystem::cleanlist() { // * open filename translation table char longname[MAXFILESIZE]; char shortname[SHORTFILESIZE]; char tabletmpname[MAXFILESIZE+SHORTFILESIZE+1]; strcpy (tabletmpname, tablename); tabletmpname[strlen(tabletmpname)-1] = '~'; // make a full copy of the table FILE* fp1 = fopen(tablename, "rb"); if (fp1 == NULL) return; FILE* fp2 = fopen(tabletmpname, "wb"); if (fp2 == NULL) return; while (dirread(longname, shortname, fp1)) dirwrite(longname, shortname, fp2); fclose(fp1); fclose(fp2); fp1 = fopen(tablename, "wb"); if (fp1 == NULL) return; fp2 = fopen(tabletmpname, "rb"); if (fp2 == NULL) return; FILE* fp; while (dirread(longname, shortname, fp2)) { char fullname[MAXFILESIZE+SHORTFILESIZE+1]; sprintf(fullname, "%s%s", pathname, shortname); fp = fopen(fullname, "rb"); if (fp != NULL) { fclose(fp); dirwrite(longname, shortname, fp1); } } fclose(fp1); fclose(fp2); }
void LaosFileSystem::makeshortname(char* shortname, char* name) { char *tmpname = new char[MAXFILESIZE]; strcpy(tmpname, name); removespaces(tmpname); shorten(tmpname, SHORTFILESIZE); char *basename = strtok(tmpname, "."); char *ext_name = strtok(NULL, "."); strtolower(basename); strtolower(ext_name); int cnt = 1; char fullname[MAXFILESIZE+SHORTFILESIZE+2]; FILE *fp = NULL; do { if (fp != NULL) fclose(fp); while ((cnt/10+strlen(basename)+2) > 8) basename[strlen(basename)-1] = 0; if (strlen(ext_name) > 0) { sprintf(shortname, "%s~%d.%s", basename, cnt++, ext_name); } else { sprintf(shortname, "%s~%d", basename, cnt++); } sprintf(fullname, "%s%s", pathname, shortname); fp = fopen(fullname, "rb"); } while (fp!=NULL); FILE *tfp = fopen(tablename, "ab"); dirwrite(name, shortname, tfp); fclose(tfp); delete(tmpname); }
void mkentry(uint16_t inum) { struct dinode rootino; struct direct dentry; uint16_t d; iread(ROOTINODE, &rootino); for (d = 0; d < swizzle32(rootino.i_size)/32; ++d) { dirread(&rootino, d, &dentry); if (dentry.d_ino == 0 && dentry.d_name[0] == '\0') { dentry.d_ino = swizzle16(inum); sprintf(dentry.d_name, "l+f%d", inum); dirwrite(&rootino, d, &dentry); return; } } printf("Sorry... No empty slots in root directory.\n"); }
static int check_dir(uint32_t ino, uint32_t parentino, const char *pathsofar) { struct sfs_inode sfi; struct sfs_dir *direntries; int *sortvector; uint32_t dirsize, ndirentries, maxdirentries, subdircount, i; int ichanged=0, dchanged=0, dotseen=0, dotdotseen=0; diskread(&sfi, ino); swapinode(&sfi); if (remember_dir(ino, pathsofar)) { /* crosslinked dir */ return 1; } bitmap_mark(ino, B_INODE, ino); count_dirs++; if (sfi.sfi_size % sizeof(struct sfs_dir) != 0) { setbadness(EXIT_RECOV); warnx("Directory /%s has illegal size %lu (fixed)", pathsofar, (unsigned long) sfi.sfi_size); sfi.sfi_size = SFS_ROUNDUP(sfi.sfi_size, sizeof(struct sfs_dir)); ichanged = 1; } if (check_inode_blocks(ino, &sfi, 1)) { ichanged = 1; } ndirentries = sfi.sfi_size/sizeof(struct sfs_dir); maxdirentries = SFS_ROUNDUP(ndirentries, SFS_BLOCKSIZE/sizeof(struct sfs_dir)); dirsize = maxdirentries * sizeof(struct sfs_dir); direntries = domalloc(dirsize); sortvector = domalloc(ndirentries * sizeof(int)); dirread(&sfi, direntries, ndirentries); for (i=ndirentries; i<maxdirentries; i++) { direntries[i].sfd_ino = SFS_NOINO; bzero(direntries[i].sfd_name, sizeof(direntries[i].sfd_name)); } for (i=0; i<ndirentries; i++) { if (check_dir_entry(pathsofar, i, &direntries[i])) { dchanged = 1; } sortvector[i] = i; } sortdir(sortvector, direntries, ndirentries); /* don't use ndirentries-1 here in case ndirentries == 0 */ for (i=0; i+1<ndirentries; i++) { struct sfs_dir *d1 = &direntries[sortvector[i]]; struct sfs_dir *d2 = &direntries[sortvector[i+1]]; assert(d1 != d2); if (d1->sfd_ino == SFS_NOINO) { continue; } if (!strcmp(d1->sfd_name, d2->sfd_name)) { if (d1->sfd_ino == d2->sfd_ino) { setbadness(EXIT_RECOV); warnx("Directory /%s: Duplicate entries for " "%s (merged)", pathsofar, d1->sfd_name); d1->sfd_ino = SFS_NOINO; d1->sfd_name[0] = 0; } else { snprintf(d1->sfd_name, sizeof(d1->sfd_name), "FSCK.%lu.%lu", (unsigned long) d1->sfd_ino, (unsigned long) uniquecounter++); setbadness(EXIT_RECOV); warnx("Directory /%s: Duplicate names %s " "(one renamed: %s)", pathsofar, d2->sfd_name, d1->sfd_name); } dchanged = 1; } } for (i=0; i<ndirentries; i++) { if (!strcmp(direntries[i].sfd_name, ".")) { if (direntries[i].sfd_ino != ino) { setbadness(EXIT_RECOV); warnx("Directory /%s: Incorrect `.' entry " "(fixed)", pathsofar); direntries[i].sfd_ino = ino; dchanged = 1; } assert(dotseen==0); /* due to duplicate checking */ dotseen = 1; } else if (!strcmp(direntries[i].sfd_name, "..")) { if (direntries[i].sfd_ino != parentino) { setbadness(EXIT_RECOV); warnx("Directory /%s: Incorrect `..' entry " "(fixed)", pathsofar); direntries[i].sfd_ino = parentino; dchanged = 1; } assert(dotdotseen==0); /* due to duplicate checking */ dotdotseen = 1; } } if (!dotseen) { if (dir_tryadd(direntries, ndirentries, ".", ino)==0) { setbadness(EXIT_RECOV); warnx("Directory /%s: No `.' entry (added)", pathsofar); dchanged = 1; } else if (dir_tryadd(direntries, maxdirentries, ".", ino)==0) { setbadness(EXIT_RECOV); warnx("Directory /%s: No `.' entry (added)", pathsofar); ndirentries++; dchanged = 1; sfi.sfi_size += sizeof(struct sfs_dir); ichanged = 1; } else { setbadness(EXIT_UNRECOV); warnx("Directory /%s: No `.' entry (NOT FIXED)", pathsofar); } } if (!dotdotseen) { if (dir_tryadd(direntries, ndirentries, "..", parentino)==0) { setbadness(EXIT_RECOV); warnx("Directory /%s: No `..' entry (added)", pathsofar); dchanged = 1; } else if (dir_tryadd(direntries, maxdirentries, "..", parentino)==0) { setbadness(EXIT_RECOV); warnx("Directory /%s: No `..' entry (added)", pathsofar); ndirentries++; dchanged = 1; sfi.sfi_size += sizeof(struct sfs_dir); ichanged = 1; } else { setbadness(EXIT_UNRECOV); warnx("Directory /%s: No `..' entry (NOT FIXED)", pathsofar); } } subdircount=0; for (i=0; i<ndirentries; i++) { if (!strcmp(direntries[i].sfd_name, ".")) { /* nothing */ } else if (!strcmp(direntries[i].sfd_name, "..")) { /* nothing */ } else if (direntries[i].sfd_ino == SFS_NOINO) { /* nothing */ } else { char path[strlen(pathsofar)+SFS_NAMELEN+1]; struct sfs_inode subsfi; diskread(&subsfi, direntries[i].sfd_ino); swapinode(&subsfi); snprintf(path, sizeof(path), "%s/%s", pathsofar, direntries[i].sfd_name); switch (subsfi.sfi_type) { case SFS_TYPE_FILE: if (check_inode_blocks(direntries[i].sfd_ino, &subsfi, 0)) { swapinode(&subsfi); diskwrite(&subsfi, direntries[i].sfd_ino); } observe_filelink(direntries[i].sfd_ino); break; case SFS_TYPE_DIR: if (check_dir(direntries[i].sfd_ino, ino, path)) { setbadness(EXIT_RECOV); warnx("Directory /%s: Crosslink to " "other directory (removed)", path); direntries[i].sfd_ino = SFS_NOINO; direntries[i].sfd_name[0] = 0; dchanged = 1; } else { subdircount++; } break; default: setbadness(EXIT_RECOV); warnx("Object /%s: Invalid inode type " "(removed)", path); direntries[i].sfd_ino = SFS_NOINO; direntries[i].sfd_name[0] = 0; dchanged = 1; break; } } } if (sfi.sfi_linkcount != subdircount+2) { setbadness(EXIT_RECOV); warnx("Directory /%s: Link count %lu should be %lu (fixed)", pathsofar, (unsigned long) sfi.sfi_linkcount, (unsigned long) subdircount+2); sfi.sfi_linkcount = subdircount+2; ichanged = 1; } if (dchanged) { dirwrite(&sfi, direntries, ndirentries); } if (ichanged) { swapinode(&sfi); diskwrite(&sfi, ino); } free(direntries); free(sortvector); return 0; }
void ckdir(uint16_t inum, uint16_t pnum, char *name) { struct dinode ino; struct direct dentry; uint16_t j; int c; int nentries; char ename[150]; iread(inum, &ino); if ((swizzle16(ino.i_mode) & F_MASK) != F_DIR) return; ++depth; if (swizzle32(ino.i_size) % 32 != 0) { printf("Directory inode %d has improper length. Fix? ", inum); if (yes()) { ino.i_size = swizzle32(swizzle32(ino.i_size) & ~0x1f); iwrite(inum, &ino); } } nentries = swizzle32(ino.i_size)/32; for (j = 0; j < nentries; ++j) { dirread(&ino, j, &dentry); #if 1 /**HP**/ { int i; for (i = 0; i < 30; ++i) if (dentry.d_name[i] == '\0') break; for ( ; i < 30; ++i) dentry.d_name[i] = '\0'; dirwrite(&ino, j, &dentry); } #endif if (dentry.d_ino == 0) continue; if (swizzle16(dentry.d_ino) < ROOTINODE || swizzle16(dentry.d_ino) >= 8 * swizzle16(superblock.s_isize)) { printf("Directory entry %s%-1.14s has out-of-range inode %u. Zap? ", name, dentry.d_name, swizzle16(dentry.d_ino)); if (yes()) { dentry.d_ino = 0; dentry.d_name[0] = '\0'; dirwrite(&ino, j, &dentry); continue; } } if (dentry.d_ino && linkmap[swizzle16(dentry.d_ino)] == -1) { printf("Directory entry %s%-1.14s points to bogus inode %u. Zap? ", name, dentry.d_name, swizzle16(dentry.d_ino)); if (yes()) { dentry.d_ino = 0; dentry.d_name[0] = '\0'; dirwrite(&ino, j, &dentry); continue; } } ++linkmap[swizzle16(dentry.d_ino)]; for (c = 0; c < 30 && dentry.d_name[c]; ++c) { if (dentry.d_name[c] == '/') { printf("Directory entry %s%-1.30s contains slash. Fix? ", name, dentry.d_name); if (yes()) { dentry.d_name[c] = 'X'; dirwrite(&ino, j, &dentry); } } } if (strncmp(dentry.d_name, ".", 30) == 0 && swizzle16(dentry.d_ino) != inum) { printf("Dot entry %s%-1.30s points to wrong place. Fix? ", name, dentry.d_name); if (yes()) { dentry.d_ino = swizzle16(inum); dirwrite(&ino, j, &dentry); } } if (strncmp(dentry.d_name, "..", 30) == 0 && swizzle16(dentry.d_ino) != pnum) { printf("DotDot entry %s%-1.30s points to wrong place. Fix? ", name, dentry.d_name); if (yes()) { dentry.d_ino = swizzle16(pnum); dirwrite(&ino, j, &dentry); } } if (swizzle16(dentry.d_ino) != pnum && swizzle16(dentry.d_ino) != inum && depth < MAXDEPTH) { strcpy(ename, name); strcat(ename, dentry.d_name); strcat(ename, "/"); ckdir(swizzle16(dentry.d_ino), inum, ename); } } --depth; }