/* return 0 on success. * return negative value on error. */ static int testfs_add_dirent(struct inode *dir, char *name, int inode_nr) { struct dirent *d; int p_offset = 0, offset = 0; int found = 0; int ret = 0; int len = strlen(name) + 1; fslice_name(name, len); assert(dir); assert(testfs_inode_get_type(dir) == I_DIR); assert(name); for (; ret == 0 && found == 0; free(d)) { p_offset = offset; if ((d = testfs_next_dirent(dir, &offset)) == NULL) break; if ((d->d_inode_nr >= 0) && (strcmp(D_NAME(d), name) == 0)) { ret = -EEXIST; continue; } if ((d->d_inode_nr >= 0) || (d->d_name_len != len)) continue; found = 1; } if (ret < 0) return ret; assert(found || (p_offset == testfs_inode_get_size(dir))); return testfs_write_dirent(dir, name, len, inode_nr, p_offset); }
static int testfs_checkfs(struct super_block *sb, struct bitmap *i_freemap, struct bitmap *b_freemap, int inode_nr) { struct inode *in = testfs_get_inode(sb, inode_nr); int size; int size_roundup = ROUNDUP(testfs_inode_get_size(in), BLOCK_SIZE); assert((testfs_inode_get_type(in) == I_FILE) || (testfs_inode_get_type(in) == I_DIR)); /* inode processing */ bitmap_mark(i_freemap, inode_nr); if (testfs_inode_get_type(in) == I_DIR) { int offset = 0; struct dirent *d; for (; (d = testfs_next_dirent(in, &offset)); free(d)) { if ((d->d_inode_nr < 0) || (strcmp(D_NAME(d), ".") == 0) || (strcmp(D_NAME(d), "..") == 0)) continue; testfs_checkfs(sb, i_freemap, b_freemap, d->d_inode_nr); } } /* block processing */ size = testfs_check_inode(sb, b_freemap, in); assert(size == size_roundup); testfs_put_inode(in); return 0; }
/* allocates memory, caller should free */ struct dirent * testfs_next_dirent(struct inode *dir, int *offset) { int ret; struct dirent d, *dp; assert(dir); assert(testfs_inode_get_type(dir) == I_DIR); if (*offset >= testfs_inode_get_size(dir)) return NULL; ret = testfs_read_data(dir, *offset, (char *)&d, sizeof(struct dirent)); if (ret < 0) return NULL; assert(d.d_name_len > 0); dp = malloc(sizeof(struct dirent) + d.d_name_len); if (!dp) return NULL; *dp = d; *offset += sizeof(struct dirent); ret = testfs_read_data(dir, *offset, D_NAME(dp), d.d_name_len); if (ret < 0) { free(dp); return NULL; } *offset += d.d_name_len; return dp; }
int cmd_cat(struct super_block *sb, struct context *c) { char *buf; int inode_nr; struct inode *in; int ret = 0; int sz; int i; if (c->nargs < 2) { return -EINVAL; } for (i = 1; ret == 0 && i < c->nargs; i++ ) { inode_nr = testfs_dir_name_to_inode_nr(c->cur_dir, c->cmd[i]); if (inode_nr < 0) return inode_nr; in = testfs_get_inode(sb, inode_nr); if (testfs_inode_get_type(in) == I_DIR) { ret = -EISDIR; goto out; } sz = testfs_inode_get_size(in); if (sz > 0) { buf = malloc(sz + 1); if (!buf) { ret = -ENOMEM; goto out; } testfs_read_data(in, 0, buf, sz); buf[sz] = 0; printf("%s\n", buf); free(buf); } out: testfs_put_inode(in); } return ret; }
int cmd_stat(struct super_block *sb, struct context *c) { int inode_nr; struct inode *in; int i; if (c->nargs < 2) { return -EINVAL; } for (i = 1; i < c->nargs; i++ ) { inode_nr = testfs_dir_name_to_inode_nr(c->cur_dir, c->cmd[i]); if (inode_nr < 0) return inode_nr; in = testfs_get_inode(sb, inode_nr); printf("%s: i_nr = %d, i_type = %d, i_size = %d\n", c->cmd[i], testfs_inode_get_nr(in), testfs_inode_get_type(in), testfs_inode_get_size(in)); testfs_put_inode(in); } return 0; }