xref: /minix/minix/fs/isofs/super.c (revision 9f988b79)
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 	size_t __unused address)
26 {
27 	/*
28 	 * This function fullfill the super block data structure using the
29 	 * information contained in the buffer.
30 	 */
31 	struct iso9660_dir_record *root_record;
32 	struct inode *root;
33 	struct dir_extent *extent;
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 	    (vol_pri->file_struct_ver != 1))
46 		return EINVAL;
47 
48 	lmfs_set_blocksize(vol_pri->logical_block_size_l);
49 	lmfs_set_blockusage(vol_pri->volume_space_size_l,
50 	    vol_pri->volume_space_size_l);
51 
52 	/* Read root directory record. */
53 	root_record = (struct iso9660_dir_record *)vol_pri->root_directory;
54 	root = alloc_inode();
55 	extent = alloc_extent();
56 
57 	extent->location =
58 	    root_record->loc_extent_l + root_record->ext_attr_rec_length;
59 	extent->length =
60 	    root_record->data_length_l / vol_pri->logical_block_size_l;
61 	if (root_record->data_length_l % vol_pri->logical_block_size_l)
62 		extent->length++;
63 
64 	if (read_inode(root, extent, 0, NULL) != OK) {
65 		free_extent(extent);
66 		put_inode(root);
67 		return EINVAL;
68 	}
69 
70 	free_extent(extent);
71 	vol_pri->inode_root = root;
72 	vol_pri->i_count = 1;
73 
74 	return OK;
75 }
76 
77 int read_vds(struct iso9660_vol_pri_desc *vol_pri, dev_t dev)
78 {
79 	/*
80 	 * This function reads from a ISO9660 filesystem (in the device dev)
81 	 * the super block and saves it in vol_pri.
82 	 */
83 	size_t offset;
84 	int vol_ok = FALSE, vol_pri_flag = FALSE;
85 	int r;
86 	static char sbbuf[ISO9660_MIN_BLOCK_SIZE];
87 	int i = 0;
88 
89 	for(offset = ISO9660_SUPER_BLOCK_POSITION;
90 	    !vol_ok && i++ < MAX_ATTEMPTS;
91 	    offset += ISO9660_MIN_BLOCK_SIZE) {
92 		/* Read the sector of the super block. */
93 		r = bdev_read(dev, offset, sbbuf, ISO9660_MIN_BLOCK_SIZE,
94 		    BDEV_NOFLAGS);
95 
96 		if (r != ISO9660_MIN_BLOCK_SIZE) {
97 			/* Damaged sector or what? */
98 			return EINVAL;
99 		}
100 
101 		if ((sbbuf[0] & BYTE) == VD_PRIMARY) {
102 			/* Copy the buffer in the data structure. */
103 			if (create_vol_pri_desc(vol_pri, sbbuf, offset) == OK) {
104 				vol_pri_flag = TRUE;
105 			}
106 		}
107 
108 		if ((sbbuf[0] & BYTE) == VD_SET_TERM) {
109 			/* I dont need to save anything about it */
110 			vol_ok = TRUE;
111 		}
112 	}
113 
114 	if (vol_ok == FALSE || vol_pri_flag == FALSE)
115 		return EINVAL;		/* If no superblock was found... */
116 	else
117 		return OK;		/* otherwise. */
118 }
119