1c2f99d7cSDavid van Moolenbroek 2c2f99d7cSDavid van Moolenbroek /* 3c2f99d7cSDavid van Moolenbroek * This file contains all the function that handle the dir records 4c2f99d7cSDavid van Moolenbroek * (inodes) for the ISO9660 filesystem. 5c2f99d7cSDavid van Moolenbroek */ 6c2f99d7cSDavid van Moolenbroek 7c2f99d7cSDavid van Moolenbroek #include "inc.h" 8c2f99d7cSDavid van Moolenbroek 9c2f99d7cSDavid van Moolenbroek static struct inode inodes[NR_INODE_RECORDS]; 10c2f99d7cSDavid van Moolenbroek static struct buf* fetch_inode(struct dir_extent *extent, size_t *offset); 11c2f99d7cSDavid van Moolenbroek 12c2f99d7cSDavid van Moolenbroek int fs_putnode(ino_t ino_nr, unsigned int count) 13c2f99d7cSDavid van Moolenbroek { 14c2f99d7cSDavid van Moolenbroek /* 15c2f99d7cSDavid van Moolenbroek * Find the inode specified by the request message and decrease its 16c2f99d7cSDavid van Moolenbroek * counter. 17c2f99d7cSDavid van Moolenbroek */ 18c2f99d7cSDavid van Moolenbroek struct inode *i_node; 19c2f99d7cSDavid van Moolenbroek 20c2f99d7cSDavid van Moolenbroek if ((i_node = find_inode(ino_nr)) == NULL) { 21c2f99d7cSDavid van Moolenbroek printf("ISOFS: trying to free unused inode\n"); 22c2f99d7cSDavid van Moolenbroek return EINVAL; 23c2f99d7cSDavid van Moolenbroek } 24c2f99d7cSDavid van Moolenbroek if (count > i_node->i_count) { 25c2f99d7cSDavid van Moolenbroek printf("ISOFS: put_node count too high\n"); 26c2f99d7cSDavid van Moolenbroek return EINVAL; 27c2f99d7cSDavid van Moolenbroek } 28c2f99d7cSDavid van Moolenbroek 29c2f99d7cSDavid van Moolenbroek i_node->i_count -= count - 1; 30c2f99d7cSDavid van Moolenbroek put_inode(i_node); 31c2f99d7cSDavid van Moolenbroek return OK; 32c2f99d7cSDavid van Moolenbroek } 33c2f99d7cSDavid van Moolenbroek 34c2f99d7cSDavid van Moolenbroek struct inode* alloc_inode(void) 35c2f99d7cSDavid van Moolenbroek { 36c2f99d7cSDavid van Moolenbroek /* 37c2f99d7cSDavid van Moolenbroek * Return a free inode from the pool. 38c2f99d7cSDavid van Moolenbroek */ 39c2f99d7cSDavid van Moolenbroek static int i; 40c2f99d7cSDavid van Moolenbroek int end = i; 41c2f99d7cSDavid van Moolenbroek struct inode *i_node; 42c2f99d7cSDavid van Moolenbroek 43c2f99d7cSDavid van Moolenbroek i = (i + 1) % NR_INODE_RECORDS; 44c2f99d7cSDavid van Moolenbroek do { 45c2f99d7cSDavid van Moolenbroek i_node = &inodes[i]; 46c2f99d7cSDavid van Moolenbroek 47c2f99d7cSDavid van Moolenbroek if (i_node->i_count == 0) { 48c2f99d7cSDavid van Moolenbroek free_extent(i_node->extent); 49c2f99d7cSDavid van Moolenbroek 50c2f99d7cSDavid van Moolenbroek memset(i_node, 0, sizeof(*i_node)); 51c2f99d7cSDavid van Moolenbroek i_node->i_count = 1; 52c2f99d7cSDavid van Moolenbroek 53c2f99d7cSDavid van Moolenbroek return i_node; 54c2f99d7cSDavid van Moolenbroek } 55c2f99d7cSDavid van Moolenbroek 56c2f99d7cSDavid van Moolenbroek i = (i + 1) % NR_INODE_RECORDS; 57c2f99d7cSDavid van Moolenbroek } 58c2f99d7cSDavid van Moolenbroek while(i != end); 59c2f99d7cSDavid van Moolenbroek 60c2f99d7cSDavid van Moolenbroek panic("No free inodes in cache"); 61c2f99d7cSDavid van Moolenbroek } 62c2f99d7cSDavid van Moolenbroek 63c2f99d7cSDavid van Moolenbroek struct inode* find_inode(ino_t i) 64c2f99d7cSDavid van Moolenbroek { 65c2f99d7cSDavid van Moolenbroek /* Get inode from cache. */ 66c2f99d7cSDavid van Moolenbroek int cpt; 67c2f99d7cSDavid van Moolenbroek struct inode *i_node; 68c2f99d7cSDavid van Moolenbroek 69c2f99d7cSDavid van Moolenbroek if (i == 0) 70c2f99d7cSDavid van Moolenbroek return NULL; 71c2f99d7cSDavid van Moolenbroek 72c2f99d7cSDavid van Moolenbroek for (cpt = 0; cpt < NR_INODE_RECORDS; cpt++) { 73c2f99d7cSDavid van Moolenbroek i_node = &inodes[cpt]; 74c2f99d7cSDavid van Moolenbroek 75c2f99d7cSDavid van Moolenbroek if ((i_node->i_stat.st_ino == i) && (i_node->i_count > 0)) 76c2f99d7cSDavid van Moolenbroek return i_node; 77c2f99d7cSDavid van Moolenbroek } 78c2f99d7cSDavid van Moolenbroek 79c2f99d7cSDavid van Moolenbroek return NULL; 80c2f99d7cSDavid van Moolenbroek } 81c2f99d7cSDavid van Moolenbroek 82c2f99d7cSDavid van Moolenbroek struct inode* get_inode(ino_t i) 83c2f99d7cSDavid van Moolenbroek { 84c2f99d7cSDavid van Moolenbroek struct inode *i_node; 85c2f99d7cSDavid van Moolenbroek struct dir_extent *extent; 86c2f99d7cSDavid van Moolenbroek 87c2f99d7cSDavid van Moolenbroek if (i == 0) 88c2f99d7cSDavid van Moolenbroek return NULL; 89c2f99d7cSDavid van Moolenbroek 90c2f99d7cSDavid van Moolenbroek /* Try to get inode from cache. */ 91c2f99d7cSDavid van Moolenbroek i_node = find_inode(i); 92c2f99d7cSDavid van Moolenbroek if (i_node != NULL) { 93c2f99d7cSDavid van Moolenbroek dup_inode(i_node); 94c2f99d7cSDavid van Moolenbroek return i_node; 95c2f99d7cSDavid van Moolenbroek } 96c2f99d7cSDavid van Moolenbroek 97c2f99d7cSDavid van Moolenbroek /* 98c2f99d7cSDavid van Moolenbroek * Inode wasn't in cache, try to load it. 99c2f99d7cSDavid van Moolenbroek * FIXME: a fake extent of one logical block is created for 100c2f99d7cSDavid van Moolenbroek * read_inode(). Reading a inode this way could be problematic if 101c2f99d7cSDavid van Moolenbroek * additional extents are stored behind the block boundary. 102c2f99d7cSDavid van Moolenbroek */ 103c2f99d7cSDavid van Moolenbroek i_node = alloc_inode(); 104c2f99d7cSDavid van Moolenbroek extent = alloc_extent(); 105c2f99d7cSDavid van Moolenbroek extent->location = i / v_pri.logical_block_size_l; 106c2f99d7cSDavid van Moolenbroek extent->length = 1; 107c2f99d7cSDavid van Moolenbroek 108c2f99d7cSDavid van Moolenbroek if (read_inode(i_node, extent, i % v_pri.logical_block_size_l, 109c2f99d7cSDavid van Moolenbroek NULL) != OK) { 110c2f99d7cSDavid van Moolenbroek free_extent(extent); 111c2f99d7cSDavid van Moolenbroek put_inode(i_node); 112c2f99d7cSDavid van Moolenbroek return NULL; 113c2f99d7cSDavid van Moolenbroek } 114c2f99d7cSDavid van Moolenbroek 115c2f99d7cSDavid van Moolenbroek free_extent(extent); 116c2f99d7cSDavid van Moolenbroek return i_node; 117c2f99d7cSDavid van Moolenbroek } 118c2f99d7cSDavid van Moolenbroek 119c2f99d7cSDavid van Moolenbroek void put_inode(struct inode *i_node) 120c2f99d7cSDavid van Moolenbroek { 121c2f99d7cSDavid van Moolenbroek if (i_node == NULL) 122c2f99d7cSDavid van Moolenbroek return; 123c2f99d7cSDavid van Moolenbroek 124c2f99d7cSDavid van Moolenbroek assert(i_node->i_count > 0); 125c2f99d7cSDavid van Moolenbroek 126c2f99d7cSDavid van Moolenbroek i_node->i_count--; 127c2f99d7cSDavid van Moolenbroek } 128c2f99d7cSDavid van Moolenbroek 129c2f99d7cSDavid van Moolenbroek void dup_inode(struct inode *i_node) 130c2f99d7cSDavid van Moolenbroek { 131c2f99d7cSDavid van Moolenbroek assert(i_node != NULL); 132c2f99d7cSDavid van Moolenbroek 133c2f99d7cSDavid van Moolenbroek i_node->i_count++; 134c2f99d7cSDavid van Moolenbroek } 135c2f99d7cSDavid van Moolenbroek 136c2f99d7cSDavid van Moolenbroek static struct buf* fetch_inode(struct dir_extent *extent, size_t *offset) 137c2f99d7cSDavid van Moolenbroek { 138c2f99d7cSDavid van Moolenbroek struct iso9660_dir_record *dir_rec; 139c2f99d7cSDavid van Moolenbroek struct buf *bp; 140c2f99d7cSDavid van Moolenbroek 141c2f99d7cSDavid van Moolenbroek /* 142c2f99d7cSDavid van Moolenbroek * Directory entries aren't allowed to cross a logical block boundary in 143c2f99d7cSDavid van Moolenbroek * ISO 9660, so we keep searching until we find something or reach the 144c2f99d7cSDavid van Moolenbroek * end of the extent. 145c2f99d7cSDavid van Moolenbroek */ 146c2f99d7cSDavid van Moolenbroek bp = read_extent_block(extent, *offset / v_pri.logical_block_size_l); 147c2f99d7cSDavid van Moolenbroek while (bp != NULL) { 148c2f99d7cSDavid van Moolenbroek dir_rec = (struct iso9660_dir_record*)(b_data(bp) + *offset % 149c2f99d7cSDavid van Moolenbroek v_pri.logical_block_size_l); 150c2f99d7cSDavid van Moolenbroek if (dir_rec->length == 0) { 151c2f99d7cSDavid van Moolenbroek *offset -= *offset % v_pri.logical_block_size_l; 152c2f99d7cSDavid van Moolenbroek *offset += v_pri.logical_block_size_l; 153c2f99d7cSDavid van Moolenbroek } 154c2f99d7cSDavid van Moolenbroek else { 155c2f99d7cSDavid van Moolenbroek break; 156c2f99d7cSDavid van Moolenbroek } 157c2f99d7cSDavid van Moolenbroek 158*0314acfbSDavid van Moolenbroek lmfs_put_block(bp); 159c2f99d7cSDavid van Moolenbroek bp = read_extent_block(extent, *offset / 160c2f99d7cSDavid van Moolenbroek v_pri.logical_block_size_l); 161c2f99d7cSDavid van Moolenbroek } 162c2f99d7cSDavid van Moolenbroek 163c2f99d7cSDavid van Moolenbroek return bp; 164c2f99d7cSDavid van Moolenbroek } 165c2f99d7cSDavid van Moolenbroek 166c2f99d7cSDavid van Moolenbroek int read_inode(struct inode *i_node, struct dir_extent *extent, size_t offset, 167c2f99d7cSDavid van Moolenbroek size_t *new_offset) 168c2f99d7cSDavid van Moolenbroek { 169c2f99d7cSDavid van Moolenbroek struct iso9660_dir_record *dir_rec; 170c2f99d7cSDavid van Moolenbroek struct buf *bp; 171c2f99d7cSDavid van Moolenbroek 172c2f99d7cSDavid van Moolenbroek /* Find inode. */ 173c2f99d7cSDavid van Moolenbroek bp = fetch_inode(extent, &offset); 174c2f99d7cSDavid van Moolenbroek if (bp == NULL) 175c2f99d7cSDavid van Moolenbroek return EOF; 176c2f99d7cSDavid van Moolenbroek 177c2f99d7cSDavid van Moolenbroek dir_rec = (struct iso9660_dir_record*)(b_data(bp) + offset % 178c2f99d7cSDavid van Moolenbroek v_pri.logical_block_size_l); 179c2f99d7cSDavid van Moolenbroek 180c2f99d7cSDavid van Moolenbroek /* Parse basic ISO 9660 specs. */ 181c2f99d7cSDavid van Moolenbroek if (check_dir_record(dir_rec, 182c2f99d7cSDavid van Moolenbroek offset % v_pri.logical_block_size_l) != OK) { 183*0314acfbSDavid van Moolenbroek lmfs_put_block(bp); 184c2f99d7cSDavid van Moolenbroek return EINVAL; 185c2f99d7cSDavid van Moolenbroek } 186c2f99d7cSDavid van Moolenbroek 187c2f99d7cSDavid van Moolenbroek memset(&i_node->i_stat, 0, sizeof(struct stat)); 188c2f99d7cSDavid van Moolenbroek 189c2f99d7cSDavid van Moolenbroek i_node->i_stat.st_ino = get_extent_absolute_block_id(extent, 190c2f99d7cSDavid van Moolenbroek offset / v_pri.logical_block_size_l) * v_pri.logical_block_size_l + 191c2f99d7cSDavid van Moolenbroek offset % v_pri.logical_block_size_l; 192c2f99d7cSDavid van Moolenbroek 193c2f99d7cSDavid van Moolenbroek read_inode_iso9660(i_node, dir_rec); 194c2f99d7cSDavid van Moolenbroek 195c2f99d7cSDavid van Moolenbroek /* Parse extensions. */ 196c2f99d7cSDavid van Moolenbroek read_inode_susp(i_node, dir_rec, bp, 197c2f99d7cSDavid van Moolenbroek offset % v_pri.logical_block_size_l); 198c2f99d7cSDavid van Moolenbroek 199c2f99d7cSDavid van Moolenbroek offset += dir_rec->length; 200c2f99d7cSDavid van Moolenbroek read_inode_extents(i_node, dir_rec, extent, &offset); 201c2f99d7cSDavid van Moolenbroek 202*0314acfbSDavid van Moolenbroek lmfs_put_block(bp); 203c2f99d7cSDavid van Moolenbroek if (new_offset != NULL) 204c2f99d7cSDavid van Moolenbroek *new_offset = offset; 205c2f99d7cSDavid van Moolenbroek return OK; 206c2f99d7cSDavid van Moolenbroek } 207c2f99d7cSDavid van Moolenbroek 208c2f99d7cSDavid van Moolenbroek void read_inode_iso9660(struct inode *i, 209c2f99d7cSDavid van Moolenbroek const struct iso9660_dir_record *dir_rec) 210c2f99d7cSDavid van Moolenbroek { 211c2f99d7cSDavid van Moolenbroek char *cp; 212c2f99d7cSDavid van Moolenbroek 213c2f99d7cSDavid van Moolenbroek /* Parse first extent. */ 214c2f99d7cSDavid van Moolenbroek if (dir_rec->data_length_l > 0) { 215c2f99d7cSDavid van Moolenbroek assert(i->extent == NULL); 216c2f99d7cSDavid van Moolenbroek i->extent = alloc_extent(); 217c2f99d7cSDavid van Moolenbroek i->extent->location = dir_rec->loc_extent_l + 218c2f99d7cSDavid van Moolenbroek dir_rec->ext_attr_rec_length; 219c2f99d7cSDavid van Moolenbroek i->extent->length = dir_rec->data_length_l / 220c2f99d7cSDavid van Moolenbroek v_pri.logical_block_size_l; 221c2f99d7cSDavid van Moolenbroek if (dir_rec->data_length_l % v_pri.logical_block_size_l) 222c2f99d7cSDavid van Moolenbroek i->extent->length++; 223c2f99d7cSDavid van Moolenbroek 224c2f99d7cSDavid van Moolenbroek i->i_stat.st_size = dir_rec->data_length_l; 225c2f99d7cSDavid van Moolenbroek } 226c2f99d7cSDavid van Moolenbroek 227c2f99d7cSDavid van Moolenbroek /* Parse timestamps (record date). */ 228c2f99d7cSDavid van Moolenbroek i->i_stat.st_atime = i->i_stat.st_mtime = i->i_stat.st_ctime = 229c2f99d7cSDavid van Moolenbroek i->i_stat.st_birthtime = date7_to_time_t(dir_rec->rec_date); 230c2f99d7cSDavid van Moolenbroek 231c2f99d7cSDavid van Moolenbroek if ((dir_rec->file_flags & D_TYPE) == D_DIRECTORY) { 232c2f99d7cSDavid van Moolenbroek i->i_stat.st_mode = S_IFDIR; 233c2f99d7cSDavid van Moolenbroek i->i_stat.st_ino = 234c2f99d7cSDavid van Moolenbroek i->extent->location * v_pri.logical_block_size_l; 235c2f99d7cSDavid van Moolenbroek } 236c2f99d7cSDavid van Moolenbroek else 237c2f99d7cSDavid van Moolenbroek i->i_stat.st_mode = S_IFREG; 238c2f99d7cSDavid van Moolenbroek i->i_stat.st_mode |= 0555; 239c2f99d7cSDavid van Moolenbroek 240c2f99d7cSDavid van Moolenbroek /* Parse file name. */ 241c2f99d7cSDavid van Moolenbroek if (dir_rec->file_id[0] == 0) 242c2f99d7cSDavid van Moolenbroek strcpy(i->i_name, "."); 243c2f99d7cSDavid van Moolenbroek else if (dir_rec->file_id[0] == 1) 244c2f99d7cSDavid van Moolenbroek strcpy(i->i_name, ".."); 245c2f99d7cSDavid van Moolenbroek else { 246c2f99d7cSDavid van Moolenbroek memcpy(i->i_name, dir_rec->file_id, dir_rec->length_file_id); 247c2f99d7cSDavid van Moolenbroek 248c2f99d7cSDavid van Moolenbroek /* Truncate/ignore file version suffix. */ 249c2f99d7cSDavid van Moolenbroek cp = strchr(i->i_name, ';'); 250c2f99d7cSDavid van Moolenbroek if (cp != NULL) 251c2f99d7cSDavid van Moolenbroek *cp = '\0'; 252c2f99d7cSDavid van Moolenbroek /* Truncate dot if file has no extension. */ 253c2f99d7cSDavid van Moolenbroek if (strchr(i->i_name, '.') + 1 == cp) 254c2f99d7cSDavid van Moolenbroek *(cp-1) = '\0'; 255c2f99d7cSDavid van Moolenbroek } 256c2f99d7cSDavid van Moolenbroek 257c2f99d7cSDavid van Moolenbroek /* Initialize stat. */ 258c2f99d7cSDavid van Moolenbroek i->i_stat.st_dev = fs_dev; 259c2f99d7cSDavid van Moolenbroek i->i_stat.st_blksize = v_pri.logical_block_size_l; 260c2f99d7cSDavid van Moolenbroek i->i_stat.st_blocks = 261c2f99d7cSDavid van Moolenbroek dir_rec->data_length_l / v_pri.logical_block_size_l; 262c2f99d7cSDavid van Moolenbroek i->i_stat.st_nlink = 1; 263c2f99d7cSDavid van Moolenbroek } 264c2f99d7cSDavid van Moolenbroek 265c2f99d7cSDavid van Moolenbroek void read_inode_extents(struct inode *i, 266c2f99d7cSDavid van Moolenbroek const struct iso9660_dir_record *dir_rec, 267c2f99d7cSDavid van Moolenbroek struct dir_extent *extent, size_t *offset) 268c2f99d7cSDavid van Moolenbroek { 269c2f99d7cSDavid van Moolenbroek struct buf *bp; 270c2f99d7cSDavid van Moolenbroek struct iso9660_dir_record *extent_rec; 271c2f99d7cSDavid van Moolenbroek struct dir_extent *cur_extent = i->extent; 272c2f99d7cSDavid van Moolenbroek int done = FALSE; 273c2f99d7cSDavid van Moolenbroek 274c2f99d7cSDavid van Moolenbroek /* 275c2f99d7cSDavid van Moolenbroek * No need to search extents if file is empty or has final directory 276c2f99d7cSDavid van Moolenbroek * record flag set. 277c2f99d7cSDavid van Moolenbroek */ 278c2f99d7cSDavid van Moolenbroek if (cur_extent == NULL || 279c2f99d7cSDavid van Moolenbroek ((dir_rec->file_flags & D_NOT_LAST_EXTENT) == 0)) 280c2f99d7cSDavid van Moolenbroek return; 281c2f99d7cSDavid van Moolenbroek 282c2f99d7cSDavid van Moolenbroek while (!done) { 283c2f99d7cSDavid van Moolenbroek bp = fetch_inode(extent, offset); 284c2f99d7cSDavid van Moolenbroek if (bp == NULL) 285c2f99d7cSDavid van Moolenbroek return; 286c2f99d7cSDavid van Moolenbroek 287c2f99d7cSDavid van Moolenbroek bp = read_extent_block(extent, 288c2f99d7cSDavid van Moolenbroek *offset / v_pri.logical_block_size_l); 289c2f99d7cSDavid van Moolenbroek extent_rec = (struct iso9660_dir_record*)(b_data(bp) + 290c2f99d7cSDavid van Moolenbroek *offset % v_pri.logical_block_size_l); 291c2f99d7cSDavid van Moolenbroek 292c2f99d7cSDavid van Moolenbroek if (check_dir_record(dir_rec, 293c2f99d7cSDavid van Moolenbroek *offset % v_pri.logical_block_size_l) != OK) { 294*0314acfbSDavid van Moolenbroek lmfs_put_block(bp); 295c2f99d7cSDavid van Moolenbroek return; 296c2f99d7cSDavid van Moolenbroek } 297c2f99d7cSDavid van Moolenbroek 298c2f99d7cSDavid van Moolenbroek /* Extent entries should share the same name. */ 299c2f99d7cSDavid van Moolenbroek if ((dir_rec->length_file_id == extent_rec->length_file_id) && 300c2f99d7cSDavid van Moolenbroek (memcmp(dir_rec->file_id, extent_rec->file_id, 301c2f99d7cSDavid van Moolenbroek dir_rec->length_file_id) == 0)) { 302c2f99d7cSDavid van Moolenbroek /* Add the extent at the end of the linked list. */ 303c2f99d7cSDavid van Moolenbroek assert(cur_extent->next == NULL); 304c2f99d7cSDavid van Moolenbroek cur_extent->next = alloc_extent(); 305c2f99d7cSDavid van Moolenbroek cur_extent->next->location = dir_rec->loc_extent_l + 306c2f99d7cSDavid van Moolenbroek dir_rec->ext_attr_rec_length; 307c2f99d7cSDavid van Moolenbroek cur_extent->next->length = dir_rec->data_length_l / 308c2f99d7cSDavid van Moolenbroek v_pri.logical_block_size_l; 309c2f99d7cSDavid van Moolenbroek if (dir_rec->data_length_l % v_pri.logical_block_size_l) 310c2f99d7cSDavid van Moolenbroek cur_extent->next->length++; 311c2f99d7cSDavid van Moolenbroek 312c2f99d7cSDavid van Moolenbroek i->i_stat.st_size += dir_rec->data_length_l; 313c2f99d7cSDavid van Moolenbroek i->i_stat.st_blocks += cur_extent->next->length; 314c2f99d7cSDavid van Moolenbroek 315c2f99d7cSDavid van Moolenbroek cur_extent = cur_extent->next; 316c2f99d7cSDavid van Moolenbroek *offset += extent_rec->length; 317c2f99d7cSDavid van Moolenbroek } 318c2f99d7cSDavid van Moolenbroek else 319c2f99d7cSDavid van Moolenbroek done = TRUE; 320c2f99d7cSDavid van Moolenbroek 321c2f99d7cSDavid van Moolenbroek /* Check if not last extent bit is not set. */ 322c2f99d7cSDavid van Moolenbroek if ((dir_rec->file_flags & D_NOT_LAST_EXTENT) == 0) 323c2f99d7cSDavid van Moolenbroek done = TRUE; 324c2f99d7cSDavid van Moolenbroek 325*0314acfbSDavid van Moolenbroek lmfs_put_block(bp); 326c2f99d7cSDavid van Moolenbroek } 327c2f99d7cSDavid van Moolenbroek } 328c2f99d7cSDavid van Moolenbroek 329c2f99d7cSDavid van Moolenbroek void read_inode_susp(struct inode *i, const struct iso9660_dir_record *dir_rec, 330c2f99d7cSDavid van Moolenbroek struct buf *bp, size_t offset) 331c2f99d7cSDavid van Moolenbroek { 332c2f99d7cSDavid van Moolenbroek int susp_offset, susp_size; 333c2f99d7cSDavid van Moolenbroek struct rrii_dir_record rrii_data; 334c2f99d7cSDavid van Moolenbroek 335c2f99d7cSDavid van Moolenbroek susp_offset = 33 + dir_rec->length_file_id; 336c2f99d7cSDavid van Moolenbroek /* Get rid of padding byte. */ 337c2f99d7cSDavid van Moolenbroek if(dir_rec->length_file_id % 2 == 0) { 338c2f99d7cSDavid van Moolenbroek susp_offset++; 339c2f99d7cSDavid van Moolenbroek } 340c2f99d7cSDavid van Moolenbroek 341c2f99d7cSDavid van Moolenbroek if(dir_rec->length - susp_offset >= 4) { 342c2f99d7cSDavid van Moolenbroek susp_size = dir_rec->length - susp_offset; 343c2f99d7cSDavid van Moolenbroek 344c2f99d7cSDavid van Moolenbroek /* Initialize record with known, sane data. */ 345c2f99d7cSDavid van Moolenbroek memcpy(rrii_data.mtime, dir_rec->rec_date, ISO9660_SIZE_DATE7); 346c2f99d7cSDavid van Moolenbroek memcpy(rrii_data.atime, dir_rec->rec_date, ISO9660_SIZE_DATE7); 347c2f99d7cSDavid van Moolenbroek memcpy(rrii_data.ctime, dir_rec->rec_date, ISO9660_SIZE_DATE7); 348c2f99d7cSDavid van Moolenbroek memcpy(rrii_data.birthtime, dir_rec->rec_date, 349c2f99d7cSDavid van Moolenbroek ISO9660_SIZE_DATE7); 350c2f99d7cSDavid van Moolenbroek 351c2f99d7cSDavid van Moolenbroek rrii_data.d_mode = i->i_stat.st_mode; 352c2f99d7cSDavid van Moolenbroek rrii_data.uid = 0; 353c2f99d7cSDavid van Moolenbroek rrii_data.gid = 0; 354c2f99d7cSDavid van Moolenbroek rrii_data.rdev = NO_DEV; 355c2f99d7cSDavid van Moolenbroek rrii_data.file_id_rrip[0] = '\0'; 356c2f99d7cSDavid van Moolenbroek rrii_data.slink_rrip[0] = '\0'; 357c2f99d7cSDavid van Moolenbroek 358c2f99d7cSDavid van Moolenbroek parse_susp_buffer(&rrii_data, b_data(bp)+offset+susp_offset, 359c2f99d7cSDavid van Moolenbroek susp_size); 360c2f99d7cSDavid van Moolenbroek 361c2f99d7cSDavid van Moolenbroek /* Copy back data from rrii_dir_record structure. */ 362c2f99d7cSDavid van Moolenbroek i->i_stat.st_atime = date7_to_time_t(rrii_data.atime); 363c2f99d7cSDavid van Moolenbroek i->i_stat.st_ctime = date7_to_time_t(rrii_data.ctime); 364c2f99d7cSDavid van Moolenbroek i->i_stat.st_mtime = date7_to_time_t(rrii_data.mtime); 365c2f99d7cSDavid van Moolenbroek i->i_stat.st_birthtime = date7_to_time_t(rrii_data.birthtime); 366c2f99d7cSDavid van Moolenbroek 367c2f99d7cSDavid van Moolenbroek i->i_stat.st_mode = rrii_data.d_mode; 368c2f99d7cSDavid van Moolenbroek i->i_stat.st_uid = rrii_data.uid; 369c2f99d7cSDavid van Moolenbroek i->i_stat.st_gid = rrii_data.gid; 370c2f99d7cSDavid van Moolenbroek i->i_stat.st_rdev = rrii_data.rdev; 371c2f99d7cSDavid van Moolenbroek 372c2f99d7cSDavid van Moolenbroek if (rrii_data.file_id_rrip[0] != '\0') 373c2f99d7cSDavid van Moolenbroek strlcpy(i->i_name, rrii_data.file_id_rrip, 374c2f99d7cSDavid van Moolenbroek sizeof(i->i_name)); 375c2f99d7cSDavid van Moolenbroek if (rrii_data.slink_rrip[0] != '\0') 376c2f99d7cSDavid van Moolenbroek strlcpy(i->s_link, rrii_data.slink_rrip, 377c2f99d7cSDavid van Moolenbroek sizeof(i->s_link)); 378c2f99d7cSDavid van Moolenbroek } 379c2f99d7cSDavid van Moolenbroek } 380c2f99d7cSDavid van Moolenbroek 381c2f99d7cSDavid van Moolenbroek int check_dir_record(const struct iso9660_dir_record *d, size_t offset) 382c2f99d7cSDavid van Moolenbroek { 383c2f99d7cSDavid van Moolenbroek /* Run some consistency check on a directory entry. */ 384c2f99d7cSDavid van Moolenbroek if ((d->length < 33) || (d->length_file_id < 1)) 385c2f99d7cSDavid van Moolenbroek return EINVAL; 386c2f99d7cSDavid van Moolenbroek if (d->length_file_id + 32 > d->length) 387c2f99d7cSDavid van Moolenbroek return EINVAL; 388c2f99d7cSDavid van Moolenbroek if (offset + d->length > v_pri.logical_block_size_l) 389c2f99d7cSDavid van Moolenbroek return EINVAL; 390c2f99d7cSDavid van Moolenbroek 391c2f99d7cSDavid van Moolenbroek return OK; 392c2f99d7cSDavid van Moolenbroek } 393c2f99d7cSDavid van Moolenbroek 394c2f99d7cSDavid van Moolenbroek int check_inodes(void) 395c2f99d7cSDavid van Moolenbroek { 396c2f99d7cSDavid van Moolenbroek /* Check whether there are no more inodes in use. Called on unmount. */ 397c2f99d7cSDavid van Moolenbroek int i; 398c2f99d7cSDavid van Moolenbroek 399c2f99d7cSDavid van Moolenbroek for (i = 0; i < NR_INODE_RECORDS; i++) 400c2f99d7cSDavid van Moolenbroek if (inodes[i].i_count > 0) 401c2f99d7cSDavid van Moolenbroek return FALSE; 402c2f99d7cSDavid van Moolenbroek 403c2f99d7cSDavid van Moolenbroek return TRUE; 404c2f99d7cSDavid van Moolenbroek } 405