/* Create and link a new directory entry for directory NAME, having a device number DEV and an inode number INO, with NFS indicating whether it is an NFS device and FOUND indicating whether we have found that the directory exists. */ static struct directory * note_directory (char const *name, struct timespec mtime, dev_t dev, ino_t ino, bool nfs, bool found, const char *contents) { struct directory *directory = attach_directory (name); directory->mtime = mtime; directory->device_number = dev; directory->inode_number = ino; directory->children = CHANGED_CHILDREN; if (nfs) DIR_SET_FLAG (directory, DIRF_NFS); if (found) DIR_SET_FLAG (directory, DIRF_FOUND); if (contents) directory->dump = dumpdir_create (contents); else directory->dump = NULL; if (! ((directory_table || (directory_table = hash_initialize (0, 0, hash_directory_canonical_name, compare_directory_canonical_names, 0))) && hash_insert (directory_table, directory))) xalloc_die (); if (! ((directory_meta_table || (directory_meta_table = hash_initialize (0, 0, hash_directory_meta, compare_directory_meta, 0))) && hash_insert (directory_meta_table, directory))) xalloc_die (); return directory; }
static struct directory * procdir (const char *name_buffer, struct stat *stat_data, dev_t device, int flag, char *entry) { struct directory *directory; bool nfs = NFS_FILE_STAT (*stat_data); if ((directory = find_directory (name_buffer)) != NULL) { if (DIR_IS_INITED (directory)) { if (flag & PD_FORCE_INIT) { assign_string (&directory->name, name_buffer); } else { *entry = 'N'; /* Avoid duplicating this directory */ return directory; } } if (strcmp (directory->name, name_buffer)) { *entry = 'N'; return directory; } /* With NFS, the same file can have two different devices if an NFS directory is mounted in multiple locations, which is relatively common when automounting. To avoid spurious incremental redumping of directories, consider all NFS devices as equal, relying on the i-node to establish differences. */ if (! ((!check_device_option || (DIR_IS_NFS (directory) && nfs) || directory->device_number == stat_data->st_dev) && directory->inode_number == stat_data->st_ino)) { /* FIXME: find_directory_meta ignores nfs */ struct directory *d = find_directory_meta (stat_data->st_dev, stat_data->st_ino); if (d) { if (strcmp (d->name, name_buffer)) { WARNOPT (WARN_RENAME_DIRECTORY, (0, 0, _("%s: Directory has been renamed from %s"), quotearg_colon (name_buffer), quote_n (1, d->name))); directory->orig = d; DIR_SET_FLAG (directory, DIRF_RENAMED); dirlist_replace_prefix (d->name, name_buffer); } directory->children = CHANGED_CHILDREN; } else { WARNOPT (WARN_RENAME_DIRECTORY, (0, 0, _("%s: Directory has been renamed"), quotearg_colon (name_buffer))); directory->children = ALL_CHILDREN; directory->device_number = stat_data->st_dev; directory->inode_number = stat_data->st_ino; } if (nfs) DIR_SET_FLAG (directory, DIRF_NFS); } else directory->children = CHANGED_CHILDREN; DIR_SET_FLAG (directory, DIRF_FOUND); } else { struct directory *d = find_directory_meta (stat_data->st_dev, stat_data->st_ino); directory = note_directory (name_buffer, get_stat_mtime(stat_data), stat_data->st_dev, stat_data->st_ino, nfs, true, NULL); if (d) { if (strcmp (d->name, name_buffer)) { WARNOPT (WARN_RENAME_DIRECTORY, (0, 0, _("%s: Directory has been renamed from %s"), quotearg_colon (name_buffer), quote_n (1, d->name))); directory->orig = d; DIR_SET_FLAG (directory, DIRF_RENAMED); dirlist_replace_prefix (d->name, name_buffer); } directory->children = CHANGED_CHILDREN; } else { DIR_SET_FLAG (directory, DIRF_NEW); WARNOPT (WARN_NEW_DIRECTORY, (0, 0, _("%s: Directory is new"), quotearg_colon (name_buffer))); directory->children = (listed_incremental_option || (OLDER_STAT_TIME (*stat_data, m) || (after_date_option && OLDER_STAT_TIME (*stat_data, c)))) ? ALL_CHILDREN : CHANGED_CHILDREN; } } /* If the directory is on another device and --one-file-system was given, omit it... */ if (one_file_system_option && device != stat_data->st_dev /* ... except if it was explicitely given in the command line */ && !is_individual_file (name_buffer)) /* FIXME: WARNOPT (WARN_XDEV, (0, 0, _("%s: directory is on a different filesystem; not dumped"), quotearg_colon (directory->name))); */ directory->children = NO_CHILDREN; else if (flag & PD_FORCE_CHILDREN) { directory->children = PD_CHILDREN(flag); if (directory->children == NO_CHILDREN) *entry = 'N'; } DIR_SET_FLAG (directory, DIRF_INIT); if (directory->children != NO_CHILDREN) { const char *tag_file_name; switch (check_exclusion_tags (name_buffer, &tag_file_name)) { case exclusion_tag_all: /* This warning can be duplicated by code in dump_file0, but only in case when the topmost directory being archived contains an exclusion tag. */ exclusion_tag_warning (name_buffer, tag_file_name, _("directory not dumped")); *entry = 'N'; directory->children = NO_CHILDREN; break; case exclusion_tag_contents: exclusion_tag_warning (name_buffer, tag_file_name, _("contents not dumped")); directory->children = NO_CHILDREN; break; case exclusion_tag_under: exclusion_tag_warning (name_buffer, tag_file_name, _("contents not dumped")); directory->tagfile = tag_file_name; break; case exclusion_tag_none: break; } } return directory; }