xref: /minix3/minix/fs/isofs/super.c (revision ef9dc93f44157dea667de514ba31c214ccba64cc)
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, major(fs_dev));
49 
50 	/* Read root directory record. */
51 	root_record = (struct iso9660_dir_record *)vol_pri->root_directory;
52 	root = alloc_inode();
53 	extent = alloc_extent();
54 
55 	extent->location =
56 	    root_record->loc_extent_l + root_record->ext_attr_rec_length;
57 	extent->length =
58 	    root_record->data_length_l / vol_pri->logical_block_size_l;
59 	if (root_record->data_length_l % vol_pri->logical_block_size_l)
60 		extent->length++;
61 
62 	if (read_inode(root, extent, 0, NULL) != OK) {
63 		free_extent(extent);
64 		put_inode(root);
65 		return EINVAL;
66 	}
67 
68 	free_extent(extent);
69 	vol_pri->inode_root = root;
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 			/* Copy the buffer in the data structure. */
101 			if (create_vol_pri_desc(vol_pri, sbbuf, offset) == OK) {
102 				vol_pri_flag = TRUE;
103 			}
104 		}
105 
106 		if ((sbbuf[0] & BYTE) == VD_SET_TERM) {
107 			/* I dont need to save anything about it */
108 			vol_ok = TRUE;
109 		}
110 	}
111 
112 	if (vol_ok == FALSE || vol_pri_flag == FALSE)
113 		return EINVAL;		/* If no superblock was found... */
114 	else
115 		return OK;		/* otherwise. */
116 }
117