LCOV - code coverage report
Current view: top level - src - cp-hash.c (source / functions) Hit Total Coverage
Test: coreutils.info Lines: 41 51 80.4 %
Date: 2018-01-30 Functions: 8 9 88.9 %

          Line data    Source code
       1             : /* cp-hash.c  -- file copying (hash search routines)
       2             :    Copyright (C) 89, 90, 91, 1995-2008 Free Software Foundation, Inc.
       3             : 
       4             :    This program is free software: you can redistribute it and/or modify
       5             :    it under the terms of the GNU General Public License as published by
       6             :    the Free Software Foundation, either version 3 of the License, or
       7             :    (at your option) any later version.
       8             : 
       9             :    This program is distributed in the hope that it will be useful,
      10             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12             :    GNU General Public License for more details.
      13             : 
      14             :    You should have received a copy of the GNU General Public License
      15             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      16             : 
      17             :    Written by Torbjorn Granlund, Sweden (tege@sics.se).
      18             :    Rewritten to use lib/hash.c by Jim Meyering.  */
      19             : 
      20             : #include <config.h>
      21             : 
      22             : #include <stdio.h>
      23             : #include <sys/types.h>
      24             : #include "system.h"
      25             : 
      26             : #include "same.h"
      27             : #include "quote.h"
      28             : #include "hash.h"
      29             : #include "error.h"
      30             : #include "cp-hash.h"
      31             : 
      32             : /* Use ST_DEV and ST_INO as the key, FILENAME as the value.
      33             :    These are used e.g., in copy.c to associate the destination name with
      34             :    the source device/inode pair so that if we encounter a matching dev/ino
      35             :    pair in the source tree we can arrange to create a hard link between
      36             :    the corresponding names in the destination tree.  */
      37             : struct Src_to_dest
      38             : {
      39             :   ino_t st_ino;
      40             :   dev_t st_dev;
      41             :   /* Destination file name (of non-directory or pre-existing directory)
      42             :      corresponding to the dev/ino of a copied file, or the destination file
      43             :      name corresponding to a dev/ino pair for a newly-created directory. */
      44             :   char *name;
      45             : };
      46             : 
      47             : /* This table maps source dev/ino to destination file name.
      48             :    We use it to preserve hard links when copying.  */
      49             : static Hash_table *src_to_dest;
      50             : 
      51             : /* Initial size of the above hash table.  */
      52             : #define INITIAL_TABLE_SIZE 103
      53             : 
      54             : static size_t
      55        1094 : src_to_dest_hash (void const *x, size_t table_size)
      56             : {
      57        1094 :   struct Src_to_dest const *p = x;
      58             : 
      59             :   /* Ignoring the device number here should be fine.  */
      60             :   /* The cast to uintmax_t prevents negative remainders
      61             :      if st_ino is negative.  */
      62        1094 :   return (uintmax_t) p->st_ino % table_size;
      63             : }
      64             : 
      65             : /* Compare two Src_to_dest entries.
      66             :    Return true if their keys are judged `equal'.  */
      67             : static bool
      68          26 : src_to_dest_compare (void const *x, void const *y)
      69             : {
      70          26 :   struct Src_to_dest const *a = x;
      71          26 :   struct Src_to_dest const *b = y;
      72          26 :   return SAME_INODE (*a, *b) ? true : false;
      73             : }
      74             : 
      75             : static void
      76          20 : src_to_dest_free (void *x)
      77             : {
      78          20 :   struct Src_to_dest *a = x;
      79          20 :   free (a->name);
      80          20 :   free (x);
      81          20 : }
      82             : 
      83             : /* Remove the entry matching INO/DEV from the table
      84             :    that maps source ino/dev to destination file name.  */
      85             : extern void
      86        1065 : forget_created (ino_t ino, dev_t dev)
      87             : {
      88             :   struct Src_to_dest probe;
      89             :   struct Src_to_dest *ent;
      90             : 
      91        1065 :   probe.st_ino = ino;
      92        1065 :   probe.st_dev = dev;
      93        1065 :   probe.name = NULL;
      94             : 
      95        1065 :   ent = hash_delete (src_to_dest, &probe);
      96        1065 :   if (ent)
      97          17 :     src_to_dest_free (ent);
      98        1065 : }
      99             : 
     100             : /* Add FILE to the list of files that we have created.
     101             :    Return true if successful.  */
     102             : 
     103             : extern bool
     104           0 : remember_created (char const *file)
     105             : {
     106             :   struct stat sb;
     107             : 
     108           0 :   if (stat (file, &sb) < 0)
     109             :     {
     110           0 :       error (0, errno, "%s", quote (file));
     111           0 :       return false;
     112             :     }
     113             : 
     114           0 :   remember_copied (file, sb.st_ino, sb.st_dev);
     115           0 :   return true;
     116             : }
     117             : 
     118             : /* If INO/DEV correspond to an already-copied source file, return the
     119             :    name of the corresponding destination file.  Otherwise, return NULL.  */
     120             : 
     121             : extern char *
     122           8 : src_to_dest_lookup (ino_t ino, dev_t dev)
     123             : {
     124             :   struct Src_to_dest ent;
     125             :   struct Src_to_dest const *e;
     126           8 :   ent.st_ino = ino;
     127           8 :   ent.st_dev = dev;
     128           8 :   e = hash_lookup (src_to_dest, &ent);
     129           8 :   return e ? e->name : NULL;
     130             : }
     131             : 
     132             : /* Add file NAME, copied from inode number INO and device number DEV,
     133             :    to the list of files we have copied.
     134             :    Return NULL if inserted, otherwise non-NULL. */
     135             : 
     136             : extern char *
     137          21 : remember_copied (const char *name, ino_t ino, dev_t dev)
     138             : {
     139             :   struct Src_to_dest *ent;
     140             :   struct Src_to_dest *ent_from_table;
     141             : 
     142          21 :   ent = xmalloc (sizeof *ent);
     143          21 :   ent->name = xstrdup (name);
     144          21 :   ent->st_ino = ino;
     145          21 :   ent->st_dev = dev;
     146             : 
     147          21 :   ent_from_table = hash_insert (src_to_dest, ent);
     148          21 :   if (ent_from_table == NULL)
     149             :     {
     150             :       /* Insertion failed due to lack of memory.  */
     151           0 :       xalloc_die ();
     152             :     }
     153             : 
     154             :   /* Determine whether there was already an entry in the table
     155             :      with a matching key.  If so, free ENT (it wasn't inserted) and
     156             :      return the `name' from the table entry.  */
     157          21 :   if (ent_from_table != ent)
     158             :     {
     159           0 :       src_to_dest_free (ent);
     160           0 :       return (char *) ent_from_table->name;
     161             :     }
     162             : 
     163             :   /* New key;  insertion succeeded.  */
     164          21 :   return NULL;
     165             : }
     166             : 
     167             : /* Initialize the hash table.  */
     168             : extern void
     169         299 : hash_init (void)
     170             : {
     171         299 :   src_to_dest = hash_initialize (INITIAL_TABLE_SIZE, NULL,
     172             :                                  src_to_dest_hash,
     173             :                                  src_to_dest_compare,
     174             :                                  src_to_dest_free);
     175         299 :   if (src_to_dest == NULL)
     176           0 :     xalloc_die ();
     177         299 : }
     178             : 
     179             : /* Reset the hash structure in the global variable `htab' to
     180             :    contain no entries.  */
     181             : 
     182             : extern void
     183         101 : forget_all (void)
     184             : {
     185         101 :   hash_free (src_to_dest);
     186         101 : }

Generated by: LCOV version 1.10