diff options
Diffstat (limited to 'gl/lib')
-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 |
4 files changed, 146 insertions, 0 deletions
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 |