コード例 #1
0
ファイル: file.c プロジェクト: DanLipsitt/libguestfs
struct guestfs_stat_list *
guestfs__lstatlist (guestfs_h *g, const char *dir, char * const*names)
{
  size_t len = guestfs___count_strings (names);
  size_t old_len;
  struct guestfs_stat_list *ret;

  ret = safe_malloc (g, sizeof *ret);
  ret->len = 0;
  ret->val = NULL;

  while (len > 0) {
    CLEANUP_FREE_STAT_LIST struct guestfs_stat_list *stats = NULL;

    /* Note we don't need to free up the strings because take_strings
     * does not do a deep copy.
     */
    CLEANUP_FREE char **first = take_strings (g, names, LSTATLIST_MAX, &names);

    len = len <= LSTATLIST_MAX ? 0 : len - LSTATLIST_MAX;

    stats = guestfs_internal_lstatlist (g, dir, first);

    if (stats == NULL) {
      guestfs_free_stat_list (ret);
      return NULL;
    }

    /* Append stats to ret. */
    old_len = ret->len;
    ret->len += stats->len;
    ret->val = safe_realloc (g, ret->val,
                             ret->len * sizeof (struct guestfs_stat));
    memcpy (&ret->val[old_len], stats->val,
            stats->len * sizeof (struct guestfs_stat));
  }

  return ret;
}
コード例 #2
0
ファイル: fuse.c プロジェクト: msmhrt/libguestfs
static int
mount_local_readdir (const char *path, void *buf, fuse_fill_dir_t filler,
                     off_t offset, struct fuse_file_info *fi)
{
  DECL_G ();
  DEBUG_CALL ("%s, %p, %ld", path, buf, (long) offset);

  time_t now;
  time (&now);

  dir_cache_remove_all_expired (g, now);

  struct guestfs_dirent_list *ents;

  ents = guestfs_readdir (g, path);
  if (ents == NULL)
    RETURN_ERRNO;

  size_t i;
  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.
   */
  char **names = malloc ((ents->len + 1) * sizeof (char *));
  if (names) {
    for (i = 0; i < ents->len; ++i)
      names[i] = ents->val[i].name;
    names[i] = NULL;

    struct guestfs_stat_list *ss = guestfs_lstatlist (g, path, names);
    if (ss) {
      for (i = 0; i < ss->len; ++i) {
        if (ss->val[i].ino >= 0) {
          struct stat statbuf;

          statbuf.st_dev = ss->val[i].dev;
          statbuf.st_ino = ss->val[i].ino;
          statbuf.st_mode = ss->val[i].mode;
          statbuf.st_nlink = ss->val[i].nlink;
          statbuf.st_uid = ss->val[i].uid;
          statbuf.st_gid = ss->val[i].gid;
          statbuf.st_rdev = ss->val[i].rdev;
          statbuf.st_size = ss->val[i].size;
          statbuf.st_blksize = ss->val[i].blksize;
          statbuf.st_blocks = ss->val[i].blocks;
          statbuf.st_atime = ss->val[i].atime;
          statbuf.st_mtime = ss->val[i].mtime;
          statbuf.st_ctime = ss->val[i].ctime;

          lsc_insert (g, path, names[i], now, &statbuf);
        }
      }
      guestfs_free_stat_list (ss);
    }

    struct guestfs_xattr_list *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 (first, num);
          if (copy)
            xac_insert (g, path, names[ni], now, copy);

          i--;
        }
      }
      guestfs_free_xattr_list (xattrs);
    }

    char **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);
  }

  guestfs_free_dirent_list (ents);

  return 0;
}