Example #1
0
/* This is the function which is called to display all files and
 * directories, and it's where the magic happens.  We are called with
 * full stat and extended attributes for each file, so there is no
 * penalty for displaying anything in those structures.  However if we
 * need other things (eg. checksum) we may have to go back to the
 * appliance and then there can be a very large penalty.
 */
static int
show_file (const char *dir, const char *name,
           const struct guestfs_stat *stat,
           const struct guestfs_xattr_list *xattrs,
           void *unused)
{
  const char *filetype;
  CLEANUP_FREE char *path = NULL, *csum = NULL, *link = NULL;

  /* Display the basic fields. */
  output_start_line ();

  if (is_reg (stat->mode))
    filetype = "-";
  else if (is_dir (stat->mode))
    filetype = "d";
  else if (is_chr (stat->mode))
    filetype = "c";
  else if (is_blk (stat->mode))
    filetype = "b";
  else if (is_fifo (stat->mode))
    filetype = "p";
  else if (is_lnk (stat->mode))
    filetype = "l";
  else if (is_sock (stat->mode))
    filetype = "s";
  else
    filetype = "u";
  output_string (filetype);
  output_int64_perms (stat->mode & 07777);

  output_int64_size (stat->size);

  /* Display extra fields when enabled. */
  if (enable_uids) {
    output_int64_uid (stat->uid);
    output_int64_uid (stat->gid);
  }

  if (enable_times) {
    output_int64_time (stat->atime);
    output_int64_time (stat->mtime);
    output_int64_time (stat->ctime);
  }

  if (enable_extra_stats) {
    output_int64_dev (stat->dev);
    output_int64 (stat->ino);
    output_int64 (stat->nlink);
    output_int64_dev (stat->rdev);
    output_int64 (stat->blocks);
  }

  /* Disabled for now -- user would definitely want these to be interpreted.
  if (enable_xattrs)
    output_xattrs (xattrs);
  */

  path = full_path (dir, name);

  if (checksum && is_reg (stat->mode)) {
    csum = guestfs_checksum (g, checksum, path);
    if (!csum)
      exit (EXIT_FAILURE);

    output_string (csum);
  }

  output_string (path);

  if (is_lnk (stat->mode))
    /* XXX Fix this for NTFS. */
    link = guestfs_readlink (g, path);
  if (link)
    output_string_link (link);

  output_end_line ();

  return 0;
}
Example #2
0
/* Visit each directory/file/etc entry in the tree.  This just stores
 * the data in the tree.  Note we don't store file content, but we
 * keep the guestfs handle open so we can pull that out later if we
 * need to.
 */
static int
visit_entry (const char *dir, const char *name,
             const struct guestfs_statns *stat_orig,
             const struct guestfs_xattr_list *xattrs_orig,
             void *vt)
{
    struct tree *t = vt;
    char *path = NULL, *csum = NULL;
    struct guestfs_statns *stat = NULL;
    struct guestfs_xattr_list *xattrs = NULL;
    size_t i;

    path = full_path (dir, name);

    /* Copy the stats and xattrs because the visit function will
     * free them after we return.
     */
    stat = guestfs_copy_statns (stat_orig);
    if (stat == NULL) {
        perror ("guestfs_copy_stat");
        goto error;
    }
    xattrs = guestfs_copy_xattr_list (xattrs_orig);
    if (xattrs == NULL) {
        perror ("guestfs_copy_xattr_list");
        goto error;
    }

    if (checksum && is_reg (stat->st_mode)) {
        csum = guestfs_checksum (t->g, checksum, path);
        if (!csum)
            goto error;
    }

    /* If --atime option was NOT passed, flatten the atime field. */
    if (!atime)
        stat->st_atime_sec = stat->st_atime_nsec = 0;

    /* If --dir-links option was NOT passed, flatten nlink field in
     * directories.
     */
    if (!dir_links && is_dir (stat->st_mode))
        stat->st_nlink = 0;

    /* If --dir-times option was NOT passed, flatten time fields in
     * directories.
     */
    if (!dir_times && is_dir (stat->st_mode))
        stat->st_atime_sec = stat->st_mtime_sec = stat->st_ctime_sec =
                                 stat->st_atime_nsec = stat->st_mtime_nsec = stat->st_ctime_nsec = 0;

    /* Add the pathname and stats to the list. */
    i = t->nr_files++;
    if (i >= t->allocated) {
        struct file *old_files = t->files;
        size_t old_allocated = t->allocated;

        /* Number of entries in an F15 guest was 111524, and in a
         * Windows guest was 10709.
         */
        if (old_allocated == 0)
            t->allocated = 1024;
        else
            t->allocated = old_allocated * 2;

        t->files = realloc (old_files, t->allocated * sizeof (struct file));
        if (t->files == NULL) {
            perror ("realloc");
            t->files = old_files;
            t->allocated = old_allocated;
            goto error;
        }
    }

    t->files[i].path = path;
    t->files[i].stat = stat;
    t->files[i].xattrs = xattrs;
    t->files[i].csum = csum;

    return 0;

error:
    free (path);
    free (csum);
    guestfs_free_statns (stat);
    guestfs_free_xattr_list (xattrs);
    return -1;
}