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