int vfs_file_begin (int const d_type, register const VFS_Query* const q) { int rc = 0; Log_Printf (LOG_DEBUG, "%s_BEGIN '%s'", (d_type == DT_LNK ? "SYMLINK" : "FILE"), q->path); if (q->stbuf) { q->stbuf->st_mode = DTTOIF(d_type) | 0444; q->stbuf->st_nlink = 1; q->stbuf->st_size = DEFAULT_SIZE; // to be computed latter vfs_set_time (DEFAULT_TIME, q); } if (q->filler) { Log_Printf (LOG_DEBUG, "error, listing not a directory : '%s'", q->path); rc = -ENOTDIR; } if (q->file) { *(q->file) = NULL; } if (q->lnk_buf) { if (d_type == DT_LNK) { if (q->lnk_bufsiz > 0) *(q->lnk_buf) = NUL; } else { Log_Printf (LOG_DEBUG, "error, readlink on regular file : '%s'", q->path); rc = -EINVAL; } } return rc; }
static int select_dirs (const struct dirent *dirent) { int result = 0; if (strcmp (dirent->d_name, ".") != 0 && strcmp (dirent->d_name, "..") != 0) { mode_t mode = 0; #ifdef _DIRENT_HAVE_D_TYPE if (dirent->d_type != DT_UNKNOWN && dirent->d_type != DT_LNK) { mode = DTTOIF (dirent->d_type); } else #endif { struct stat st; g_autofree char *path = NULL; path = g_build_filename (LIBLOCALEDIR, dirent->d_name, NULL); if (g_stat (path, &st) == 0) { mode = st.st_mode; } } result = S_ISDIR (mode); } return result; }
static int aux_files(lua_State *L) { DIR *d = lua_touserdata(L, lua_upvalueindex(1)); struct dirent *entry; if (d == NULL) luaL_error(L, "attempt to use closed dir"); entry = readdir(d); if (entry == NULL) { closedir(d); lua_pushnil(L); lua_replace(L, lua_upvalueindex(1)); lua_pushnil(L); } else { lua_pushstring(L, entry->d_name); #if 0 #ifdef _DIRENT_HAVE_D_TYPE lua_pushstring(L, filetype(DTTOIF(entry->d_type))); return 2; #endif #endif } return 1; }
static int readdir(const Branches &branches_, const char *dirname_, void *buf_, const fuse_fill_dir_t filler_) { HashSet names; string basepath; struct stat st = {0}; for(size_t i = 0, ei = branches_.size(); i != ei; i++) { int rv; int dirfd; DIR *dh; basepath = fs::path::make(&branches_[i].path,dirname_); dh = fs::opendir(basepath); if(!dh) continue; dirfd = fs::dirfd(dh); st.st_dev = fs::devid(dirfd); if(st.st_dev == (dev_t)-1) st.st_dev = i; rv = 0; for(struct dirent *de = fs::readdir(dh); de && !rv; de = fs::readdir(dh)) { rv = names.put(de->d_name); if(rv == 0) continue; st.st_ino = de->d_ino; st.st_mode = DTTOIF(de->d_type); fs::inode::recompute(&st); rv = filler_(buf_,de->d_name,&st,NO_OFFSET); if(rv) return (fs::closedir(dh),-ENOMEM); } fs::closedir(dh); } return 0; }
/* We use this function for lstat as well since we don't have any. */ static int my_stat (const char *name, struct stat *st) { long int idx = find_file (name); if (idx == -1) { PRINTF ("my_stat (\"%s\", ...) = -1 (%s)\n", name, strerror (errno)); return -1; } memset (st, '\0', sizeof (*st)); if (filesystem[idx].type == DT_UNKNOWN) st->st_mode = DTTOIF (idx + 1 < nfiles && filesystem[idx].level < filesystem[idx + 1].level ? DT_DIR : DT_REG) | 0777; else st->st_mode = DTTOIF (filesystem[idx].type) | 0777; PRINTF ("my_stat (\"%s\", { st_mode: %o }) = 0\n", name, st->st_mode); return 0; }
static inline void osd_it_append_attrs(struct lu_dirent *ent, __u32 attr, int len, __u16 type) { const unsigned align = sizeof(struct luda_type) - 1; struct luda_type *lt; /* check if file type is required */ if (attr & LUDA_TYPE) { len = (len + align) & ~align; lt = (void *)ent->lde_name + len; lt->lt_type = cpu_to_le16(DTTOIF(type)); ent->lde_attrs |= LUDA_TYPE; } ent->lde_attrs = cpu_to_le32(ent->lde_attrs); }
static void walk_readdir_process_dir(const char* dir, CIRCLE_handle* handle) { /* TODO: may need to try these functions multiple times */ DIR* dirp = mfu_opendir(dir); /* if there is a permissions error and the usr read & execute are being turned * on when walk_stat=0 then catch the permissions error and turn the bits on */ if (dirp == NULL) { if (errno == EACCES && SET_DIR_PERMS) { struct stat st; mfu_lstat(dir, &st); // turn on the usr read & execute bits st.st_mode |= S_IRUSR; st.st_mode |= S_IXUSR; mfu_chmod(dir, st.st_mode); dirp = mfu_opendir(dir); if (dirp == NULL) { if (errno == EACCES) { MFU_LOG(MFU_LOG_ERR, "Failed to open directory with opendir: `%s' (errno=%d %s)", dir, errno, strerror(errno)); } } } } if (! dirp) { /* TODO: print error */ } else { /* Read all directory entries */ while (1) { /* read next directory entry */ struct dirent* entry = mfu_readdir(dirp); if (entry == NULL) { break; } /* process component, unless it's "." or ".." */ char* name = entry->d_name; if ((strncmp(name, ".", 2)) && (strncmp(name, "..", 3))) { /* <dir> + '/' + <name> + '/0' */ char newpath[CIRCLE_MAX_STRING_LEN]; size_t len = strlen(dir) + 1 + strlen(name) + 1; if (len < sizeof(newpath)) { /* build full path to item */ strcpy(newpath, dir); strcat(newpath, "/"); strcat(newpath, name); #ifdef _DIRENT_HAVE_D_TYPE /* record info for item */ mode_t mode; int have_mode = 0; if (entry->d_type != DT_UNKNOWN) { /* unlink files here if remove option is on, * and dtype is known without a stat */ if (REMOVE_FILES && (entry->d_type != DT_DIR)) { mfu_unlink(newpath); } else { /* we can read object type from directory entry */ have_mode = 1; mode = DTTOIF(entry->d_type); mfu_flist_insert_stat(CURRENT_LIST, newpath, mode, NULL); } } else { /* type is unknown, we need to stat it */ struct stat st; int status = mfu_lstat(newpath, &st); if (status == 0) { have_mode = 1; mode = st.st_mode; /* unlink files here if remove option is on, * and stat was necessary to get type */ if (REMOVE_FILES && !S_ISDIR(st.st_mode)) { mfu_unlink(newpath); } else { mfu_flist_insert_stat(CURRENT_LIST, newpath, mode, &st); } } else { /* error */ } } /* increment our item count */ reduce_items++; /* recurse into directories */ if (have_mode && S_ISDIR(mode)) { handle->enqueue(newpath); } #endif } else { /* TODO: print error in correct format */ /* name is too long */ MFU_LOG(MFU_LOG_ERR, "Path name is too long: %lu chars exceeds limit %lu", len, sizeof(newpath)); } } } } mfu_closedir(dirp); return; }
/* ================= Sys_ListFiles_r Internal function to filesystem. Conventions apply: - files should hold at least MAX_LISTED_FILES - *count_p must be initialized in range [0, MAX_LISTED_FILES - 1] - depth must be 0 on the first call ================= */ void Sys_ListFiles_r(const char *path, const char *filter, unsigned flags, size_t baselen, int *count_p, void **files, int depth) { struct dirent *ent; DIR *dir; struct stat st; char fullpath[MAX_OSPATH]; char *name; size_t len; void *info; if ((dir = opendir(path)) == NULL) { return; } while ((ent = readdir(dir)) != NULL) { if (ent->d_name[0] == '.') { continue; // ignore dotfiles } len = Q_concat(fullpath, sizeof(fullpath), path, "/", ent->d_name, NULL); if (len >= sizeof(fullpath)) { continue; } st.st_mode = 0; #ifdef _DIRENT_HAVE_D_TYPE // try to avoid stat() if possible if (!(flags & FS_SEARCH_EXTRAINFO) && ent->d_type != DT_UNKNOWN && ent->d_type != DT_LNK) { st.st_mode = DTTOIF(ent->d_type); } #endif if (st.st_mode == 0 && stat(fullpath, &st) == -1) { continue; } // pattern search implies recursive search if ((flags & FS_SEARCH_BYFILTER) && S_ISDIR(st.st_mode) && depth < MAX_LISTED_DEPTH) { Sys_ListFiles_r(fullpath, filter, flags, baselen, count_p, files, depth + 1); // re-check count if (*count_p >= MAX_LISTED_FILES) { break; } } // check type if (flags & FS_SEARCH_DIRSONLY) { if (!S_ISDIR(st.st_mode)) { continue; } } else { if (!S_ISREG(st.st_mode)) { continue; } } // check filter if (filter) { if (flags & FS_SEARCH_BYFILTER) { if (!FS_WildCmp(filter, fullpath + baselen)) { continue; } } else { if (!FS_ExtCmp(filter, ent->d_name)) { continue; } } } // strip path if (flags & FS_SEARCH_SAVEPATH) { name = fullpath + baselen; } else { name = ent->d_name; } // strip extension if (flags & FS_SEARCH_STRIPEXT) { *COM_FileExtension(name) = 0; if (!*name) { continue; } } // copy info off if (flags & FS_SEARCH_EXTRAINFO) { info = FS_CopyInfo(name, st.st_size, st.st_ctime, st.st_mtime); } else { info = FS_CopyString(name); } files[(*count_p)++] = info; if (*count_p >= MAX_LISTED_FILES) { break; } } closedir(dir); }
static void overlay_readdirplus_full(fuse_req_t req, size_t size, off_t offset, struct workspace_dh_struct *dh) { unsigned int error=0; char *buff=NULL; size_t pos=0; size_t dirent_size; struct fuse_entry_param e; char *name=NULL; struct directory_struct *directory=dh->directory; struct overlay_readdir_struct *overlay_readdir=(struct overlay_readdir_struct *)dh->handle.data; struct entry_struct *entry, *result; struct inode_struct *inode; unsigned char dtype; struct name_struct xname={NULL, 0, 0}; int res=0; memset(&e, 0, sizeof(struct fuse_entry_param)); e.generation = 1; e.attr_timeout = fs_options.attr_timeout; e.entry_timeout = fs_options.entry_timeout; e.attr.st_blksize=4096; e.attr.st_blocks=0; buff=malloc(size); if (! buff) { error=ENOMEM; goto error; } if (lock_directory(directory, _DIRECTORY_LOCK_EXCL)==-1) { free(buff); buff=NULL; error=EAGAIN; goto error; } while (pos<size) { if (offset==0) { inode=dh->parent->inode; /* the . entry */ e.ino = inode->ino; e.attr.st_ino = e.ino; e.attr.st_mode = inode->mode; e.attr.st_nlink = inode->nlink; e.attr.st_uid = inode->uid; e.attr.st_gid = inode->gid; e.attr.st_rdev = inode->rdev; e.attr.st_size = 0; e.attr.st_atim.tv_sec = 0; e.attr.st_atim.tv_nsec = 0; e.attr.st_mtim.tv_sec = inode->mtim.tv_sec; e.attr.st_mtim.tv_nsec = inode->mtim.tv_nsec; e.attr.st_ctim.tv_sec = inode->ctim.tv_sec; e.attr.st_ctim.tv_nsec = inode->ctim.tv_nsec; name = (char *) dotname; inode->nlookup++; } else if (offset==1) { /* the .. entry */ if ( ! dh->parent->parent ) { inode=dh->parent->inode; } else { inode=dh->parent->parent->inode; } e.ino = inode->ino; e.attr.st_ino = e.ino; e.attr.st_mode = inode->mode; e.attr.st_nlink = inode->nlink; e.attr.st_uid = inode->uid; e.attr.st_gid = inode->gid; e.attr.st_rdev = inode->rdev; e.attr.st_size = 0; e.attr.st_atim.tv_sec = 0; e.attr.st_atim.tv_nsec = 0; e.attr.st_mtim.tv_sec = inode->mtim.tv_sec; e.attr.st_mtim.tv_nsec = inode->mtim.tv_nsec; e.attr.st_ctim.tv_sec = inode->ctim.tv_sec; e.attr.st_ctim.tv_nsec = inode->ctim.tv_nsec; name = (char *) dotdotname; inode->nlookup++; } else { if (! dh->entry) { readdir: res=get_direntry(overlay_readdir, &xname, &dtype, &error); if (res<=0) { if (res==-1) { free(buff); unlock_directory(directory, _DIRECTORY_LOCK_EXCL); goto error; } dh->mode |= _WORKSPACE_READDIR_MODE_FINISH; break; } if (fstatat(overlay_readdir->fd, xname.name, &e.attr, AT_SYMLINK_NOFOLLOW | AT_NO_AUTOMOUNT)==-1) { goto readdir; } logoutput("overlayfs_readdirplus_real_full: read %s", xname.name); xname.len=strlen(xname.name); calculate_nameindex(&xname); error=0; entry=create_entry(dh->parent, &xname); inode=create_inode(); if (entry && inode) { result=insert_entry_batch(directory, entry, &error, 0); if (result==entry) { memcpy(&entry->synctime, &dh->synctime, sizeof(struct timespec)); inode->mode=DTTOIF(dtype); add_inode_hashtable(inode, increase_inodes_workspace, (void *) dh->object->workspace_mount); inode->alias=entry; entry->inode=inode; adjust_pathmax(dh->pathinfo.len + 1 + xname.len); } else { if (error==EEXIST) { destroy_entry(entry); entry=result; memcpy(&entry->synctime, &dh->synctime, sizeof(struct timespec)); free(inode); inode=entry->inode; } else { free(buff); destroy_entry(entry); free(inode); goto error; } } e.attr.st_ino=inode->ino; e.ino=inode->ino; e.attr.st_rdev = inode->rdev; e.attr.st_dev = 0; name=entry->name.name; } else { if (entry) { destroy_entry(entry); entry=NULL; } if (inode) { free(inode); inode=NULL; } error=ENOMEM; free(buff); goto error; } name=entry->name.name; dh->entry=entry; inode->mode = e.attr.st_mode; inode->nlink = e.attr.st_nlink; inode->uid = e.attr.st_uid; inode->gid = e.attr.st_gid; inode->rdev = e.attr.st_rdev; inode->mtim.tv_sec = e.attr.st_mtim.tv_sec; inode->mtim.tv_nsec = e.attr.st_mtim.tv_nsec; inode->ctim.tv_sec = e.attr.st_ctim.tv_sec; inode->ctim.tv_nsec = e.attr.st_ctim.tv_nsec; if (S_ISDIR(e.attr.st_mode)) { e.attr.st_size=0; } else { inode->size=e.attr.st_size; } } else { entry=dh->entry; inode=entry->inode; name=entry->name.name; e.attr.st_mode = inode->mode; e.attr.st_nlink = inode->nlink; e.attr.st_uid = inode->uid; e.attr.st_gid = inode->gid; e.attr.st_rdev = inode->rdev; if (S_ISDIR(inode->mode)) { e.attr.st_size = 0; } else { e.attr.st_size = inode->size; } e.attr.st_atim.tv_sec = 0; e.attr.st_atim.tv_nsec = 0; e.attr.st_mtim.tv_sec = inode->mtim.tv_sec; e.attr.st_mtim.tv_nsec = inode->mtim.tv_nsec; e.attr.st_ctim.tv_sec = inode->ctim.tv_sec; e.attr.st_ctim.tv_nsec = inode->ctim.tv_nsec; inode->nlookup++; } e.ino = inode->ino; e.attr.st_ino = e.ino; } dirent_size=fuse_add_direntry_plus(req, buff+pos, size-pos, name, &e, offset+1); if (pos + dirent_size > size) { dh->offset=offset+1; break; } /* increase counter and clear the various fields */ dh->entry=NULL; /* forget current entry to force readdir */ offset++; pos += dirent_size; } unlock_directory(directory, _DIRECTORY_LOCK_EXCL); fuse_reply_buf(req, buff, pos); free(buff); buff=NULL; return; error: fuse_reply_err(req, error); }
static void overlay_readdir_full(fuse_req_t req, size_t size, off_t offset, struct workspace_dh_struct *dh) { unsigned int error=0; char *buff=NULL; size_t pos=0; size_t dirent_size; struct stat st; char *name=NULL; struct directory_struct *directory=dh->directory; struct overlay_readdir_struct *overlay_readdir=(struct overlay_readdir_struct *)dh->handle.data; struct entry_struct *entry, *result; struct inode_struct *inode; struct name_struct xname={NULL, 0, 0}; unsigned char dtype=0; int res; memset(&st, 0, sizeof(struct stat)); buff=malloc(size); if (! buff) { error=ENOMEM; goto error; } if (lock_directory(directory, _DIRECTORY_LOCK_EXCL)==-1) { free(buff); buff=NULL; error=EAGAIN; goto error; } while (pos<size) { if (offset==0) { inode=dh->parent->inode; /* the . entry */ st.st_ino = inode->ino; st.st_mode = S_IFDIR; name = (char *) dotname; } else if (offset==1) { /* the .. entry */ if ( ! dh->parent->parent ) { inode=dh->parent->inode; st.st_ino = inode->ino; } else { struct entry_struct *parent=dh->parent->parent; inode=parent->inode; st.st_ino=inode->ino; } st.st_mode = S_IFDIR; name = (char *) dotdotname; } else { if (! dh->entry) { readdir: res=get_direntry(overlay_readdir, &xname, &dtype, &error); if (res<=0) { if (res==-1) { free(buff); unlock_directory(directory, _DIRECTORY_LOCK_EXCL); goto error; } dh->mode |= _WORKSPACE_READDIR_MODE_FINISH; break; } xname.len=strlen(xname.name); calculate_nameindex(&xname); error=0; entry=create_entry(dh->parent, &xname); inode=create_inode(); if (entry && inode) { result=insert_entry_batch(directory, entry, &error, 0); if (result==entry) { entry->inode->mode=DTTOIF(dtype); add_inode_hashtable(inode, increase_inodes_workspace, (void *) dh->object->workspace_mount); inode->alias=entry; entry->inode=inode; adjust_pathmax(dh->pathinfo.len + 1 + xname.len); } else { if (error==EEXIST) { destroy_entry(entry); entry=result; free(inode); inode=entry->inode; } else { free(buff); destroy_entry(entry); free(inode); goto error; } } st.st_mode=entry->inode->mode; st.st_ino=entry->inode->ino; name=entry->name.name; } else { if (entry) { destroy_entry(entry); entry=NULL; } if (inode) { free(inode); inode=NULL; } error=ENOMEM; free(buff); goto error; } dh->entry=entry; } else { entry=dh->entry; st.st_ino=entry->inode->ino; st.st_mode=entry->inode->mode; name=entry->name.name; } } dirent_size=fuse_add_direntry(req, buff+pos, size-pos, name, &st, offset+1); if (pos + dirent_size > size) { dh->offset = offset + 1; break; } /* increase counter and clear the various fields */ dh->entry=NULL; /* forget current entry to force readdir */ offset++; pos += dirent_size; } unlock_directory(directory, _DIRECTORY_LOCK_EXCL); fuse_reply_buf(req, buff, pos); free(buff); buff=NULL; return; error: fuse_reply_err(req, error); }
int main( int argc, char *argv[]) { (void) argc; (void) argv; /* File type macros */ { assert (DTTOIF(DT_REG) == S_IFREG); assert (DTTOIF(DT_DIR) == S_IFDIR); assert (DTTOIF(DT_FIFO) == S_IFIFO); assert (DTTOIF(DT_SOCK) == S_IFSOCK); assert (DTTOIF(DT_CHR) == S_IFCHR); assert (DTTOIF(DT_BLK) == S_IFBLK); assert (IFTODT(S_IFREG) == DT_REG); assert (IFTODT(S_IFDIR) == DT_DIR); assert (IFTODT(S_IFIFO) == DT_FIFO); assert (IFTODT(S_IFSOCK) == DT_SOCK); assert (IFTODT(S_IFCHR) == DT_CHR); assert (IFTODT(S_IFBLK) == DT_BLK); } /* Basic directory retrieval */ { DIR *dir; struct dirent *ent; int found = 0; /* Open directory */ dir = opendir ("tests/1"); if (dir == NULL) { fprintf (stderr, "Directory tests not found\n"); abort (); } /* Read entries */ while ((ent = readdir (dir)) != NULL) { /* Check each file */ if (strcmp (ent->d_name, ".") == 0) { /* Directory itself */ #ifdef _DIRENT_HAVE_D_TYPE assert (ent->d_type == DT_DIR); #endif #ifdef _DIRENT_HAVE_D_NAMLEN assert (ent->d_namlen == 1); #endif #ifdef _D_EXACT_NAMLEN assert (_D_EXACT_NAMLEN(ent) == 1); #endif #ifdef _D_ALLOC_NAMLEN assert (_D_ALLOC_NAMLEN(ent) > 1); #endif found |= 1; } else if (strcmp (ent->d_name, "..") == 0) { /* Parent directory */ #ifdef _DIRENT_HAVE_D_TYPE assert (ent->d_type == DT_DIR); #endif #ifdef _DIRENT_HAVE_D_NAMLEN assert (ent->d_namlen == 2); #endif #ifdef _D_EXACT_NAMLEN assert (_D_EXACT_NAMLEN(ent) == 2); #endif #ifdef _D_ALLOC_NAMLEN assert (_D_ALLOC_NAMLEN(ent) > 2); #endif found |= 2; } else if (strcmp (ent->d_name, "file") == 0) { /* Regular file */ #ifdef _DIRENT_HAVE_D_TYPE assert (ent->d_type == DT_REG); #endif #ifdef _DIRENT_HAVE_D_NAMLEN assert (ent->d_namlen == 4); #endif #ifdef _D_EXACT_NAMLEN assert (_D_EXACT_NAMLEN(ent) == 4); #endif #ifdef _D_ALLOC_NAMLEN assert (_D_ALLOC_NAMLEN(ent) > 4); #endif found |= 4; } else if (strcmp (ent->d_name, "dir") == 0) { /* Just a directory */ #ifdef _DIRENT_HAVE_D_TYPE assert (ent->d_type == DT_DIR); #endif #ifdef _DIRENT_HAVE_D_NAMLEN assert (ent->d_namlen == 3); #endif #ifdef _D_EXACT_NAMLEN assert (_D_EXACT_NAMLEN(ent) == 3); #endif #ifdef _D_ALLOC_NAMLEN assert (_D_ALLOC_NAMLEN(ent) > 3); #endif found |= 8; } else { /* Other file */ fprintf (stderr, "Unexpected file %s\n", ent->d_name); abort (); } } /* Make sure that all files were found */ assert (found == 0xf); closedir (dir); } /* Rewind of directory stream */ { DIR *dir; struct dirent *ent; int found = 0; /* Open directory */ dir = opendir ("tests/1"); assert (dir != NULL); /* Read entries */ while ((ent = readdir (dir)) != NULL) { /* Check each file */ if (strcmp (ent->d_name, ".") == 0) { /* Directory itself */ found |= 1; } else if (strcmp (ent->d_name, "..") == 0) { /* Parent directory */ found |= 2; } else if (strcmp (ent->d_name, "file") == 0) { /* Regular file */ found |= 4; } else if (strcmp (ent->d_name, "dir") == 0) { /* Just a directory */ found |= 8; } else { /* Other file */ fprintf (stderr, "Unexpected file %s\n", ent->d_name); abort (); } } /* Make sure that all files were found */ assert (found == 0xf); /* Rewind stream and read entries again */ rewinddir (dir); found = 0; /* Read entries */ while ((ent = readdir (dir)) != NULL) { /* Check each file */ if (strcmp (ent->d_name, ".") == 0) { /* Directory itself */ found |= 1; } else if (strcmp (ent->d_name, "..") == 0) { /* Parent directory */ found |= 2; } else if (strcmp (ent->d_name, "file") == 0) { /* Regular file */ found |= 4; } else if (strcmp (ent->d_name, "dir") == 0) { /* Just a directory */ found |= 8; } else { /* Other file */ fprintf (stderr, "Unexpected file %s\n", ent->d_name); abort (); } } /* Make sure that all files were found */ assert (found == 0xf); closedir (dir); } printf ("OK\n"); return EXIT_SUCCESS; }
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; }
/* MyPrintDirectoryListing prints a FTP directory entry, represented by a CFDictionary as returned by CFFTPCreateParsedResourceListing, as a single line of text, much like you'd get from "ls -l". */ static void MyPrintDirectoryListing(CFDictionaryRef dictionary) { CFDateRef cfModDate; CFNumberRef cfType, cfMode, cfSize; CFStringRef cfOwner, cfName, cfLink, cfGroup; char owner[256], group[256], name[256]; char permString[12], link[1024]; SInt64 size; SInt32 mode, type; assert(dictionary != NULL); /* You should not assume that the directory entry dictionary will contain all the possible keys. Most of the time it will, however, depending on the FTP server, some of the keys may be missing. */ cfType = CFDictionaryGetValue(dictionary, kCFFTPResourceType); if (cfType) { assert(CFGetTypeID(cfType) == CFNumberGetTypeID()); CFNumberGetValue(cfType, kCFNumberSInt32Type, &type); cfMode = CFDictionaryGetValue(dictionary, kCFFTPResourceMode); if (cfMode) { assert(CFGetTypeID(cfMode) == CFNumberGetTypeID()); CFNumberGetValue(cfMode, kCFNumberSInt32Type, &mode); /* Converts inode status information into a symbolic string */ strmode(mode + DTTOIF(type), permString); fprintf(stderr, "%s ", permString); } } cfOwner = CFDictionaryGetValue(dictionary, kCFFTPResourceOwner); if (cfOwner) { assert(CFGetTypeID(cfOwner) == CFStringGetTypeID()); CFStringGetCString(cfOwner, owner, sizeof(owner), kCFStringEncodingASCII); fprintf(stderr, "%9s", owner); } cfGroup = CFDictionaryGetValue(dictionary, kCFFTPResourceGroup); if (cfGroup) { assert(CFGetTypeID(cfGroup) == CFStringGetTypeID()); CFStringGetCString(cfGroup, group, sizeof(group), kCFStringEncodingASCII); fprintf(stderr, "%9s", group); } cfSize = CFDictionaryGetValue(dictionary, kCFFTPResourceSize); if (cfSize) { assert(CFGetTypeID(cfSize) == CFNumberGetTypeID()); CFNumberGetValue(cfSize, kCFNumberSInt64Type, &size); fprintf(stderr, "%9lld ", size); } cfModDate = CFDictionaryGetValue(dictionary, kCFFTPResourceModDate); if (cfModDate) { CFLocaleRef locale; CFDateFormatterRef formatDate; CFDateFormatterRef formatTime; CFStringRef cfDate; CFStringRef cfTime; char date[256]; char time[256]; assert(CFGetTypeID(cfModDate) == CFDateGetTypeID()); locale = CFLocaleCopyCurrent(); assert(locale != NULL); formatDate = CFDateFormatterCreate(kCFAllocatorDefault, locale, kCFDateFormatterShortStyle, kCFDateFormatterNoStyle ); assert(formatDate != NULL); formatTime = CFDateFormatterCreate(kCFAllocatorDefault, locale, kCFDateFormatterNoStyle, kCFDateFormatterShortStyle); assert(formatTime != NULL); cfDate = CFDateFormatterCreateStringWithDate(kCFAllocatorDefault, formatDate, cfModDate); assert(cfDate != NULL); cfTime = CFDateFormatterCreateStringWithDate(kCFAllocatorDefault, formatTime, cfModDate); assert(cfTime != NULL); CFStringGetCString(cfDate, date, sizeof(date), kCFStringEncodingUTF8); CFStringGetCString(cfTime, time, sizeof(time), kCFStringEncodingUTF8); fprintf(stderr, "%10s %5s ", date, time); CFRelease(cfTime); CFRelease(cfDate); CFRelease(formatTime); CFRelease(formatDate); CFRelease(locale); } /* Note that this sample assumes UTF-8 since that's what the Mac OS X FTP server returns, however, some servers may use a different encoding. */ cfName = CFDictionaryGetValue(dictionary, kCFFTPResourceName); if (cfName) { assert(CFGetTypeID(cfName) == CFStringGetTypeID()); CFStringGetCString(cfName, name, sizeof(name), kCFStringEncodingUTF8); fprintf(stderr, "%s", name); cfLink = CFDictionaryGetValue(dictionary, kCFFTPResourceLink); if (cfLink) { assert(CFGetTypeID(cfLink) == CFStringGetTypeID()); CFStringGetCString(cfLink, link, sizeof(link), kCFStringEncodingUTF8); if (strlen(link) > 0) fprintf(stderr, " -> %s", link); } } fprintf(stderr, "\n"); }
enum dir_visit_next_op dir_search_i( dir_visitor_t visitor, void * ctx, int maxLevel, error_monitor_t em, mem_buffer_t buffer) { DIR * dirp; struct dirent dbuf; struct dirent * dp; char * path; int rv; size_t bufSize; enum dir_visit_next_op nextOp; if (maxLevel == 0) return dir_visit_next_go; path = (char *)mem_buffer_make_continuous(buffer, 0); bufSize = mem_buffer_size(buffer); dirp = dir_open(path, 0, em); if (dirp == NULL) return dir_visit_next_go; nextOp = dir_visit_next_go; while((rv = readdir_r(dirp, &dbuf, &dp)) == 0 && dp) { if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0) continue; if ( mem_buffer_strcat(buffer, "/") != 0 || mem_buffer_strcat(buffer, dp->d_name) != 0) break; if (S_ISDIR(DTTOIF(dp->d_type))) { if (visitor->on_dir_enter) { nextOp = visitor->on_dir_enter( (const char *)mem_buffer_make_continuous(buffer, 0), dp->d_name, ctx); if (nextOp == dir_visit_next_exit) break; } else { nextOp = dir_visit_next_go; } if (nextOp == dir_visit_next_go) { nextOp = dir_search_i( visitor, ctx, maxLevel > 0 ? maxLevel - 1 : maxLevel, em, buffer); if (nextOp == dir_visit_next_exit) break; } if (visitor->on_dir_leave) { nextOp = visitor->on_dir_leave( (const char *)mem_buffer_make_continuous(buffer, 0), dp->d_name, ctx); if (nextOp == dir_visit_next_exit) break; } } else if (S_ISREG(DTTOIF(dp->d_type))) { if (visitor->on_file) { nextOp = visitor->on_file( (const char *)mem_buffer_make_continuous(buffer, 0), dp->d_name, ctx); if (nextOp == dir_visit_next_exit) break; } } /*restore curent path*/ mem_buffer_set_size(buffer, bufSize); path = (char *)mem_buffer_make_continuous(buffer, 0); if (path == NULL) { CPE_ERROR_EX(em, ENOMEM, "no memory for dir search path"); nextOp = dir_visit_next_exit; break; } path[bufSize - 1] = 0; } /*clear resources*/ dir_close(dirp, em); return nextOp == dir_visit_next_exit ? dir_visit_next_exit : dir_visit_next_go; }