int find_path(xfs_mount_t *mp, const char *path, xfs_inode_t **result) { xfs_inode_t *current; xfs_ino_t inode; struct xfs_name xname; int error; error = libxfs_iget(mp, NULL, mp->m_sb.sb_rootino, 0, ¤t, 0); assert(error==0); xname = first_name(path); while (xname.len != 0) { if (!(current->i_d.di_mode & S_IFDIR)) { libxfs_iput(current, 0); return XFS_ERROR(ENOTDIR); } error = libxfs_dir_lookup(NULL, current, &xname, &inode, NULL); if (error != 0) { return error; } /* Done with current: make it available */ libxfs_iput(current, 0); error = libxfs_iget(mp, NULL, inode, 0, ¤t, 0); if (error != 0) { printf("Failed to get inode for %s %d\n", xname.name, xname.len); return XFS_ERROR(EIO); } xname = next_name(xname); } *result = current; return 0; }
int copy_filldir(void *dirents, const char *name, int namelen, off_t offset, uint64_t inumber, unsigned flags) { char dname[256]; char lname[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; strcpy(dname, data->base); strcat(dname, "/"); strncat(dname, name, namelen); strcpy(lname, data->local); strcat(lname, "/"); strncat(lname, name, namelen); 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("-"); } } printf(" %s -> %s\n", dname, lname); if (strncmp(name, ".", namelen) == 0) libxfs_iput(inode, 0); else if (strncmp(name, "..", namelen) == 0) libxfs_iput(inode, 0); else { copy_tree(data->mp, dname, lname, inode); libxfs_iput(inode, 0); } return 0; }
int main(int argc, char *argv[]) { xfs_mount_t *mp; xfs_inode_t *inode = NULL; char *progname; char *source_name; char *parent; int r; if (argc != 3) { printf("Usage: xfs-rcopy raw_device directory\n"); printf("Copies the named directory from an XFS file system to the current directory\n"); return 1; } progname = argv[0]; source_name = argv[1]; parent = argv[2]; mp = mount_xfs(progname, source_name); if (mp == NULL) return 1; r = find_path(mp, parent, &inode); if (r) { printf("Can't find %s\n", parent); libxfs_umount(mp); return 1; } copy_tree(mp, parent, last(parent), inode); libxfs_iput(inode, 0); libxfs_umount(mp); return 0; }
int fuse_xfs_opendir(const char *path, struct fuse_file_info *fi) { int r; xfs_inode_t *inode=NULL; log_debug("opendir %s\n", path); r = find_path(current_xfs_mount(), path, &inode); if (r) { return -ENOENT; } libxfs_iput(inode, 0); return 0; }
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_readdir(const char *path, void *buf, //fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi) { log_debug("readdir %s\n", path); int r; struct filler_info_struct filler_info; xfs_inode_t *inode=NULL; r = find_path(current_xfs_mount(), path, &inode); if (r) { return -ENOENT; } filler_info.buf = buf; //filler_info.filler = filler; xfs_readdir(inode, (void *)&filler_info, 1024000, &offset, fuse_xfs_filldir); 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; }
char *fetchline(xfs_mount_t *mp, char *path) { xfs_inode_t *inode; xfs_off_t ofs = 0; char *line; int r; free_completions(); r = find_path(mp, path, &inode); if (r == 0) { r = xfs_readdir(inode, NULL, 102400, &ofs, cli_complete_xfs_filldir); libxfs_iput(inode, 0); } rl_completion_entry_function = (Function *)dir_generator; rl_bind_key('\t', rl_complete); line = readline(get_prompt(path)); if (line && *line) add_history(line); return line; }
int fuse_xfs_filldir(void *filler_info, const char *name, int namelen, off_t offset, uint64_t inumber, unsigned flags) { int r; char dir_entry[256]; xfs_inode_t *inode=NULL; struct stat stbuf; struct stat *stats = NULL; struct filler_info_struct *filler_data = (struct filler_info_struct *) filler_info; memcpy(dir_entry, name, namelen); dir_entry[namelen] = '\0'; if (libxfs_iget(current_xfs_mount(), NULL, inumber, 0, &inode, 0)) { return 0; } if (!xfs_stat(inode, &stbuf)) { stats = &stbuf; } log_debug("Direntry %s\n", dir_entry); r = filler_data->filler(filler_data->buf, dir_entry, stats, 0); libxfs_iput(inode, 0); return r; }
static int fuse_xfs_release(const char *path, struct fuse_file_info *fi) { log_debug("release %s\n", path); libxfs_iput((xfs_inode_t *)fi->fh, 0); return 0; }
static void parseproto( xfs_mount_t *mp, xfs_inode_t *pip, struct fsxattr *fsxp, char **pp, char *name) { #define IF_REGULAR 0 #define IF_RESERVED 1 #define IF_BLOCK 2 #define IF_CHAR 3 #define IF_DIRECTORY 4 #define IF_SYMLINK 5 #define IF_FIFO 6 char *buf; int committed; int error; xfs_fsblock_t first; int flags; xfs_bmap_free_t flist; int fmt; int i; xfs_inode_t *ip; int len; long long llen; int majdev; int mindev; int mode; char *mstr; xfs_trans_t *tp; int val; int isroot = 0; cred_t creds; char *value; struct xfs_name xname; memset(&creds, 0, sizeof(creds)); mstr = getstr(pp); switch (mstr[0]) { case '-': fmt = IF_REGULAR; break; case 'r': fmt = IF_RESERVED; break; case 'b': fmt = IF_BLOCK; break; case 'c': fmt = IF_CHAR; break; case 'd': fmt = IF_DIRECTORY; break; case 'l': fmt = IF_SYMLINK; break; case 'p': fmt = IF_FIFO; break; default: fprintf(stderr, _("%s: bad format string %s\n"), progname, mstr); exit(1); } mode = 0; switch (mstr[1]) { case '-': break; case 'u': mode |= S_ISUID; break; default: fprintf(stderr, _("%s: bad format string %s\n"), progname, mstr); exit(1); } switch (mstr[2]) { case '-': break; case 'g': mode |= S_ISGID; break; default: fprintf(stderr, _("%s: bad format string %s\n"), progname, mstr); exit(1); } val = 0; for (i = 3; i < 6; i++) { if (mstr[i] < '0' || mstr[i] > '7') { fprintf(stderr, _("%s: bad format string %s\n"), progname, mstr); exit(1); } val = val * 8 + mstr[i] - '0'; } mode |= val; creds.cr_uid = (int)getnum(pp); creds.cr_gid = (int)getnum(pp); xname.name = (uchar_t *)name; xname.len = name ? strlen(name) : 0; tp = libxfs_trans_alloc(mp, 0); flags = XFS_ILOG_CORE; xfs_bmap_init(&flist, &first); switch (fmt) { case IF_REGULAR: buf = newregfile(pp, &len); getres(tp, XFS_B_TO_FSB(mp, len)); error = libxfs_inode_alloc(&tp, pip, mode|S_IFREG, 1, 0, &creds, fsxp, &ip); if (error) fail(_("Inode allocation failed"), error); flags |= newfile(tp, ip, &flist, &first, 0, 0, buf, len); if (buf) free(buf); libxfs_trans_ijoin(tp, pip, 0); newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &flist, 1); libxfs_trans_ihold(tp, pip); break; case IF_RESERVED: /* pre-allocated space only */ value = getstr(pp); llen = cvtnum(mp->m_sb.sb_blocksize, mp->m_sb.sb_sectsize, value); getres(tp, XFS_B_TO_FSB(mp, llen)); error = libxfs_inode_alloc(&tp, pip, mode|S_IFREG, 1, 0, &creds, fsxp, &ip); if (error) fail(_("Inode pre-allocation failed"), error); libxfs_trans_ijoin(tp, pip, 0); newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &flist, 1); libxfs_trans_ihold(tp, pip); libxfs_trans_log_inode(tp, ip, flags); error = libxfs_bmap_finish(&tp, &flist, &committed); if (error) fail(_("Pre-allocated file creation failed"), error); libxfs_trans_commit(tp, 0); rsvfile(mp, ip, llen); return; case IF_BLOCK: getres(tp, 0); majdev = (int)getnum(pp); mindev = (int)getnum(pp); error = libxfs_inode_alloc(&tp, pip, mode|S_IFBLK, 1, IRIX_MKDEV(majdev, mindev), &creds, fsxp, &ip); if (error) { fail(_("Inode allocation failed"), error); } libxfs_trans_ijoin(tp, pip, 0); newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &flist, 1); libxfs_trans_ihold(tp, pip); flags |= XFS_ILOG_DEV; break; case IF_CHAR: getres(tp, 0); majdev = (int)getnum(pp); mindev = (int)getnum(pp); error = libxfs_inode_alloc(&tp, pip, mode|S_IFCHR, 1, IRIX_MKDEV(majdev, mindev), &creds, fsxp, &ip); if (error) fail(_("Inode allocation failed"), error); libxfs_trans_ijoin(tp, pip, 0); newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &flist, 1); libxfs_trans_ihold(tp, pip); flags |= XFS_ILOG_DEV; break; case IF_FIFO: getres(tp, 0); error = libxfs_inode_alloc(&tp, pip, mode|S_IFIFO, 1, 0, &creds, fsxp, &ip); if (error) fail(_("Inode allocation failed"), error); libxfs_trans_ijoin(tp, pip, 0); newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &flist, 1); libxfs_trans_ihold(tp, pip); break; case IF_SYMLINK: buf = getstr(pp); len = (int)strlen(buf); getres(tp, XFS_B_TO_FSB(mp, len)); error = libxfs_inode_alloc(&tp, pip, mode|S_IFLNK, 1, 0, &creds, fsxp, &ip); if (error) fail(_("Inode allocation failed"), error); flags |= newfile(tp, ip, &flist, &first, 1, 1, buf, len); libxfs_trans_ijoin(tp, pip, 0); newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &flist, 1); libxfs_trans_ihold(tp, pip); break; case IF_DIRECTORY: getres(tp, 0); error = libxfs_inode_alloc(&tp, pip, mode|S_IFDIR, 1, 0, &creds, fsxp, &ip); if (error) fail(_("Inode allocation failed"), error); ip->i_d.di_nlink++; /* account for . */ if (!pip) { pip = ip; mp->m_sb.sb_rootino = ip->i_ino; libxfs_mod_sb(tp, XFS_SB_ROOTINO); mp->m_rootip = ip; isroot = 1; } else { libxfs_trans_ijoin(tp, pip, 0); newdirent(mp, tp, pip, &xname, ip->i_ino, &first, &flist, 1); pip->i_d.di_nlink++; libxfs_trans_ihold(tp, pip); libxfs_trans_log_inode(tp, pip, XFS_ILOG_CORE); } newdirectory(mp, tp, ip, pip); libxfs_trans_log_inode(tp, ip, flags); error = libxfs_bmap_finish(&tp, &flist, &committed); if (error) fail(_("Directory creation failed"), error); libxfs_trans_ihold(tp, ip); libxfs_trans_commit(tp, 0); /* * RT initialization. Do this here to ensure that * the RT inodes get placed after the root inode. */ if (isroot) rtinit(mp); tp = NULL; for (;;) { name = getstr(pp); if (!name) break; if (strcmp(name, "$") == 0) break; parseproto(mp, ip, fsxp, pp, name); } libxfs_iput(ip, 0); return; } libxfs_trans_log_inode(tp, ip, flags); error = libxfs_bmap_finish(&tp, &flist, &committed); if (error) { fail(_("Error encountered creating file from prototype file"), error); } libxfs_trans_commit(tp, 0); }
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; }