GRUB-1.98 changes
[grub2/jjazz.git] / util / mkisofs / hash.c
blob41e76b342c4277f87faf7077a2ec2d4ae141bdfd
1 /*
2 * File hash.c - generate hash tables for iso9660 filesystem.
4 Written by Eric Youngdale (1993).
6 Copyright 1993 Yggdrasil Computing, Incorporated
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
22 #include <stdlib.h>
23 #include "config.h"
24 #include "mkisofs.h"
26 #define NR_HASH 1024
28 #define HASH_FN(DEV, INO) ((DEV + INO + (INO >> 2) + (INO << 8)) % NR_HASH)
30 static struct file_hash * hash_table[NR_HASH] = {0,};
32 void FDECL1(add_hash, struct directory_entry *, spnt){
33 struct file_hash * s_hash;
34 unsigned int hash_number;
36 if(spnt->size == 0 || spnt->starting_block == 0)
37 if(spnt->size != 0 || spnt->starting_block != 0) {
38 fprintf(stderr,"Non zero-length file assigned zero extent.\n");
39 exit(1);
42 if (spnt->dev == (dev_t) UNCACHED_DEVICE || spnt->inode == UNCACHED_INODE) return;
43 hash_number = HASH_FN((unsigned int) spnt->dev, (unsigned int) spnt->inode);
45 #if 0
46 if (verbose > 1) fprintf(stderr,"%s ",spnt->name);
47 #endif
48 s_hash = (struct file_hash *) e_malloc(sizeof(struct file_hash));
49 s_hash->next = hash_table[hash_number];
50 s_hash->inode = spnt->inode;
51 s_hash->dev = spnt->dev;
52 s_hash->starting_block = spnt->starting_block;
53 s_hash->size = spnt->size;
54 hash_table[hash_number] = s_hash;
57 struct file_hash * FDECL2(find_hash, dev_t, dev, ino_t, inode){
58 unsigned int hash_number;
59 struct file_hash * spnt;
60 hash_number = HASH_FN((unsigned int) dev, (unsigned int) inode);
61 if (dev == (dev_t) UNCACHED_DEVICE || inode == UNCACHED_INODE) return NULL;
63 spnt = hash_table[hash_number];
64 while(spnt){
65 if(spnt->inode == inode && spnt->dev == dev) return spnt;
66 spnt = spnt->next;
68 return NULL;
72 static struct file_hash * directory_hash_table[NR_HASH] = {0,};
74 void FDECL2(add_directory_hash, dev_t, dev, ino_t, inode){
75 struct file_hash * s_hash;
76 unsigned int hash_number;
78 if (dev == (dev_t) UNCACHED_DEVICE || inode == UNCACHED_INODE) return;
79 hash_number = HASH_FN((unsigned int) dev, (unsigned int) inode);
81 s_hash = (struct file_hash *) e_malloc(sizeof(struct file_hash));
82 s_hash->next = directory_hash_table[hash_number];
83 s_hash->inode = inode;
84 s_hash->dev = dev;
85 directory_hash_table[hash_number] = s_hash;
88 struct file_hash * FDECL2(find_directory_hash, dev_t, dev, ino_t, inode){
89 unsigned int hash_number;
90 struct file_hash * spnt;
91 hash_number = HASH_FN((unsigned int) dev, (unsigned int) inode);
92 if (dev == (dev_t) UNCACHED_DEVICE || inode == UNCACHED_INODE) return NULL;
94 spnt = directory_hash_table[hash_number];
95 while(spnt){
96 if(spnt->inode == inode && spnt->dev == dev) return spnt;
97 spnt = spnt->next;
99 return NULL;
102 struct name_hash
104 struct name_hash * next;
105 struct directory_entry * de;
108 #define NR_NAME_HASH 128
110 static struct name_hash * name_hash_table[NR_NAME_HASH] = {0,};
113 * Find the hash bucket for this name.
115 static unsigned int FDECL1(name_hash, const char *, name)
117 unsigned int hash = 0;
118 const char * p;
120 p = name;
122 while (*p)
125 * Don't hash the iso9660 version number. This way
126 * we can detect duplicates in cases where we have
127 * directories (i.e. foo) and non-directories
128 * (i.e. foo;1).
130 if( *p == ';' )
132 break;
134 hash = (hash << 15) + (hash << 3) + (hash >> 3) + *p++;
136 return hash % NR_NAME_HASH;
139 void FDECL1(add_file_hash, struct directory_entry *, de){
140 struct name_hash * new;
141 int hash;
143 new = (struct name_hash *) e_malloc(sizeof(struct name_hash));
144 new->de = de;
145 new->next = NULL;
146 hash = name_hash(de->isorec.name);
148 /* Now insert into the hash table */
149 new->next = name_hash_table[hash];
150 name_hash_table[hash] = new;
153 struct directory_entry * FDECL1(find_file_hash, char *, name)
155 struct name_hash * nh;
156 char * p1;
157 char * p2;
159 for(nh = name_hash_table[name_hash(name)]; nh; nh = nh->next)
161 p1 = name;
162 p2 = nh->de->isorec.name;
165 * Look for end of string, or a mismatch.
167 while(1==1)
169 if( (*p1 == '\0' || *p1 == ';')
170 || (*p2 == '\0' || *p2 == ';')
171 || (*p1 != *p2) )
173 break;
175 p1++;
176 p2++;
180 * If we are at the end of both strings, then
181 * we have a match.
183 if( (*p1 == '\0' || *p1 == ';')
184 && (*p2 == '\0' || *p2 == ';') )
186 return nh->de;
189 return NULL;
192 int FDECL1(delete_file_hash, struct directory_entry *, de){
193 struct name_hash * nh, *prev;
194 int hash;
196 prev = NULL;
197 hash = name_hash(de->isorec.name);
198 for(nh = name_hash_table[hash]; nh; nh = nh->next) {
199 if(nh->de == de) break;
200 prev = nh;
202 if(!nh) return 1;
203 if(!prev)
204 name_hash_table[hash] = nh->next;
205 else
206 prev->next = nh->next;
207 free(nh);
208 return 0;
211 void flush_file_hash(){
212 struct name_hash * nh, *nh1;
213 int i;
215 for(i=0; i<NR_NAME_HASH; i++) {
216 nh = name_hash_table[i];
217 while(nh) {
218 nh1 = nh->next;
219 free(nh);
220 nh = nh1;
222 name_hash_table[i] = NULL;