int op_chown (const char *path, uid_t uid, gid_t gid) { int rt; int rc; ino_t ino; struct ufs_vnode *vnode; struct inode *inode; uufsd_t *ufs = current_ufs(); RETURN_IF_RDONLY(ufs); debugf("enter"); debugf("path = %s", path); rt = do_readvnode(ufs, path, &ino, &vnode); if (rt) { debugf("do_readvnode(%s, &ino, &vnode); failed", path); return rt; } inode = vnode2inode(vnode); if (uid != -1) inode->i_gid = gid; if (gid != -1) inode->i_uid = uid; rc=vnode_put(vnode,1); if (rc) { debugf("vnode_put(vnode,1); failed"); return -EIO; } debugf("leave"); return 0; }
int do_killfilebyinode (uufsd_t *ufs, ino_t ino, struct ufs_vnode *vnode) { int rc; debugf("enter"); struct inode *inode = vnode2inode(vnode); inode->i_nlink = 0; if (inode->i_blocks) { ufs_truncate(ufs, vnode, 0); } rc = ufs_free_inode(ufs, vnode, ino, inode->i_mode); if (rc) { debugf("Unable to free inode\n"); return -EIO; } ufs_clear_inode(vnode); rc = ufs_write_inode(ufs, ino, vnode); if (rc) { debugf("ufs_write_inode(ufs, ino, inode); failed"); return -EIO; } debugf("leave"); return 0; }
static int ufs_new_dir_block(uufsd_t *ufs, ino_t dir_ino, struct ufs_vnode *parent, char **block) { struct direct *dir = NULL; int retval; char *buf; int rec_len; struct fs *fs = &ufs->d_fs; int dirsize = DIRBLKSIZ; int blocksize = fragroundup(fs, dirsize); retval = ufs_get_mem(blocksize, &buf); if (retval) return retval; memset(buf, 0, blocksize); dir = (struct direct *) buf; //retval = ufs_set_rec_len(ufs, dirsize, dir); //if (retval) //return retval; if (dir_ino) { /* * Set up entry for '.' */ dir->d_ino = dir_ino; dir->d_namlen = 1; dir->d_name[0] = '.'; dir->d_type = DT_DIR; rec_len = dirsize - UFS_DIR_REC_LEN(1); dir->d_reclen = UFS_DIR_REC_LEN(1); /* * Set up entry for '..' */ dir = (struct direct *) (buf + dir->d_reclen); //retval = ufs_set_rec_len(ufs, rec_len, dir); //if (retval) //return retval; dir->d_ino = vnode2inode(parent)->i_number; dir->d_namlen = 2; dir->d_name[0] = '.'; dir->d_name[1] = '.'; dir->d_type = DT_DIR; dir->d_reclen = rec_len; } *block = buf; return 0; }
static void ufs_clear_inode(struct ufs_vnode *vnode) { struct inode *inode = vnode2inode(vnode); inode->i_size = 0; inode->i_mtime = inode->i_ctime = inode->i_atime = 0; inode->i_blocks = 0; inode->i_effnlink = 0; inode->i_count = 0; inode->i_endoff = 0; inode->i_diroff = 0; inode->i_offset = 0; inode->i_reclen = 0; inode->i_mode = 0; inode->i_nlink = 0; inode->i_flags = 0; inode->i_uid = 0; inode->i_gid = 0; }
int op_chown (const char *path, uid_t uid, gid_t gid) { int rt; errcode_t rc; ext2_ino_t ino; struct ext2_vnode *vnode; struct ext2_inode *inode; ext2_filsys e2fs; FUSE_EXT2_LOCK; e2fs = current_ext2fs(); debugf("enter"); debugf("path = %s", path); rt = do_readvnode(e2fs, path, &ino, &vnode, DONT_OPEN_FILE); if (rt) { debugf("do_readvnode(%s, &ino, &vnode); failed", path); goto err; } inode = vnode2inode(vnode); if (uid != -1) inode->i_gid = gid; if (gid != -1) inode->i_uid = uid; rc=vnode_put(vnode,1); if (rc) { debugf("vnode_put(vnode,1); failed"); rt = -EIO; goto err; } rt = 0; err: debugf("leave"); FUSE_EXT2_UNLOCK; return rt; }
int op_utimens (const char *path, const struct timespec tv[2]) { int rt; errcode_t rc; ext2_ino_t ino; struct ext2_vnode *vnode; struct ext2_inode *inode; ext2_filsys e2fs; FUSE_EXT2_LOCK; e2fs = current_ext2fs(); debugf("enter"); debugf("path = %s", path); rt = do_readvnode(e2fs, path, &ino, &vnode, DONT_OPEN_FILE); if (rt) { debugf("do_readvnode(%s, &ino, &vnode); failed", path); FUSE_EXT2_UNLOCK; return rt; } inode = vnode2inode(vnode); inode->i_atime = tv[0].tv_sec; inode->i_mtime = tv[0].tv_sec; rc=vnode_put(vnode,1); if (rc) { debugf("vnode_put(vnode,1); failed"); FUSE_EXT2_UNLOCK; return -EIO; } debugf("leave"); FUSE_EXT2_UNLOCK; return 0; }
int op_unlink (const char *path) { int rt; errcode_t rc; char *p_path; char *r_path; ext2_ino_t p_ino; struct ext2_inode p_inode; ext2_ino_t r_ino; struct ext2_vnode *r_vnode; struct ext2_inode *r_inode; ext2_filsys e2fs; FUSE_EXT2_LOCK; e2fs = current_ext2fs(); debugf("enter"); debugf("path = %s", path); rt=do_check_split(path, &p_path, &r_path); if (rt != 0) { debugf("do_check_split: failed"); goto err; } debugf("parent: %s, child: %s", p_path, r_path); rt = do_readinode(e2fs, p_path, &p_ino, &p_inode); if (rt) { debugf("do_readinode(%s, &p_ino, &p_inode); failed", p_path); goto err_free_split; } rt = do_readvnode(e2fs, path, &r_ino, &r_vnode, DONT_OPEN_FILE); if (rt) { debugf("do_readvnode(%s, &r_ino, &r_vnode); failed", path); goto err_free_split; } r_inode = vnode2inode(r_vnode); if(LINUX_S_ISDIR(r_inode->i_mode)) { debugf("%s is a directory", path); vnode_put(r_vnode,0); rt = -EISDIR; goto err_free_split; } rc = ext2fs_unlink(e2fs, p_ino, r_path, r_ino, 0); if (rc) { debugf("ext2fs_unlink(e2fs, %d, %s, %d, 0); failed", p_ino, r_path, r_ino); vnode_put(r_vnode,0); rt = -EIO; goto err_free_split; } if (r_inode->i_links_count > 0) { r_inode->i_links_count -= 1; } p_inode.i_ctime = p_inode.i_mtime = e2fs->now ? e2fs->now : time(NULL); rc = ext2fs_write_inode(e2fs, p_ino, &p_inode); if (rc) { debugf("ext2fs_write_inode(e2fs, p_ino, &p_inode); failed"); vnode_put(r_vnode,1); rt = -EIO; goto err_free_split; } r_inode->i_ctime = e2fs->now ? e2fs->now : time(NULL); rc = vnode_put(r_vnode,1); if (rc) { debugf("vnode_put(r_vnode,1); failed"); rt = -EIO; goto err_free_split; } free_split(p_path, r_path); debugf("leave"); FUSE_EXT2_UNLOCK; return 0; err_free_split: free_split(p_path, r_path); err: FUSE_EXT2_UNLOCK; return rt; }
int ufs_dir_iterate(uufsd_t *ufs, ino_t dirino, int (*func)( struct direct *dirent, int n, char *buf, void *priv_data), void *priv_data) { int i, ret = 0; ufs2_daddr_t ndb; ufs2_daddr_t blkno; int blksize = ufs->d_fs.fs_bsize; u_int64_t dir_size; char *dirbuf = NULL; struct ufs_vnode *vnode; vnode = vnode_get(ufs, dirino); if (vnode == NULL) { ret = -ENOMEM; goto out; } dir_size = vnode2inode(vnode)->i_size; dirbuf = malloc(blksize); if (!dirbuf) { ret = -ENOMEM; goto out; } ndb = howmany(dir_size, ufs->d_fs.fs_bsize); int offset, pos = 0; for (i = 0; i < ndb ; i++) { ret = ufs_bmap(ufs, vnode, i, &blkno); if (ret) { ret = -EIO; goto out; } blksize = ufs_inode_io_size(vnode2inode(vnode), pos, 0); if (blkread(ufs, fsbtodb(&ufs->d_fs, blkno), dirbuf, blksize) == -1) { debugf("Unable to read block %d\n",blkno); ret = -EIO; goto out; } offset = 0; while (offset < blksize && pos + offset < dir_size) { struct direct *de = (struct direct *)(dirbuf + offset); /* HACK: Restrict frame for func() operations * to blocks of DIRBLKSIZ bytes */ int blockoff = offset % DIRBLKSIZ; char * dirblock = dirbuf + (offset-blockoff); ret = (*func)(de, blockoff, dirblock, priv_data); if (ret & DIRENT_CHANGED) { if (blkwrite(ufs, fsbtodb(&ufs->d_fs, blkno), dirbuf, blksize) == -1) { debugf("Unable to write block %d\n",blkno); ret = -EIO; goto out; } } if (ret & DIRENT_ABORT) { ret = 0; goto out; } offset += de->d_reclen; } pos += blksize; } out: if (vnode) { vnode_put(vnode, 0); } if (dirbuf) { free(dirbuf); } return ret; }
static int ufs_mkdir(uufsd_t *ufs, ino_t parent, ino_t inum, char *name) { int retval; struct ufs_vnode *parent_vnode = NULL, *vnode = NULL; struct inode *parent_inode, *inode; ino_t ino = inum; ino_t scratch_ino; ufs2_daddr_t blk; char *block = 0; struct fs *fs = &ufs->d_fs; int dirsize = DIRBLKSIZ; int blocksize = fragroundup(fs, dirsize); parent_vnode = vnode_get(ufs, parent); if (!parent_vnode) { return ENOENT; } parent_inode = vnode2inode(parent_vnode); /* * Allocate an inode, if necessary */ if (!ino) { retval = ufs_valloc(parent_vnode, DTTOIF(DT_DIR), &vnode); if (retval) goto cleanup; ino = vnode->inode.i_number; inode = vnode2inode(vnode); } /* * Allocate a data block for the directory */ retval = ufs_block_alloc(ufs, inode, fragroundup(fs, dirsize), &blk); if (retval) goto cleanup; /* * Create a scratch template for the directory */ retval = ufs_new_dir_block(ufs, vnode->inode.i_number, parent_vnode, &block); if (retval) goto cleanup; /* * Get the parent's inode, if necessary if (parent != ino) { parent_vnode = vnode_get(ufs, parent); if (retval) goto cleanup; } else memset(&parent_inode, 0, sizeof(parent_inode)); */ /* * Create the inode structure.... */ inode->i_mode = DT_DIR | (0777); inode->i_uid = inode->i_gid = 0; UFS_DINODE(inode)->di_db[0] = blk; inode->i_nlink = 1; inode->i_size = dirsize; /* * Write out the inode and inode data block */ retval = blkwrite(ufs, fsbtodb(fs, blk), block, blocksize); if (retval == -1) goto cleanup; /* * Link the directory into the filesystem hierarchy */ if (name) { retval = ufs_lookup(ufs, parent, name, strlen(name), &scratch_ino); if (!retval) { retval = EEXIST; name = 0; goto cleanup; } if (retval != ENOENT) goto cleanup; retval = ufs_link(ufs, parent, name, vnode, DTTOIF(DT_DIR)); if (retval) goto cleanup; } /* * Update parent inode's counts */ if (parent != ino) { parent_inode->i_nlink++; } cleanup: if (vnode) vnode_put(vnode, 1); if (parent_vnode) vnode_put(parent_vnode, 1); if (block) ufs_free_mem(&block); return retval; }
int op_mkdir (const char *path, mode_t mode) { int rt; time_t tm; char *p_path; char *r_path; ino_t ino; struct ufs_vnode *vnode; struct ufs_vnode *child_vnode; struct inode *inode; struct fuse_context *ctx; uufsd_t *ufs = current_ufs(); RETURN_IF_RDONLY(ufs); debugf("enter"); debugf("path = %s, mode: 0%o, dir:0%o", path, mode, S_IFDIR); rt=do_check_split(path, &p_path ,&r_path); if (rt != 0) { debugf("do_check(%s); failed", path); return rt; } debugf("parent: %s, child: %s, pathmax: %d", p_path, r_path, PATH_MAX); rt = do_readvnode(ufs, p_path, &ino, &vnode); if (!vnode) { debugf("do_readvnode(%s, &ino, &vnode); failed", p_path); free_split(p_path, r_path); return rt; } debugf("calling ufs_mkdir(ufs, %d, 0, %s);", ino, r_path); rt = ufs_mkdir(ufs, ino, 0, r_path); if (rt) { debugf("ufs_mkdir(ufs, %d, 0, %s); failed (%d)", ino, r_path, rt); free_split(p_path, r_path); return rt; } rt = do_readvnode(ufs, path, &ino, &child_vnode); if (rt) { debugf("do_readvnode(%s, &ino, &child_vnode); failed", path); return -EIO; } tm = ufs->now ? ufs->now : time(NULL); inode = vnode2inode(child_vnode); inode->i_mode = S_IFDIR | mode; inode->i_ctime = inode->i_atime = inode->i_mtime = tm; ctx = fuse_get_context(); if (ctx) { inode->i_uid = ctx->uid; inode->i_gid = ctx->gid; } vnode_put(child_vnode, 1); inode = vnode2inode(vnode); inode->i_ctime = inode->i_mtime = tm; vnode_put(vnode, 1); free_split(p_path, r_path); debugf("leave"); return 0; }
int op_link (const char *source, const char *dest) { int rc; char *p_path; char *r_path; ino_t d_ino, ino; struct ufs_vnode *vnode; struct inode *inode; uufsd_t *ufs = current_ufs(); RETURN_IF_RDONLY(ufs); debugf("source: %s, dest: %s", source, dest); rc = do_check(source); if (rc != 0) { debugf("do_check(%s); failed", source); return rc; } rc = do_check_split(dest, &p_path, &r_path); if (rc != 0) { debugf("do_check(%s); failed", dest); return rc; } debugf("parent: %s, child: %s", p_path, r_path); rc = do_readvnode(ufs, p_path, &d_ino, &vnode); if (rc) { debugf("do_readvnode(%s, &d_ino, &inode); failed", p_path); free_split(p_path, r_path); return rc; } vnode_put(vnode, 0); rc = do_readvnode(ufs, source, &ino, &vnode); if (rc) { debugf("do_readvnode(%s, &d_ino, &inode); failed", source); free_split(p_path, r_path); return rc; } inode = vnode2inode(vnode); rc = ufs_link(ufs, d_ino, r_path, vnode, inode->i_mode); if (rc) { debugf("ufs_link() failed"); vnode_put(vnode, 0); free_split(p_path, r_path); return rc; } inode->i_mtime = inode->i_atime = inode->i_ctime = ufs->now ? ufs->now : time(NULL); rc = vnode_put(vnode, 1); if (rc) { debugf("vnode_put(vnode,1); failed"); free_split(p_path, r_path); return -EIO; } debugf("done"); return 0; }
int op_link (const char *source, const char *dest) { int rc; char *p_path; char *r_path; ext2_ino_t ino; ext2_ino_t d_ino; struct ext2_vnode *vnode; struct ext2_inode *inode; struct ext2_inode d_inode; ext2_filsys e2fs = current_ext2fs(); debugf("source: %s, dest: %s", source, dest); rc = do_check(source); if (rc != 0) { debugf("do_check(%s); failed", source); return rc; } rc = do_check_split(dest, &p_path, &r_path); if (rc != 0) { debugf("do_check(%s); failed", dest); return rc; } debugf("parent: %s, child: %s", p_path, r_path); rc = do_readinode(e2fs, p_path, &d_ino, &d_inode); if (rc) { debugf("do_readinode(%s, &ino, &inode); failed", p_path); free_split(p_path, r_path); return rc; } rc = do_readvnode(e2fs, source, &ino, &vnode); if (rc) { debugf("do_readvnode(%s, &ino, &vnode); failed", source); free_split(p_path, r_path); return rc; } inode = vnode2inode(vnode); do { debugf("calling ext2fs_link(e2fs, %d, %s, %d, %d);", d_ino, r_path, ino, do_modetoext2lag(inode->i_mode)); rc = ext2fs_link(e2fs, d_ino, r_path, ino, do_modetoext2lag(inode->i_mode)); if (rc == EXT2_ET_DIR_NO_SPACE) { debugf("calling ext2fs_expand_dir(e2fs, &d)", d_ino); if (ext2fs_expand_dir(e2fs, d_ino)) { debugf("error while expanding directory %s (%d)", p_path, d_ino); vnode_put(vnode, 0); free_split(p_path, r_path); return -ENOSPC; } } } while (rc == EXT2_ET_DIR_NO_SPACE); if (rc) { debugf("ext2fs_link(e2fs, %d, %s, %d, %d); failed", d_ino, r_path, ino, do_modetoext2lag(inode->i_mode)); vnode_put(vnode, 0); free_split(p_path, r_path); return -EIO; } d_inode.i_mtime = d_inode.i_ctime = inode->i_ctime = e2fs->now ? e2fs->now : time(NULL); inode->i_links_count += 1; rc=vnode_put(vnode,1); if (rc) { debugf("vnode_put(vnode,1); failed"); free_split(p_path, r_path); return -EIO; } rc = ext2fs_write_inode(e2fs, d_ino, &d_inode); if (rc) { debugf("ext2fs_write_inode(e2fs, d_ino, &d_inode); failed"); free_split(p_path, r_path); return -EIO; } debugf("done"); return 0; }
int op_unlink (const char *path) { int rt; char *p_path; char *r_path; ino_t p_ino; struct ufs_vnode *p_vnode; ino_t r_ino; struct ufs_vnode *r_vnode; struct inode *r_inode; struct inode *p_inode; uufsd_t *ufs = current_ufs(); RETURN_IF_RDONLY(ufs); debugf("enter"); debugf("path = %s", path); rt = do_check_split(path, &p_path, &r_path); if (rt != 0) { debugf("do_check_split: failed"); return rt; } debugf("parent: %s, child: %s", p_path, r_path); rt = do_readvnode(ufs, p_path, &p_ino, &p_vnode); if (rt) { debugf("do_readinode(%s, &p_ino, &p_inode); failed", p_path); free_split(p_path, r_path); return rt; } rt = do_readvnode(ufs, path, &r_ino, &r_vnode); if (rt) { debugf("do_readvnode(%s, &r_ino, &r_vnode); failed", path); free_split(p_path, r_path); return rt; } r_inode = vnode2inode(r_vnode); if(S_ISDIR(r_inode->i_mode)) { debugf("%s is a directory", path); vnode_put(r_vnode, 0); free_split(p_path, r_path); return -EISDIR; } rt = ufs_unlink(ufs, p_ino, r_path, r_ino, 0); if (rt) { debugf("ufs_unlink(ufs, %d, %s, %d, 0); failed", p_ino, r_path, r_ino); vnode_put(r_vnode, 0); vnode_put(p_vnode, 0); free_split(p_path, r_path); return -EIO; } if (r_inode->i_nlink > 0) { r_inode->i_nlink -= 1; } p_inode = vnode2inode(p_vnode); p_inode->i_ctime = p_inode->i_mtime = ufs->now ? ufs->now : time(NULL); rt = vnode_put(p_vnode, 1); if (rt) { debugf("ufs_write_inode(ufs, p_ino, &p_inode); failed"); vnode_put(r_vnode,1); free_split(p_path, r_path); return -EIO; } r_inode->i_ctime = ufs->now ? ufs->now : time(NULL); rt = vnode_put(r_vnode, 1); if (rt) { debugf("vnode_put(r_vnode, 1); failed"); free_split(p_path, r_path); return -EIO; } free_split(p_path, r_path); debugf("leave"); return 0; }