diff options
-rw-r--r-- | ChangeLog | 24 | ||||
-rw-r--r-- | bootstrap.conf | 1 | ||||
-rw-r--r-- | gl/lib/file-set.c | 56 | ||||
-rw-r--r-- | gl/lib/file-set.h | 12 | ||||
-rw-r--r-- | gl/lib/hash-triple.c | 57 | ||||
-rw-r--r-- | gl/lib/hash-triple.h | 21 | ||||
-rw-r--r-- | gl/modules/file-set | 27 | ||||
-rw-r--r-- | gl/modules/hash-triple | 25 | ||||
-rw-r--r-- | src/Makefile.am | 9 | ||||
-rw-r--r-- | src/copy.c | 64 |
10 files changed, 235 insertions, 61 deletions
@@ -1,5 +1,29 @@ 2007-08-23 Jim Meyering <jim@meyering.net> + Move functions from copy.c into new modules, since ln needs them, too. + * bootstrap.conf (gnulib_modules): Add file-set. + * gl/lib/file-set.c (record_file, seen_file): Functions from copy.c. + * gl/lib/file-set.h: Add prototypes. + * gl/lib/hash-triple.c (triple_hash, triple_hash_no_name): + (triple_compare, triple_free): Functions from copy.c. + * gl/lib/hash-triple.h (struct F_triple): Define. From copy.c. + Add prototypes. + * gl/modules/file-set: New module. + * gl/modules/hash-triple: New module. + * src/Makefile.am (copy_sources): New variable. + (ginstall_SOURCES, cp_SOURCES, mv_SOURCES): Use it. + * src/copy.c: Include hash-triple.h. + No longer include hash-pjw.h. + (copy_internal): Don't pass a NULL third argument to record_file, + since that function no longer accepts that. + (record_file): Move this function to file-set.c. + Along the way, remove the code to allow a NULL stat-buffer pointer. + Adjust sole caller. + (seen_file): Move this function to file-set.c. + (struct F_triple): Move declaration to hash-triple.h. + (triple_compare, triple_free, triple_hash, triple_hash_no_name): + Move these functions to hash-triple.c. + bootstrap: generate more ignorable names * bootstrap (slurp): When generating ignorable names, also map .sin to .sed, .gperf to .c, and .y to .c. diff --git a/bootstrap.conf b/bootstrap.conf index 68896c77b..3fe04972c 100644 --- a/bootstrap.conf +++ b/bootstrap.conf @@ -45,6 +45,7 @@ gnulib_modules=" cycle-check d-ino d-type diacrit dirfd dirname dup2 error euidaccess exclude exitfail fchdir fcntl fcntl-safer fdl + file-set file-type fileblocks filemode filenamecat fnmatch-gnu fopen-safer fprintftime diff --git a/gl/lib/file-set.c b/gl/lib/file-set.c new file mode 100644 index 000000000..ad03f90ce --- /dev/null +++ b/gl/lib/file-set.c @@ -0,0 +1,56 @@ +#include <config.h> +#include "file-set.h" + +#include "hash-triple.h" +#include "xalloc.h" + +/* Record destination file, FILE, and dev/ino from *STATS, + in the hash table, HT. If HT is NULL, return immediately. + If memory allocation fails, exit immediately. */ +void +record_file (Hash_table *ht, char const *file, struct stat const *stats) +{ + struct F_triple *ent; + + if (ht == NULL) + return; + + ent = xmalloc (sizeof *ent); + ent->name = xstrdup (file); + ent->st_ino = stats->st_ino; + ent->st_dev = stats->st_dev; + + { + struct F_triple *ent_from_table = hash_insert (ht, ent); + if (ent_from_table == NULL) + { + /* Insertion failed due to lack of memory. */ + xalloc_die (); + } + + if (ent_from_table != ent) + { + /* There was alread a matching entry in the table, so ENT was + not inserted. Free it. */ + triple_free (ent); + } + } +} + +/* Return true if there is an entry in hash table, HT, + for the file described by FILE and STATS. */ +bool +seen_file (Hash_table const *ht, char const *file, + struct stat const *stats) +{ + struct F_triple new_ent; + + if (ht == NULL) + return false; + + new_ent.name = (char *) file; + new_ent.st_ino = stats->st_ino; + new_ent.st_dev = stats->st_dev; + + return !!hash_lookup (ht, &new_ent); +} diff --git a/gl/lib/file-set.h b/gl/lib/file-set.h new file mode 100644 index 000000000..a5a159e94 --- /dev/null +++ b/gl/lib/file-set.h @@ -0,0 +1,12 @@ +#include <sys/types.h> +#include <sys/stat.h> +#include <stdbool.h> + +#include "hash.h" + +extern void record_file (Hash_table *ht, char const *file, + struct stat const *stats) + __attribute__((nonnull(2, 3))); + +extern bool seen_file (Hash_table const *ht, char const *file, + struct stat const *stats); diff --git a/gl/lib/hash-triple.c b/gl/lib/hash-triple.c new file mode 100644 index 000000000..dfe2a592d --- /dev/null +++ b/gl/lib/hash-triple.c @@ -0,0 +1,57 @@ +#include <config.h> + +#include "hash-triple.h" + +#include <stdlib.h> + +#include "hash-pjw.h" +#include "same.h" +#include "same-inode.h" + +/* Hash an F_triple. */ +size_t +triple_hash (void const *x, size_t table_size) +{ + struct F_triple const *p = x; + + /* Also take the name into account, so that when moving N hard links to the + same file (all listed on the command line) all into the same directory, + we don't experience any N^2 behavior. */ + /* FIXME-maybe: is it worth the overhead of doing this + just to avoid N^2 in such an unusual case? N would have + to be very large to make the N^2 factor noticable, and + one would probably encounter a limit on the length of + a command line before it became a problem. */ + size_t tmp = hash_pjw (p->name, table_size); + + /* Ignoring the device number here should be fine. */ + return (tmp | p->st_ino) % table_size; +} + +/* Hash an F_triple. */ +size_t +triple_hash_no_name (void const *x, size_t table_size) +{ + struct F_triple const *p = x; + + /* Ignoring the device number here should be fine. */ + return p->st_ino % table_size; +} + +/* Compare two F_triple structs. */ +bool +triple_compare (void const *x, void const *y) +{ + struct F_triple const *a = x; + struct F_triple const *b = y; + return (SAME_INODE (*a, *b) && same_name (a->name, b->name)) ? true : false; +} + +/* Free an F_triple. */ +void +triple_free (void *x) +{ + struct F_triple *a = x; + free (a->name); + free (a); +} diff --git a/gl/lib/hash-triple.h b/gl/lib/hash-triple.h new file mode 100644 index 000000000..7abe97044 --- /dev/null +++ b/gl/lib/hash-triple.h @@ -0,0 +1,21 @@ +#ifndef HASH_TRIPLE_H +#define HASH_TRIPLE_H + +#include <sys/types.h> +#include <sys/stat.h> +#include <stdbool.h> + +/* Describe a just-created or just-renamed destination file. */ +struct F_triple +{ + char *name; + ino_t st_ino; + dev_t st_dev; +}; + +extern size_t triple_hash (void const *x, size_t table_size); +extern size_t triple_hash_no_name (void const *x, size_t table_size); +extern bool triple_compare (void const *x, void const *y); +extern void triple_free (void *x); + +#endif diff --git a/gl/modules/file-set b/gl/modules/file-set new file mode 100644 index 000000000..7895cdac1 --- /dev/null +++ b/gl/modules/file-set @@ -0,0 +1,27 @@ +Description: +Very specialized set-of-files code. + +Files: +lib/file-set.c +lib/file-set.h + +Depends-on: +hash +hash-triple +stdbool +xalloc +xalloc-die + +configure.ac: + +Makefile.am: +lib_SOURCES += file-set.c + +Include: +"file-set.h" + +License: +GPL + +Maintainer: +Jim Meyering diff --git a/gl/modules/hash-triple b/gl/modules/hash-triple new file mode 100644 index 000000000..b746d4751 --- /dev/null +++ b/gl/modules/hash-triple @@ -0,0 +1,25 @@ +Description: +Hash functions for file-related triples: name, device, inode. + +Files: +lib/hash-triple.c +lib/hash-triple.h + +Depends-on: +hash-pjw +same +same-inode + +configure.ac: + +Makefile.am: +lib_SOURCES += hash-triple.c + +Include: +"hash-triple.h" + +License: +GPL + +Maintainer: +Jim Meyering diff --git a/src/Makefile.am b/src/Makefile.am index 7e481adef..43f138c04 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -200,24 +200,27 @@ uninstall-local: rm -f $(installed_su); \ else :; fi +copy_sources = copy.c cp-hash.c + # Use `ginstall' in the definition of PROGRAMS and in dependencies to avoid # confusion with the `install' target. The install rule transforms `ginstall' # to install before applying any user-specified name transformations. transform = s/ginstall/install/; @program_transform_name@ -ginstall_SOURCES = install.c copy.c cp-hash.c +ginstall_SOURCES = install.c $(copy_sources) # This is for the '[' program. Automake transliterates '[' to '_'. __SOURCES = lbracket.c -cp_SOURCES = cp.c copy.c cp-hash.c +cp_SOURCES = cp.c $(copy_sources) dir_SOURCES = ls.c ls-dir.c vdir_SOURCES = ls.c ls-vdir.c +ln_SOURCES = ln.c ls_SOURCES = ls.c ls-ls.c chown_SOURCES = chown.c chown-core.c chgrp_SOURCES = chgrp.c chown-core.c -mv_SOURCES = mv.c copy.c cp-hash.c remove.c +mv_SOURCES = mv.c remove.c $(copy_sources) rm_SOURCES = rm.c remove.c uname_SOURCES = uname.c uname-uname.c diff --git a/src/copy.c b/src/copy.c index b7bf92a6c..c1d8519d5 100644 --- a/src/copy.c +++ b/src/copy.c @@ -44,7 +44,7 @@ #include "full-write.h" #include "getpagesize.h" #include "hash.h" -#include "hash-pjw.h" +#include "hash-triple.h" #include "lchmod.h" #include "quote.h" #include "same.h" @@ -77,14 +77,6 @@ struct dir_list dev_t dev; }; -/* Describe a just-created or just-renamed destination file. */ -struct F_triple -{ - char *name; - ino_t st_ino; - dev_t st_dev; -}; - /* Initial size of the cp.dest_info hash table. */ #define DEST_INFO_INITIAL_CAPACITY 61 @@ -904,54 +896,6 @@ overwrite_prompt (char const *dst_name, struct stat const *dst_sb) } } -/* Hash an F_triple. */ -static size_t -triple_hash (void const *x, size_t table_size) -{ - struct F_triple const *p = x; - - /* Also take the name into account, so that when moving N hard links to the - same file (all listed on the command line) all into the same directory, - we don't experience any N^2 behavior. */ - /* FIXME-maybe: is it worth the overhead of doing this - just to avoid N^2 in such an unusual case? N would have - to be very large to make the N^2 factor noticable, and - one would probably encounter a limit on the length of - a command line before it became a problem. */ - size_t tmp = hash_pjw (p->name, table_size); - - /* Ignoring the device number here should be fine. */ - return (tmp | p->st_ino) % table_size; -} - -/* Hash an F_triple. */ -static size_t -triple_hash_no_name (void const *x, size_t table_size) -{ - struct F_triple const *p = x; - - /* Ignoring the device number here should be fine. */ - return p->st_ino % table_size; -} - -/* Compare two F_triple structs. */ -static bool -triple_compare (void const *x, void const *y) -{ - struct F_triple const *a = x; - struct F_triple const *b = y; - return (SAME_INODE (*a, *b) && same_name (a->name, b->name)) ? true : false; -} - -/* Free an F_triple. */ -static void -triple_free (void *x) -{ - struct F_triple *a = x; - free (a->name); - free (a); -} - /* Initialize the hash table implementing a set of F_triple entries corresponding to destination files. */ extern void @@ -1941,7 +1885,11 @@ copy_internal (char const *src_name, char const *dst_name, } if (command_line_arg) - record_file (x->dest_info, dst_name, NULL); + { + struct stat sb; + if (lstat (dst_name, &sb) == 0) + record_file (x->dest_info, dst_name, &sb); + } if ( ! preserve_metadata) return true; |