xref: /minix3/minix/fs/isofs/inode.c (revision 3e2c6c96745db64738bad809b90b163a66e7b201)
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