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