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