static int visitor_function_wrapper (const char *dir, const char *filename, const struct guestfs_statns *stat, const struct guestfs_xattr_list *xattrs, void *opaque) { CAMLparam0 (); CAMLlocal5 (dirv, filenamev, statv, xattrsv, v); struct visitor_function_wrapper_args *args = opaque; assert (dir != NULL); assert (stat != NULL); assert (xattrs != NULL); assert (args != NULL); dirv = caml_copy_string (dir); if (filename == NULL) filenamev = Val_int (0); /* None */ else { filenamev = caml_alloc (1, 0); v = caml_copy_string (filename); Store_field (filenamev, 0, v); } statv = copy_statns (stat); xattrsv = copy_xattr_list (xattrs); /* Call the visitor_function. */ value argsv[4] = { dirv, filenamev, statv, xattrsv }; v = caml_callbackN_exn (*args->fvp, 4, argsv); if (Is_exception_result (v)) { /* The visitor_function raised an exception. Store the exception * in the 'exn' field on the stack of guestfs_int_mllib_visit, and * return an error. */ *args->exnp = Extract_exception (v); return -1; } /* No error, return normally. */ CAMLreturnT (int, 0); }
static int mount_local_readdir (const char *path, void *buf, fuse_fill_dir_t filler, off_t offset, struct fuse_file_info *fi) { time_t now; size_t i; char **names; CLEANUP_FREE_DIRENT_LIST struct guestfs_dirent_list *ents = NULL; DECL_G (); DEBUG_CALL ("%s, %p, %ld", path, buf, (long) offset); time (&now); dir_cache_remove_all_expired (g, now); ents = guestfs_readdir (g, path); if (ents == NULL) RETURN_ERRNO; for (i = 0; i < ents->len; ++i) { struct stat stat; memset (&stat, 0, sizeof stat); stat.st_ino = ents->val[i].ino; switch (ents->val[i].ftyp) { case 'b': stat.st_mode = S_IFBLK; break; case 'c': stat.st_mode = S_IFCHR; break; case 'd': stat.st_mode = S_IFDIR; break; case 'f': stat.st_mode = S_IFIFO; break; case 'l': stat.st_mode = S_IFLNK; break; case 'r': stat.st_mode = S_IFREG; break; case 's': stat.st_mode = S_IFSOCK; break; case 'u': case '?': default: stat.st_mode = 0; } /* Copied from the example, which also ignores 'offset'. I'm * not quite sure how this is ever supposed to work on large * directories. XXX */ if (filler (buf, ents->val[i].name, &stat, 0)) break; } /* Now prepopulate the directory caches. This step is just an * optimization, don't worry if it fails. */ names = malloc ((ents->len + 1) * sizeof (char *)); if (names) { CLEANUP_FREE_STATNS_LIST struct guestfs_statns_list *ss = NULL; CLEANUP_FREE_XATTR_LIST struct guestfs_xattr_list *xattrs = NULL; char **links; for (i = 0; i < ents->len; ++i) names[i] = ents->val[i].name; names[i] = NULL; ss = guestfs_lstatnslist (g, path, names); if (ss) { for (i = 0; i < ss->len; ++i) { if (ss->val[i].st_ino >= 0) { struct stat statbuf; memset (&statbuf, 0, sizeof statbuf); statbuf.st_dev = ss->val[i].st_dev; statbuf.st_ino = ss->val[i].st_ino; statbuf.st_mode = ss->val[i].st_mode; statbuf.st_nlink = ss->val[i].st_nlink; statbuf.st_uid = ss->val[i].st_uid; statbuf.st_gid = ss->val[i].st_gid; statbuf.st_rdev = ss->val[i].st_rdev; statbuf.st_size = ss->val[i].st_size; statbuf.st_blksize = ss->val[i].st_blksize; statbuf.st_blocks = ss->val[i].st_blocks; statbuf.st_atime = ss->val[i].st_atime_sec; #ifdef HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC statbuf.st_atim.tv_nsec = ss->val[i].st_atime_nsec; #endif statbuf.st_mtime = ss->val[i].st_mtime_sec; #ifdef HAVE_STRUCT_STAT_ST_MTIM_TV_NSEC statbuf.st_mtim.tv_nsec = ss->val[i].st_mtime_nsec; #endif statbuf.st_ctime = ss->val[i].st_ctime_sec; #ifdef HAVE_STRUCT_STAT_ST_CTIM_TV_NSEC statbuf.st_ctim.tv_nsec = ss->val[i].st_ctime_nsec; #endif lsc_insert (g, path, names[i], now, &statbuf); } } } xattrs = guestfs_lxattrlist (g, path, names); if (xattrs) { size_t ni, num; struct guestfs_xattr *first; struct guestfs_xattr_list *copy; for (i = 0, ni = 0; i < xattrs->len; ++i, ++ni) { /* assert (strlen (xattrs->val[i].attrname) == 0); */ if (xattrs->val[i].attrval_len > 0) { ++i; first = &xattrs->val[i]; num = 0; for (; i < xattrs->len && strlen (xattrs->val[i].attrname) > 0; ++i) num++; copy = copy_xattr_list (g, first, num); if (copy) xac_insert (g, path, names[ni], now, copy); i--; } } } links = guestfs_readlinklist (g, path, names); if (links) { for (i = 0; names[i] != NULL; ++i) { if (links[i][0]) /* Note that rlc_insert owns the string links[i] after this, */ rlc_insert (g, path, names[i], now, links[i]); else /* which is why we have to free links[i] here. */ free (links[i]); } free (links); /* free the array, not the strings */ } free (names); } return 0; }