xref: /minix3/minix/fs/isofs/super.c (revision 1311233cfbe0c8d7c7a17bdf5274fbcdd76d7702)
1c2f99d7cSDavid van Moolenbroek /*
2c2f99d7cSDavid van Moolenbroek  * Functions to manage the superblock of the filesystem. These functions are
3c2f99d7cSDavid van Moolenbroek  * are called at the beginning and at the end of the server.
4c2f99d7cSDavid van Moolenbroek  */
5c2f99d7cSDavid van Moolenbroek 
6c2f99d7cSDavid van Moolenbroek #include "inc.h"
7c2f99d7cSDavid van Moolenbroek #include <string.h>
8c2f99d7cSDavid van Moolenbroek #include <minix/com.h>
9c2f99d7cSDavid van Moolenbroek #include <minix/u64.h>
10c2f99d7cSDavid van Moolenbroek #include <minix/bdev.h>
11c2f99d7cSDavid van Moolenbroek 
12c2f99d7cSDavid van Moolenbroek int release_vol_pri_desc(struct iso9660_vol_pri_desc *vol_pri)
13c2f99d7cSDavid van Moolenbroek {
14c2f99d7cSDavid van Moolenbroek 	/* Release the root dir root. */
15c2f99d7cSDavid van Moolenbroek 	if (vol_pri->i_count > 0) {
16c2f99d7cSDavid van Moolenbroek 		put_inode(vol_pri->inode_root);
17c2f99d7cSDavid van Moolenbroek 		vol_pri->inode_root = NULL;
18c2f99d7cSDavid van Moolenbroek 		vol_pri->i_count = 0;
19c2f99d7cSDavid van Moolenbroek 	}
20c2f99d7cSDavid van Moolenbroek 
21c2f99d7cSDavid van Moolenbroek 	return OK;
22c2f99d7cSDavid van Moolenbroek }
23c2f99d7cSDavid van Moolenbroek 
24c2f99d7cSDavid van Moolenbroek static int create_vol_pri_desc(struct iso9660_vol_pri_desc *vol_pri, char *buf,
25c2f99d7cSDavid van Moolenbroek 	size_t __unused address)
26c2f99d7cSDavid van Moolenbroek {
27c2f99d7cSDavid van Moolenbroek 	/*
28c2f99d7cSDavid van Moolenbroek 	 * This function fullfill the super block data structure using the
29c2f99d7cSDavid van Moolenbroek 	 * information contained in the buffer.
30c2f99d7cSDavid van Moolenbroek 	 */
31c2f99d7cSDavid van Moolenbroek 	struct iso9660_dir_record *root_record;
32c2f99d7cSDavid van Moolenbroek 	struct inode *root;
33c2f99d7cSDavid van Moolenbroek 	struct dir_extent *extent;
34c2f99d7cSDavid van Moolenbroek 
35c2f99d7cSDavid van Moolenbroek 	if (vol_pri->i_count > 0)
36c2f99d7cSDavid van Moolenbroek 		release_vol_pri_desc(vol_pri);
37c2f99d7cSDavid van Moolenbroek 
38c2f99d7cSDavid van Moolenbroek 	memcpy(vol_pri, buf, 2048);
39c2f99d7cSDavid van Moolenbroek 
40c2f99d7cSDavid van Moolenbroek 	/* Check various fields for consistency. */
41c2f99d7cSDavid van Moolenbroek 	if ((memcmp(vol_pri->standard_id, "CD001",
42c2f99d7cSDavid van Moolenbroek 	    ISO9660_SIZE_STANDARD_ID) != 0) ||
43c2f99d7cSDavid van Moolenbroek 	    (vol_pri->vd_version != 1) ||
44c2f99d7cSDavid van Moolenbroek 	    (vol_pri->logical_block_size_l < 2048) ||
45c2f99d7cSDavid van Moolenbroek 	    (vol_pri->file_struct_ver != 1))
46c2f99d7cSDavid van Moolenbroek 		return EINVAL;
47c2f99d7cSDavid van Moolenbroek 
480314acfbSDavid van Moolenbroek 	lmfs_set_blocksize(vol_pri->logical_block_size_l);
49*1311233cSDavid van Moolenbroek 	lmfs_set_blockusage(vol_pri->volume_space_size_l,
50*1311233cSDavid van Moolenbroek 	    vol_pri->volume_space_size_l);
51c2f99d7cSDavid van Moolenbroek 
52c2f99d7cSDavid van Moolenbroek 	/* Read root directory record. */
53c2f99d7cSDavid van Moolenbroek 	root_record = (struct iso9660_dir_record *)vol_pri->root_directory;
54c2f99d7cSDavid van Moolenbroek 	root = alloc_inode();
55c2f99d7cSDavid van Moolenbroek 	extent = alloc_extent();
56c2f99d7cSDavid van Moolenbroek 
57c2f99d7cSDavid van Moolenbroek 	extent->location =
58c2f99d7cSDavid van Moolenbroek 	    root_record->loc_extent_l + root_record->ext_attr_rec_length;
59c2f99d7cSDavid van Moolenbroek 	extent->length =
60c2f99d7cSDavid van Moolenbroek 	    root_record->data_length_l / vol_pri->logical_block_size_l;
61c2f99d7cSDavid van Moolenbroek 	if (root_record->data_length_l % vol_pri->logical_block_size_l)
62c2f99d7cSDavid van Moolenbroek 		extent->length++;
63c2f99d7cSDavid van Moolenbroek 
64c2f99d7cSDavid van Moolenbroek 	if (read_inode(root, extent, 0, NULL) != OK) {
65c2f99d7cSDavid van Moolenbroek 		free_extent(extent);
66c2f99d7cSDavid van Moolenbroek 		put_inode(root);
67c2f99d7cSDavid van Moolenbroek 		return EINVAL;
68c2f99d7cSDavid van Moolenbroek 	}
69c2f99d7cSDavid van Moolenbroek 
70c2f99d7cSDavid van Moolenbroek 	free_extent(extent);
71c2f99d7cSDavid van Moolenbroek 	vol_pri->inode_root = root;
72c2f99d7cSDavid van Moolenbroek 	vol_pri->i_count = 1;
73c2f99d7cSDavid van Moolenbroek 
74c2f99d7cSDavid van Moolenbroek 	return OK;
75c2f99d7cSDavid van Moolenbroek }
76c2f99d7cSDavid van Moolenbroek 
77c2f99d7cSDavid van Moolenbroek int read_vds(struct iso9660_vol_pri_desc *vol_pri, dev_t dev)
78c2f99d7cSDavid van Moolenbroek {
79c2f99d7cSDavid van Moolenbroek 	/*
80c2f99d7cSDavid van Moolenbroek 	 * This function reads from a ISO9660 filesystem (in the device dev)
81c2f99d7cSDavid van Moolenbroek 	 * the super block and saves it in vol_pri.
82c2f99d7cSDavid van Moolenbroek 	 */
83c2f99d7cSDavid van Moolenbroek 	size_t offset;
84c2f99d7cSDavid van Moolenbroek 	int vol_ok = FALSE, vol_pri_flag = FALSE;
85c2f99d7cSDavid van Moolenbroek 	int r;
86c2f99d7cSDavid van Moolenbroek 	static char sbbuf[ISO9660_MIN_BLOCK_SIZE];
87c2f99d7cSDavid van Moolenbroek 	int i = 0;
88c2f99d7cSDavid van Moolenbroek 
89c2f99d7cSDavid van Moolenbroek 	for(offset = ISO9660_SUPER_BLOCK_POSITION;
90c2f99d7cSDavid van Moolenbroek 	    !vol_ok && i++ < MAX_ATTEMPTS;
91c2f99d7cSDavid van Moolenbroek 	    offset += ISO9660_MIN_BLOCK_SIZE) {
92c2f99d7cSDavid van Moolenbroek 		/* Read the sector of the super block. */
93c2f99d7cSDavid van Moolenbroek 		r = bdev_read(dev, offset, sbbuf, ISO9660_MIN_BLOCK_SIZE,
94c2f99d7cSDavid van Moolenbroek 		    BDEV_NOFLAGS);
95c2f99d7cSDavid van Moolenbroek 
96c2f99d7cSDavid van Moolenbroek 		if (r != ISO9660_MIN_BLOCK_SIZE) {
97c2f99d7cSDavid van Moolenbroek 			/* Damaged sector or what? */
98c2f99d7cSDavid van Moolenbroek 			return EINVAL;
99c2f99d7cSDavid van Moolenbroek 		}
100c2f99d7cSDavid van Moolenbroek 
101c2f99d7cSDavid van Moolenbroek 		if ((sbbuf[0] & BYTE) == VD_PRIMARY) {
102c2f99d7cSDavid van Moolenbroek 			/* Copy the buffer in the data structure. */
103c2f99d7cSDavid van Moolenbroek 			if (create_vol_pri_desc(vol_pri, sbbuf, offset) == OK) {
104c2f99d7cSDavid van Moolenbroek 				vol_pri_flag = TRUE;
105c2f99d7cSDavid van Moolenbroek 			}
106c2f99d7cSDavid van Moolenbroek 		}
107c2f99d7cSDavid van Moolenbroek 
108c2f99d7cSDavid van Moolenbroek 		if ((sbbuf[0] & BYTE) == VD_SET_TERM) {
109c2f99d7cSDavid van Moolenbroek 			/* I dont need to save anything about it */
110c2f99d7cSDavid van Moolenbroek 			vol_ok = TRUE;
111c2f99d7cSDavid van Moolenbroek 		}
112c2f99d7cSDavid van Moolenbroek 	}
113c2f99d7cSDavid van Moolenbroek 
114c2f99d7cSDavid van Moolenbroek 	if (vol_ok == FALSE || vol_pri_flag == FALSE)
115c2f99d7cSDavid van Moolenbroek 		return EINVAL;		/* If no superblock was found... */
116c2f99d7cSDavid van Moolenbroek 	else
117c2f99d7cSDavid van Moolenbroek 		return OK;		/* otherwise. */
118c2f99d7cSDavid van Moolenbroek }
119