void filldir(File *t, Ofile *f, int dnum, int nrecur) { Odir d; int i; Rune rbuf[40]; char buf[UTFmax*nelem(rbuf)]; File *nt; if(dnum == 0xFFFFFFFF || oreaddir(f, dnum, &d) != 1) return; /* * i hope there are no broken files with * circular trees. i hate infinite loops. */ if(nrecur > 100) sysfatal("tree too large in office file: probably circular"); filldir(t, f, d.left, nrecur+1); /* add current tree entry */ runestrecpy(rbuf, rbuf+sizeof rbuf, d.name); for(i=0; rbuf[i]; i++) if(rbuf[i] == L' ') rbuf[i] = L'␣'; else if(rbuf[i] <= 0x20 || rbuf[i] == L'/' || (0x80 <= rbuf[i] && rbuf[i] <= 0x9F)) rbuf[i] = ':'; snprint(buf, sizeof buf, "%S", rbuf); if(d.dir == 0xFFFFFFFF) { /* make file */ nt = createfile(t, buf, nil, 0444, nil); if(nt == nil) sysfatal("nt nil: create %s: %r", buf); nt->aux = copydir(&d); nt->Dir.length = d.size; } else /* make directory */ nt = createfile(t, buf, nil, DMDIR|0777, nil); filldir(t, f, d.right, nrecur+1); if(d.dir != 0xFFFFFFFF) filldir(nt, f, d.dir, nrecur+1); closefile(nt); }
static int conndirgen(Usbfs *fs, Qid q, int i, Dir *d, void *) { Dirtab *tab; i++; /* skip root */ if(i < nelem(conndirtab) - 1) /* null terminated */ tab = &conndirtab[i]; else return -1; filldir(fs, d, tab, qnum(q.path)); return 0; }
void main(int argc, char **argv) { char *mtpt; Ofile *f; Odir d; mtpt = "/mnt/doc"; ARGBEGIN{ case 'm': mtpt = ARGF(); break; default: goto Usage; }ARGEND if(argc != 1) { Usage: fprint(2, "usage: olefs file\n"); exits("usage"); } f = oleopen(argv[0]); if(f == nil) { print("error opening %s: %r\n", argv[0]); exits("open"); } // dumpdir(f, 0); if(oreaddir(f, 0, &d) != 1) { fprint(2, "oreaddir error: %r\n"); exits("oreaddir"); } olesrv.tree = alloctree(nil, nil, DMDIR|0777, nil); filldir(olesrv.tree->root, f, d.dir, 0); postmountsrv(&olesrv, nil, mtpt, MREPL); exits(0); }
static int rootdirgen(Usbfs *fs, Qid, int i, Dir *d, void *) { Ether *e; Dirtab *tab; int cn; e = fs->aux; i++; /* skip root */ cn = 0; if(i < nelem(rootdirtab) - 1) /* null terminated */ tab = &rootdirtab[i]; else{ cn = i - nelem(rootdirtab) + 1; if(cn < e->nconns) tab = &conndirtab[0]; else return -1; } filldir(fs, d, tab, cn); return 0; }
static int ubifs_printdir(struct file *file, void *dirent) { int err, over = 0; struct qstr nm; union ubifs_key key; struct ubifs_dent_node *dent; struct inode *dir = file->f_path.dentry->d_inode; struct ubifs_info *c = dir->i_sb->s_fs_info; dbg_gen("dir ino %lu, f_pos %#llx", dir->i_ino, file->f_pos); if (file->f_pos > UBIFS_S_KEY_HASH_MASK || file->f_pos == 2) /* * The directory was seek'ed to a senseless position or there * are no more entries. */ return 0; if (file->f_pos == 1) { /* Find the first entry in TNC and save it */ lowest_dent_key(c, &key, dir->i_ino); nm.name = NULL; dent = ubifs_tnc_next_ent(c, &key, &nm); if (IS_ERR(dent)) { err = PTR_ERR(dent); goto out; } file->f_pos = key_hash_flash(c, &dent->key); file->private_data = dent; } dent = file->private_data; if (!dent) { /* * The directory was seek'ed to and is now readdir'ed. * Find the entry corresponding to @file->f_pos or the * closest one. */ dent_key_init_hash(c, &key, dir->i_ino, file->f_pos); nm.name = NULL; dent = ubifs_tnc_next_ent(c, &key, &nm); if (IS_ERR(dent)) { err = PTR_ERR(dent); goto out; } file->f_pos = key_hash_flash(c, &dent->key); file->private_data = dent; } while (1) { dbg_gen("feed '%s', ino %llu, new f_pos %#x", dent->name, (unsigned long long)le64_to_cpu(dent->inum), key_hash_flash(c, &dent->key)); ubifs_assert(le64_to_cpu(dent->ch.sqnum) > ubifs_inode(dir)->creat_sqnum); nm.len = le16_to_cpu(dent->nlen); over = filldir(c, (char *)dent->name, nm.len, le64_to_cpu(dent->inum), dent->type); if (over) return 0; /* Switch to the next entry */ key_read(c, &dent->key, &key); nm.name = (char *)dent->name; dent = ubifs_tnc_next_ent(c, &key, &nm); if (IS_ERR(dent)) { err = PTR_ERR(dent); goto out; } kfree(file->private_data); file->f_pos = key_hash_flash(c, &dent->key); file->private_data = dent; cond_resched(); } out: if (err != -ENOENT) { ubifs_err("cannot find next direntry, error %d", err); return err; } kfree(file->private_data); file->private_data = NULL; file->f_pos = 2; return 0; }
static int ubifs_create(struct inode *dir, struct dentry *dentry, umode_t mode, struct nameidata *nd) { struct inode *inode; struct ubifs_info *c = dir->i_sb->s_fs_info; int err, sz_change = CALC_DENT_SIZE(dentry->d_name.len); struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1, .dirtied_ino = 1 }; struct ubifs_inode *dir_ui = ubifs_inode(dir); /* * Budget request settings: new inode, new direntry, changing the * parent directory inode. */ dbg_gen("dent '%.*s', mode %#hx in dir ino %lu", dentry->d_name.len, dentry->d_name.name, mode, dir->i_ino); err = ubifs_budget_space(c, &req); if (err) return err; inode = ubifs_new_inode(c, dir, mode); if (IS_ERR(inode)) { err = PTR_ERR(inode); goto out_budg; } mutex_lock(&dir_ui->ui_mutex); dir->i_size += sz_change; dir_ui->ui_size = dir->i_size; dir->i_mtime = dir->i_ctime = inode->i_ctime; err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 0, 0); if (err) goto out_cancel; mutex_unlock(&dir_ui->ui_mutex); ubifs_release_budget(c, &req); insert_inode_hash(inode); d_instantiate(dentry, inode); return 0; out_cancel: dir->i_size -= sz_change; dir_ui->ui_size = dir->i_size; mutex_unlock(&dir_ui->ui_mutex); make_bad_inode(inode); iput(inode); out_budg: ubifs_release_budget(c, &req); ubifs_err("cannot create regular file, error %d", err); return err; } /** * vfs_dent_type - get VFS directory entry type. * @type: UBIFS directory entry type * * This function converts UBIFS directory entry type into VFS directory entry * type. */ static unsigned int vfs_dent_type(uint8_t type) { switch (type) { case UBIFS_ITYPE_REG: return DT_REG; case UBIFS_ITYPE_DIR: return DT_DIR; case UBIFS_ITYPE_LNK: return DT_LNK; case UBIFS_ITYPE_BLK: return DT_BLK; case UBIFS_ITYPE_CHR: return DT_CHR; case UBIFS_ITYPE_FIFO: return DT_FIFO; case UBIFS_ITYPE_SOCK: return DT_SOCK; default: BUG(); } return 0; } /* * The classical Unix view for directory is that it is a linear array of * (name, inode number) entries. Linux/VFS assumes this model as well. * Particularly, 'readdir()' call wants us to return a directory entry offset * which later may be used to continue 'readdir()'ing the directory or to * 'seek()' to that specific direntry. Obviously UBIFS does not really fit this * model because directory entries are identified by keys, which may collide. * * UBIFS uses directory entry hash value for directory offsets, so * 'seekdir()'/'telldir()' may not always work because of possible key * collisions. But UBIFS guarantees that consecutive 'readdir()' calls work * properly by means of saving full directory entry name in the private field * of the file description object. * * This means that UBIFS cannot support NFS which requires full * 'seekdir()'/'telldir()' support. */ static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir) { int err, over = 0; struct qstr nm; union ubifs_key key; struct ubifs_dent_node *dent; struct inode *dir = file_inode(file); struct ubifs_info *c = dir->i_sb->s_fs_info; dbg_gen("dir ino %lu, f_pos %#llx", dir->i_ino, file->f_pos); if (file->f_pos > UBIFS_S_KEY_HASH_MASK || file->f_pos == 2) /* * The directory was seek'ed to a senseless position or there * are no more entries. */ return 0; /* File positions 0 and 1 correspond to "." and ".." */ if (file->f_pos == 0) { ubifs_assert(!file->private_data); over = filldir(dirent, ".", 1, 0, dir->i_ino, DT_DIR); if (over) return 0; file->f_pos = 1; } if (file->f_pos == 1) { ubifs_assert(!file->private_data); over = filldir(dirent, "..", 2, 1, parent_ino(file->f_path.dentry), DT_DIR); if (over) return 0; /* Find the first entry in TNC and save it */ lowest_dent_key(c, &key, dir->i_ino); nm.name = NULL; dent = ubifs_tnc_next_ent(c, &key, &nm); if (IS_ERR(dent)) { err = PTR_ERR(dent); goto out; } file->f_pos = key_hash_flash(c, &dent->key); file->private_data = dent; } dent = file->private_data; if (!dent) { /* * The directory was seek'ed to and is now readdir'ed. * Find the entry corresponding to @file->f_pos or the * closest one. */ dent_key_init_hash(c, &key, dir->i_ino, file->f_pos); nm.name = NULL; dent = ubifs_tnc_next_ent(c, &key, &nm); if (IS_ERR(dent)) { err = PTR_ERR(dent); goto out; } file->f_pos = key_hash_flash(c, &dent->key); file->private_data = dent; } while (1) { dbg_gen("feed '%s', ino %llu, new f_pos %#x", dent->name, (unsigned long long)le64_to_cpu(dent->inum), key_hash_flash(c, &dent->key)); ubifs_assert(le64_to_cpu(dent->ch.sqnum) > ubifs_inode(dir)->creat_sqnum); nm.len = le16_to_cpu(dent->nlen); over = filldir(dirent, dent->name, nm.len, file->f_pos, le64_to_cpu(dent->inum), vfs_dent_type(dent->type)); if (over) return 0; /* Switch to the next entry */ key_read(c, &dent->key, &key); nm.name = dent->name; dent = ubifs_tnc_next_ent(c, &key, &nm); if (IS_ERR(dent)) { err = PTR_ERR(dent); goto out; } kfree(file->private_data); file->f_pos = key_hash_flash(c, &dent->key); file->private_data = dent; cond_resched(); } out: if (err != -ENOENT) { ubifs_err("cannot find next direntry, error %d", err); return err; } kfree(file->private_data); file->private_data = NULL; file->f_pos = 2; return 0; }
ssize_t llu_iop_filldirentries(struct inode *dir, _SYSIO_OFF_T *basep, char *buf, size_t nbytes) { struct llu_inode_info *lli = llu_i2info(dir); struct intnl_stat *st = llu_i2stat(dir); loff_t pos = *basep; struct ll_dir_chain chain; struct page *page; int filled = 0; int rc; int done; __u16 type; ENTRY; liblustre_wait_event(0); if (st->st_size == 0) { CWARN("dir size is 0?\n"); RETURN(0); } if (pos == MDS_DIR_END_OFF) /* * end-of-file. */ RETURN(0); rc = 0; done = 0; ll_dir_chain_init(&chain); page = llu_dir_read_page(dir, pos, 0, &chain); while (rc == 0 && !done) { struct lu_dirpage *dp; struct lu_dirent *ent; if (!IS_ERR(page)) { /* * If page is empty (end of directoryis reached), * use this value. */ __u64 hash = MDS_DIR_END_OFF; __u64 next; dp = page->addr; for (ent = lu_dirent_start(dp); ent != NULL && !done; ent = lu_dirent_next(ent)) { char *name; int namelen; struct lu_fid fid; __u64 ino; hash = le64_to_cpu(ent->lde_hash); namelen = le16_to_cpu(ent->lde_namelen); if (hash < pos) /* * Skip until we find target hash * value. */ continue; if (namelen == 0) /* * Skip dummy record. */ continue; fid = ent->lde_fid; name = ent->lde_name; fid_le_to_cpu(&fid, &fid); ino = cl_fid_build_ino(&fid, 0); type = ll_dirent_type_get(ent); done = filldir(buf, nbytes, name, namelen, (loff_t)hash, ino, type, &filled); } next = le64_to_cpu(dp->ldp_hash_end); OBD_PAGE_FREE(page); if (!done) { pos = next; if (pos == MDS_DIR_END_OFF) /* * End of directory reached. */ done = 1; else if (1 /* chain is exhausted*/) /* * Normal case: continue to the next * page. */ page = llu_dir_read_page(dir, pos, 1, &chain); else { /* * go into overflow page. */ } } else { pos = hash; if (filled == 0) GOTO(out, filled = -EINVAL); } } else { rc = PTR_ERR(page); CERROR("error reading dir "DFID" at %lu: rc %d\n", PFID(&lli->lli_fid), (unsigned long)pos, rc); } } lli->lli_dir_pos = (loff_t)pos; *basep = lli->lli_dir_pos; out: ll_dir_chain_fini(&chain); liblustre_wait_event(0); RETURN(filled); }
int main(int argc, char **argv) { int fe, fd, fm; int i, j, type; int new_id; int nrows, ncols, nbasins; int map_id, dir_id, bas_id; char map_name[GNAME_MAX], new_map_name[GNAME_MAX]; const char *tempfile1, *tempfile2, *tempfile3; char dir_name[GNAME_MAX]; char bas_name[GNAME_MAX]; struct Cell_head window; struct GModule *module; struct Option *opt1, *opt2, *opt3, *opt4, *opt5; struct Flag *flag1; int in_type, bufsz; void *in_buf; CELL *out_buf; struct band3 bnd, bndC; /* Initialize the GRASS environment variables */ G_gisinit(argv[0]); module = G_define_module(); G_add_keyword(_("raster")); G_add_keyword(_("hydrology")); module->description = _("Filters and generates a depressionless elevation map and a " "flow direction map from a given elevation raster map."); opt1 = G_define_standard_option(G_OPT_R_ELEV); opt2 = G_define_standard_option(G_OPT_R_OUTPUT); opt2->key = "depressionless"; opt2->description = _("Name for output depressionless elevation raster map"); opt4 = G_define_standard_option(G_OPT_R_OUTPUT); opt4->key = "direction"; opt4->description = _("Name for output flow direction map for depressionless elevation raster map"); opt5 = G_define_standard_option(G_OPT_R_OUTPUT); opt5->key = "areas"; opt5->required = NO; opt5->description = _("Name for output raster map of problem areas"); opt3 = G_define_option(); opt3->key = "type"; opt3->type = TYPE_STRING; opt3->required = NO; opt3->description = _("Aspect direction format"); opt3->options = "agnps,answers,grass"; opt3->answer = "grass"; flag1 = G_define_flag(); flag1->key = 'f'; flag1->description = _("Find unresolved areas only"); if (G_parser(argc, argv)) exit(EXIT_FAILURE); if (flag1->answer && opt5->answer == NULL) { G_fatal_error(_("The '%c' flag requires '%s'to be specified"), flag1->key, opt5->key); } type = 0; strcpy(map_name, opt1->answer); strcpy(new_map_name, opt2->answer); strcpy(dir_name, opt4->answer); if (opt5->answer != NULL) strcpy(bas_name, opt5->answer); if (strcmp(opt3->answer, "agnps") == 0) type = 1; else if (strcmp(opt3->answer, "answers") == 0) type = 2; else if (strcmp(opt3->answer, "grass") == 0) type = 3; G_debug(1, "output type (1=AGNPS, 2=ANSWERS, 3=GRASS): %d", type); if (type == 3) G_verbose_message(_("Direction map is D8 resolution, i.e. 45 degrees")); /* open the maps and get their file id */ map_id = Rast_open_old(map_name, ""); /* allocate cell buf for the map layer */ in_type = Rast_get_map_type(map_id); /* set the pointers for multi-typed functions */ set_func_pointers(in_type); /* get the window information */ G_get_window(&window); nrows = Rast_window_rows(); ncols = Rast_window_cols(); /* buffers for internal use */ bndC.ns = ncols; bndC.sz = sizeof(CELL) * ncols; bndC.b[0] = G_calloc(ncols, sizeof(CELL)); bndC.b[1] = G_calloc(ncols, sizeof(CELL)); bndC.b[2] = G_calloc(ncols, sizeof(CELL)); /* buffers for external use */ bnd.ns = ncols; bnd.sz = ncols * bpe(); bnd.b[0] = G_calloc(ncols, bpe()); bnd.b[1] = G_calloc(ncols, bpe()); bnd.b[2] = G_calloc(ncols, bpe()); in_buf = get_buf(); tempfile1 = G_tempfile(); tempfile2 = G_tempfile(); tempfile3 = G_tempfile(); fe = open(tempfile1, O_RDWR | O_CREAT, 0666); /* elev */ fd = open(tempfile2, O_RDWR | O_CREAT, 0666); /* dirn */ fm = open(tempfile3, O_RDWR | O_CREAT, 0666); /* problems */ G_message(_("Reading elevation map...")); for (i = 0; i < nrows; i++) { G_percent(i, nrows, 2); get_row(map_id, in_buf, i); write(fe, in_buf, bnd.sz); } G_percent(1, 1, 1); Rast_close(map_id); /* fill single-cell holes and take a first stab at flow directions */ G_message(_("Filling sinks...")); filldir(fe, fd, nrows, &bnd); /* determine flow directions for ambiguous cases */ G_message(_("Determining flow directions for ambiguous cases...")); resolve(fd, nrows, &bndC); /* mark and count the sinks in each internally drained basin */ nbasins = dopolys(fd, fm, nrows, ncols); if (flag1->answer) { /* determine the watershed for each sink */ wtrshed(fm, fd, nrows, ncols, 4); /* fill all of the watersheds up to the elevation necessary for drainage */ ppupdate(fe, fm, nrows, nbasins, &bnd, &bndC); /* repeat the first three steps to get the final directions */ G_message(_("Repeat to get the final directions...")); filldir(fe, fd, nrows, &bnd); resolve(fd, nrows, &bndC); nbasins = dopolys(fd, fm, nrows, ncols); } G_free(bndC.b[0]); G_free(bndC.b[1]); G_free(bndC.b[2]); G_free(bnd.b[0]); G_free(bnd.b[1]); G_free(bnd.b[2]); out_buf = Rast_allocate_c_buf(); bufsz = ncols * sizeof(CELL); lseek(fe, 0, SEEK_SET); new_id = Rast_open_new(new_map_name, in_type); lseek(fd, 0, SEEK_SET); dir_id = Rast_open_new(dir_name, CELL_TYPE); if (opt5->answer != NULL) { lseek(fm, 0, SEEK_SET); bas_id = Rast_open_new(bas_name, CELL_TYPE); for (i = 0; i < nrows; i++) { read(fm, out_buf, bufsz); Rast_put_row(bas_id, out_buf, CELL_TYPE); } Rast_close(bas_id); close(fm); } for (i = 0; i < nrows; i++) { read(fe, in_buf, bnd.sz); put_row(new_id, in_buf); read(fd, out_buf, bufsz); for (j = 0; j < ncols; j += 1) out_buf[j] = dir_type(type, out_buf[j]); Rast_put_row(dir_id, out_buf, CELL_TYPE); } Rast_close(new_id); close(fe); Rast_close(dir_id); close(fd); G_free(in_buf); G_free(out_buf); exit(EXIT_SUCCESS); }
static int fsstat(Usbfs *fs, Qid qid, Dir *d) { filldir(fs, d, qdirtab(qid.path), qnum(qid.path)); return 0; }
void __mfs_readdir(struct mfs_volume* volume, const ps16_t route, struct printdir *printdir) { u8_t cluster[CLUSTER_SIZE] = {0, }; const u32_t entry_per_data_cluster = CLUSTER_SIZE / sizeof(struct mfs_dirent); s16_t composited_file_name[128] = {0, }; BOOL has_long_file_name_next_entry = FALSE; u128 current_cluster_number = 0; u32_t current_entry_number = 0; u128 read_position = 0; struct mfs_dirent* current_dirent = NULL; static s16_t path[1024]={0}; struct file* filp = printdir->filp; void* dirent = printdir->dirent; filldir_t filldir = printdir->filldir; u128 end_cluster = get_end_cluster(volume); strncpy(path, route, 1024); current_cluster_number = get_cluster_number(volume, path); if(current_cluster_number == 0) { return ; } // 볼륨이 무효하다. if(volume == NULL) return ; read_position = read_cluster(volume, current_cluster_number); seek_volume(volume, read_position); read_volume(volume, cluster, sizeof(u8_t), CLUSTER_SIZE); while(current_cluster_number != end_cluster) { // 클러스터의 첫 엔트리를 얻는다. current_dirent = get_first_entry(cluster, ¤t_entry_number, has_long_file_name_next_entry); // 클러스터의 모든 엔트리를 검사한다. while(current_entry_number != entry_per_data_cluster) { // if(current_dirent->size != 0) // { // 얻은 엔트리가 LongFileName인지 여부 검사 if(is_long_file_name(current_dirent->attribute) == TRUE) { // LongFileName일 경우 LongFileName을 조합한다. composite_long_file_name(volume, current_cluster_number, current_entry_number, composited_file_name); } else { // 일반 FileName일 경우 복사 strcpy(composited_file_name, current_dirent->name); } if(is_normal_dir(current_dirent->attribute) == TRUE) { static char buf[1024] = ""; int len; buf[0] = '\0'; strcat(buf, path); len = strlen(path); if(len > 0){ if(path[len-1] != '/') strcat(buf, "/"); } strcat(buf, composited_file_name); if(filldir(dirent, composited_file_name, strlen(composited_file_name), filp->f_pos++, 2, DT_DIR)){ printk("WARNING %s %d", __FILE__,__LINE__); return ; } strcat(buf, "*<DIR>\n"); printk(buf); } else if(is_normal_file(current_dirent->attribute) == TRUE) { static char buf[1024]=""; buf[0]='\0'; printk("garig %p %p %p %s\n", filp, dirent, filldir, composited_file_name); if(filldir(dirent, composited_file_name, strlen(composited_file_name), filp->f_pos++, 2, DT_REG)){ printk("WARNING %s %d", __FILE__, __LINE__); return ; } strcat(buf, composited_file_name); strcat(buf, "*<FILE>\n"); printk(buf); } // } // 다음 엔트리를 얻는다. current_dirent = get_next_entry(cluster, ¤t_entry_number, &has_long_file_name_next_entry); } current_cluster_number = read_fat_index(volume, current_cluster_number); // 지정된 번호의 클러스터를 읽는다. read_position = read_cluster(volume, current_cluster_number); seek_volume(volume, read_position); read_volume(volume, cluster, sizeof(u8_t), CLUSTER_SIZE); } return ; }
static int fuse_direntplus_link(struct file *file, struct fuse_direntplus *direntplus, u64 attr_version) { int err; struct fuse_entry_out *o = &direntplus->entry_out; struct fuse_dirent *dirent = &direntplus->dirent; struct dentry *parent = file->f_path.dentry; struct qstr name = { .len = dirent->namelen, .name = dirent->name }; struct dentry *dentry; struct dentry *alias; struct inode *dir = parent->d_inode; struct fuse_conn *fc; struct inode *inode; if (!o->nodeid) { /* * Unlike in the case of fuse_lookup, zero nodeid does not mean * ENOENT. Instead, it only means the userspace filesystem did * not want to return attributes/handle for this entry. * * So do nothing. */ return 0; } if (name.name[0] == '.') { /* * We could potentially refresh the attributes of the directory * and its parent? */ if (name.len == 1) return 0; if (name.name[1] == '.' && name.len == 2) return 0; } if (invalid_nodeid(o->nodeid)) return -EIO; if (!fuse_valid_type(o->attr.mode)) return -EIO; fc = get_fuse_conn(dir); name.hash = full_name_hash(name.name, name.len); dentry = d_lookup(parent, &name); if (dentry) { inode = dentry->d_inode; if (!inode) { d_drop(dentry); } else if (get_node_id(inode) != o->nodeid || ((o->attr.mode ^ inode->i_mode) & S_IFMT)) { err = d_invalidate(dentry); if (err) goto out; } else if (is_bad_inode(inode)) { err = -EIO; goto out; } else { struct fuse_inode *fi; fi = get_fuse_inode(inode); spin_lock(&fc->lock); fi->nlookup++; spin_unlock(&fc->lock); fuse_change_attributes(inode, &o->attr, entry_attr_timeout(o), attr_version); /* * The other branch to 'found' comes via fuse_iget() * which bumps nlookup inside */ goto found; } dput(dentry); } dentry = d_alloc(parent, &name); err = -ENOMEM; if (!dentry) goto out; dentry->d_op = &fuse_dentry_operations; inode = fuse_iget(dir->i_sb, o->nodeid, o->generation, &o->attr, entry_attr_timeout(o), attr_version); if (!inode) goto out; alias = fuse_materialise_dentry(dentry, inode); err = PTR_ERR(alias); if (IS_ERR(alias)) goto out; if (alias) { dput(dentry); dentry = alias; } found: fuse_change_entry_timeout(dentry, o); err = 0; out: dput(dentry); return err; } static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file, void *dstbuf, filldir_t filldir, u64 attr_version) { struct fuse_direntplus *direntplus; struct fuse_dirent *dirent; size_t reclen; int over = 0; int ret; while (nbytes >= FUSE_NAME_OFFSET_DIRENTPLUS) { direntplus = (struct fuse_direntplus *) buf; dirent = &direntplus->dirent; reclen = FUSE_DIRENTPLUS_SIZE(direntplus); if (!dirent->namelen || dirent->namelen > FUSE_NAME_MAX) return -EIO; if (reclen > nbytes) break; if (memchr(dirent->name, '/', dirent->namelen) != NULL) return -EIO; if (!over) { /* We fill entries into dstbuf only as much as it can hold. But we still continue iterating over remaining entries to link them. If not, we need to send a FORGET for each of those which we did not link. */ over = filldir(dstbuf, dirent->name, dirent->namelen, file->f_pos, dirent->ino, dirent->type); file->f_pos = dirent->off; } buf += reclen; nbytes -= reclen; ret = fuse_direntplus_link(file, direntplus, attr_version); if (ret) fuse_force_forget(file, direntplus->entry_out.nodeid); } return 0; } static int fuse_readdir(struct file *file, void *dstbuf, filldir_t filldir) { int plus, err; size_t nbytes; struct page *page; struct inode *inode = file->f_path.dentry->d_inode; struct fuse_conn *fc = get_fuse_conn(inode); struct fuse_req *req; u64 attr_version = 0; if (is_bad_inode(inode)) return -EIO; req = fuse_get_req(fc, 1); if (IS_ERR(req)) return PTR_ERR(req); page = alloc_page(GFP_KERNEL); if (!page) { fuse_put_request(fc, req); return -ENOMEM; } plus = fuse_use_readdirplus(inode, file); req->out.argpages = 1; req->num_pages = 1; req->pages[0] = page; req->page_descs[0].length = PAGE_SIZE; if (plus) { attr_version = fuse_get_attr_version(fc); fuse_read_fill(req, file, file->f_pos, PAGE_SIZE, FUSE_READDIRPLUS); } else { fuse_read_fill(req, file, file->f_pos, PAGE_SIZE, FUSE_READDIR); } fuse_request_send(fc, req); nbytes = req->out.args[0].size; err = req->out.h.error; fuse_put_request(fc, req); if (!err) { if (plus) { err = parse_dirplusfile(page_address(page), nbytes, file, dstbuf, filldir, attr_version); } else { err = parse_dirfile(page_address(page), nbytes, file, dstbuf, filldir); } } __free_page(page); fuse_invalidate_attr(inode); /* atime changed */ return err; }
static int ubifs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd) { struct inode *inode; struct ubifs_info *c = dir->i_sb->s_fs_info; int err, sz_change = CALC_DENT_SIZE(dentry->d_name.len); struct ubifs_budget_req req = { .new_ino = 1, .new_dent = 1, .dirtied_ino = 1 }; struct ubifs_inode *dir_ui = ubifs_inode(dir); /* * Budget request settings: new inode, new direntry, changing the * parent directory inode. */ dbg_gen("dent '%.*s', mode %#x in dir ino %lu", dentry->d_name.len, dentry->d_name.name, mode, dir->i_ino); err = ubifs_budget_space(c, &req); if (err) return err; inode = ubifs_new_inode(c, dir, mode); if (IS_ERR(inode)) { err = PTR_ERR(inode); goto out_budg; } mutex_lock(&dir_ui->ui_mutex); dir->i_size += sz_change; dir_ui->ui_size = dir->i_size; dir->i_mtime = dir->i_ctime = inode->i_ctime; err = ubifs_jnl_update(c, dir, &dentry->d_name, inode, 0, 0); if (err) goto out_cancel; mutex_unlock(&dir_ui->ui_mutex); ubifs_release_budget(c, &req); insert_inode_hash(inode); d_instantiate(dentry, inode); return 0; out_cancel: dir->i_size -= sz_change; dir_ui->ui_size = dir->i_size; mutex_unlock(&dir_ui->ui_mutex); make_bad_inode(inode); iput(inode); out_budg: ubifs_release_budget(c, &req); ubifs_err("cannot create regular file, error %d", err); return err; } static unsigned int vfs_dent_type(uint8_t type) { switch (type) { case UBIFS_ITYPE_REG: return DT_REG; case UBIFS_ITYPE_DIR: return DT_DIR; case UBIFS_ITYPE_LNK: return DT_LNK; case UBIFS_ITYPE_BLK: return DT_BLK; case UBIFS_ITYPE_CHR: return DT_CHR; case UBIFS_ITYPE_FIFO: return DT_FIFO; case UBIFS_ITYPE_SOCK: return DT_SOCK; default: BUG(); } return 0; } static int ubifs_readdir(struct file *file, void *dirent, filldir_t filldir) { int err, over = 0; struct qstr nm; union ubifs_key key; struct ubifs_dent_node *dent; struct inode *dir = file->f_path.dentry->d_inode; struct ubifs_info *c = dir->i_sb->s_fs_info; dbg_gen("dir ino %lu, f_pos %#llx", dir->i_ino, file->f_pos); if (file->f_pos > UBIFS_S_KEY_HASH_MASK || file->f_pos == 2) /* * The directory was seek'ed to a senseless position or there * are no more entries. */ return 0; /* File positions 0 and 1 correspond to "." and ".." */ if (file->f_pos == 0) { ubifs_assert(!file->private_data); over = filldir(dirent, ".", 1, 0, dir->i_ino, DT_DIR); if (over) return 0; file->f_pos = 1; } if (file->f_pos == 1) { ubifs_assert(!file->private_data); over = filldir(dirent, "..", 2, 1, parent_ino(file->f_path.dentry), DT_DIR); if (over) return 0; /* Find the first entry in TNC and save it */ lowest_dent_key(c, &key, dir->i_ino); nm.name = NULL; dent = ubifs_tnc_next_ent(c, &key, &nm); if (IS_ERR(dent)) { err = PTR_ERR(dent); goto out; } file->f_pos = key_hash_flash(c, &dent->key); file->private_data = dent; } dent = file->private_data; if (!dent) { /* * The directory was seek'ed to and is now readdir'ed. * Find the entry corresponding to @file->f_pos or the * closest one. */ dent_key_init_hash(c, &key, dir->i_ino, file->f_pos); nm.name = NULL; dent = ubifs_tnc_next_ent(c, &key, &nm); if (IS_ERR(dent)) { err = PTR_ERR(dent); goto out; } file->f_pos = key_hash_flash(c, &dent->key); file->private_data = dent; } while (1) { dbg_gen("feed '%s', ino %llu, new f_pos %#x", dent->name, (unsigned long long)le64_to_cpu(dent->inum), key_hash_flash(c, &dent->key)); ubifs_assert(le64_to_cpu(dent->ch.sqnum) > ubifs_inode(dir)->creat_sqnum); nm.len = le16_to_cpu(dent->nlen); over = filldir(dirent, dent->name, nm.len, file->f_pos, le64_to_cpu(dent->inum), vfs_dent_type(dent->type)); if (over) return 0; /* Switch to the next entry */ key_read(c, &dent->key, &key); nm.name = dent->name; dent = ubifs_tnc_next_ent(c, &key, &nm); if (IS_ERR(dent)) { err = PTR_ERR(dent); goto out; } kfree(file->private_data); file->f_pos = key_hash_flash(c, &dent->key); file->private_data = dent; cond_resched(); } out: if (err != -ENOENT) { ubifs_err("cannot find next direntry, error %d", err); return err; } kfree(file->private_data); file->private_data = NULL; file->f_pos = 2; return 0; }
//读取目录下面有什么文件 int baiduapi_readdir(const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi) { (void) offset; (void) fi; char buff[2048]; char fullpath[PATHLEN]; sprintf(fullpath, "%s%s", basepath, path); int pathlen = strlen(fullpath); if (fullpath[pathlen - 1] != '/') { //如果路径不是以‘/’结尾的,加一个‘/’ fullpath[pathlen] = '/'; fullpath[++pathlen] = '\0'; }; struct stat st; memset(&st, 0, sizeof(struct stat)); st.st_nlink = 1; snprintf(buff, sizeof(buff) - 1, "https://pcs.baidu.com/rest/2.0/pcs/file?" "method=list&" "access_token=%s&" "path=%s" , Access_Token, URLEncode(fullpath)); FILE *tpfile = tmpfile(); if (!tpfile) { int lasterrno = errno; errorlog("create temp file error:%s\n", strerror(errno)); return -lasterrno; } Http *r = Httpinit(buff); if (r == NULL) { int lasterrno = errno; errorlog("can't resolve domain:%s\n", strerror(errno)); fclose(tpfile); return -lasterrno; } r->method = get; r->writefunc = savetofile; r->writeprame = tpfile; if ((errno = request(r)) != CURLE_OK) { errorlog("network error:%d\n", errno); fclose(tpfile); Httpdestroy(r); return -EPROTO; } Httpdestroy(r); json_object *json_get = json_object_from_FILE(tpfile); fclose(tpfile); if (json_get == NULL) { errorlog("json_object_from_FILE filed!\n"); return -EPROTO; } json_object *jerror_code; if (json_object_object_get_ex(json_get, "error_code",&jerror_code)) { int errorno = json_object_get_int(jerror_code) ; json_object_put(json_get); return handleerror(errorno); } json_object *jlist; json_object_object_get_ex(json_get, "list",&jlist); filler(buf, ".", NULL, 0); filler(buf, "..", NULL, 0); int i; for (i = 0; i < json_object_array_length(jlist); ++i) { json_object *filenode = json_object_array_get_idx(jlist, i); json_object *jmtime; json_object_object_get_ex(filenode, "mtime",&jmtime); st.st_mtim.tv_sec = json_object_get_int64(jmtime); json_object *jctime; json_object_object_get_ex(filenode, "ctime",&jctime); st.st_ctim.tv_sec = json_object_get_int64(jctime); json_object *jfs_id; json_object_object_get_ex(filenode, "fs_id",&jfs_id); st.st_ino = json_object_get_int64(jfs_id); json_object *jsize; json_object_object_get_ex(filenode, "size",&jsize); st.st_size = json_object_get_int64(jsize); json_object *jisdir; json_object_object_get_ex(filenode, "isdir",&jisdir); if (json_object_get_boolean(jisdir)) { st.st_mode = S_IFDIR | 0755; } else { st.st_mode = S_IFREG | 0444; } json_object *jpath; json_object_object_get_ex(filenode, "path",&jpath); filler(buf, json_object_get_string(jpath) + pathlen, &st, 0); addscache(json_object_get_string(jpath) + strlen(basepath), st); } json_object_put(json_get); filldir(path, buf, filler); return 0; }