1c2f99d7cSDavid van Moolenbroek
2c2f99d7cSDavid van Moolenbroek /*
3c2f99d7cSDavid van Moolenbroek * This file contains all the function that handle the dir records
4c2f99d7cSDavid van Moolenbroek * (inodes) for the ISO9660 filesystem.
5c2f99d7cSDavid van Moolenbroek */
6c2f99d7cSDavid van Moolenbroek
7c2f99d7cSDavid van Moolenbroek #include "inc.h"
8c2f99d7cSDavid van Moolenbroek
9b1d06847SJean-Baptiste Boric #include "uthash.h"
10b1d06847SJean-Baptiste Boric
11b1d06847SJean-Baptiste Boric struct inode_cache {
12b1d06847SJean-Baptiste Boric ino_t key;
13b1d06847SJean-Baptiste Boric struct inode *value;
14b1d06847SJean-Baptiste Boric UT_hash_handle hh;
15b1d06847SJean-Baptiste Boric } ;
16b1d06847SJean-Baptiste Boric
17b1d06847SJean-Baptiste Boric struct inode_cache *icache = NULL;
18b1d06847SJean-Baptiste Boric
19b1d06847SJean-Baptiste Boric void read_inode_iso9660(struct inode_dir_entry *i,
20b1d06847SJean-Baptiste Boric const struct iso9660_dir_record *dir_rec, struct dir_extent *extent,
21b1d06847SJean-Baptiste Boric size_t offset, int name_only);
22b1d06847SJean-Baptiste Boric
23b1d06847SJean-Baptiste Boric #ifdef ISO9660_OPTION_MODE3
24b1d06847SJean-Baptiste Boric static void read_inode_extents(struct inode_dir_entry *i,
25b1d06847SJean-Baptiste Boric const struct iso9660_dir_record *dir_rec, struct dir_extent *extent,
26b1d06847SJean-Baptiste Boric size_t *offset);
27b1d06847SJean-Baptiste Boric #endif
28b1d06847SJean-Baptiste Boric
29b1d06847SJean-Baptiste Boric #ifdef ISO9660_OPTION_ROCKRIDGE
30b1d06847SJean-Baptiste Boric void read_inode_susp(struct inode_dir_entry *i,
31b1d06847SJean-Baptiste Boric const struct iso9660_dir_record *dir_rec, struct buf *bp, size_t offset,
32b1d06847SJean-Baptiste Boric int name_only);
33b1d06847SJean-Baptiste Boric #endif
34b1d06847SJean-Baptiste Boric
35b1d06847SJean-Baptiste Boric static int check_dir_record(const struct iso9660_dir_record *d, size_t offset);
36c2f99d7cSDavid van Moolenbroek
fs_putnode(ino_t ino_nr,unsigned int count)37c2f99d7cSDavid van Moolenbroek int fs_putnode(ino_t ino_nr, unsigned int count)
38c2f99d7cSDavid van Moolenbroek {
39c2f99d7cSDavid van Moolenbroek /*
40c2f99d7cSDavid van Moolenbroek * Find the inode specified by the request message and decrease its
41c2f99d7cSDavid van Moolenbroek * counter.
42c2f99d7cSDavid van Moolenbroek */
43c2f99d7cSDavid van Moolenbroek struct inode *i_node;
44c2f99d7cSDavid van Moolenbroek
45b1d06847SJean-Baptiste Boric if ((i_node = get_inode(ino_nr)) == NULL) {
46b1d06847SJean-Baptiste Boric puts("ISOFS: trying to free unused inode");
47c2f99d7cSDavid van Moolenbroek return EINVAL;
48c2f99d7cSDavid van Moolenbroek }
49c2f99d7cSDavid van Moolenbroek if (count > i_node->i_count) {
50b1d06847SJean-Baptiste Boric puts("ISOFS: put_node count too high");
51c2f99d7cSDavid van Moolenbroek return EINVAL;
52c2f99d7cSDavid van Moolenbroek }
53c2f99d7cSDavid van Moolenbroek
54c2f99d7cSDavid van Moolenbroek i_node->i_count -= count - 1;
55c2f99d7cSDavid van Moolenbroek put_inode(i_node);
56c2f99d7cSDavid van Moolenbroek return OK;
57c2f99d7cSDavid van Moolenbroek }
58c2f99d7cSDavid van Moolenbroek
59c2f99d7cSDavid van Moolenbroek
get_inode(ino_t ino_nr)60b1d06847SJean-Baptiste Boric struct inode* get_inode(ino_t ino_nr) {
61b1d06847SJean-Baptiste Boric /* Return an already opened inode from cache. */
62b1d06847SJean-Baptiste Boric struct inode *i_node = inode_cache_get(ino_nr);
63c2f99d7cSDavid van Moolenbroek
64b1d06847SJean-Baptiste Boric if (i_node == NULL)
65b1d06847SJean-Baptiste Boric return NULL;
66c2f99d7cSDavid van Moolenbroek
67b1d06847SJean-Baptiste Boric if (i_node->i_count == 0)
68b1d06847SJean-Baptiste Boric return NULL;
69c2f99d7cSDavid van Moolenbroek
70c2f99d7cSDavid van Moolenbroek return i_node;
71c2f99d7cSDavid van Moolenbroek }
72c2f99d7cSDavid van Moolenbroek
open_inode(ino_t ino_nr)73b1d06847SJean-Baptiste Boric struct inode* open_inode(ino_t ino_nr) {
74b1d06847SJean-Baptiste Boric /* Return an inode from cache. */
75b1d06847SJean-Baptiste Boric struct inode *i_node = inode_cache_get(ino_nr);
76b1d06847SJean-Baptiste Boric if (i_node == NULL)
77c2f99d7cSDavid van Moolenbroek return NULL;
78c2f99d7cSDavid van Moolenbroek
79b1d06847SJean-Baptiste Boric i_node->i_count++;
80c2f99d7cSDavid van Moolenbroek
81c2f99d7cSDavid van Moolenbroek return i_node;
82c2f99d7cSDavid van Moolenbroek }
83c2f99d7cSDavid van Moolenbroek
put_inode(struct inode * i_node)84b1d06847SJean-Baptiste Boric void put_inode(struct inode *i_node) {
85c2f99d7cSDavid van Moolenbroek if (i_node == NULL)
86c2f99d7cSDavid van Moolenbroek return;
87c2f99d7cSDavid van Moolenbroek
88c2f99d7cSDavid van Moolenbroek assert(i_node->i_count > 0);
89c2f99d7cSDavid van Moolenbroek i_node->i_count--;
90b1d06847SJean-Baptiste Boric
91b1d06847SJean-Baptiste Boric if(i_node->i_count == 0)
92b1d06847SJean-Baptiste Boric i_node->i_mountpoint = FALSE;
93c2f99d7cSDavid van Moolenbroek }
94c2f99d7cSDavid van Moolenbroek
dup_inode(struct inode * i_node)95b1d06847SJean-Baptiste Boric void dup_inode(struct inode *i_node) {
96c2f99d7cSDavid van Moolenbroek assert(i_node != NULL);
97b1d06847SJean-Baptiste Boric assert(i_node->i_count > 0);
98c2f99d7cSDavid van Moolenbroek
99c2f99d7cSDavid van Moolenbroek i_node->i_count++;
100c2f99d7cSDavid van Moolenbroek }
101c2f99d7cSDavid van Moolenbroek
read_directory(struct inode * dir)102b1d06847SJean-Baptiste Boric int read_directory(struct inode *dir) {
103*3e2c6c96SDavid van Moolenbroek #define MAX_ENTRIES 256 /* avoid using lots of stack.. */
104b1d06847SJean-Baptiste Boric /* Read all entries in a directory. */
105*3e2c6c96SDavid van Moolenbroek size_t pos = 0, saved_pos, cur_entry, num_entries, cpt;
106*3e2c6c96SDavid van Moolenbroek struct inode_dir_entry entries[MAX_ENTRIES + 1];
107*3e2c6c96SDavid van Moolenbroek int status;
108c2f99d7cSDavid van Moolenbroek
109b1d06847SJean-Baptiste Boric if (dir->dir_contents)
110b1d06847SJean-Baptiste Boric return OK;
111b1d06847SJean-Baptiste Boric
112b1d06847SJean-Baptiste Boric if (!S_ISDIR(dir->i_stat.st_mode))
113b1d06847SJean-Baptiste Boric return ENOTDIR;
114b1d06847SJean-Baptiste Boric
115*3e2c6c96SDavid van Moolenbroek /*
116*3e2c6c96SDavid van Moolenbroek * We do not know how many inode entries we will find, but we want to
117*3e2c6c96SDavid van Moolenbroek * allocate an array of the right size for dir->dir_contents. First
118*3e2c6c96SDavid van Moolenbroek * find out how many entries there are, and store up to MAX_ENTRIES of
119*3e2c6c96SDavid van Moolenbroek * them into a temporary array on the stack. If there are more than
120*3e2c6c96SDavid van Moolenbroek * MAX_ENTRIES entries, we have to do a second pass on the part of the
121*3e2c6c96SDavid van Moolenbroek * directory that we did not manage to fit in the temporary array.
122*3e2c6c96SDavid van Moolenbroek *
123*3e2c6c96SDavid van Moolenbroek * The entire service needs massive structural improvement (and in
124*3e2c6c96SDavid van Moolenbroek * particular, no dynamic memory allocation like this), but for now
125*3e2c6c96SDavid van Moolenbroek * this is the simplest way to be fast for small directories while at
126*3e2c6c96SDavid van Moolenbroek * the same time supporting seriously large directories.
127*3e2c6c96SDavid van Moolenbroek */
128*3e2c6c96SDavid van Moolenbroek cur_entry = 0;
129*3e2c6c96SDavid van Moolenbroek num_entries = 0;
130b1d06847SJean-Baptiste Boric
131*3e2c6c96SDavid van Moolenbroek while ((status = read_inode(&entries[cur_entry], &dir->extent,
132*3e2c6c96SDavid van Moolenbroek &pos)) == OK) {
133b1d06847SJean-Baptiste Boric /* Dump the entry if it's not to be exported to userland. */
134b1d06847SJean-Baptiste Boric if (entries[cur_entry].i_node->skip) {
135b1d06847SJean-Baptiste Boric free_inode_dir_entry(&entries[cur_entry]);
136b1d06847SJean-Baptiste Boric continue;
137b1d06847SJean-Baptiste Boric }
138*3e2c6c96SDavid van Moolenbroek
139*3e2c6c96SDavid van Moolenbroek if (cur_entry < MAX_ENTRIES) {
140*3e2c6c96SDavid van Moolenbroek cur_entry++;
141*3e2c6c96SDavid van Moolenbroek
142*3e2c6c96SDavid van Moolenbroek /*
143*3e2c6c96SDavid van Moolenbroek * As long as more entries fit in the temporary array,
144*3e2c6c96SDavid van Moolenbroek * update the saved position of the next entry. Once
145*3e2c6c96SDavid van Moolenbroek * we hit the first entry that does not fit (if any),
146*3e2c6c96SDavid van Moolenbroek * the updating stops and we will have the correct
147*3e2c6c96SDavid van Moolenbroek * saved position.
148*3e2c6c96SDavid van Moolenbroek */
149*3e2c6c96SDavid van Moolenbroek saved_pos = pos;
150*3e2c6c96SDavid van Moolenbroek } else {
151*3e2c6c96SDavid van Moolenbroek /*
152*3e2c6c96SDavid van Moolenbroek * No room in the temporary array. Free the entry
153*3e2c6c96SDavid van Moolenbroek * again. This is costly but only for those rare
154*3e2c6c96SDavid van Moolenbroek * directories that have more than MAX_ENTRIES entries.
155*3e2c6c96SDavid van Moolenbroek */
156*3e2c6c96SDavid van Moolenbroek free_inode_dir_entry(&entries[cur_entry]);
157c2f99d7cSDavid van Moolenbroek }
158c2f99d7cSDavid van Moolenbroek
159*3e2c6c96SDavid van Moolenbroek num_entries++;
160*3e2c6c96SDavid van Moolenbroek }
161*3e2c6c96SDavid van Moolenbroek
162*3e2c6c96SDavid van Moolenbroek /*
163*3e2c6c96SDavid van Moolenbroek * Allocate a dynamic array of the correct size, and populate it with
164*3e2c6c96SDavid van Moolenbroek * all the entries in the temporary array. For large directories, the
165*3e2c6c96SDavid van Moolenbroek * temporary array will have partial results, in which case we have to
166*3e2c6c96SDavid van Moolenbroek * do a second pass on the rest below.
167*3e2c6c96SDavid van Moolenbroek */
168*3e2c6c96SDavid van Moolenbroek dir->dir_contents =
169*3e2c6c96SDavid van Moolenbroek alloc_mem(sizeof(struct inode_dir_entry) * num_entries);
170*3e2c6c96SDavid van Moolenbroek
171*3e2c6c96SDavid van Moolenbroek memcpy(dir->dir_contents, entries,
172*3e2c6c96SDavid van Moolenbroek sizeof(struct inode_dir_entry) * cur_entry);
173*3e2c6c96SDavid van Moolenbroek
174*3e2c6c96SDavid van Moolenbroek /*
175*3e2c6c96SDavid van Moolenbroek * The second pass. This pass starts from the saved position and reads
176*3e2c6c96SDavid van Moolenbroek * only the entries that did not fit in the temporary array. This time
177*3e2c6c96SDavid van Moolenbroek * we can read straight into the actual destination array. We expect
178*3e2c6c96SDavid van Moolenbroek * to find the same entries as during the first pass.
179*3e2c6c96SDavid van Moolenbroek */
180*3e2c6c96SDavid van Moolenbroek while (cur_entry < num_entries) {
181*3e2c6c96SDavid van Moolenbroek if (read_inode(&dir->dir_contents[cur_entry], &dir->extent,
182*3e2c6c96SDavid van Moolenbroek &saved_pos) != OK)
183*3e2c6c96SDavid van Moolenbroek panic("unexpected EOF or error rereading directory");
184*3e2c6c96SDavid van Moolenbroek
185*3e2c6c96SDavid van Moolenbroek if (dir->dir_contents[cur_entry].i_node->skip) {
186*3e2c6c96SDavid van Moolenbroek free_inode_dir_entry(&entries[cur_entry]);
187*3e2c6c96SDavid van Moolenbroek continue;
188*3e2c6c96SDavid van Moolenbroek }
189*3e2c6c96SDavid van Moolenbroek
190*3e2c6c96SDavid van Moolenbroek cur_entry++;
191*3e2c6c96SDavid van Moolenbroek }
192*3e2c6c96SDavid van Moolenbroek
193*3e2c6c96SDavid van Moolenbroek dir->dir_size = num_entries;
194b1d06847SJean-Baptiste Boric
195b1d06847SJean-Baptiste Boric /* The name pointer has to point to the new memory location. */
196*3e2c6c96SDavid van Moolenbroek for (cpt = 0; cpt < num_entries; cpt++) {
197b1d06847SJean-Baptiste Boric if (dir->dir_contents[cpt].r_name == NULL)
198b1d06847SJean-Baptiste Boric dir->dir_contents[cpt].name =
199b1d06847SJean-Baptiste Boric dir->dir_contents[cpt].i_name;
200b1d06847SJean-Baptiste Boric else
201b1d06847SJean-Baptiste Boric dir->dir_contents[cpt].name =
202b1d06847SJean-Baptiste Boric dir->dir_contents[cpt].r_name;
203c2f99d7cSDavid van Moolenbroek }
204c2f99d7cSDavid van Moolenbroek
205b1d06847SJean-Baptiste Boric return (status == EOF) ? OK : status;
206c2f99d7cSDavid van Moolenbroek }
207c2f99d7cSDavid van Moolenbroek
check_inodes(void)208b1d06847SJean-Baptiste Boric int check_inodes(void) {
209b1d06847SJean-Baptiste Boric /* Check whether there are no more inodes in use. Called on unmount. */
210b1d06847SJean-Baptiste Boric int i;
211b1d06847SJean-Baptiste Boric
212b1d06847SJean-Baptiste Boric /* XXX: actually check for inodes in use. */
213b1d06847SJean-Baptiste Boric return TRUE;
214b1d06847SJean-Baptiste Boric }
215b1d06847SJean-Baptiste Boric
read_inode(struct inode_dir_entry * dir_entry,struct dir_extent * extent,size_t * offset)216b1d06847SJean-Baptiste Boric int read_inode(struct inode_dir_entry *dir_entry, struct dir_extent *extent,
217b1d06847SJean-Baptiste Boric size_t *offset)
218c2f99d7cSDavid van Moolenbroek {
219c2f99d7cSDavid van Moolenbroek struct iso9660_dir_record *dir_rec;
220c2f99d7cSDavid van Moolenbroek struct buf *bp;
221b1d06847SJean-Baptiste Boric struct inode *i_node;
222b1d06847SJean-Baptiste Boric ino_t ino_nr;
223b1d06847SJean-Baptiste Boric int name_only = FALSE;
224c2f99d7cSDavid van Moolenbroek
225c2f99d7cSDavid van Moolenbroek /* Find inode. */
226b1d06847SJean-Baptiste Boric bp = read_extent_block(extent, *offset);
227b1d06847SJean-Baptiste Boric if (bp == NULL) {
228c2f99d7cSDavid van Moolenbroek return EOF;
229b1d06847SJean-Baptiste Boric }
230c2f99d7cSDavid van Moolenbroek
231b1d06847SJean-Baptiste Boric /* Check if we are crossing a sector boundary. */
232b1d06847SJean-Baptiste Boric dir_rec = (struct iso9660_dir_record*)(b_data(bp) + *offset %
233c2f99d7cSDavid van Moolenbroek v_pri.logical_block_size_l);
234c2f99d7cSDavid van Moolenbroek
235b1d06847SJean-Baptiste Boric if (dir_rec->length == 0) {
236b1d06847SJean-Baptiste Boric *offset = ((*offset / v_pri.logical_block_size_l) + 1) *
237b1d06847SJean-Baptiste Boric v_pri.logical_block_size_l;
238b1d06847SJean-Baptiste Boric
239b1d06847SJean-Baptiste Boric lmfs_put_block(bp);
240b1d06847SJean-Baptiste Boric bp = read_extent_block(extent, *offset);
241b1d06847SJean-Baptiste Boric if (bp == NULL) {
242b1d06847SJean-Baptiste Boric return EOF;
243b1d06847SJean-Baptiste Boric }
244b1d06847SJean-Baptiste Boric
245b1d06847SJean-Baptiste Boric dir_rec = (struct iso9660_dir_record*)(b_data(bp) + *offset %
246b1d06847SJean-Baptiste Boric v_pri.logical_block_size_l);
247b1d06847SJean-Baptiste Boric }
248b1d06847SJean-Baptiste Boric
249c2f99d7cSDavid van Moolenbroek /* Parse basic ISO 9660 specs. */
250b1d06847SJean-Baptiste Boric if (check_dir_record(dir_rec, *offset % v_pri.logical_block_size_l)
251b1d06847SJean-Baptiste Boric != OK) {
2520314acfbSDavid van Moolenbroek lmfs_put_block(bp);
253c2f99d7cSDavid van Moolenbroek return EINVAL;
254c2f99d7cSDavid van Moolenbroek }
255c2f99d7cSDavid van Moolenbroek
256b1d06847SJean-Baptiste Boric /* Get inode */
257b1d06847SJean-Baptiste Boric if ((dir_rec->file_flags & D_TYPE) == D_DIRECTORY) {
258b1d06847SJean-Baptiste Boric ino_nr = dir_rec->loc_extent_l;
259b1d06847SJean-Baptiste Boric }
260b1d06847SJean-Baptiste Boric else {
261b1d06847SJean-Baptiste Boric ino_nr = get_extent_absolute_block_id(extent, *offset)
262b1d06847SJean-Baptiste Boric * v_pri.logical_block_size_l +
263b1d06847SJean-Baptiste Boric *offset % v_pri.logical_block_size_l;
264b1d06847SJean-Baptiste Boric }
265c2f99d7cSDavid van Moolenbroek
266*3e2c6c96SDavid van Moolenbroek memset(dir_entry, 0, sizeof(*dir_entry));
267*3e2c6c96SDavid van Moolenbroek
268b1d06847SJean-Baptiste Boric i_node = inode_cache_get(ino_nr);
269b1d06847SJean-Baptiste Boric if (i_node) {
270b1d06847SJean-Baptiste Boric /* Inode was already loaded, parse file names only. */
271b1d06847SJean-Baptiste Boric dir_entry->i_node = i_node;
272b1d06847SJean-Baptiste Boric i_node->i_refcount++;
273c2f99d7cSDavid van Moolenbroek
274b1d06847SJean-Baptiste Boric memset(&dir_entry->i_name[0], 0, sizeof(dir_entry->i_name));
275b1d06847SJean-Baptiste Boric
276b1d06847SJean-Baptiste Boric name_only = TRUE;
277b1d06847SJean-Baptiste Boric }
278b1d06847SJean-Baptiste Boric else {
279b1d06847SJean-Baptiste Boric /* Inode wasn't in memory, parse it. */
280b1d06847SJean-Baptiste Boric i_node = alloc_mem(sizeof(struct inode));
281b1d06847SJean-Baptiste Boric dir_entry->i_node = i_node;
282b1d06847SJean-Baptiste Boric i_node->i_refcount = 1;
283b1d06847SJean-Baptiste Boric i_node->i_stat.st_ino = ino_nr;
284b1d06847SJean-Baptiste Boric inode_cache_add(ino_nr, i_node);
285b1d06847SJean-Baptiste Boric }
286b1d06847SJean-Baptiste Boric
287b1d06847SJean-Baptiste Boric dir_entry->i_node = i_node;
288b1d06847SJean-Baptiste Boric read_inode_iso9660(dir_entry, dir_rec, extent, *offset, name_only);
289c2f99d7cSDavid van Moolenbroek
290c2f99d7cSDavid van Moolenbroek /* Parse extensions. */
291b1d06847SJean-Baptiste Boric #ifdef ISO9660_OPTION_ROCKRIDGE
292b1d06847SJean-Baptiste Boric read_inode_susp(dir_entry, dir_rec, bp,
293b1d06847SJean-Baptiste Boric *offset % v_pri.logical_block_size_l, name_only);
294b1d06847SJean-Baptiste Boric #endif
295c2f99d7cSDavid van Moolenbroek
296b1d06847SJean-Baptiste Boric *offset += dir_rec->length;
297b1d06847SJean-Baptiste Boric if (dir_rec->length % 2)
298b1d06847SJean-Baptiste Boric (*offset)++;
299b1d06847SJean-Baptiste Boric
300b1d06847SJean-Baptiste Boric #ifdef ISO9660_OPTION_MODE3
301b1d06847SJean-Baptiste Boric read_inode_extents(dir_entry, dir_rec, extent, offset);
302b1d06847SJean-Baptiste Boric #endif
303c2f99d7cSDavid van Moolenbroek
3040314acfbSDavid van Moolenbroek lmfs_put_block(bp);
305b1d06847SJean-Baptiste Boric
306c2f99d7cSDavid van Moolenbroek return OK;
307c2f99d7cSDavid van Moolenbroek }
308c2f99d7cSDavid van Moolenbroek
inode_cache_get(ino_t ino_nr)309b1d06847SJean-Baptiste Boric struct inode* inode_cache_get(ino_t ino_nr) {
310b1d06847SJean-Baptiste Boric struct inode_cache *i_node;
311b1d06847SJean-Baptiste Boric HASH_FIND(hh, icache, &ino_nr, sizeof(ino_t), i_node);
312c2f99d7cSDavid van Moolenbroek
313b1d06847SJean-Baptiste Boric if (i_node)
314b1d06847SJean-Baptiste Boric return i_node->value;
315b1d06847SJean-Baptiste Boric else
316b1d06847SJean-Baptiste Boric return NULL;
317c2f99d7cSDavid van Moolenbroek }
318c2f99d7cSDavid van Moolenbroek
inode_cache_add(ino_t ino_nr,struct inode * i_node)319b1d06847SJean-Baptiste Boric void inode_cache_add(ino_t ino_nr, struct inode *i_node) {
320b1d06847SJean-Baptiste Boric struct inode_cache *c_check;
321b1d06847SJean-Baptiste Boric struct inode_cache *c_entry;
322c2f99d7cSDavid van Moolenbroek
323b1d06847SJean-Baptiste Boric HASH_FIND(hh, icache, &ino_nr, sizeof(ino_t), c_check);
324b1d06847SJean-Baptiste Boric
325b1d06847SJean-Baptiste Boric if (c_check == NULL) {
326b1d06847SJean-Baptiste Boric c_entry = alloc_mem(sizeof(struct inode_cache));
327b1d06847SJean-Baptiste Boric c_entry->key = ino_nr;
328b1d06847SJean-Baptiste Boric c_entry->value = i_node;
329b1d06847SJean-Baptiste Boric
330b1d06847SJean-Baptiste Boric HASH_ADD(hh, icache, key, sizeof(ino_t), c_entry);
331c2f99d7cSDavid van Moolenbroek }
332c2f99d7cSDavid van Moolenbroek else
333b1d06847SJean-Baptiste Boric panic("Trying to insert inode into cache twice");
334b1d06847SJean-Baptiste Boric }
335b1d06847SJean-Baptiste Boric
read_inode_iso9660(struct inode_dir_entry * i,const struct iso9660_dir_record * dir_rec,struct dir_extent * extent,size_t offset,int name_only)336b1d06847SJean-Baptiste Boric void read_inode_iso9660(struct inode_dir_entry *i,
337b1d06847SJean-Baptiste Boric const struct iso9660_dir_record *dir_rec, struct dir_extent *extent,
338b1d06847SJean-Baptiste Boric size_t offset, int name_only)
339b1d06847SJean-Baptiste Boric {
340b1d06847SJean-Baptiste Boric char *cp;
341c2f99d7cSDavid van Moolenbroek
342c2f99d7cSDavid van Moolenbroek /* Parse file name. */
343c2f99d7cSDavid van Moolenbroek if (dir_rec->file_id[0] == 0)
344c2f99d7cSDavid van Moolenbroek strcpy(i->i_name, ".");
345c2f99d7cSDavid van Moolenbroek else if (dir_rec->file_id[0] == 1)
346c2f99d7cSDavid van Moolenbroek strcpy(i->i_name, "..");
347c2f99d7cSDavid van Moolenbroek else {
348c2f99d7cSDavid van Moolenbroek memcpy(i->i_name, dir_rec->file_id, dir_rec->length_file_id);
349c2f99d7cSDavid van Moolenbroek
350c2f99d7cSDavid van Moolenbroek /* Truncate/ignore file version suffix. */
351c2f99d7cSDavid van Moolenbroek cp = strchr(i->i_name, ';');
352b1d06847SJean-Baptiste Boric if (cp != NULL) {
353c2f99d7cSDavid van Moolenbroek *cp = '\0';
354c2f99d7cSDavid van Moolenbroek /* Truncate dot if file has no extension. */
355c2f99d7cSDavid van Moolenbroek if (strchr(i->i_name, '.') + 1 == cp)
356c2f99d7cSDavid van Moolenbroek *(cp-1) = '\0';
357c2f99d7cSDavid van Moolenbroek }
358b1d06847SJean-Baptiste Boric }
359b1d06847SJean-Baptiste Boric
360b1d06847SJean-Baptiste Boric if (name_only == TRUE)
361b1d06847SJean-Baptiste Boric return;
362b1d06847SJean-Baptiste Boric
363b1d06847SJean-Baptiste Boric /* Parse first extent. */
364b1d06847SJean-Baptiste Boric if (dir_rec->data_length_l > 0) {
365b1d06847SJean-Baptiste Boric i->i_node->extent.location = dir_rec->loc_extent_l +
366b1d06847SJean-Baptiste Boric dir_rec->ext_attr_rec_length;
367b1d06847SJean-Baptiste Boric i->i_node->extent.length = dir_rec->data_length_l /
368b1d06847SJean-Baptiste Boric v_pri.logical_block_size_l;
369b1d06847SJean-Baptiste Boric
370b1d06847SJean-Baptiste Boric if (dir_rec->data_length_l % v_pri.logical_block_size_l)
371b1d06847SJean-Baptiste Boric i->i_node->extent.length++;
372b1d06847SJean-Baptiste Boric
373b1d06847SJean-Baptiste Boric i->i_node->i_stat.st_size = dir_rec->data_length_l;
374b1d06847SJean-Baptiste Boric }
375b1d06847SJean-Baptiste Boric
376b1d06847SJean-Baptiste Boric /* Parse timestamps (record date). */
377b1d06847SJean-Baptiste Boric i->i_node->i_stat.st_atime = i->i_node->i_stat.st_mtime =
378b1d06847SJean-Baptiste Boric i->i_node->i_stat.st_ctime = i->i_node->i_stat.st_birthtime =
379b1d06847SJean-Baptiste Boric date7_to_time_t(dir_rec->rec_date);
380b1d06847SJean-Baptiste Boric
381b1d06847SJean-Baptiste Boric if ((dir_rec->file_flags & D_TYPE) == D_DIRECTORY)
382b1d06847SJean-Baptiste Boric i->i_node->i_stat.st_mode = S_IFDIR;
383b1d06847SJean-Baptiste Boric else
384b1d06847SJean-Baptiste Boric i->i_node->i_stat.st_mode = S_IFREG;
385b1d06847SJean-Baptiste Boric
386b1d06847SJean-Baptiste Boric i->i_node->i_stat.st_mode |= 0555;
387c2f99d7cSDavid van Moolenbroek
388c2f99d7cSDavid van Moolenbroek /* Initialize stat. */
389b1d06847SJean-Baptiste Boric i->i_node->i_stat.st_dev = fs_dev;
390b1d06847SJean-Baptiste Boric i->i_node->i_stat.st_blksize = v_pri.logical_block_size_l;
3918d0759b0SDavid van Moolenbroek i->i_node->i_stat.st_blocks = dir_rec->data_length_l / 512;
392b1d06847SJean-Baptiste Boric i->i_node->i_stat.st_nlink = 1;
393c2f99d7cSDavid van Moolenbroek }
394c2f99d7cSDavid van Moolenbroek
395b1d06847SJean-Baptiste Boric #ifdef ISO9660_OPTION_ROCKRIDGE
396b1d06847SJean-Baptiste Boric
read_inode_susp(struct inode_dir_entry * i,const struct iso9660_dir_record * dir_rec,struct buf * bp,size_t offset,int name_only)397b1d06847SJean-Baptiste Boric void read_inode_susp(struct inode_dir_entry *i,
398b1d06847SJean-Baptiste Boric const struct iso9660_dir_record *dir_rec, struct buf *bp, size_t offset,
399b1d06847SJean-Baptiste Boric int name_only)
400c2f99d7cSDavid van Moolenbroek {
401b1d06847SJean-Baptiste Boric int susp_offset, susp_size, name_length;
402c2f99d7cSDavid van Moolenbroek struct rrii_dir_record rrii_data;
403c2f99d7cSDavid van Moolenbroek
404c2f99d7cSDavid van Moolenbroek susp_offset = 33 + dir_rec->length_file_id;
405c2f99d7cSDavid van Moolenbroek /* Get rid of padding byte. */
406c2f99d7cSDavid van Moolenbroek if(dir_rec->length_file_id % 2 == 0) {
407c2f99d7cSDavid van Moolenbroek susp_offset++;
408c2f99d7cSDavid van Moolenbroek }
409c2f99d7cSDavid van Moolenbroek
410b1d06847SJean-Baptiste Boric if(dir_rec->length - susp_offset < 4)
411b1d06847SJean-Baptiste Boric return;
412b1d06847SJean-Baptiste Boric
413c2f99d7cSDavid van Moolenbroek susp_size = dir_rec->length - susp_offset;
414c2f99d7cSDavid van Moolenbroek
415c2f99d7cSDavid van Moolenbroek /* Initialize record with known, sane data. */
416c2f99d7cSDavid van Moolenbroek memcpy(rrii_data.mtime, dir_rec->rec_date, ISO9660_SIZE_DATE7);
417c2f99d7cSDavid van Moolenbroek memcpy(rrii_data.atime, dir_rec->rec_date, ISO9660_SIZE_DATE7);
418c2f99d7cSDavid van Moolenbroek memcpy(rrii_data.ctime, dir_rec->rec_date, ISO9660_SIZE_DATE7);
419b1d06847SJean-Baptiste Boric memcpy(rrii_data.birthtime, dir_rec->rec_date, ISO9660_SIZE_DATE7);
420c2f99d7cSDavid van Moolenbroek
421b1d06847SJean-Baptiste Boric rrii_data.d_mode = i->i_node->i_stat.st_mode;
422b1d06847SJean-Baptiste Boric rrii_data.uid = SYS_UID;
423b1d06847SJean-Baptiste Boric rrii_data.gid = SYS_GID;
424c2f99d7cSDavid van Moolenbroek rrii_data.rdev = NO_DEV;
425c2f99d7cSDavid van Moolenbroek rrii_data.file_id_rrip[0] = '\0';
426c2f99d7cSDavid van Moolenbroek rrii_data.slink_rrip[0] = '\0';
427b1d06847SJean-Baptiste Boric rrii_data.reparented_inode = NULL;
428c2f99d7cSDavid van Moolenbroek
429b1d06847SJean-Baptiste Boric parse_susp_buffer(&rrii_data, b_data(bp)+offset+susp_offset, susp_size);
430c2f99d7cSDavid van Moolenbroek
431c2f99d7cSDavid van Moolenbroek /* Copy back data from rrii_dir_record structure. */
432b1d06847SJean-Baptiste Boric if (rrii_data.file_id_rrip[0] != '\0') {
433b1d06847SJean-Baptiste Boric name_length = strlen(rrii_data.file_id_rrip);
434b1d06847SJean-Baptiste Boric i->r_name = alloc_mem(name_length + 1);
435b1d06847SJean-Baptiste Boric memcpy(i->r_name, rrii_data.file_id_rrip, name_length);
436c2f99d7cSDavid van Moolenbroek }
437c2f99d7cSDavid van Moolenbroek
438b1d06847SJean-Baptiste Boric if (rrii_data.slink_rrip[0] != '\0') {
439b1d06847SJean-Baptiste Boric name_length = strlen(rrii_data.slink_rrip);
440b1d06847SJean-Baptiste Boric i->i_node->s_name = alloc_mem(name_length + 1);
441b1d06847SJean-Baptiste Boric memcpy(i->i_node->s_name, rrii_data.slink_rrip, name_length);
442b1d06847SJean-Baptiste Boric }
443b1d06847SJean-Baptiste Boric
444b1d06847SJean-Baptiste Boric if (rrii_data.reparented_inode) {
445b1d06847SJean-Baptiste Boric /* Recycle the inode already parsed. */
446b1d06847SJean-Baptiste Boric i->i_node = rrii_data.reparented_inode;
447b1d06847SJean-Baptiste Boric return;
448b1d06847SJean-Baptiste Boric }
449b1d06847SJean-Baptiste Boric
450b1d06847SJean-Baptiste Boric /* XXX: not the correct way to ignore reparented directory holder... */
451b1d06847SJean-Baptiste Boric if (strcmp(rrii_data.file_id_rrip, ".rr_moved") == 0)
452b1d06847SJean-Baptiste Boric i->i_node->skip = 1;
453b1d06847SJean-Baptiste Boric
454b1d06847SJean-Baptiste Boric if (name_only == TRUE)
455b1d06847SJean-Baptiste Boric return;
456b1d06847SJean-Baptiste Boric
457b1d06847SJean-Baptiste Boric /* Write back all Rock Ridge properties. */
458b1d06847SJean-Baptiste Boric i->i_node->i_stat.st_atime = date7_to_time_t(rrii_data.atime);
459b1d06847SJean-Baptiste Boric i->i_node->i_stat.st_ctime = date7_to_time_t(rrii_data.ctime);
460b1d06847SJean-Baptiste Boric i->i_node->i_stat.st_mtime = date7_to_time_t(rrii_data.mtime);
461b1d06847SJean-Baptiste Boric i->i_node->i_stat.st_birthtime = date7_to_time_t(rrii_data.birthtime);
462b1d06847SJean-Baptiste Boric
463b1d06847SJean-Baptiste Boric i->i_node->i_stat.st_mode = rrii_data.d_mode;
464b1d06847SJean-Baptiste Boric i->i_node->i_stat.st_uid = rrii_data.uid;
465b1d06847SJean-Baptiste Boric i->i_node->i_stat.st_gid = rrii_data.gid;
466b1d06847SJean-Baptiste Boric i->i_node->i_stat.st_rdev = rrii_data.rdev;
467b1d06847SJean-Baptiste Boric }
468b1d06847SJean-Baptiste Boric
469b1d06847SJean-Baptiste Boric #endif
470b1d06847SJean-Baptiste Boric
471b1d06847SJean-Baptiste Boric #ifdef ISO9660_OPTION_MODE3
472b1d06847SJean-Baptiste Boric
read_inode_extents(struct inode * i,const struct iso9660_dir_record * dir_rec,struct dir_extent * extent,size_t * offset)473b1d06847SJean-Baptiste Boric void read_inode_extents(struct inode *i,
474b1d06847SJean-Baptiste Boric const struct iso9660_dir_record *dir_rec,
475b1d06847SJean-Baptiste Boric struct dir_extent *extent, size_t *offset)
476c2f99d7cSDavid van Moolenbroek {
477b1d06847SJean-Baptiste Boric panic("read_inode_extents() isn't implemented yet!");
478b1d06847SJean-Baptiste Boric }
479b1d06847SJean-Baptiste Boric
480b1d06847SJean-Baptiste Boric #endif
481b1d06847SJean-Baptiste Boric
check_dir_record(const struct iso9660_dir_record * d,size_t offset)482b1d06847SJean-Baptiste Boric int check_dir_record(const struct iso9660_dir_record *d, size_t offset) {
483c2f99d7cSDavid van Moolenbroek /* Run some consistency check on a directory entry. */
484c2f99d7cSDavid van Moolenbroek if ((d->length < 33) || (d->length_file_id < 1))
485c2f99d7cSDavid van Moolenbroek return EINVAL;
486c2f99d7cSDavid van Moolenbroek if (d->length_file_id + 32 > d->length)
487c2f99d7cSDavid van Moolenbroek return EINVAL;
488c2f99d7cSDavid van Moolenbroek if (offset + d->length > v_pri.logical_block_size_l)
489c2f99d7cSDavid van Moolenbroek return EINVAL;
490c2f99d7cSDavid van Moolenbroek
491c2f99d7cSDavid van Moolenbroek return OK;
492c2f99d7cSDavid van Moolenbroek }
493