/* 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; }
/* 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; }