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)
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. */
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");
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
);
46 if (verbose
> 1) fprintf(stderr
,"%s ",spnt
->name
);
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
];
65 if(spnt
->inode
== inode
&& spnt
->dev
== dev
) return spnt
;
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
;
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
];
96 if(spnt
->inode
== inode
&& spnt
->dev
== dev
) return spnt
;
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;
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
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;
143 new = (struct name_hash
*) e_malloc(sizeof(struct name_hash
));
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
;
159 for(nh
= name_hash_table
[name_hash(name
)]; nh
; nh
= nh
->next
)
162 p2
= nh
->de
->isorec
.name
;
165 * Look for end of string, or a mismatch.
169 if( (*p1
== '\0' || *p1
== ';')
170 || (*p2
== '\0' || *p2
== ';')
180 * If we are at the end of both strings, then
183 if( (*p1
== '\0' || *p1
== ';')
184 && (*p2
== '\0' || *p2
== ';') )
192 int FDECL1(delete_file_hash
, struct directory_entry
*, de
){
193 struct name_hash
* nh
, *prev
;
197 hash
= name_hash(de
->isorec
.name
);
198 for(nh
= name_hash_table
[hash
]; nh
; nh
= nh
->next
) {
199 if(nh
->de
== de
) break;
204 name_hash_table
[hash
] = nh
->next
;
206 prev
->next
= nh
->next
;
211 void flush_file_hash(){
212 struct name_hash
* nh
, *nh1
;
215 for(i
=0; i
<NR_NAME_HASH
; i
++) {
216 nh
= name_hash_table
[i
];
222 name_hash_table
[i
] = NULL
;