STATIC int xfs_file_readdir( struct file *file, struct dir_context *ctx) { struct inode *inode = file_inode(file); xfs_inode_t *ip = XFS_I(inode); size_t bufsize; /* * The Linux API doesn't pass down the total size of the buffer * we read into down to the filesystem. With the filldir concept * it's not needed for correct information, but the XFS dir2 leaf * code wants an estimate of the buffer size to calculate it's * readahead window and size the buffers used for mapping to * physical blocks. * * Try to give it an estimate that's good enough, maybe at some * point we can change the ->readdir prototype to include the * buffer size. For now we use the current glibc buffer size. */ bufsize = (size_t)min_t(loff_t, 32768, ip->i_d.di_size); return xfs_readdir(NULL, ip, ctx, bufsize); }
void copy_tree(xfs_mount_t *mp, char *parent, char *local, xfs_inode_t *inode) { xfs_off_t ofs; int r, fd; struct filldir_data filldata; char *buffer[BUFSIZE]; off_t offset; if (xfs_is_dir(inode)) { mkdir(local, 0770); filldata.mp = mp; filldata.base = parent; filldata.local = local; ofs = 0; r = xfs_readdir(inode, (void *)&filldata, 102400, &ofs, copy_filldir); if (r != 0) { printf("Not a directory\n"); } } else if (!xfs_is_link(inode)) { r = 10; offset = 0; fd = open(local, 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); } }
STATIC int xfs_file_readdir( struct file *filp, void *dirent, filldir_t filldir) { struct inode *inode = filp->f_path.dentry->d_inode; xfs_inode_t *ip = XFS_I(inode); int error; size_t bufsize; /* * The Linux API doesn't pass down the total size of the buffer * we read into down to the filesystem. With the filldir concept * it's not needed for correct information, but the XFS dir2 leaf * code wants an estimate of the buffer size to calculate it's * readahead window and size the buffers used for mapping to * physical blocks. * * Try to give it an estimate that's good enough, maybe at some * point we can change the ->readdir prototype to include the * buffer size. For now we use the current glibc buffer size. */ bufsize = (size_t)min_t(loff_t, 32768, ip->i_d.di_size); error = xfs_readdir(ip, dirent, bufsize, (xfs_off_t *)&filp->f_pos, filldir); if (error) return -error; 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 xfs_file_readdir( struct file *filp, void *dirent, filldir_t filldir) { struct inode *inode = filp->f_path.dentry->d_inode; xfs_inode_t *ip = XFS_I(inode); int error; size_t bufsize; bufsize = (size_t)min_t(loff_t, 32768, ip->i_d.di_size); error = xfs_readdir(ip, dirent, bufsize, (xfs_off_t *)&filp->f_pos, filldir); if (error) return -error; 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; }
STATIC int xfs_file_readdir( struct file *filp, void *dirent, filldir_t filldir) { struct inode *inode = filp->f_path.dentry->d_inode; xfs_inode_t *ip = XFS_I(inode); struct hack_callback buf; struct hack_dirent *de; int error; loff_t size; int eof = 0; xfs_off_t start_offset, curr_offset, offset; /* * Try fairly hard to get memory */ buf.len = PAGE_CACHE_SIZE; do { buf.dirent = kmalloc(buf.len, GFP_KERNEL); if (buf.dirent) break; buf.len >>= 1; } while (buf.len >= 1024); if (!buf.dirent) return -ENOMEM; curr_offset = filp->f_pos; if (curr_offset == 0x7fffffff) offset = 0xffffffff; else offset = filp->f_pos; while (!eof) { unsigned int reclen; start_offset = offset; buf.used = 0; error = -xfs_readdir(ip, &buf, buf.len, &offset, xfs_hack_filldir); if (error || offset == start_offset) { size = 0; break; } size = buf.used; de = (struct hack_dirent *)buf.dirent; curr_offset = de->offset /* & 0x7fffffff */; while (size > 0) { if (filldir(dirent, de->name, de->namlen, curr_offset & 0x7fffffff, de->ino, de->d_type)) { goto done; } reclen = ALIGN(sizeof(struct hack_dirent) + de->namlen, sizeof(u64)); size -= reclen; de = (struct hack_dirent *)((char *)de + reclen); curr_offset = de->offset /* & 0x7fffffff */; } } done: if (!error) { if (size == 0) filp->f_pos = offset & 0x7fffffff; else if (de) filp->f_pos = curr_offset; } kfree(buf.dirent); return 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; }