386BSD 0.1 development
authorWilliam F. Jolitz <wjolitz@soda.berkeley.edu>
Fri, 30 Aug 1991 05:24:26 +0000 (21:24 -0800)
committerWilliam F. Jolitz <wjolitz@soda.berkeley.edu>
Fri, 30 Aug 1991 05:24:26 +0000 (21:24 -0800)
Work on file usr/othersrc/public/fileutils-3.2/fileutils-3.2/src/cp-hash.c

Co-Authored-By: Lynne Greer Jolitz <ljolitz@cardio.ucsf.edu>
Synthesized-from: 386BSD-0.1

usr/othersrc/public/fileutils-3.2/fileutils-3.2/src/cp-hash.c [new file with mode: 0644]

diff --git a/usr/othersrc/public/fileutils-3.2/fileutils-3.2/src/cp-hash.c b/usr/othersrc/public/fileutils-3.2/fileutils-3.2/src/cp-hash.c
new file mode 100644 (file)
index 0000000..a0afcfc
--- /dev/null
@@ -0,0 +1,217 @@
+/* cp-hash.c  -- file copying (hash search routines)
+   Copyright (C) 1989, 1990, 1991 Free Software Foundation.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+   Written by Torbjorn Granlund, Sweden (tege@sics.se). */
+
+#include <stdio.h>
+#include "cp.h"
+
+char *hash_insert ();
+char *hash_insert2 ();
+
+struct htab *htab;
+char new_file;
+
+/* Add PATH to the list of files that we have created.
+   Return 0 if successful, 1 if not. */
+
+int
+remember_created (path)
+     char *path;
+{
+  struct stat sb;
+
+  if (stat (path, &sb) < 0)
+    {
+      error (0, errno, "%s", path);
+      return 1;
+    }
+
+  hash_insert (sb.st_ino, sb.st_dev, &new_file);
+  return 0;
+}
+
+/* Add path NODE, copied from inode number INO and device number DEV,
+   to the list of files we have copied.
+   Return NULL if inserted, otherwise non-NULL. */
+
+char *
+remember_copied (node, ino, dev)
+     char *node;
+     ino_t ino;
+     dev_t dev;
+{
+  return hash_insert (ino, dev, node);
+}
+
+/* Allocate space for the hash structures, and set the global
+   variable `htab' to point to it.  The initial hash module is specified in
+   MODULUS, and the number of entries are specified in ENTRY_TAB_SIZE.  (The
+   hash structure will be rebuilt when ENTRY_TAB_SIZE entries have been
+   inserted, and MODULUS and ENTRY_TAB_SIZE in the global `htab' will be
+   doubled.)  */
+
+void
+hash_init (modulus, entry_tab_size)
+     unsigned modulus;
+     unsigned entry_tab_size;
+{
+  struct htab *htab_r;
+
+  htab_r = (struct htab *)
+    xmalloc (sizeof (struct htab) + sizeof (struct entry *) * modulus);
+
+  htab_r->entry_tab = (struct entry *)
+    xmalloc (sizeof (struct entry) * entry_tab_size);
+
+  htab_r->modulus = modulus;
+  htab_r->entry_tab_size = entry_tab_size;
+  htab = htab_r;
+
+  forget_all ();
+}
+
+/* Reset the hash structure in the global variable `htab' to
+   contain no entries.  */
+
+void
+forget_all ()
+{
+  int i;
+  struct entry **p;
+
+  htab->first_free_entry = 0;
+
+  p = htab->hash;
+  for (i = htab->modulus; i > 0; i--)
+    *p++ = NULL;
+}
+\f
+/* Insert path NODE, copied from inode number INO and device number DEV,
+   into the hash structure in the global variable `htab', if an entry with
+   the same inode and device was not found already.
+   Return NULL if inserted, otherwise non-NULL. */
+
+char *
+hash_insert (ino, dev, node)
+     ino_t ino;
+     dev_t dev;
+     char *node;
+{
+  struct htab *htab_r = htab;
+
+  if (htab_r->first_free_entry >= htab_r->entry_tab_size)
+    {
+      int i;
+      struct entry *ep;
+      unsigned modulus;
+      unsigned entry_tab_size;
+
+      /* Increase the number of hash entries, and re-hash the data.
+        The method of shrinking and increasing is made to compactify
+        the heap.  If twice as much data would be allocated
+        straightforwardly, we would never re-use a byte of memory.  */
+
+      /* Let htab shrink.  Keep only the header, not the pointer vector.  */
+
+      htab_r = (struct htab *)
+       xrealloc ((char *) htab_r, sizeof (struct htab));
+
+      modulus = 2 * htab_r->modulus;
+      entry_tab_size = 2 * htab_r->entry_tab_size;
+
+      /* Increase the number of possible entries.  */
+
+      htab_r->entry_tab = (struct entry *)
+       xrealloc ((char *) htab_r->entry_tab,
+                 sizeof (struct entry) * entry_tab_size);
+
+      /* Increase the size of htab again.  */
+
+      htab_r = (struct htab *)
+       xrealloc ((char *) htab_r,
+                 sizeof (struct htab) + sizeof (struct entry *) * modulus);
+
+      htab_r->modulus = modulus;
+      htab_r->entry_tab_size = entry_tab_size;
+      htab = htab_r;
+
+      i = htab_r->first_free_entry;
+
+      /* Make the increased hash table empty.  The entries are still
+        available in htab->entry_tab.  */
+
+      forget_all ();
+
+      /* Go through the entries and install them in the pointer vector
+        htab->hash.  The items are actually inserted in htab->entry_tab at
+        the position where they already are.  The htab->coll_link need
+        however be updated.  Could be made a little more efficient.  */
+
+      for (ep = htab_r->entry_tab; i > 0; i--)
+       {
+         hash_insert2 (htab_r, ep->ino, ep->dev, ep->node);
+         ep++;
+       }
+    }
+
+  return hash_insert2 (htab_r, ino, dev, node);
+}
+
+/* Insert path NODE, copied from inode number INO and device number DEV,
+   into the hash structure HTAB, if not already present.
+   Return NULL if inserted, otherwise non-NULL. */
+
+char *
+hash_insert2 (htab, ino, dev, node)
+     struct htab *htab;
+     ino_t ino;
+     dev_t dev;
+     char *node;
+{
+  struct entry **hp, *ep2, *ep;
+  hp = &htab->hash[ino % htab->modulus];
+  ep2 = *hp;
+
+  /* Collision?  */
+
+  if (ep2 != NULL)
+    {
+      ep = ep2;
+
+      /* Search for an entry with the same data.  */
+
+      do
+       {
+         if (ep->ino == ino && ep->dev == dev)
+           return ep->node;    /* Found an entry with the same data.  */
+         ep = ep->coll_link;
+       }
+      while (ep != NULL);
+
+      /* Did not find it.  */
+
+    }
+
+  ep = *hp = &htab->entry_tab[htab->first_free_entry++];
+  ep->ino = ino;
+  ep->dev = dev;
+  ep->node = node;
+  ep->coll_link = ep2;         /* ep2 is NULL if not collision.  */
+
+  return NULL;
+}