1 /* cp-hash.c -- file copying (hash search routines)
2 Copyright (C) 1989, 1990, 1991, 1995 Free Software Foundation.
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 2, or (at your option)
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.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 Written by Torbjorn Granlund, Sweden (tege@sics.se). */
25 char *hash_insert2 ();
30 /* Add PATH to the list of files that we have created.
31 Return 0 if successful, 1 if not. */
34 remember_created (path
)
39 if (stat (path
, &sb
) < 0)
41 error (0, errno
, "%s", path
);
45 hash_insert (sb
.st_ino
, sb
.st_dev
, &new_file
);
49 /* Add path NODE, copied from inode number INO and device number DEV,
50 to the list of files we have copied.
51 Return NULL if inserted, otherwise non-NULL. */
54 remember_copied (node
, ino
, dev
)
59 return hash_insert (ino
, dev
, node
);
62 /* Allocate space for the hash structures, and set the global
63 variable `htab' to point to it. The initial hash module is specified in
64 MODULUS, and the number of entries are specified in ENTRY_TAB_SIZE. (The
65 hash structure will be rebuilt when ENTRY_TAB_SIZE entries have been
66 inserted, and MODULUS and ENTRY_TAB_SIZE in the global `htab' will be
70 hash_init (modulus
, entry_tab_size
)
72 unsigned entry_tab_size
;
76 htab_r
= (struct htab
*)
77 xmalloc (sizeof (struct htab
) + sizeof (struct entry
*) * modulus
);
79 htab_r
->entry_tab
= (struct entry
*)
80 xmalloc (sizeof (struct entry
) * entry_tab_size
);
82 htab_r
->modulus
= modulus
;
83 htab_r
->entry_tab_size
= entry_tab_size
;
89 /* Reset the hash structure in the global variable `htab' to
90 contain no entries. */
98 htab
->first_free_entry
= 0;
101 for (i
= htab
->modulus
; i
> 0; i
--)
105 /* Insert path NODE, copied from inode number INO and device number DEV,
106 into the hash structure in the global variable `htab', if an entry with
107 the same inode and device was not found already.
108 Return NULL if inserted, otherwise non-NULL. */
111 hash_insert (ino
, dev
, node
)
116 struct htab
*htab_r
= htab
;
118 if (htab_r
->first_free_entry
>= htab_r
->entry_tab_size
)
123 unsigned entry_tab_size
;
125 /* Increase the number of hash entries, and re-hash the data.
126 The method of shrinking and increasing is made to compactify
127 the heap. If twice as much data would be allocated
128 straightforwardly, we would never re-use a byte of memory. */
130 /* Let htab shrink. Keep only the header, not the pointer vector. */
132 htab_r
= (struct htab
*)
133 xrealloc ((char *) htab_r
, sizeof (struct htab
));
135 modulus
= 2 * htab_r
->modulus
;
136 entry_tab_size
= 2 * htab_r
->entry_tab_size
;
138 /* Increase the number of possible entries. */
140 htab_r
->entry_tab
= (struct entry
*)
141 xrealloc ((char *) htab_r
->entry_tab
,
142 sizeof (struct entry
) * entry_tab_size
);
144 /* Increase the size of htab again. */
146 htab_r
= (struct htab
*)
147 xrealloc ((char *) htab_r
,
148 sizeof (struct htab
) + sizeof (struct entry
*) * modulus
);
150 htab_r
->modulus
= modulus
;
151 htab_r
->entry_tab_size
= entry_tab_size
;
154 i
= htab_r
->first_free_entry
;
156 /* Make the increased hash table empty. The entries are still
157 available in htab->entry_tab. */
161 /* Go through the entries and install them in the pointer vector
162 htab->hash. The items are actually inserted in htab->entry_tab at
163 the position where they already are. The htab->coll_link need
164 however be updated. Could be made a little more efficient. */
166 for (ep
= htab_r
->entry_tab
; i
> 0; i
--)
168 hash_insert2 (htab_r
, ep
->ino
, ep
->dev
, ep
->node
);
173 return hash_insert2 (htab_r
, ino
, dev
, node
);
176 /* Insert path NODE, copied from inode number INO and device number DEV,
177 into the hash structure HTAB, if not already present.
178 Return NULL if inserted, otherwise non-NULL. */
181 hash_insert2 (htab
, ino
, dev
, node
)
187 struct entry
**hp
, *ep2
, *ep
;
188 hp
= &htab
->hash
[ino
% htab
->modulus
];
197 /* Search for an entry with the same data. */
201 if (ep
->ino
== ino
&& ep
->dev
== dev
)
202 return ep
->node
; /* Found an entry with the same data. */
207 /* Did not find it. */
211 ep
= *hp
= &htab
->entry_tab
[htab
->first_free_entry
++];
215 ep
->coll_link
= ep2
; /* ep2 is NULL if not collision. */