Example #1
0
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);
}
Example #2
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;
}