int dir_try_enter(zone_t z, ino_t child, char const *name) { struct direct *dir_entry = alloc_block(); int r = 0; block_t b; int i, l; b = z << zone_shift; for (l = 0; l < zone_per_block; l++, b++) { get_block(b, dir_entry); for (i = 0; i < NR_DIR_ENTRIES(block_size); i++) if (!dir_entry[i].d_ino) break; if(i < NR_DIR_ENTRIES(block_size)) { r = 1; dir_entry[i].d_ino = child; assert(sizeof(dir_entry[i].d_name) == MFS_DIRSIZ); if (verbose && strlen(name) > MFS_DIRSIZ) fprintf(stderr, "File name %s is too long, truncated\n", name); strncpy(dir_entry[i].d_name, name, MFS_DIRSIZ); put_block(b, dir_entry); break; } } free(dir_entry); return r; }
/* * Search a directory for a name and return its * inode number. */ static int search_directory(const char *name, int length, struct open_file *f, ino32_t *inumber_p) { struct file *fp = (struct file *)f->f_fsdata; struct mfs_sblock *fs = fp->f_fs; struct mfs_direct *dp; struct mfs_direct *dbuf; size_t buf_size; int namlen; int rc; fp->f_seekp = 0; while (fp->f_seekp < (off_t)fp->f_di.mdi_size) { rc = buf_read_file(f, (void *)&dbuf, &buf_size); if (rc) return rc; if (buf_size == 0) return EIO; /* XXX we assume, that buf_read_file reads an fs block and * doesn't truncate buffer. Currently i_size in MFS doesn't * the same as size of allocated blocks, it makes buf_read_file * to truncate buf_size. */ if (buf_size < fs->mfs_block_size) buf_size = fs->mfs_block_size; for (dp = dbuf; dp < &dbuf[NR_DIR_ENTRIES(fs)]; dp++) { char *cp; if (fs2h32(dp->mfsd_ino) == (ino32_t) 0) continue; /* Compute the length of the name */ cp = memchr(dp->mfsd_name, '\0', sizeof(dp->mfsd_name)); if (cp == NULL) namlen = sizeof(dp->mfsd_name); else namlen = cp - (dp->mfsd_name); if (namlen == length && !memcmp(name, dp->mfsd_name, length)) { /* found entry */ *inumber_p = fs2h32(dp->mfsd_ino); return 0; } } fp->f_seekp += buf_size; } return ENOENT; }
void sizeup_dir(struct fs_size * fssize) { char *token[MAX_TOKENS], *p; char line[LINE_LEN]; FILE *f; off_t size; int dir_entries = 2; zone_t dir_zones = 0, fzones, indirects; while (1) { get_line(line, token); p = token[0]; if (*p == '$') { dir_zones = (dir_entries / (NR_DIR_ENTRIES(block_size) * zone_per_block)); if(dir_entries % (NR_DIR_ENTRIES(block_size) * zone_per_block)) dir_zones++; if(dir_zones > NR_DZONES) dir_zones++; /* Max single indir */ fssize->zonecount += dir_zones; return; } p = token[1]; fssize->inocount++; dir_entries++; if (*p == 'd') { sizeup_dir(fssize); } else if (*p == 'b' || *p == 'c') { } else if (*p == 's') { fssize->zonecount++; /* Symlink contents is always stored a block */ } else { if ((f = fopen(token[4], "rb")) == NULL) { warn("dynamic sizing: can't open %s", token[4]); } else if (fseek(f, 0, SEEK_END) < 0) { pexit("dynamic size detection failed: seek to end of %s", token[4]); } else if ( (size = ftell(f)) == (off_t)(-1)) { pexit("dynamic size detection failed: can't tell size of %s", token[4]); } else { fclose(f); fzones = roundup(size, zone_size) / zone_size; indirects = 0; /* XXX overflow? fzones is u32, size is potentially 64-bit */ if (fzones > NR_DZONES) indirects++; /* single indirect needed */ if (fzones > nr_indirzones) { /* Each further group of 'indir_per_zone' * needs one supplementary indirect zone: */ indirects += roundup(fzones - nr_indirzones, indir_per_zone) / indir_per_zone; indirects++; /* + double indirect needed!*/ } fssize->zonecount += fzones + indirects; } } } }
void print_fs(void) { int i, j; ino_t k; struct inode *inode2; unsigned short *usbuf; block_t b; struct direct *dir; assert(inodes_per_block * sizeof(*inode2) == block_size); if(!(inode2 = alloc_block())) err(1, "couldn't allocate a block of inodes"); assert(NR_DIR_ENTRIES(block_size)*sizeof(*dir) == block_size); if(!(dir = alloc_block())) err(1, "couldn't allocate a block of directory entries"); usbuf = alloc_block(); get_super_block(usbuf); printf("\nSuperblock: "); for (i = 0; i < 8; i++) printf("%06ho ", usbuf[i]); printf("\n "); for (i = 0; i < 8; i++) printf("%#04hX ", usbuf[i]); printf("\n "); for (i = 8; i < 15; i++) printf("%06ho ", usbuf[i]); printf("\n "); for (i = 8; i < 15; i++) printf("%#04hX ", usbuf[i]); get_block((block_t) INODE_MAP, usbuf); printf("...\nInode map: "); for (i = 0; i < 9; i++) printf("%06ho ", usbuf[i]); get_block((block_t) zone_map, usbuf); printf("...\nZone map: "); for (i = 0; i < 9; i++) printf("%06ho ", usbuf[i]); printf("...\n"); free(usbuf); usbuf = NULL; k = 0; for (b = inode_offset; k < nrinodes; b++) { get_block(b, inode2); for (i = 0; i < inodes_per_block; i++) { k = inodes_per_block * (int) (b - inode_offset) + i + 1; /* Lint but OK */ if (k > nrinodes) break; { if (inode2[i].i_mode != 0) { printf("Inode %3u: mode=", (unsigned)k); printf("%06o", (unsigned)inode2[i].i_mode); printf(" uid=%2d gid=%2d size=", (int)inode2[i].i_uid, (int)inode2[i].i_gid); printf("%6ld", (long)inode2[i].i_size); printf(" zone[0]=%u\n", (unsigned)inode2[i].i_zone[0]); } if ((inode2[i].i_mode & S_IFMT) == S_IFDIR) { /* This is a directory */ get_block(inode2[i].i_zone[0] << zone_shift, dir); for (j = 0; j < NR_DIR_ENTRIES(block_size); j++) if (dir[j].d_ino) printf("\tInode %2u: %s\n", (unsigned)dir[j].d_ino, dir[j].d_name); } } } } if (zone_shift) printf("%d inodes used. %u zones (%u blocks) used.\n", (int)next_inode-1, next_zone, next_zone*zone_per_block); else printf("%d inodes used. %u zones used.\n", (int)next_inode-1, next_zone); free(dir); free(inode2); }