xref: /minix3/minix/fs/isofs/inode.c (revision 0314acfb2d68447dfa1b0b33aa4c25b1cbfa85d3)
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 
9c2f99d7cSDavid van Moolenbroek static struct inode inodes[NR_INODE_RECORDS];
10c2f99d7cSDavid van Moolenbroek static struct buf* fetch_inode(struct dir_extent *extent, size_t *offset);
11c2f99d7cSDavid van Moolenbroek 
12c2f99d7cSDavid van Moolenbroek int fs_putnode(ino_t ino_nr, unsigned int count)
13c2f99d7cSDavid van Moolenbroek {
14c2f99d7cSDavid van Moolenbroek 	/*
15c2f99d7cSDavid van Moolenbroek 	 * Find the inode specified by the request message and decrease its
16c2f99d7cSDavid van Moolenbroek 	 * counter.
17c2f99d7cSDavid van Moolenbroek 	 */
18c2f99d7cSDavid van Moolenbroek 	struct inode *i_node;
19c2f99d7cSDavid van Moolenbroek 
20c2f99d7cSDavid van Moolenbroek 	if ((i_node = find_inode(ino_nr)) == NULL) {
21c2f99d7cSDavid van Moolenbroek 		printf("ISOFS: trying to free unused inode\n");
22c2f99d7cSDavid van Moolenbroek 		return EINVAL;
23c2f99d7cSDavid van Moolenbroek 	}
24c2f99d7cSDavid van Moolenbroek 	if (count > i_node->i_count) {
25c2f99d7cSDavid van Moolenbroek 		printf("ISOFS: put_node count too high\n");
26c2f99d7cSDavid van Moolenbroek 		return EINVAL;
27c2f99d7cSDavid van Moolenbroek 	}
28c2f99d7cSDavid van Moolenbroek 
29c2f99d7cSDavid van Moolenbroek 	i_node->i_count -= count - 1;
30c2f99d7cSDavid van Moolenbroek 	put_inode(i_node);
31c2f99d7cSDavid van Moolenbroek 	return OK;
32c2f99d7cSDavid van Moolenbroek }
33c2f99d7cSDavid van Moolenbroek 
34c2f99d7cSDavid van Moolenbroek struct inode* alloc_inode(void)
35c2f99d7cSDavid van Moolenbroek {
36c2f99d7cSDavid van Moolenbroek 	/*
37c2f99d7cSDavid van Moolenbroek 	 * Return a free inode from the pool.
38c2f99d7cSDavid van Moolenbroek 	 */
39c2f99d7cSDavid van Moolenbroek 	static int i;
40c2f99d7cSDavid van Moolenbroek 	int end = i;
41c2f99d7cSDavid van Moolenbroek 	struct inode *i_node;
42c2f99d7cSDavid van Moolenbroek 
43c2f99d7cSDavid van Moolenbroek 	i = (i + 1) % NR_INODE_RECORDS;
44c2f99d7cSDavid van Moolenbroek 	do {
45c2f99d7cSDavid van Moolenbroek 		i_node = &inodes[i];
46c2f99d7cSDavid van Moolenbroek 
47c2f99d7cSDavid van Moolenbroek 		if (i_node->i_count == 0) {
48c2f99d7cSDavid van Moolenbroek 			free_extent(i_node->extent);
49c2f99d7cSDavid van Moolenbroek 
50c2f99d7cSDavid van Moolenbroek 			memset(i_node, 0, sizeof(*i_node));
51c2f99d7cSDavid van Moolenbroek 			i_node->i_count = 1;
52c2f99d7cSDavid van Moolenbroek 
53c2f99d7cSDavid van Moolenbroek 			return i_node;
54c2f99d7cSDavid van Moolenbroek 		}
55c2f99d7cSDavid van Moolenbroek 
56c2f99d7cSDavid van Moolenbroek 		i = (i + 1) % NR_INODE_RECORDS;
57c2f99d7cSDavid van Moolenbroek 	}
58c2f99d7cSDavid van Moolenbroek 	while(i != end);
59c2f99d7cSDavid van Moolenbroek 
60c2f99d7cSDavid van Moolenbroek 	panic("No free inodes in cache");
61c2f99d7cSDavid van Moolenbroek }
62c2f99d7cSDavid van Moolenbroek 
63c2f99d7cSDavid van Moolenbroek struct inode* find_inode(ino_t i)
64c2f99d7cSDavid van Moolenbroek {
65c2f99d7cSDavid van Moolenbroek 	/* Get inode from cache. */
66c2f99d7cSDavid van Moolenbroek 	int cpt;
67c2f99d7cSDavid van Moolenbroek 	struct inode *i_node;
68c2f99d7cSDavid van Moolenbroek 
69c2f99d7cSDavid van Moolenbroek 	if (i == 0)
70c2f99d7cSDavid van Moolenbroek 		return NULL;
71c2f99d7cSDavid van Moolenbroek 
72c2f99d7cSDavid van Moolenbroek 	for (cpt = 0; cpt < NR_INODE_RECORDS; cpt++) {
73c2f99d7cSDavid van Moolenbroek 		i_node = &inodes[cpt];
74c2f99d7cSDavid van Moolenbroek 
75c2f99d7cSDavid van Moolenbroek 		if ((i_node->i_stat.st_ino == i) && (i_node->i_count > 0))
76c2f99d7cSDavid van Moolenbroek 			return i_node;
77c2f99d7cSDavid van Moolenbroek 	}
78c2f99d7cSDavid van Moolenbroek 
79c2f99d7cSDavid van Moolenbroek 	return NULL;
80c2f99d7cSDavid van Moolenbroek }
81c2f99d7cSDavid van Moolenbroek 
82c2f99d7cSDavid van Moolenbroek struct inode* get_inode(ino_t i)
83c2f99d7cSDavid van Moolenbroek {
84c2f99d7cSDavid van Moolenbroek 	struct inode *i_node;
85c2f99d7cSDavid van Moolenbroek 	struct dir_extent *extent;
86c2f99d7cSDavid van Moolenbroek 
87c2f99d7cSDavid van Moolenbroek 	if (i == 0)
88c2f99d7cSDavid van Moolenbroek 		return NULL;
89c2f99d7cSDavid van Moolenbroek 
90c2f99d7cSDavid van Moolenbroek 	/* Try to get inode from cache. */
91c2f99d7cSDavid van Moolenbroek 	i_node = find_inode(i);
92c2f99d7cSDavid van Moolenbroek 	if (i_node != NULL) {
93c2f99d7cSDavid van Moolenbroek 		dup_inode(i_node);
94c2f99d7cSDavid van Moolenbroek 		return i_node;
95c2f99d7cSDavid van Moolenbroek 	}
96c2f99d7cSDavid van Moolenbroek 
97c2f99d7cSDavid van Moolenbroek 	/*
98c2f99d7cSDavid van Moolenbroek 	 * Inode wasn't in cache, try to load it.
99c2f99d7cSDavid van Moolenbroek 	 * FIXME: a fake extent of one logical block is created for
100c2f99d7cSDavid van Moolenbroek 	 * read_inode(). Reading a inode this way could be problematic if
101c2f99d7cSDavid van Moolenbroek 	 * additional extents are stored behind the block boundary.
102c2f99d7cSDavid van Moolenbroek 	 */
103c2f99d7cSDavid van Moolenbroek 	i_node = alloc_inode();
104c2f99d7cSDavid van Moolenbroek 	extent = alloc_extent();
105c2f99d7cSDavid van Moolenbroek 	extent->location = i / v_pri.logical_block_size_l;
106c2f99d7cSDavid van Moolenbroek 	extent->length = 1;
107c2f99d7cSDavid van Moolenbroek 
108c2f99d7cSDavid van Moolenbroek 	if (read_inode(i_node, extent, i % v_pri.logical_block_size_l,
109c2f99d7cSDavid van Moolenbroek 	    NULL) != OK) {
110c2f99d7cSDavid van Moolenbroek 		free_extent(extent);
111c2f99d7cSDavid van Moolenbroek 		put_inode(i_node);
112c2f99d7cSDavid van Moolenbroek 		return NULL;
113c2f99d7cSDavid van Moolenbroek 	}
114c2f99d7cSDavid van Moolenbroek 
115c2f99d7cSDavid van Moolenbroek 	free_extent(extent);
116c2f99d7cSDavid van Moolenbroek 	return i_node;
117c2f99d7cSDavid van Moolenbroek }
118c2f99d7cSDavid van Moolenbroek 
119c2f99d7cSDavid van Moolenbroek void put_inode(struct inode *i_node)
120c2f99d7cSDavid van Moolenbroek {
121c2f99d7cSDavid van Moolenbroek 	if (i_node == NULL)
122c2f99d7cSDavid van Moolenbroek 		return;
123c2f99d7cSDavid van Moolenbroek 
124c2f99d7cSDavid van Moolenbroek 	assert(i_node->i_count > 0);
125c2f99d7cSDavid van Moolenbroek 
126c2f99d7cSDavid van Moolenbroek 	i_node->i_count--;
127c2f99d7cSDavid van Moolenbroek }
128c2f99d7cSDavid van Moolenbroek 
129c2f99d7cSDavid van Moolenbroek void dup_inode(struct inode *i_node)
130c2f99d7cSDavid van Moolenbroek {
131c2f99d7cSDavid van Moolenbroek 	assert(i_node != NULL);
132c2f99d7cSDavid van Moolenbroek 
133c2f99d7cSDavid van Moolenbroek 	i_node->i_count++;
134c2f99d7cSDavid van Moolenbroek }
135c2f99d7cSDavid van Moolenbroek 
136c2f99d7cSDavid van Moolenbroek static struct buf* fetch_inode(struct dir_extent *extent, size_t *offset)
137c2f99d7cSDavid van Moolenbroek {
138c2f99d7cSDavid van Moolenbroek 	struct iso9660_dir_record *dir_rec;
139c2f99d7cSDavid van Moolenbroek 	struct buf *bp;
140c2f99d7cSDavid van Moolenbroek 
141c2f99d7cSDavid van Moolenbroek 	/*
142c2f99d7cSDavid van Moolenbroek 	 * Directory entries aren't allowed to cross a logical block boundary in
143c2f99d7cSDavid van Moolenbroek 	 * ISO 9660, so we keep searching until we find something or reach the
144c2f99d7cSDavid van Moolenbroek 	 * end of the extent.
145c2f99d7cSDavid van Moolenbroek 	 */
146c2f99d7cSDavid van Moolenbroek 	bp = read_extent_block(extent, *offset / v_pri.logical_block_size_l);
147c2f99d7cSDavid van Moolenbroek 	while (bp != NULL) {
148c2f99d7cSDavid van Moolenbroek 		dir_rec = (struct iso9660_dir_record*)(b_data(bp) + *offset %
149c2f99d7cSDavid van Moolenbroek 		          v_pri.logical_block_size_l);
150c2f99d7cSDavid van Moolenbroek 		if (dir_rec->length == 0) {
151c2f99d7cSDavid van Moolenbroek 			*offset -= *offset % v_pri.logical_block_size_l;
152c2f99d7cSDavid van Moolenbroek 			*offset += v_pri.logical_block_size_l;
153c2f99d7cSDavid van Moolenbroek 		}
154c2f99d7cSDavid van Moolenbroek 		else {
155c2f99d7cSDavid van Moolenbroek 			break;
156c2f99d7cSDavid van Moolenbroek 		}
157c2f99d7cSDavid van Moolenbroek 
158*0314acfbSDavid van Moolenbroek 		lmfs_put_block(bp);
159c2f99d7cSDavid van Moolenbroek 		bp = read_extent_block(extent, *offset /
160c2f99d7cSDavid van Moolenbroek 		    v_pri.logical_block_size_l);
161c2f99d7cSDavid van Moolenbroek 	}
162c2f99d7cSDavid van Moolenbroek 
163c2f99d7cSDavid van Moolenbroek 	return bp;
164c2f99d7cSDavid van Moolenbroek }
165c2f99d7cSDavid van Moolenbroek 
166c2f99d7cSDavid van Moolenbroek int read_inode(struct inode *i_node, struct dir_extent *extent, size_t offset,
167c2f99d7cSDavid van Moolenbroek 	size_t *new_offset)
168c2f99d7cSDavid van Moolenbroek {
169c2f99d7cSDavid van Moolenbroek 	struct iso9660_dir_record *dir_rec;
170c2f99d7cSDavid van Moolenbroek 	struct buf *bp;
171c2f99d7cSDavid van Moolenbroek 
172c2f99d7cSDavid van Moolenbroek 	/* Find inode. */
173c2f99d7cSDavid van Moolenbroek 	bp = fetch_inode(extent, &offset);
174c2f99d7cSDavid van Moolenbroek 	if (bp == NULL)
175c2f99d7cSDavid van Moolenbroek 		return EOF;
176c2f99d7cSDavid van Moolenbroek 
177c2f99d7cSDavid van Moolenbroek 	dir_rec = (struct iso9660_dir_record*)(b_data(bp) + offset %
178c2f99d7cSDavid van Moolenbroek 	          v_pri.logical_block_size_l);
179c2f99d7cSDavid van Moolenbroek 
180c2f99d7cSDavid van Moolenbroek 	/* Parse basic ISO 9660 specs. */
181c2f99d7cSDavid van Moolenbroek 	if (check_dir_record(dir_rec,
182c2f99d7cSDavid van Moolenbroek 	    offset % v_pri.logical_block_size_l) != OK) {
183*0314acfbSDavid van Moolenbroek 		lmfs_put_block(bp);
184c2f99d7cSDavid van Moolenbroek 		return EINVAL;
185c2f99d7cSDavid van Moolenbroek 	}
186c2f99d7cSDavid van Moolenbroek 
187c2f99d7cSDavid van Moolenbroek 	memset(&i_node->i_stat, 0, sizeof(struct stat));
188c2f99d7cSDavid van Moolenbroek 
189c2f99d7cSDavid van Moolenbroek 	i_node->i_stat.st_ino = get_extent_absolute_block_id(extent,
190c2f99d7cSDavid van Moolenbroek 	    offset / v_pri.logical_block_size_l) * v_pri.logical_block_size_l +
191c2f99d7cSDavid van Moolenbroek 	    offset % v_pri.logical_block_size_l;
192c2f99d7cSDavid van Moolenbroek 
193c2f99d7cSDavid van Moolenbroek 	read_inode_iso9660(i_node, dir_rec);
194c2f99d7cSDavid van Moolenbroek 
195c2f99d7cSDavid van Moolenbroek 	/* Parse extensions. */
196c2f99d7cSDavid van Moolenbroek 	read_inode_susp(i_node, dir_rec, bp,
197c2f99d7cSDavid van Moolenbroek 	    offset % v_pri.logical_block_size_l);
198c2f99d7cSDavid van Moolenbroek 
199c2f99d7cSDavid van Moolenbroek 	offset += dir_rec->length;
200c2f99d7cSDavid van Moolenbroek 	read_inode_extents(i_node, dir_rec, extent, &offset);
201c2f99d7cSDavid van Moolenbroek 
202*0314acfbSDavid van Moolenbroek 	lmfs_put_block(bp);
203c2f99d7cSDavid van Moolenbroek 	if (new_offset != NULL)
204c2f99d7cSDavid van Moolenbroek 		*new_offset = offset;
205c2f99d7cSDavid van Moolenbroek 	return OK;
206c2f99d7cSDavid van Moolenbroek }
207c2f99d7cSDavid van Moolenbroek 
208c2f99d7cSDavid van Moolenbroek void read_inode_iso9660(struct inode *i,
209c2f99d7cSDavid van Moolenbroek 	const struct iso9660_dir_record *dir_rec)
210c2f99d7cSDavid van Moolenbroek {
211c2f99d7cSDavid van Moolenbroek 	char *cp;
212c2f99d7cSDavid van Moolenbroek 
213c2f99d7cSDavid van Moolenbroek 	/* Parse first extent. */
214c2f99d7cSDavid van Moolenbroek 	if (dir_rec->data_length_l > 0) {
215c2f99d7cSDavid van Moolenbroek 		assert(i->extent == NULL);
216c2f99d7cSDavid van Moolenbroek 		i->extent = alloc_extent();
217c2f99d7cSDavid van Moolenbroek 		i->extent->location = dir_rec->loc_extent_l +
218c2f99d7cSDavid van Moolenbroek 		                      dir_rec->ext_attr_rec_length;
219c2f99d7cSDavid van Moolenbroek 		i->extent->length = dir_rec->data_length_l /
220c2f99d7cSDavid van Moolenbroek 		                    v_pri.logical_block_size_l;
221c2f99d7cSDavid van Moolenbroek 		if (dir_rec->data_length_l % v_pri.logical_block_size_l)
222c2f99d7cSDavid van Moolenbroek 			i->extent->length++;
223c2f99d7cSDavid van Moolenbroek 
224c2f99d7cSDavid van Moolenbroek 		i->i_stat.st_size = dir_rec->data_length_l;
225c2f99d7cSDavid van Moolenbroek 	}
226c2f99d7cSDavid van Moolenbroek 
227c2f99d7cSDavid van Moolenbroek 	/* Parse timestamps (record date). */
228c2f99d7cSDavid van Moolenbroek 	i->i_stat.st_atime = i->i_stat.st_mtime = i->i_stat.st_ctime =
229c2f99d7cSDavid van Moolenbroek 	    i->i_stat.st_birthtime = date7_to_time_t(dir_rec->rec_date);
230c2f99d7cSDavid van Moolenbroek 
231c2f99d7cSDavid van Moolenbroek 	if ((dir_rec->file_flags & D_TYPE) == D_DIRECTORY) {
232c2f99d7cSDavid van Moolenbroek 		i->i_stat.st_mode = S_IFDIR;
233c2f99d7cSDavid van Moolenbroek 		i->i_stat.st_ino =
234c2f99d7cSDavid van Moolenbroek 		    i->extent->location * v_pri.logical_block_size_l;
235c2f99d7cSDavid van Moolenbroek 	}
236c2f99d7cSDavid van Moolenbroek 	else
237c2f99d7cSDavid van Moolenbroek 		i->i_stat.st_mode = S_IFREG;
238c2f99d7cSDavid van Moolenbroek 	i->i_stat.st_mode |= 0555;
239c2f99d7cSDavid van Moolenbroek 
240c2f99d7cSDavid van Moolenbroek 	/* Parse file name. */
241c2f99d7cSDavid van Moolenbroek 	if (dir_rec->file_id[0] == 0)
242c2f99d7cSDavid van Moolenbroek 		strcpy(i->i_name, ".");
243c2f99d7cSDavid van Moolenbroek 	else if (dir_rec->file_id[0] == 1)
244c2f99d7cSDavid van Moolenbroek 		strcpy(i->i_name, "..");
245c2f99d7cSDavid van Moolenbroek 	else {
246c2f99d7cSDavid van Moolenbroek 		memcpy(i->i_name, dir_rec->file_id, dir_rec->length_file_id);
247c2f99d7cSDavid van Moolenbroek 
248c2f99d7cSDavid van Moolenbroek 		/* Truncate/ignore file version suffix. */
249c2f99d7cSDavid van Moolenbroek 		cp = strchr(i->i_name, ';');
250c2f99d7cSDavid van Moolenbroek 		if (cp != NULL)
251c2f99d7cSDavid van Moolenbroek 			*cp = '\0';
252c2f99d7cSDavid van Moolenbroek 		/* Truncate dot if file has no extension. */
253c2f99d7cSDavid van Moolenbroek 		if (strchr(i->i_name, '.') + 1 == cp)
254c2f99d7cSDavid van Moolenbroek 			*(cp-1) = '\0';
255c2f99d7cSDavid van Moolenbroek 	}
256c2f99d7cSDavid van Moolenbroek 
257c2f99d7cSDavid van Moolenbroek 	/* Initialize stat. */
258c2f99d7cSDavid van Moolenbroek 	i->i_stat.st_dev = fs_dev;
259c2f99d7cSDavid van Moolenbroek 	i->i_stat.st_blksize = v_pri.logical_block_size_l;
260c2f99d7cSDavid van Moolenbroek 	i->i_stat.st_blocks =
261c2f99d7cSDavid van Moolenbroek 	    dir_rec->data_length_l / v_pri.logical_block_size_l;
262c2f99d7cSDavid van Moolenbroek 	i->i_stat.st_nlink = 1;
263c2f99d7cSDavid van Moolenbroek }
264c2f99d7cSDavid van Moolenbroek 
265c2f99d7cSDavid van Moolenbroek void read_inode_extents(struct inode *i,
266c2f99d7cSDavid van Moolenbroek 	const struct iso9660_dir_record *dir_rec,
267c2f99d7cSDavid van Moolenbroek 	struct dir_extent *extent, size_t *offset)
268c2f99d7cSDavid van Moolenbroek {
269c2f99d7cSDavid van Moolenbroek 	struct buf *bp;
270c2f99d7cSDavid van Moolenbroek 	struct iso9660_dir_record *extent_rec;
271c2f99d7cSDavid van Moolenbroek 	struct dir_extent *cur_extent = i->extent;
272c2f99d7cSDavid van Moolenbroek 	int done = FALSE;
273c2f99d7cSDavid van Moolenbroek 
274c2f99d7cSDavid van Moolenbroek 	/*
275c2f99d7cSDavid van Moolenbroek 	 * No need to search extents if file is empty or has final directory
276c2f99d7cSDavid van Moolenbroek 	 * record flag set.
277c2f99d7cSDavid van Moolenbroek 	 */
278c2f99d7cSDavid van Moolenbroek 	if (cur_extent == NULL ||
279c2f99d7cSDavid van Moolenbroek 	    ((dir_rec->file_flags & D_NOT_LAST_EXTENT) == 0))
280c2f99d7cSDavid van Moolenbroek 		return;
281c2f99d7cSDavid van Moolenbroek 
282c2f99d7cSDavid van Moolenbroek 	while (!done) {
283c2f99d7cSDavid van Moolenbroek 		bp = fetch_inode(extent, offset);
284c2f99d7cSDavid van Moolenbroek 		if (bp == NULL)
285c2f99d7cSDavid van Moolenbroek 			return;
286c2f99d7cSDavid van Moolenbroek 
287c2f99d7cSDavid van Moolenbroek 		bp = read_extent_block(extent,
288c2f99d7cSDavid van Moolenbroek 		    *offset / v_pri.logical_block_size_l);
289c2f99d7cSDavid van Moolenbroek 		extent_rec = (struct iso9660_dir_record*)(b_data(bp) +
290c2f99d7cSDavid van Moolenbroek 		    *offset % v_pri.logical_block_size_l);
291c2f99d7cSDavid van Moolenbroek 
292c2f99d7cSDavid van Moolenbroek 		if (check_dir_record(dir_rec,
293c2f99d7cSDavid van Moolenbroek 		    *offset % v_pri.logical_block_size_l) != OK) {
294*0314acfbSDavid van Moolenbroek 			lmfs_put_block(bp);
295c2f99d7cSDavid van Moolenbroek 			return;
296c2f99d7cSDavid van Moolenbroek 		}
297c2f99d7cSDavid van Moolenbroek 
298c2f99d7cSDavid van Moolenbroek 		/* Extent entries should share the same name. */
299c2f99d7cSDavid van Moolenbroek 		if ((dir_rec->length_file_id == extent_rec->length_file_id) &&
300c2f99d7cSDavid van Moolenbroek 		    (memcmp(dir_rec->file_id, extent_rec->file_id,
301c2f99d7cSDavid van Moolenbroek 		    dir_rec->length_file_id) == 0)) {
302c2f99d7cSDavid van Moolenbroek 			/* Add the extent at the end of the linked list. */
303c2f99d7cSDavid van Moolenbroek 			assert(cur_extent->next == NULL);
304c2f99d7cSDavid van Moolenbroek 			cur_extent->next = alloc_extent();
305c2f99d7cSDavid van Moolenbroek 			cur_extent->next->location = dir_rec->loc_extent_l +
306c2f99d7cSDavid van Moolenbroek 			    dir_rec->ext_attr_rec_length;
307c2f99d7cSDavid van Moolenbroek 			cur_extent->next->length = dir_rec->data_length_l /
308c2f99d7cSDavid van Moolenbroek 			    v_pri.logical_block_size_l;
309c2f99d7cSDavid van Moolenbroek 			if (dir_rec->data_length_l % v_pri.logical_block_size_l)
310c2f99d7cSDavid van Moolenbroek 				cur_extent->next->length++;
311c2f99d7cSDavid van Moolenbroek 
312c2f99d7cSDavid van Moolenbroek 			i->i_stat.st_size += dir_rec->data_length_l;
313c2f99d7cSDavid van Moolenbroek 			i->i_stat.st_blocks += cur_extent->next->length;
314c2f99d7cSDavid van Moolenbroek 
315c2f99d7cSDavid van Moolenbroek 			cur_extent = cur_extent->next;
316c2f99d7cSDavid van Moolenbroek 			*offset += extent_rec->length;
317c2f99d7cSDavid van Moolenbroek 		}
318c2f99d7cSDavid van Moolenbroek 		else
319c2f99d7cSDavid van Moolenbroek 			done = TRUE;
320c2f99d7cSDavid van Moolenbroek 
321c2f99d7cSDavid van Moolenbroek 		/* Check if not last extent bit is not set. */
322c2f99d7cSDavid van Moolenbroek 		if ((dir_rec->file_flags & D_NOT_LAST_EXTENT) == 0)
323c2f99d7cSDavid van Moolenbroek 			done = TRUE;
324c2f99d7cSDavid van Moolenbroek 
325*0314acfbSDavid van Moolenbroek 		lmfs_put_block(bp);
326c2f99d7cSDavid van Moolenbroek 	}
327c2f99d7cSDavid van Moolenbroek }
328c2f99d7cSDavid van Moolenbroek 
329c2f99d7cSDavid van Moolenbroek void read_inode_susp(struct inode *i, const struct iso9660_dir_record *dir_rec,
330c2f99d7cSDavid van Moolenbroek 	struct buf *bp, size_t offset)
331c2f99d7cSDavid van Moolenbroek {
332c2f99d7cSDavid van Moolenbroek 	int susp_offset, susp_size;
333c2f99d7cSDavid van Moolenbroek 	struct rrii_dir_record rrii_data;
334c2f99d7cSDavid van Moolenbroek 
335c2f99d7cSDavid van Moolenbroek 	susp_offset = 33 + dir_rec->length_file_id;
336c2f99d7cSDavid van Moolenbroek 	/* Get rid of padding byte. */
337c2f99d7cSDavid van Moolenbroek 	if(dir_rec->length_file_id % 2 == 0) {
338c2f99d7cSDavid van Moolenbroek 		susp_offset++;
339c2f99d7cSDavid van Moolenbroek 	}
340c2f99d7cSDavid van Moolenbroek 
341c2f99d7cSDavid van Moolenbroek 	if(dir_rec->length - susp_offset >= 4) {
342c2f99d7cSDavid van Moolenbroek 		susp_size = dir_rec->length - susp_offset;
343c2f99d7cSDavid van Moolenbroek 
344c2f99d7cSDavid van Moolenbroek 		/* Initialize record with known, sane data. */
345c2f99d7cSDavid van Moolenbroek 		memcpy(rrii_data.mtime, dir_rec->rec_date, ISO9660_SIZE_DATE7);
346c2f99d7cSDavid van Moolenbroek 		memcpy(rrii_data.atime, dir_rec->rec_date, ISO9660_SIZE_DATE7);
347c2f99d7cSDavid van Moolenbroek 		memcpy(rrii_data.ctime, dir_rec->rec_date, ISO9660_SIZE_DATE7);
348c2f99d7cSDavid van Moolenbroek 		memcpy(rrii_data.birthtime, dir_rec->rec_date,
349c2f99d7cSDavid van Moolenbroek 		    ISO9660_SIZE_DATE7);
350c2f99d7cSDavid van Moolenbroek 
351c2f99d7cSDavid van Moolenbroek 		rrii_data.d_mode = i->i_stat.st_mode;
352c2f99d7cSDavid van Moolenbroek 		rrii_data.uid    = 0;
353c2f99d7cSDavid van Moolenbroek 		rrii_data.gid    = 0;
354c2f99d7cSDavid van Moolenbroek 		rrii_data.rdev   = NO_DEV;
355c2f99d7cSDavid van Moolenbroek 		rrii_data.file_id_rrip[0] = '\0';
356c2f99d7cSDavid van Moolenbroek 		rrii_data.slink_rrip[0]   = '\0';
357c2f99d7cSDavid van Moolenbroek 
358c2f99d7cSDavid van Moolenbroek 		parse_susp_buffer(&rrii_data, b_data(bp)+offset+susp_offset,
359c2f99d7cSDavid van Moolenbroek 		    susp_size);
360c2f99d7cSDavid van Moolenbroek 
361c2f99d7cSDavid van Moolenbroek 		/* Copy back data from rrii_dir_record structure. */
362c2f99d7cSDavid van Moolenbroek 		i->i_stat.st_atime = date7_to_time_t(rrii_data.atime);
363c2f99d7cSDavid van Moolenbroek 		i->i_stat.st_ctime = date7_to_time_t(rrii_data.ctime);
364c2f99d7cSDavid van Moolenbroek 		i->i_stat.st_mtime = date7_to_time_t(rrii_data.mtime);
365c2f99d7cSDavid van Moolenbroek 		i->i_stat.st_birthtime = date7_to_time_t(rrii_data.birthtime);
366c2f99d7cSDavid van Moolenbroek 
367c2f99d7cSDavid van Moolenbroek 		i->i_stat.st_mode = rrii_data.d_mode;
368c2f99d7cSDavid van Moolenbroek 		i->i_stat.st_uid  = rrii_data.uid;
369c2f99d7cSDavid van Moolenbroek 		i->i_stat.st_gid  = rrii_data.gid;
370c2f99d7cSDavid van Moolenbroek 		i->i_stat.st_rdev = rrii_data.rdev;
371c2f99d7cSDavid van Moolenbroek 
372c2f99d7cSDavid van Moolenbroek 		if (rrii_data.file_id_rrip[0] != '\0')
373c2f99d7cSDavid van Moolenbroek 			strlcpy(i->i_name, rrii_data.file_id_rrip,
374c2f99d7cSDavid van Moolenbroek 			   sizeof(i->i_name));
375c2f99d7cSDavid van Moolenbroek 		if (rrii_data.slink_rrip[0] != '\0')
376c2f99d7cSDavid van Moolenbroek 			strlcpy(i->s_link, rrii_data.slink_rrip,
377c2f99d7cSDavid van Moolenbroek 			   sizeof(i->s_link));
378c2f99d7cSDavid van Moolenbroek 	}
379c2f99d7cSDavid van Moolenbroek }
380c2f99d7cSDavid van Moolenbroek 
381c2f99d7cSDavid van Moolenbroek int check_dir_record(const struct iso9660_dir_record *d, size_t offset)
382c2f99d7cSDavid van Moolenbroek {
383c2f99d7cSDavid van Moolenbroek 	/* Run some consistency check on a directory entry. */
384c2f99d7cSDavid van Moolenbroek 	if ((d->length < 33) || (d->length_file_id < 1))
385c2f99d7cSDavid van Moolenbroek 		return EINVAL;
386c2f99d7cSDavid van Moolenbroek 	if (d->length_file_id + 32 > d->length)
387c2f99d7cSDavid van Moolenbroek 		return EINVAL;
388c2f99d7cSDavid van Moolenbroek 	if (offset + d->length > v_pri.logical_block_size_l)
389c2f99d7cSDavid van Moolenbroek 		return EINVAL;
390c2f99d7cSDavid van Moolenbroek 
391c2f99d7cSDavid van Moolenbroek 	return OK;
392c2f99d7cSDavid van Moolenbroek }
393c2f99d7cSDavid van Moolenbroek 
394c2f99d7cSDavid van Moolenbroek int check_inodes(void)
395c2f99d7cSDavid van Moolenbroek {
396c2f99d7cSDavid van Moolenbroek 	/* Check whether there are no more inodes in use. Called on unmount. */
397c2f99d7cSDavid van Moolenbroek 	int i;
398c2f99d7cSDavid van Moolenbroek 
399c2f99d7cSDavid van Moolenbroek 	for (i = 0; i < NR_INODE_RECORDS; i++)
400c2f99d7cSDavid van Moolenbroek 		if (inodes[i].i_count > 0)
401c2f99d7cSDavid van Moolenbroek 			return FALSE;
402c2f99d7cSDavid van Moolenbroek 
403c2f99d7cSDavid van Moolenbroek 	return TRUE;
404c2f99d7cSDavid van Moolenbroek }
405