static int testfs_pwd(struct super_block *sb, struct inode *in) { int p_inode_nr; struct inode *p_in; struct dirent *d; int ret; assert(in); assert(testfs_inode_get_nr(in) >= 0); p_inode_nr = testfs_dir_name_to_inode_nr(in, ".."); assert(p_inode_nr >= 0); if (p_inode_nr == testfs_inode_get_nr(in)) { printf("/"); return 1; } p_in = testfs_get_inode(sb, p_inode_nr); d = testfs_find_dirent(p_in, testfs_inode_get_nr(in)); assert(d); ret = testfs_pwd(sb, p_in); testfs_put_inode(p_in); printf("%s%s", ret == 1 ? "" : "/", D_NAME(d)); free(d); return 0; }
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; }
int cmd_write(struct super_block *sb, struct context *c) { int inode_nr; struct inode *in; int size; int ret = 0; char * filename = c->cmd[1]; char * content = c->cmd[2]; if (c->nargs != 3) { return -EINVAL; } inode_nr = testfs_dir_name_to_inode_nr(c->cur_dir, filename); 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; } size = strlen(content); testfs_tx_start(sb, TX_WRITE); ret = testfs_write_data(in, 0, content, size); if (ret >= 0) { testfs_truncate_data(in, size); } testfs_sync_inode(in); testfs_tx_commit(sb, TX_WRITE); out: testfs_put_inode(in); return ret; }
int main(int argc, char * const argv[]) { struct super_block *sb; char *line = NULL; size_t line_size = 0; ssize_t nr; int ret; struct context c; // context contains command line arguments/parameters, // inode of directory from which cmd was issued, and no of args. struct args * args = parse_arguments(argc, argv); // args->disk contains the name of the disk file. // initializes the in memory structure sb with data that is // read from the disk. after successful execution, we have // sb initialized to dsuper_block read from disk. ret = testfs_init_super_block(args->disk, args->corrupt, &sb); //fslice_clear(); if (ret) { EXIT("testfs_init_super_block"); } /* if the inode does not exist in the inode_hash_map (which is an inmemory map of all inode blocks, create a new inode by allocating memory to it. read the dinode from disk into that memory inode */ c.cur_dir = testfs_get_inode(sb, 0); /* root dir */ for (; PROMPT, (nr = getline(&line, &line_size, stdin)) != EOF;) { char * name; char * args; printf("command: %s\n", line); name = strtok(line, " \t\n"); args = strtok(NULL, "\n"); handle_command(sb, &c, name, args); if (can_quit) { break; } } free(line); // decrement inode count by 1. remove inode from in_memory hash map if // inode count has become 0. testfs_put_inode(c.cur_dir); testfs_close_super_block(sb); return 0; }
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_rm(struct super_block *sb, struct context *c) { int inode_nr; struct inode *in; if (c->nargs != 2) { return -EINVAL; } testfs_tx_start(sb, TX_RM); inode_nr = testfs_remove_dirent(sb, c->cur_dir, c->cmd[1]); if (inode_nr < 0) { testfs_tx_commit(sb, TX_RM); return inode_nr; } in = testfs_get_inode(sb, inode_nr); testfs_remove_inode(in); testfs_sync_inode(c->cur_dir); testfs_tx_commit(sb, TX_RM); return 0; }
int cmd_cd(struct super_block *sb, struct context *c) { int inode_nr; struct inode *dir_inode; if (c->nargs != 2) { return -EINVAL; } inode_nr = testfs_dir_name_to_inode_nr(c->cur_dir, c->cmd[1]); if (inode_nr < 0) return inode_nr; dir_inode = testfs_get_inode(sb, inode_nr); if (testfs_inode_get_type(dir_inode) != I_DIR) { testfs_put_inode(dir_inode); return -ENOTDIR; } testfs_put_inode(c->cur_dir); c->cur_dir = dir_inode; return 0; }
/* returns negative value if name within dir is not empty */ static int testfs_remove_dirent_allowed(struct super_block *sb, int inode_nr) { struct inode *dir; int offset = 0; struct dirent *d; int ret = 0; dir = testfs_get_inode(sb, inode_nr); if (testfs_inode_get_type(dir) != I_DIR) goto out; for (; ret == 0 && (d = testfs_next_dirent(dir, &offset)); free(d)) { if ((d->d_inode_nr < 0) || (strcmp(D_NAME(d), ".") == 0) || (strcmp(D_NAME(d), "..") == 0)) continue; ret = -ENOTEMPTY; } out: testfs_put_inode(dir); return ret; }
int cmd_lsr(struct super_block *sb, struct context *c) { int inode_nr; struct inode *in; char *cdir = "."; if (c->nargs != 1 && c->nargs != 2) { return -EINVAL; } if (c->nargs == 2) { cdir = c->cmd[1]; } assert(c->cur_dir); inode_nr = testfs_dir_name_to_inode_nr(c->cur_dir, cdir); if (inode_nr < 0) return inode_nr; in = testfs_get_inode(sb, inode_nr); testfs_ls(in, 1); testfs_put_inode(in); return 0; }
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; }
static int testfs_ls(struct inode *in, int recursive) { int offset = 0; struct dirent *d; for (; (d = testfs_next_dirent(in, &offset)); free(d)) { struct inode *cin; if (d->d_inode_nr < 0) continue; cin = testfs_get_inode(testfs_inode_get_sb(in), d->d_inode_nr); printf("%s%s\n", D_NAME(d), (testfs_inode_get_type(cin) == I_DIR) ? "/":""); if (recursive && testfs_inode_get_type(cin) == I_DIR && (strcmp(D_NAME(d), ".") != 0) && (strcmp(D_NAME(d), "..") != 0)) { testfs_ls(cin, recursive); } testfs_put_inode(cin); } return 0; }