/* * careful here - this function can get called recursively, so * we need to be very careful about how much stack we use. * uio is kmalloced for this reason... */ STATIC const char * xfs_vn_get_link( struct dentry *dentry, struct inode *inode, struct delayed_call *done) { char *link; int error = -ENOMEM; if (!dentry) return ERR_PTR(-ECHILD); link = kmalloc(MAXPATHLEN+1, GFP_KERNEL); if (!link) goto out_err; error = xfs_readlink(XFS_I(d_inode(dentry)), link); if (unlikely(error)) goto out_kfree; set_delayed_call(done, kfree_link, link); return link; out_kfree: kfree(link); out_err: return ERR_PTR(error); }
/* * careful here - this function can get called recursively, so * we need to be very careful about how much stack we use. * uio is kmalloced for this reason... */ STATIC void * xfs_vn_follow_link( struct dentry *dentry, struct nameidata *nd) { char *link; int error = -ENOMEM; link = kmalloc(MAXPATHLEN+1, GFP_KERNEL); if (!link) goto out_err; error = -xfs_readlink(XFS_I(dentry->d_inode), link); if (unlikely(error)) goto out_kfree; nd_set_link(nd, link); return NULL; out_kfree: kfree(link); out_err: nd_set_link(nd, ERR_PTR(error)); return NULL; }
STATIC int xfs_readlink_by_handle( xfs_mount_t *mp, void __user *arg, struct inode *parinode) { struct inode *inode; xfs_fsop_handlereq_t hreq; __u32 olen; void *link; int error; if (!capable(CAP_SYS_ADMIN)) return -XFS_ERROR(EPERM); if (copy_from_user(&hreq, arg, sizeof(xfs_fsop_handlereq_t))) return -XFS_ERROR(EFAULT); error = xfs_vget_fsop_handlereq(mp, parinode, &hreq, &inode); if (error) return -error; /* Restrict this handle operation to symlinks only. */ if (!S_ISLNK(inode->i_mode)) { error = -XFS_ERROR(EINVAL); goto out_iput; } if (copy_from_user(&olen, hreq.ohandlen, sizeof(__u32))) { error = -XFS_ERROR(EFAULT); goto out_iput; } link = kmalloc(MAXPATHLEN+1, GFP_KERNEL); if (!link) goto out_iput; error = -xfs_readlink(XFS_I(inode), link); if (error) goto out_kfree; error = do_readlink(hreq.ohandle, olen, link); if (error) goto out_kfree; out_kfree: kfree(link); out_iput: iput(inode); return error; }
int xfs_readlink_by_handle( struct file *parfilp, xfs_fsop_handlereq_t *hreq) { struct dentry *dentry; __u32 olen; void *link; int error; if (!capable(CAP_SYS_ADMIN)) return -EPERM; dentry = xfs_handlereq_to_dentry(parfilp, hreq); if (IS_ERR(dentry)) return PTR_ERR(dentry); /* Restrict this handle operation to symlinks only. */ if (!d_is_symlink(dentry)) { error = -EINVAL; goto out_dput; } if (copy_from_user(&olen, hreq->ohandlen, sizeof(__u32))) { error = -EFAULT; goto out_dput; } link = kmalloc(MAXPATHLEN+1, GFP_KERNEL); if (!link) { error = -ENOMEM; goto out_dput; } error = xfs_readlink(XFS_I(d_inode(dentry)), link); if (error) goto out_kfree; error = readlink_copy(hreq->ohandle, olen, link); if (error) goto out_kfree; out_kfree: kfree(link); out_dput: dput(dentry); return error; }
int cli_ls_xfs_filldir(void *dirents, const char *name, int namelen, off_t offset, uint64_t inumber, unsigned flags) { char dname[256]; char symlink[256]; int r; xfs_inode_t *inode=NULL; struct stat fstats; char mode[]="rwxrwxrwx"; int tests[]={S_IRUSR,S_IWUSR,S_IXUSR,S_IRGRP,S_IWGRP,S_IXGRP,S_IROTH,S_IWOTH,S_IXOTH}; struct filldir_data *data = (struct filldir_data *) dirents; memcpy(dname, name, namelen); dname[namelen] = '\0'; r = libxfs_iget(data->mp, NULL, inumber, 0, &inode, 0); if (r) printf("Panic! %d\n", r); r = xfs_stat(inode, &fstats); if (r) printf("Panic! stats %d\n", r); if (xfs_is_dir(inode)) { printf("d"); } else if (xfs_is_link(inode)) { printf("l"); } else printf("-"); for (r=0; r<9; r++) { if (fstats.st_mode & tests[r]) { printf("%c", mode[r]); } else { printf("-"); } } print_int(fstats.st_uid, 6); print_int(fstats.st_gid, 6); print_int(fstats.st_size, 12); printf(" %s", dname); if (xfs_is_link(inode)) { r = xfs_readlink(inode, symlink, 0, 255, NULL); if (r > 0) { symlink[r] = '\0'; printf("->%s", symlink); } } printf("\n"); libxfs_iput(inode, 0); return 0; }
static int fuse_xfs_readlink(const char *path, char *buf, size_t size) { int r; xfs_inode_t *inode=NULL; log_debug("readlink %s\n", path); r = find_path(current_xfs_mount(), path, &inode); if (r) { return -ENOENT; } r = xfs_readlink(inode, buf, 0, size, NULL); if (r < 0) { return r; } libxfs_iput(inode, 0); return 0; }
/* * careful here - this function can get called recursively, so * we need to be very careful about how much stack we use. * uio is kmalloced for this reason... */ STATIC const char * xfs_vn_follow_link( struct dentry *dentry, void **cookie) { char *link; int error = -ENOMEM; link = kmalloc(MAXPATHLEN+1, GFP_KERNEL); if (!link) goto out_err; error = xfs_readlink(XFS_I(d_inode(dentry)), link); if (unlikely(error)) goto out_kfree; return *cookie = link; out_kfree: kfree(link); out_err: return ERR_PTR(error); }
int main(int argc, char *argv[]) { xfs_mount_t *mp; xfs_inode_t *inode = NULL; xfs_off_t ofs; struct filldir_data filldata; char *progname; char *source_name; int r, fd; char *line; char path[FILENAME_MAX] = "/"; char newpath[FILENAME_MAX] = "/"; char *buffer[BUFSIZE]; off_t offset; if (argc != 2) { printf("Usage: xfs-cli raw_device\n"); return 1; } progname = argv[0]; source_name = argv[1]; mp = mount_xfs(progname, source_name); if (mp == NULL) return 1; while (line == fetchline(mp, path)) { inode = NULL; strip(line, ' '); if (strncmp(line, "cd ", 3) == 0) { if (strcmp(line+3, "..") == 0) { goto_parent(path); } else { strcpy(newpath, path); strcat(newpath, line+3); r = find_path(mp, newpath, &inode); if ((!r) && (xfs_is_dir(inode))) { //TODO: check if it is a directory strcpy(path, newpath); strcat(path, "/"); printf("%s\n", path); } else { if (r) { printf("No such directory\n"); } else { printf("Not a directory\n"); } } } } else if (strcmp(line, "ls") == 0) { r = find_path(mp, path, &inode); if (!r) { //TODO: check if it is a directory ofs=0; filldata.mp = mp; filldata.base = inode; r = xfs_readdir(inode, (void *)&filldata, 102400, &ofs, cli_ls_xfs_filldir); if (r != 0) { printf("Not a directory\n"); } } else { printf("No such directory\n"); } } else if (strncmp(line, "cat ", 4) == 0) { strcpy(newpath, path); strcat(newpath, line+4); r = find_path(mp, newpath, &inode); if (r) printf("File not found\n"); else if (xfs_is_regular(inode)) { //TODO: check if it is a file r = 10; offset = 0; while (r) { r = xfs_readfile(inode, buffer, offset, BUFSIZE, NULL); if (r) { write(1, buffer, r); offset += r; } } } else if (xfs_is_link(inode)) { r = 10; offset = 0; while (r) { r = xfs_readlink(inode, buffer, offset, BUFSIZE, NULL); if (r) { write(1, buffer, r); offset += r; } } } else { printf("Not a regular file\n"); } } else if (strncmp(line, "get ", 4) == 0) { strcpy(newpath, path); strcat(newpath, line+4); r = find_path(mp, newpath, &inode); if ((!r) && (xfs_is_regular(inode))) { //TODO: check if it is a file r = 10; offset = 0; fd = open(line+4, O_WRONLY|O_CREAT, 0660); if (fd < 0) { printf("Failed to open local file\n"); } else { while (r) { r = xfs_readfile(inode, buffer, offset, BUFSIZE, NULL); if (r) { write(fd, buffer, r); offset += r; } } close(fd); printf("Retrieved %ld bytes\n", offset); } } else { if (r) printf("File not found\n"); else printf("Not a regular file\n"); } } else if (strcmp(line, "exit") == 0) { libxfs_umount(mp); return 0; } else if (strcmp(line, "pwd") == 0) { printf("%s\n", path); } else { printf("Unknown command\n"); } free(line); if (inode) { libxfs_iput(inode, 0); } } libxfs_umount(mp); return 0; }