xref: /minix3/minix/fs/isofs/inode.c (revision 8d0759b089e4b67dfcc7cc954724c4da7bb25a87)
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 
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 
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 
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 
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 
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 
102b1d06847SJean-Baptiste Boric int read_directory(struct inode *dir) {
103b1d06847SJean-Baptiste Boric #define MAX_ENTRIES 4096
104b1d06847SJean-Baptiste Boric 	/* Read all entries in a directory. */
105b1d06847SJean-Baptiste Boric 	size_t pos = 0, cur_entry = 0, cpt;
106b1d06847SJean-Baptiste Boric 	struct inode_dir_entry entries[MAX_ENTRIES];
107b1d06847SJean-Baptiste Boric 	int status = OK;
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 
115b1d06847SJean-Baptiste Boric 	for (cur_entry = 0; status == OK && cur_entry < MAX_ENTRIES; cur_entry++) {
116b1d06847SJean-Baptiste Boric 		memset(&entries[cur_entry], 0, sizeof(struct inode_dir_entry));
117b1d06847SJean-Baptiste Boric 
118b1d06847SJean-Baptiste Boric 		status = read_inode(&entries[cur_entry], &dir->extent, &pos);
119b1d06847SJean-Baptiste Boric 		if (status != OK)
120c2f99d7cSDavid van Moolenbroek 			break;
121b1d06847SJean-Baptiste Boric 
122b1d06847SJean-Baptiste Boric 		/* Dump the entry if it's not to be exported to userland. */
123b1d06847SJean-Baptiste Boric 		if (entries[cur_entry].i_node->skip) {
124b1d06847SJean-Baptiste Boric 			free_inode_dir_entry(&entries[cur_entry]);
125b1d06847SJean-Baptiste Boric 			continue;
126b1d06847SJean-Baptiste Boric 		}
127c2f99d7cSDavid van Moolenbroek 	}
128c2f99d7cSDavid van Moolenbroek 
129b1d06847SJean-Baptiste Boric 	/* Resize dynamic array to correct size */
130b1d06847SJean-Baptiste Boric 	dir->dir_contents = alloc_mem(sizeof(struct inode_dir_entry) * cur_entry);
131b1d06847SJean-Baptiste Boric 	memcpy(dir->dir_contents, entries, sizeof(struct inode_dir_entry) * cur_entry);
132b1d06847SJean-Baptiste Boric 	dir->dir_size = cur_entry;
133b1d06847SJean-Baptiste Boric 
134b1d06847SJean-Baptiste Boric 	/* The name pointer has to point to the new memory location. */
135b1d06847SJean-Baptiste Boric 	for (cpt = 0; cpt < cur_entry; cpt++) {
136b1d06847SJean-Baptiste Boric 		if (dir->dir_contents[cpt].r_name == NULL)
137b1d06847SJean-Baptiste Boric 			dir->dir_contents[cpt].name =
138b1d06847SJean-Baptiste Boric 			    dir->dir_contents[cpt].i_name;
139b1d06847SJean-Baptiste Boric 		else
140b1d06847SJean-Baptiste Boric 			dir->dir_contents[cpt].name =
141b1d06847SJean-Baptiste Boric 			    dir->dir_contents[cpt].r_name;
142c2f99d7cSDavid van Moolenbroek 	}
143c2f99d7cSDavid van Moolenbroek 
144b1d06847SJean-Baptiste Boric 	return (status == EOF) ? OK : status;
145c2f99d7cSDavid van Moolenbroek }
146c2f99d7cSDavid van Moolenbroek 
147b1d06847SJean-Baptiste Boric int check_inodes(void) {
148b1d06847SJean-Baptiste Boric 	/* Check whether there are no more inodes in use. Called on unmount. */
149b1d06847SJean-Baptiste Boric 	int i;
150b1d06847SJean-Baptiste Boric 
151b1d06847SJean-Baptiste Boric 	/* XXX: actually check for inodes in use. */
152b1d06847SJean-Baptiste Boric 	return TRUE;
153b1d06847SJean-Baptiste Boric }
154b1d06847SJean-Baptiste Boric 
155b1d06847SJean-Baptiste Boric int read_inode(struct inode_dir_entry *dir_entry, struct dir_extent *extent,
156b1d06847SJean-Baptiste Boric 	size_t *offset)
157c2f99d7cSDavid van Moolenbroek {
158c2f99d7cSDavid van Moolenbroek 	struct iso9660_dir_record *dir_rec;
159c2f99d7cSDavid van Moolenbroek 	struct buf *bp;
160b1d06847SJean-Baptiste Boric 	struct inode *i_node;
161b1d06847SJean-Baptiste Boric 	ino_t ino_nr;
162b1d06847SJean-Baptiste Boric 	int name_only = FALSE;
163c2f99d7cSDavid van Moolenbroek 
164c2f99d7cSDavid van Moolenbroek 	/* Find inode. */
165b1d06847SJean-Baptiste Boric 	bp = read_extent_block(extent, *offset);
166b1d06847SJean-Baptiste Boric 	if (bp == NULL) {
167c2f99d7cSDavid van Moolenbroek 		return EOF;
168b1d06847SJean-Baptiste Boric 	}
169c2f99d7cSDavid van Moolenbroek 
170b1d06847SJean-Baptiste Boric 	/* Check if we are crossing a sector boundary. */
171b1d06847SJean-Baptiste Boric 	dir_rec = (struct iso9660_dir_record*)(b_data(bp) + *offset %
172c2f99d7cSDavid van Moolenbroek 	          v_pri.logical_block_size_l);
173c2f99d7cSDavid van Moolenbroek 
174b1d06847SJean-Baptiste Boric 	if (dir_rec->length == 0) {
175b1d06847SJean-Baptiste Boric 		*offset = ((*offset / v_pri.logical_block_size_l) + 1) *
176b1d06847SJean-Baptiste Boric 		    v_pri.logical_block_size_l;
177b1d06847SJean-Baptiste Boric 
178b1d06847SJean-Baptiste Boric 		lmfs_put_block(bp);
179b1d06847SJean-Baptiste Boric 		bp = read_extent_block(extent, *offset);
180b1d06847SJean-Baptiste Boric 		if (bp == NULL) {
181b1d06847SJean-Baptiste Boric 			return EOF;
182b1d06847SJean-Baptiste Boric 		}
183b1d06847SJean-Baptiste Boric 
184b1d06847SJean-Baptiste Boric 		dir_rec = (struct iso9660_dir_record*)(b_data(bp) + *offset %
185b1d06847SJean-Baptiste Boric 	          v_pri.logical_block_size_l);
186b1d06847SJean-Baptiste Boric 	}
187b1d06847SJean-Baptiste Boric 
188c2f99d7cSDavid van Moolenbroek 	/* Parse basic ISO 9660 specs. */
189b1d06847SJean-Baptiste Boric 	if (check_dir_record(dir_rec, *offset % v_pri.logical_block_size_l)
190b1d06847SJean-Baptiste Boric 	    != OK) {
1910314acfbSDavid van Moolenbroek 		lmfs_put_block(bp);
192c2f99d7cSDavid van Moolenbroek 		return EINVAL;
193c2f99d7cSDavid van Moolenbroek 	}
194c2f99d7cSDavid van Moolenbroek 
195b1d06847SJean-Baptiste Boric 	/* Get inode */
196b1d06847SJean-Baptiste Boric 	if ((dir_rec->file_flags & D_TYPE) == D_DIRECTORY) {
197b1d06847SJean-Baptiste Boric 		ino_nr = dir_rec->loc_extent_l;
198b1d06847SJean-Baptiste Boric 	}
199b1d06847SJean-Baptiste Boric 	else {
200b1d06847SJean-Baptiste Boric 		ino_nr = get_extent_absolute_block_id(extent, *offset)
201b1d06847SJean-Baptiste Boric 		    * v_pri.logical_block_size_l +
202b1d06847SJean-Baptiste Boric 		    *offset % v_pri.logical_block_size_l;
203b1d06847SJean-Baptiste Boric 	}
204c2f99d7cSDavid van Moolenbroek 
205b1d06847SJean-Baptiste Boric 	i_node = inode_cache_get(ino_nr);
206b1d06847SJean-Baptiste Boric 	if (i_node) {
207b1d06847SJean-Baptiste Boric 		/* Inode was already loaded, parse file names only. */
208b1d06847SJean-Baptiste Boric 		dir_entry->i_node = i_node;
209b1d06847SJean-Baptiste Boric 		i_node->i_refcount++;
210c2f99d7cSDavid van Moolenbroek 
211b1d06847SJean-Baptiste Boric 		memset(&dir_entry->i_name[0], 0, sizeof(dir_entry->i_name));
212b1d06847SJean-Baptiste Boric 
213b1d06847SJean-Baptiste Boric 		name_only = TRUE;
214b1d06847SJean-Baptiste Boric 	}
215b1d06847SJean-Baptiste Boric 	else {
216b1d06847SJean-Baptiste Boric 		/* Inode wasn't in memory, parse it. */
217b1d06847SJean-Baptiste Boric 		i_node = alloc_mem(sizeof(struct inode));
218b1d06847SJean-Baptiste Boric 		dir_entry->i_node = i_node;
219b1d06847SJean-Baptiste Boric 		i_node->i_refcount = 1;
220b1d06847SJean-Baptiste Boric 		i_node->i_stat.st_ino = ino_nr;
221b1d06847SJean-Baptiste Boric 		inode_cache_add(ino_nr, i_node);
222b1d06847SJean-Baptiste Boric 	}
223b1d06847SJean-Baptiste Boric 
224b1d06847SJean-Baptiste Boric 	dir_entry->i_node = i_node;
225b1d06847SJean-Baptiste Boric 	read_inode_iso9660(dir_entry, dir_rec, extent, *offset, name_only);
226c2f99d7cSDavid van Moolenbroek 
227c2f99d7cSDavid van Moolenbroek 	/* Parse extensions. */
228b1d06847SJean-Baptiste Boric #ifdef ISO9660_OPTION_ROCKRIDGE
229b1d06847SJean-Baptiste Boric 	read_inode_susp(dir_entry, dir_rec, bp,
230b1d06847SJean-Baptiste Boric 	    *offset % v_pri.logical_block_size_l, name_only);
231b1d06847SJean-Baptiste Boric #endif
232c2f99d7cSDavid van Moolenbroek 
233b1d06847SJean-Baptiste Boric 	*offset += dir_rec->length;
234b1d06847SJean-Baptiste Boric 	if (dir_rec->length % 2)
235b1d06847SJean-Baptiste Boric 		(*offset)++;
236b1d06847SJean-Baptiste Boric 
237b1d06847SJean-Baptiste Boric #ifdef ISO9660_OPTION_MODE3
238b1d06847SJean-Baptiste Boric 	read_inode_extents(dir_entry, dir_rec, extent, offset);
239b1d06847SJean-Baptiste Boric #endif
240c2f99d7cSDavid van Moolenbroek 
2410314acfbSDavid van Moolenbroek 	lmfs_put_block(bp);
242b1d06847SJean-Baptiste Boric 
243c2f99d7cSDavid van Moolenbroek 	return OK;
244c2f99d7cSDavid van Moolenbroek }
245c2f99d7cSDavid van Moolenbroek 
246b1d06847SJean-Baptiste Boric struct inode* inode_cache_get(ino_t ino_nr) {
247b1d06847SJean-Baptiste Boric 	struct inode_cache *i_node;
248b1d06847SJean-Baptiste Boric 	HASH_FIND(hh, icache, &ino_nr, sizeof(ino_t), i_node);
249c2f99d7cSDavid van Moolenbroek 
250b1d06847SJean-Baptiste Boric 	if (i_node)
251b1d06847SJean-Baptiste Boric 		return i_node->value;
252b1d06847SJean-Baptiste Boric 	else
253b1d06847SJean-Baptiste Boric 		return NULL;
254c2f99d7cSDavid van Moolenbroek }
255c2f99d7cSDavid van Moolenbroek 
256b1d06847SJean-Baptiste Boric void inode_cache_add(ino_t ino_nr, struct inode *i_node) {
257b1d06847SJean-Baptiste Boric 	struct inode_cache *c_check;
258b1d06847SJean-Baptiste Boric 	struct inode_cache *c_entry;
259c2f99d7cSDavid van Moolenbroek 
260b1d06847SJean-Baptiste Boric 	HASH_FIND(hh, icache, &ino_nr, sizeof(ino_t), c_check);
261b1d06847SJean-Baptiste Boric 
262b1d06847SJean-Baptiste Boric 	if (c_check == NULL) {
263b1d06847SJean-Baptiste Boric 		c_entry = alloc_mem(sizeof(struct inode_cache));
264b1d06847SJean-Baptiste Boric 		c_entry->key = ino_nr;
265b1d06847SJean-Baptiste Boric 		c_entry->value = i_node;
266b1d06847SJean-Baptiste Boric 
267b1d06847SJean-Baptiste Boric 		HASH_ADD(hh, icache, key, sizeof(ino_t), c_entry);
268c2f99d7cSDavid van Moolenbroek 	}
269c2f99d7cSDavid van Moolenbroek 	else
270b1d06847SJean-Baptiste Boric 		panic("Trying to insert inode into cache twice");
271b1d06847SJean-Baptiste Boric }
272b1d06847SJean-Baptiste Boric 
273b1d06847SJean-Baptiste Boric void read_inode_iso9660(struct inode_dir_entry *i,
274b1d06847SJean-Baptiste Boric 	const struct iso9660_dir_record *dir_rec, struct dir_extent *extent,
275b1d06847SJean-Baptiste Boric 	size_t offset, int name_only)
276b1d06847SJean-Baptiste Boric {
277b1d06847SJean-Baptiste Boric 	char *cp;
278c2f99d7cSDavid van Moolenbroek 
279c2f99d7cSDavid van Moolenbroek 	/* Parse file name. */
280c2f99d7cSDavid van Moolenbroek 	if (dir_rec->file_id[0] == 0)
281c2f99d7cSDavid van Moolenbroek 		strcpy(i->i_name, ".");
282c2f99d7cSDavid van Moolenbroek 	else if (dir_rec->file_id[0] == 1)
283c2f99d7cSDavid van Moolenbroek 		strcpy(i->i_name, "..");
284c2f99d7cSDavid van Moolenbroek 	else {
285c2f99d7cSDavid van Moolenbroek 		memcpy(i->i_name, dir_rec->file_id, dir_rec->length_file_id);
286c2f99d7cSDavid van Moolenbroek 
287c2f99d7cSDavid van Moolenbroek 		/* Truncate/ignore file version suffix. */
288c2f99d7cSDavid van Moolenbroek 		cp = strchr(i->i_name, ';');
289b1d06847SJean-Baptiste Boric 		if (cp != NULL) {
290c2f99d7cSDavid van Moolenbroek 			*cp = '\0';
291c2f99d7cSDavid van Moolenbroek 			/* Truncate dot if file has no extension. */
292c2f99d7cSDavid van Moolenbroek 			if (strchr(i->i_name, '.') + 1 == cp)
293c2f99d7cSDavid van Moolenbroek 				*(cp-1) = '\0';
294c2f99d7cSDavid van Moolenbroek 		}
295b1d06847SJean-Baptiste Boric 	}
296b1d06847SJean-Baptiste Boric 
297b1d06847SJean-Baptiste Boric 	if (name_only == TRUE)
298b1d06847SJean-Baptiste Boric 		return;
299b1d06847SJean-Baptiste Boric 
300b1d06847SJean-Baptiste Boric 	/* Parse first extent. */
301b1d06847SJean-Baptiste Boric 	if (dir_rec->data_length_l > 0) {
302b1d06847SJean-Baptiste Boric 		i->i_node->extent.location = dir_rec->loc_extent_l +
303b1d06847SJean-Baptiste Boric 		    dir_rec->ext_attr_rec_length;
304b1d06847SJean-Baptiste Boric 		i->i_node->extent.length = dir_rec->data_length_l /
305b1d06847SJean-Baptiste Boric 		    v_pri.logical_block_size_l;
306b1d06847SJean-Baptiste Boric 
307b1d06847SJean-Baptiste Boric 		if (dir_rec->data_length_l % v_pri.logical_block_size_l)
308b1d06847SJean-Baptiste Boric 			i->i_node->extent.length++;
309b1d06847SJean-Baptiste Boric 
310b1d06847SJean-Baptiste Boric 		i->i_node->i_stat.st_size = dir_rec->data_length_l;
311b1d06847SJean-Baptiste Boric 	}
312b1d06847SJean-Baptiste Boric 
313b1d06847SJean-Baptiste Boric 	/* Parse timestamps (record date). */
314b1d06847SJean-Baptiste Boric 	i->i_node->i_stat.st_atime = i->i_node->i_stat.st_mtime =
315b1d06847SJean-Baptiste Boric 	    i->i_node->i_stat.st_ctime = i->i_node->i_stat.st_birthtime =
316b1d06847SJean-Baptiste Boric 	    date7_to_time_t(dir_rec->rec_date);
317b1d06847SJean-Baptiste Boric 
318b1d06847SJean-Baptiste Boric 	if ((dir_rec->file_flags & D_TYPE) == D_DIRECTORY)
319b1d06847SJean-Baptiste Boric 		i->i_node->i_stat.st_mode = S_IFDIR;
320b1d06847SJean-Baptiste Boric 	else
321b1d06847SJean-Baptiste Boric 		i->i_node->i_stat.st_mode = S_IFREG;
322b1d06847SJean-Baptiste Boric 
323b1d06847SJean-Baptiste Boric 	i->i_node->i_stat.st_mode |= 0555;
324c2f99d7cSDavid van Moolenbroek 
325c2f99d7cSDavid van Moolenbroek 	/* Initialize stat. */
326b1d06847SJean-Baptiste Boric 	i->i_node->i_stat.st_dev = fs_dev;
327b1d06847SJean-Baptiste Boric 	i->i_node->i_stat.st_blksize = v_pri.logical_block_size_l;
328*8d0759b0SDavid van Moolenbroek 	i->i_node->i_stat.st_blocks = dir_rec->data_length_l / 512;
329b1d06847SJean-Baptiste Boric 	i->i_node->i_stat.st_nlink = 1;
330c2f99d7cSDavid van Moolenbroek }
331c2f99d7cSDavid van Moolenbroek 
332b1d06847SJean-Baptiste Boric #ifdef ISO9660_OPTION_ROCKRIDGE
333b1d06847SJean-Baptiste Boric 
334b1d06847SJean-Baptiste Boric void read_inode_susp(struct inode_dir_entry *i,
335b1d06847SJean-Baptiste Boric 	const struct iso9660_dir_record *dir_rec, struct buf *bp, size_t offset,
336b1d06847SJean-Baptiste Boric 	int name_only)
337c2f99d7cSDavid van Moolenbroek {
338b1d06847SJean-Baptiste Boric 	int susp_offset, susp_size, name_length;
339c2f99d7cSDavid van Moolenbroek 	struct rrii_dir_record rrii_data;
340c2f99d7cSDavid van Moolenbroek 
341c2f99d7cSDavid van Moolenbroek 	susp_offset = 33 + dir_rec->length_file_id;
342c2f99d7cSDavid van Moolenbroek 	/* Get rid of padding byte. */
343c2f99d7cSDavid van Moolenbroek 	if(dir_rec->length_file_id % 2 == 0) {
344c2f99d7cSDavid van Moolenbroek 		susp_offset++;
345c2f99d7cSDavid van Moolenbroek 	}
346c2f99d7cSDavid van Moolenbroek 
347b1d06847SJean-Baptiste Boric 	if(dir_rec->length - susp_offset < 4)
348b1d06847SJean-Baptiste Boric 		return;
349b1d06847SJean-Baptiste Boric 
350c2f99d7cSDavid van Moolenbroek 	susp_size = dir_rec->length - susp_offset;
351c2f99d7cSDavid van Moolenbroek 
352c2f99d7cSDavid van Moolenbroek 	/* Initialize record with known, sane data. */
353c2f99d7cSDavid van Moolenbroek 	memcpy(rrii_data.mtime, dir_rec->rec_date, ISO9660_SIZE_DATE7);
354c2f99d7cSDavid van Moolenbroek 	memcpy(rrii_data.atime, dir_rec->rec_date, ISO9660_SIZE_DATE7);
355c2f99d7cSDavid van Moolenbroek 	memcpy(rrii_data.ctime, dir_rec->rec_date, ISO9660_SIZE_DATE7);
356b1d06847SJean-Baptiste Boric 	memcpy(rrii_data.birthtime, dir_rec->rec_date, ISO9660_SIZE_DATE7);
357c2f99d7cSDavid van Moolenbroek 
358b1d06847SJean-Baptiste Boric 	rrii_data.d_mode = i->i_node->i_stat.st_mode;
359b1d06847SJean-Baptiste Boric 	rrii_data.uid    = SYS_UID;
360b1d06847SJean-Baptiste Boric 	rrii_data.gid    = SYS_GID;
361c2f99d7cSDavid van Moolenbroek 	rrii_data.rdev   = NO_DEV;
362c2f99d7cSDavid van Moolenbroek 	rrii_data.file_id_rrip[0] = '\0';
363c2f99d7cSDavid van Moolenbroek 	rrii_data.slink_rrip[0]   = '\0';
364b1d06847SJean-Baptiste Boric 	rrii_data.reparented_inode = NULL;
365c2f99d7cSDavid van Moolenbroek 
366b1d06847SJean-Baptiste Boric 	parse_susp_buffer(&rrii_data, b_data(bp)+offset+susp_offset, susp_size);
367c2f99d7cSDavid van Moolenbroek 
368c2f99d7cSDavid van Moolenbroek 	/* Copy back data from rrii_dir_record structure. */
369b1d06847SJean-Baptiste Boric 	if (rrii_data.file_id_rrip[0] != '\0') {
370b1d06847SJean-Baptiste Boric 		name_length = strlen(rrii_data.file_id_rrip);
371b1d06847SJean-Baptiste Boric 		i->r_name = alloc_mem(name_length + 1);
372b1d06847SJean-Baptiste Boric 		memcpy(i->r_name, rrii_data.file_id_rrip, name_length);
373c2f99d7cSDavid van Moolenbroek 	}
374c2f99d7cSDavid van Moolenbroek 
375b1d06847SJean-Baptiste Boric 	if (rrii_data.slink_rrip[0] != '\0') {
376b1d06847SJean-Baptiste Boric 		name_length = strlen(rrii_data.slink_rrip);
377b1d06847SJean-Baptiste Boric 		i->i_node->s_name = alloc_mem(name_length + 1);
378b1d06847SJean-Baptiste Boric 		memcpy(i->i_node->s_name, rrii_data.slink_rrip, name_length);
379b1d06847SJean-Baptiste Boric 	}
380b1d06847SJean-Baptiste Boric 
381b1d06847SJean-Baptiste Boric 	if (rrii_data.reparented_inode) {
382b1d06847SJean-Baptiste Boric 		/* Recycle the inode already parsed. */
383b1d06847SJean-Baptiste Boric 		i->i_node = rrii_data.reparented_inode;
384b1d06847SJean-Baptiste Boric 		return;
385b1d06847SJean-Baptiste Boric 	}
386b1d06847SJean-Baptiste Boric 
387b1d06847SJean-Baptiste Boric 	/* XXX: not the correct way to ignore reparented directory holder... */
388b1d06847SJean-Baptiste Boric 	if (strcmp(rrii_data.file_id_rrip, ".rr_moved") == 0)
389b1d06847SJean-Baptiste Boric 		i->i_node->skip = 1;
390b1d06847SJean-Baptiste Boric 
391b1d06847SJean-Baptiste Boric 	if (name_only == TRUE)
392b1d06847SJean-Baptiste Boric 		return;
393b1d06847SJean-Baptiste Boric 
394b1d06847SJean-Baptiste Boric 	/* Write back all Rock Ridge properties. */
395b1d06847SJean-Baptiste Boric 	i->i_node->i_stat.st_atime = date7_to_time_t(rrii_data.atime);
396b1d06847SJean-Baptiste Boric 	i->i_node->i_stat.st_ctime = date7_to_time_t(rrii_data.ctime);
397b1d06847SJean-Baptiste Boric 	i->i_node->i_stat.st_mtime = date7_to_time_t(rrii_data.mtime);
398b1d06847SJean-Baptiste Boric 	i->i_node->i_stat.st_birthtime = date7_to_time_t(rrii_data.birthtime);
399b1d06847SJean-Baptiste Boric 
400b1d06847SJean-Baptiste Boric 	i->i_node->i_stat.st_mode = rrii_data.d_mode;
401b1d06847SJean-Baptiste Boric 	i->i_node->i_stat.st_uid  = rrii_data.uid;
402b1d06847SJean-Baptiste Boric 	i->i_node->i_stat.st_gid  = rrii_data.gid;
403b1d06847SJean-Baptiste Boric 	i->i_node->i_stat.st_rdev = rrii_data.rdev;
404b1d06847SJean-Baptiste Boric }
405b1d06847SJean-Baptiste Boric 
406b1d06847SJean-Baptiste Boric #endif
407b1d06847SJean-Baptiste Boric 
408b1d06847SJean-Baptiste Boric #ifdef ISO9660_OPTION_MODE3
409b1d06847SJean-Baptiste Boric 
410b1d06847SJean-Baptiste Boric void read_inode_extents(struct inode *i,
411b1d06847SJean-Baptiste Boric 	const struct iso9660_dir_record *dir_rec,
412b1d06847SJean-Baptiste Boric 	struct dir_extent *extent, size_t *offset)
413c2f99d7cSDavid van Moolenbroek {
414b1d06847SJean-Baptiste Boric 	panic("read_inode_extents() isn't implemented yet!");
415b1d06847SJean-Baptiste Boric }
416b1d06847SJean-Baptiste Boric 
417b1d06847SJean-Baptiste Boric #endif
418b1d06847SJean-Baptiste Boric 
419b1d06847SJean-Baptiste Boric int check_dir_record(const struct iso9660_dir_record *d, size_t offset) {
420c2f99d7cSDavid van Moolenbroek 	/* Run some consistency check on a directory entry. */
421c2f99d7cSDavid van Moolenbroek 	if ((d->length < 33) || (d->length_file_id < 1))
422c2f99d7cSDavid van Moolenbroek 		return EINVAL;
423c2f99d7cSDavid van Moolenbroek 	if (d->length_file_id + 32 > d->length)
424c2f99d7cSDavid van Moolenbroek 		return EINVAL;
425c2f99d7cSDavid van Moolenbroek 	if (offset + d->length > v_pri.logical_block_size_l)
426c2f99d7cSDavid van Moolenbroek 		return EINVAL;
427c2f99d7cSDavid van Moolenbroek 
428c2f99d7cSDavid van Moolenbroek 	return OK;
429c2f99d7cSDavid van Moolenbroek }
430