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 9b1d06847SJean-Baptiste Boric #include "uthash.h" 10b1d06847SJean-Baptiste Boric 11b1d06847SJean-Baptiste Boric struct inode_cache { 12b1d06847SJean-Baptiste Boric ino_t key; 13b1d06847SJean-Baptiste Boric struct inode *value; 14b1d06847SJean-Baptiste Boric UT_hash_handle hh; 15b1d06847SJean-Baptiste Boric } ; 16b1d06847SJean-Baptiste Boric 17b1d06847SJean-Baptiste Boric struct inode_cache *icache = NULL; 18b1d06847SJean-Baptiste Boric 19b1d06847SJean-Baptiste Boric void read_inode_iso9660(struct inode_dir_entry *i, 20b1d06847SJean-Baptiste Boric const struct iso9660_dir_record *dir_rec, struct dir_extent *extent, 21b1d06847SJean-Baptiste Boric size_t offset, int name_only); 22b1d06847SJean-Baptiste Boric 23b1d06847SJean-Baptiste Boric #ifdef ISO9660_OPTION_MODE3 24b1d06847SJean-Baptiste Boric static void read_inode_extents(struct inode_dir_entry *i, 25b1d06847SJean-Baptiste Boric const struct iso9660_dir_record *dir_rec, struct dir_extent *extent, 26b1d06847SJean-Baptiste Boric size_t *offset); 27b1d06847SJean-Baptiste Boric #endif 28b1d06847SJean-Baptiste Boric 29b1d06847SJean-Baptiste Boric #ifdef ISO9660_OPTION_ROCKRIDGE 30b1d06847SJean-Baptiste Boric void read_inode_susp(struct inode_dir_entry *i, 31b1d06847SJean-Baptiste Boric const struct iso9660_dir_record *dir_rec, struct buf *bp, size_t offset, 32b1d06847SJean-Baptiste Boric int name_only); 33b1d06847SJean-Baptiste Boric #endif 34b1d06847SJean-Baptiste Boric 35b1d06847SJean-Baptiste Boric static int check_dir_record(const struct iso9660_dir_record *d, size_t offset); 36c2f99d7cSDavid van Moolenbroek 37c2f99d7cSDavid van Moolenbroek int fs_putnode(ino_t ino_nr, unsigned int count) 38c2f99d7cSDavid van Moolenbroek { 39c2f99d7cSDavid van Moolenbroek /* 40c2f99d7cSDavid van Moolenbroek * Find the inode specified by the request message and decrease its 41c2f99d7cSDavid van Moolenbroek * counter. 42c2f99d7cSDavid van Moolenbroek */ 43c2f99d7cSDavid van Moolenbroek struct inode *i_node; 44c2f99d7cSDavid van Moolenbroek 45b1d06847SJean-Baptiste Boric if ((i_node = get_inode(ino_nr)) == NULL) { 46b1d06847SJean-Baptiste Boric puts("ISOFS: trying to free unused inode"); 47c2f99d7cSDavid van Moolenbroek return EINVAL; 48c2f99d7cSDavid van Moolenbroek } 49c2f99d7cSDavid van Moolenbroek if (count > i_node->i_count) { 50b1d06847SJean-Baptiste Boric puts("ISOFS: put_node count too high"); 51c2f99d7cSDavid van Moolenbroek return EINVAL; 52c2f99d7cSDavid van Moolenbroek } 53c2f99d7cSDavid van Moolenbroek 54c2f99d7cSDavid van Moolenbroek i_node->i_count -= count - 1; 55c2f99d7cSDavid van Moolenbroek put_inode(i_node); 56c2f99d7cSDavid van Moolenbroek return OK; 57c2f99d7cSDavid van Moolenbroek } 58c2f99d7cSDavid van Moolenbroek 59c2f99d7cSDavid van Moolenbroek 60b1d06847SJean-Baptiste Boric struct inode* get_inode(ino_t ino_nr) { 61b1d06847SJean-Baptiste Boric /* Return an already opened inode from cache. */ 62b1d06847SJean-Baptiste Boric struct inode *i_node = inode_cache_get(ino_nr); 63c2f99d7cSDavid van Moolenbroek 64b1d06847SJean-Baptiste Boric if (i_node == NULL) 65b1d06847SJean-Baptiste Boric return NULL; 66c2f99d7cSDavid van Moolenbroek 67b1d06847SJean-Baptiste Boric if (i_node->i_count == 0) 68b1d06847SJean-Baptiste Boric return NULL; 69c2f99d7cSDavid van Moolenbroek 70c2f99d7cSDavid van Moolenbroek return i_node; 71c2f99d7cSDavid van Moolenbroek } 72c2f99d7cSDavid van Moolenbroek 73b1d06847SJean-Baptiste Boric struct inode* open_inode(ino_t ino_nr) { 74b1d06847SJean-Baptiste Boric /* Return an inode from cache. */ 75b1d06847SJean-Baptiste Boric struct inode *i_node = inode_cache_get(ino_nr); 76b1d06847SJean-Baptiste Boric if (i_node == NULL) 77c2f99d7cSDavid van Moolenbroek return NULL; 78c2f99d7cSDavid van Moolenbroek 79b1d06847SJean-Baptiste Boric i_node->i_count++; 80c2f99d7cSDavid van Moolenbroek 81c2f99d7cSDavid van Moolenbroek return i_node; 82c2f99d7cSDavid van Moolenbroek } 83c2f99d7cSDavid van Moolenbroek 84b1d06847SJean-Baptiste Boric void put_inode(struct inode *i_node) { 85c2f99d7cSDavid van Moolenbroek if (i_node == NULL) 86c2f99d7cSDavid van Moolenbroek return; 87c2f99d7cSDavid van Moolenbroek 88c2f99d7cSDavid van Moolenbroek assert(i_node->i_count > 0); 89c2f99d7cSDavid van Moolenbroek i_node->i_count--; 90b1d06847SJean-Baptiste Boric 91b1d06847SJean-Baptiste Boric if(i_node->i_count == 0) 92b1d06847SJean-Baptiste Boric i_node->i_mountpoint = FALSE; 93c2f99d7cSDavid van Moolenbroek } 94c2f99d7cSDavid van Moolenbroek 95b1d06847SJean-Baptiste Boric void dup_inode(struct inode *i_node) { 96c2f99d7cSDavid van Moolenbroek assert(i_node != NULL); 97b1d06847SJean-Baptiste Boric assert(i_node->i_count > 0); 98c2f99d7cSDavid van Moolenbroek 99c2f99d7cSDavid van Moolenbroek i_node->i_count++; 100c2f99d7cSDavid van Moolenbroek } 101c2f99d7cSDavid van Moolenbroek 102b1d06847SJean-Baptiste Boric int read_directory(struct inode *dir) { 103b1d06847SJean-Baptiste Boric #define MAX_ENTRIES 4096 104b1d06847SJean-Baptiste Boric /* Read all entries in a directory. */ 105b1d06847SJean-Baptiste Boric size_t pos = 0, cur_entry = 0, cpt; 106b1d06847SJean-Baptiste Boric struct inode_dir_entry entries[MAX_ENTRIES]; 107b1d06847SJean-Baptiste Boric int status = OK; 108c2f99d7cSDavid van Moolenbroek 109b1d06847SJean-Baptiste Boric if (dir->dir_contents) 110b1d06847SJean-Baptiste Boric return OK; 111b1d06847SJean-Baptiste Boric 112b1d06847SJean-Baptiste Boric if (!S_ISDIR(dir->i_stat.st_mode)) 113b1d06847SJean-Baptiste Boric return ENOTDIR; 114b1d06847SJean-Baptiste Boric 115b1d06847SJean-Baptiste Boric for (cur_entry = 0; status == OK && cur_entry < MAX_ENTRIES; cur_entry++) { 116b1d06847SJean-Baptiste Boric memset(&entries[cur_entry], 0, sizeof(struct inode_dir_entry)); 117b1d06847SJean-Baptiste Boric 118b1d06847SJean-Baptiste Boric status = read_inode(&entries[cur_entry], &dir->extent, &pos); 119b1d06847SJean-Baptiste Boric if (status != OK) 120c2f99d7cSDavid van Moolenbroek break; 121b1d06847SJean-Baptiste Boric 122b1d06847SJean-Baptiste Boric /* Dump the entry if it's not to be exported to userland. */ 123b1d06847SJean-Baptiste Boric if (entries[cur_entry].i_node->skip) { 124b1d06847SJean-Baptiste Boric free_inode_dir_entry(&entries[cur_entry]); 125b1d06847SJean-Baptiste Boric continue; 126b1d06847SJean-Baptiste Boric } 127c2f99d7cSDavid van Moolenbroek } 128c2f99d7cSDavid van Moolenbroek 129b1d06847SJean-Baptiste Boric /* Resize dynamic array to correct size */ 130b1d06847SJean-Baptiste Boric dir->dir_contents = alloc_mem(sizeof(struct inode_dir_entry) * cur_entry); 131b1d06847SJean-Baptiste Boric memcpy(dir->dir_contents, entries, sizeof(struct inode_dir_entry) * cur_entry); 132b1d06847SJean-Baptiste Boric dir->dir_size = cur_entry; 133b1d06847SJean-Baptiste Boric 134b1d06847SJean-Baptiste Boric /* The name pointer has to point to the new memory location. */ 135b1d06847SJean-Baptiste Boric for (cpt = 0; cpt < cur_entry; cpt++) { 136b1d06847SJean-Baptiste Boric if (dir->dir_contents[cpt].r_name == NULL) 137b1d06847SJean-Baptiste Boric dir->dir_contents[cpt].name = 138b1d06847SJean-Baptiste Boric dir->dir_contents[cpt].i_name; 139b1d06847SJean-Baptiste Boric else 140b1d06847SJean-Baptiste Boric dir->dir_contents[cpt].name = 141b1d06847SJean-Baptiste Boric dir->dir_contents[cpt].r_name; 142c2f99d7cSDavid van Moolenbroek } 143c2f99d7cSDavid van Moolenbroek 144b1d06847SJean-Baptiste Boric return (status == EOF) ? OK : status; 145c2f99d7cSDavid van Moolenbroek } 146c2f99d7cSDavid van Moolenbroek 147b1d06847SJean-Baptiste Boric int check_inodes(void) { 148b1d06847SJean-Baptiste Boric /* Check whether there are no more inodes in use. Called on unmount. */ 149b1d06847SJean-Baptiste Boric int i; 150b1d06847SJean-Baptiste Boric 151b1d06847SJean-Baptiste Boric /* XXX: actually check for inodes in use. */ 152b1d06847SJean-Baptiste Boric return TRUE; 153b1d06847SJean-Baptiste Boric } 154b1d06847SJean-Baptiste Boric 155b1d06847SJean-Baptiste Boric int read_inode(struct inode_dir_entry *dir_entry, struct dir_extent *extent, 156b1d06847SJean-Baptiste Boric size_t *offset) 157c2f99d7cSDavid van Moolenbroek { 158c2f99d7cSDavid van Moolenbroek struct iso9660_dir_record *dir_rec; 159c2f99d7cSDavid van Moolenbroek struct buf *bp; 160b1d06847SJean-Baptiste Boric struct inode *i_node; 161b1d06847SJean-Baptiste Boric ino_t ino_nr; 162b1d06847SJean-Baptiste Boric int name_only = FALSE; 163c2f99d7cSDavid van Moolenbroek 164c2f99d7cSDavid van Moolenbroek /* Find inode. */ 165b1d06847SJean-Baptiste Boric bp = read_extent_block(extent, *offset); 166b1d06847SJean-Baptiste Boric if (bp == NULL) { 167c2f99d7cSDavid van Moolenbroek return EOF; 168b1d06847SJean-Baptiste Boric } 169c2f99d7cSDavid van Moolenbroek 170b1d06847SJean-Baptiste Boric /* Check if we are crossing a sector boundary. */ 171b1d06847SJean-Baptiste Boric dir_rec = (struct iso9660_dir_record*)(b_data(bp) + *offset % 172c2f99d7cSDavid van Moolenbroek v_pri.logical_block_size_l); 173c2f99d7cSDavid van Moolenbroek 174b1d06847SJean-Baptiste Boric if (dir_rec->length == 0) { 175b1d06847SJean-Baptiste Boric *offset = ((*offset / v_pri.logical_block_size_l) + 1) * 176b1d06847SJean-Baptiste Boric v_pri.logical_block_size_l; 177b1d06847SJean-Baptiste Boric 178b1d06847SJean-Baptiste Boric lmfs_put_block(bp); 179b1d06847SJean-Baptiste Boric bp = read_extent_block(extent, *offset); 180b1d06847SJean-Baptiste Boric if (bp == NULL) { 181b1d06847SJean-Baptiste Boric return EOF; 182b1d06847SJean-Baptiste Boric } 183b1d06847SJean-Baptiste Boric 184b1d06847SJean-Baptiste Boric dir_rec = (struct iso9660_dir_record*)(b_data(bp) + *offset % 185b1d06847SJean-Baptiste Boric v_pri.logical_block_size_l); 186b1d06847SJean-Baptiste Boric } 187b1d06847SJean-Baptiste Boric 188c2f99d7cSDavid van Moolenbroek /* Parse basic ISO 9660 specs. */ 189b1d06847SJean-Baptiste Boric if (check_dir_record(dir_rec, *offset % v_pri.logical_block_size_l) 190b1d06847SJean-Baptiste Boric != OK) { 1910314acfbSDavid van Moolenbroek lmfs_put_block(bp); 192c2f99d7cSDavid van Moolenbroek return EINVAL; 193c2f99d7cSDavid van Moolenbroek } 194c2f99d7cSDavid van Moolenbroek 195b1d06847SJean-Baptiste Boric /* Get inode */ 196b1d06847SJean-Baptiste Boric if ((dir_rec->file_flags & D_TYPE) == D_DIRECTORY) { 197b1d06847SJean-Baptiste Boric ino_nr = dir_rec->loc_extent_l; 198b1d06847SJean-Baptiste Boric } 199b1d06847SJean-Baptiste Boric else { 200b1d06847SJean-Baptiste Boric ino_nr = get_extent_absolute_block_id(extent, *offset) 201b1d06847SJean-Baptiste Boric * v_pri.logical_block_size_l + 202b1d06847SJean-Baptiste Boric *offset % v_pri.logical_block_size_l; 203b1d06847SJean-Baptiste Boric } 204c2f99d7cSDavid van Moolenbroek 205b1d06847SJean-Baptiste Boric i_node = inode_cache_get(ino_nr); 206b1d06847SJean-Baptiste Boric if (i_node) { 207b1d06847SJean-Baptiste Boric /* Inode was already loaded, parse file names only. */ 208b1d06847SJean-Baptiste Boric dir_entry->i_node = i_node; 209b1d06847SJean-Baptiste Boric i_node->i_refcount++; 210c2f99d7cSDavid van Moolenbroek 211b1d06847SJean-Baptiste Boric memset(&dir_entry->i_name[0], 0, sizeof(dir_entry->i_name)); 212b1d06847SJean-Baptiste Boric 213b1d06847SJean-Baptiste Boric name_only = TRUE; 214b1d06847SJean-Baptiste Boric } 215b1d06847SJean-Baptiste Boric else { 216b1d06847SJean-Baptiste Boric /* Inode wasn't in memory, parse it. */ 217b1d06847SJean-Baptiste Boric i_node = alloc_mem(sizeof(struct inode)); 218b1d06847SJean-Baptiste Boric dir_entry->i_node = i_node; 219b1d06847SJean-Baptiste Boric i_node->i_refcount = 1; 220b1d06847SJean-Baptiste Boric i_node->i_stat.st_ino = ino_nr; 221b1d06847SJean-Baptiste Boric inode_cache_add(ino_nr, i_node); 222b1d06847SJean-Baptiste Boric } 223b1d06847SJean-Baptiste Boric 224b1d06847SJean-Baptiste Boric dir_entry->i_node = i_node; 225b1d06847SJean-Baptiste Boric read_inode_iso9660(dir_entry, dir_rec, extent, *offset, name_only); 226c2f99d7cSDavid van Moolenbroek 227c2f99d7cSDavid van Moolenbroek /* Parse extensions. */ 228b1d06847SJean-Baptiste Boric #ifdef ISO9660_OPTION_ROCKRIDGE 229b1d06847SJean-Baptiste Boric read_inode_susp(dir_entry, dir_rec, bp, 230b1d06847SJean-Baptiste Boric *offset % v_pri.logical_block_size_l, name_only); 231b1d06847SJean-Baptiste Boric #endif 232c2f99d7cSDavid van Moolenbroek 233b1d06847SJean-Baptiste Boric *offset += dir_rec->length; 234b1d06847SJean-Baptiste Boric if (dir_rec->length % 2) 235b1d06847SJean-Baptiste Boric (*offset)++; 236b1d06847SJean-Baptiste Boric 237b1d06847SJean-Baptiste Boric #ifdef ISO9660_OPTION_MODE3 238b1d06847SJean-Baptiste Boric read_inode_extents(dir_entry, dir_rec, extent, offset); 239b1d06847SJean-Baptiste Boric #endif 240c2f99d7cSDavid van Moolenbroek 2410314acfbSDavid van Moolenbroek lmfs_put_block(bp); 242b1d06847SJean-Baptiste Boric 243c2f99d7cSDavid van Moolenbroek return OK; 244c2f99d7cSDavid van Moolenbroek } 245c2f99d7cSDavid van Moolenbroek 246b1d06847SJean-Baptiste Boric struct inode* inode_cache_get(ino_t ino_nr) { 247b1d06847SJean-Baptiste Boric struct inode_cache *i_node; 248b1d06847SJean-Baptiste Boric HASH_FIND(hh, icache, &ino_nr, sizeof(ino_t), i_node); 249c2f99d7cSDavid van Moolenbroek 250b1d06847SJean-Baptiste Boric if (i_node) 251b1d06847SJean-Baptiste Boric return i_node->value; 252b1d06847SJean-Baptiste Boric else 253b1d06847SJean-Baptiste Boric return NULL; 254c2f99d7cSDavid van Moolenbroek } 255c2f99d7cSDavid van Moolenbroek 256b1d06847SJean-Baptiste Boric void inode_cache_add(ino_t ino_nr, struct inode *i_node) { 257b1d06847SJean-Baptiste Boric struct inode_cache *c_check; 258b1d06847SJean-Baptiste Boric struct inode_cache *c_entry; 259c2f99d7cSDavid van Moolenbroek 260b1d06847SJean-Baptiste Boric HASH_FIND(hh, icache, &ino_nr, sizeof(ino_t), c_check); 261b1d06847SJean-Baptiste Boric 262b1d06847SJean-Baptiste Boric if (c_check == NULL) { 263b1d06847SJean-Baptiste Boric c_entry = alloc_mem(sizeof(struct inode_cache)); 264b1d06847SJean-Baptiste Boric c_entry->key = ino_nr; 265b1d06847SJean-Baptiste Boric c_entry->value = i_node; 266b1d06847SJean-Baptiste Boric 267b1d06847SJean-Baptiste Boric HASH_ADD(hh, icache, key, sizeof(ino_t), c_entry); 268c2f99d7cSDavid van Moolenbroek } 269c2f99d7cSDavid van Moolenbroek else 270b1d06847SJean-Baptiste Boric panic("Trying to insert inode into cache twice"); 271b1d06847SJean-Baptiste Boric } 272b1d06847SJean-Baptiste Boric 273b1d06847SJean-Baptiste Boric void read_inode_iso9660(struct inode_dir_entry *i, 274b1d06847SJean-Baptiste Boric const struct iso9660_dir_record *dir_rec, struct dir_extent *extent, 275b1d06847SJean-Baptiste Boric size_t offset, int name_only) 276b1d06847SJean-Baptiste Boric { 277b1d06847SJean-Baptiste Boric char *cp; 278c2f99d7cSDavid van Moolenbroek 279c2f99d7cSDavid van Moolenbroek /* Parse file name. */ 280c2f99d7cSDavid van Moolenbroek if (dir_rec->file_id[0] == 0) 281c2f99d7cSDavid van Moolenbroek strcpy(i->i_name, "."); 282c2f99d7cSDavid van Moolenbroek else if (dir_rec->file_id[0] == 1) 283c2f99d7cSDavid van Moolenbroek strcpy(i->i_name, ".."); 284c2f99d7cSDavid van Moolenbroek else { 285c2f99d7cSDavid van Moolenbroek memcpy(i->i_name, dir_rec->file_id, dir_rec->length_file_id); 286c2f99d7cSDavid van Moolenbroek 287c2f99d7cSDavid van Moolenbroek /* Truncate/ignore file version suffix. */ 288c2f99d7cSDavid van Moolenbroek cp = strchr(i->i_name, ';'); 289b1d06847SJean-Baptiste Boric if (cp != NULL) { 290c2f99d7cSDavid van Moolenbroek *cp = '\0'; 291c2f99d7cSDavid van Moolenbroek /* Truncate dot if file has no extension. */ 292c2f99d7cSDavid van Moolenbroek if (strchr(i->i_name, '.') + 1 == cp) 293c2f99d7cSDavid van Moolenbroek *(cp-1) = '\0'; 294c2f99d7cSDavid van Moolenbroek } 295b1d06847SJean-Baptiste Boric } 296b1d06847SJean-Baptiste Boric 297b1d06847SJean-Baptiste Boric if (name_only == TRUE) 298b1d06847SJean-Baptiste Boric return; 299b1d06847SJean-Baptiste Boric 300b1d06847SJean-Baptiste Boric /* Parse first extent. */ 301b1d06847SJean-Baptiste Boric if (dir_rec->data_length_l > 0) { 302b1d06847SJean-Baptiste Boric i->i_node->extent.location = dir_rec->loc_extent_l + 303b1d06847SJean-Baptiste Boric dir_rec->ext_attr_rec_length; 304b1d06847SJean-Baptiste Boric i->i_node->extent.length = dir_rec->data_length_l / 305b1d06847SJean-Baptiste Boric v_pri.logical_block_size_l; 306b1d06847SJean-Baptiste Boric 307b1d06847SJean-Baptiste Boric if (dir_rec->data_length_l % v_pri.logical_block_size_l) 308b1d06847SJean-Baptiste Boric i->i_node->extent.length++; 309b1d06847SJean-Baptiste Boric 310b1d06847SJean-Baptiste Boric i->i_node->i_stat.st_size = dir_rec->data_length_l; 311b1d06847SJean-Baptiste Boric } 312b1d06847SJean-Baptiste Boric 313b1d06847SJean-Baptiste Boric /* Parse timestamps (record date). */ 314b1d06847SJean-Baptiste Boric i->i_node->i_stat.st_atime = i->i_node->i_stat.st_mtime = 315b1d06847SJean-Baptiste Boric i->i_node->i_stat.st_ctime = i->i_node->i_stat.st_birthtime = 316b1d06847SJean-Baptiste Boric date7_to_time_t(dir_rec->rec_date); 317b1d06847SJean-Baptiste Boric 318b1d06847SJean-Baptiste Boric if ((dir_rec->file_flags & D_TYPE) == D_DIRECTORY) 319b1d06847SJean-Baptiste Boric i->i_node->i_stat.st_mode = S_IFDIR; 320b1d06847SJean-Baptiste Boric else 321b1d06847SJean-Baptiste Boric i->i_node->i_stat.st_mode = S_IFREG; 322b1d06847SJean-Baptiste Boric 323b1d06847SJean-Baptiste Boric i->i_node->i_stat.st_mode |= 0555; 324c2f99d7cSDavid van Moolenbroek 325c2f99d7cSDavid van Moolenbroek /* Initialize stat. */ 326b1d06847SJean-Baptiste Boric i->i_node->i_stat.st_dev = fs_dev; 327b1d06847SJean-Baptiste Boric i->i_node->i_stat.st_blksize = v_pri.logical_block_size_l; 328*8d0759b0SDavid van Moolenbroek i->i_node->i_stat.st_blocks = dir_rec->data_length_l / 512; 329b1d06847SJean-Baptiste Boric i->i_node->i_stat.st_nlink = 1; 330c2f99d7cSDavid van Moolenbroek } 331c2f99d7cSDavid van Moolenbroek 332b1d06847SJean-Baptiste Boric #ifdef ISO9660_OPTION_ROCKRIDGE 333b1d06847SJean-Baptiste Boric 334b1d06847SJean-Baptiste Boric void read_inode_susp(struct inode_dir_entry *i, 335b1d06847SJean-Baptiste Boric const struct iso9660_dir_record *dir_rec, struct buf *bp, size_t offset, 336b1d06847SJean-Baptiste Boric int name_only) 337c2f99d7cSDavid van Moolenbroek { 338b1d06847SJean-Baptiste Boric int susp_offset, susp_size, name_length; 339c2f99d7cSDavid van Moolenbroek struct rrii_dir_record rrii_data; 340c2f99d7cSDavid van Moolenbroek 341c2f99d7cSDavid van Moolenbroek susp_offset = 33 + dir_rec->length_file_id; 342c2f99d7cSDavid van Moolenbroek /* Get rid of padding byte. */ 343c2f99d7cSDavid van Moolenbroek if(dir_rec->length_file_id % 2 == 0) { 344c2f99d7cSDavid van Moolenbroek susp_offset++; 345c2f99d7cSDavid van Moolenbroek } 346c2f99d7cSDavid van Moolenbroek 347b1d06847SJean-Baptiste Boric if(dir_rec->length - susp_offset < 4) 348b1d06847SJean-Baptiste Boric return; 349b1d06847SJean-Baptiste Boric 350c2f99d7cSDavid van Moolenbroek susp_size = dir_rec->length - susp_offset; 351c2f99d7cSDavid van Moolenbroek 352c2f99d7cSDavid van Moolenbroek /* Initialize record with known, sane data. */ 353c2f99d7cSDavid van Moolenbroek memcpy(rrii_data.mtime, dir_rec->rec_date, ISO9660_SIZE_DATE7); 354c2f99d7cSDavid van Moolenbroek memcpy(rrii_data.atime, dir_rec->rec_date, ISO9660_SIZE_DATE7); 355c2f99d7cSDavid van Moolenbroek memcpy(rrii_data.ctime, dir_rec->rec_date, ISO9660_SIZE_DATE7); 356b1d06847SJean-Baptiste Boric memcpy(rrii_data.birthtime, dir_rec->rec_date, ISO9660_SIZE_DATE7); 357c2f99d7cSDavid van Moolenbroek 358b1d06847SJean-Baptiste Boric rrii_data.d_mode = i->i_node->i_stat.st_mode; 359b1d06847SJean-Baptiste Boric rrii_data.uid = SYS_UID; 360b1d06847SJean-Baptiste Boric rrii_data.gid = SYS_GID; 361c2f99d7cSDavid van Moolenbroek rrii_data.rdev = NO_DEV; 362c2f99d7cSDavid van Moolenbroek rrii_data.file_id_rrip[0] = '\0'; 363c2f99d7cSDavid van Moolenbroek rrii_data.slink_rrip[0] = '\0'; 364b1d06847SJean-Baptiste Boric rrii_data.reparented_inode = NULL; 365c2f99d7cSDavid van Moolenbroek 366b1d06847SJean-Baptiste Boric parse_susp_buffer(&rrii_data, b_data(bp)+offset+susp_offset, susp_size); 367c2f99d7cSDavid van Moolenbroek 368c2f99d7cSDavid van Moolenbroek /* Copy back data from rrii_dir_record structure. */ 369b1d06847SJean-Baptiste Boric if (rrii_data.file_id_rrip[0] != '\0') { 370b1d06847SJean-Baptiste Boric name_length = strlen(rrii_data.file_id_rrip); 371b1d06847SJean-Baptiste Boric i->r_name = alloc_mem(name_length + 1); 372b1d06847SJean-Baptiste Boric memcpy(i->r_name, rrii_data.file_id_rrip, name_length); 373c2f99d7cSDavid van Moolenbroek } 374c2f99d7cSDavid van Moolenbroek 375b1d06847SJean-Baptiste Boric if (rrii_data.slink_rrip[0] != '\0') { 376b1d06847SJean-Baptiste Boric name_length = strlen(rrii_data.slink_rrip); 377b1d06847SJean-Baptiste Boric i->i_node->s_name = alloc_mem(name_length + 1); 378b1d06847SJean-Baptiste Boric memcpy(i->i_node->s_name, rrii_data.slink_rrip, name_length); 379b1d06847SJean-Baptiste Boric } 380b1d06847SJean-Baptiste Boric 381b1d06847SJean-Baptiste Boric if (rrii_data.reparented_inode) { 382b1d06847SJean-Baptiste Boric /* Recycle the inode already parsed. */ 383b1d06847SJean-Baptiste Boric i->i_node = rrii_data.reparented_inode; 384b1d06847SJean-Baptiste Boric return; 385b1d06847SJean-Baptiste Boric } 386b1d06847SJean-Baptiste Boric 387b1d06847SJean-Baptiste Boric /* XXX: not the correct way to ignore reparented directory holder... */ 388b1d06847SJean-Baptiste Boric if (strcmp(rrii_data.file_id_rrip, ".rr_moved") == 0) 389b1d06847SJean-Baptiste Boric i->i_node->skip = 1; 390b1d06847SJean-Baptiste Boric 391b1d06847SJean-Baptiste Boric if (name_only == TRUE) 392b1d06847SJean-Baptiste Boric return; 393b1d06847SJean-Baptiste Boric 394b1d06847SJean-Baptiste Boric /* Write back all Rock Ridge properties. */ 395b1d06847SJean-Baptiste Boric i->i_node->i_stat.st_atime = date7_to_time_t(rrii_data.atime); 396b1d06847SJean-Baptiste Boric i->i_node->i_stat.st_ctime = date7_to_time_t(rrii_data.ctime); 397b1d06847SJean-Baptiste Boric i->i_node->i_stat.st_mtime = date7_to_time_t(rrii_data.mtime); 398b1d06847SJean-Baptiste Boric i->i_node->i_stat.st_birthtime = date7_to_time_t(rrii_data.birthtime); 399b1d06847SJean-Baptiste Boric 400b1d06847SJean-Baptiste Boric i->i_node->i_stat.st_mode = rrii_data.d_mode; 401b1d06847SJean-Baptiste Boric i->i_node->i_stat.st_uid = rrii_data.uid; 402b1d06847SJean-Baptiste Boric i->i_node->i_stat.st_gid = rrii_data.gid; 403b1d06847SJean-Baptiste Boric i->i_node->i_stat.st_rdev = rrii_data.rdev; 404b1d06847SJean-Baptiste Boric } 405b1d06847SJean-Baptiste Boric 406b1d06847SJean-Baptiste Boric #endif 407b1d06847SJean-Baptiste Boric 408b1d06847SJean-Baptiste Boric #ifdef ISO9660_OPTION_MODE3 409b1d06847SJean-Baptiste Boric 410b1d06847SJean-Baptiste Boric void read_inode_extents(struct inode *i, 411b1d06847SJean-Baptiste Boric const struct iso9660_dir_record *dir_rec, 412b1d06847SJean-Baptiste Boric struct dir_extent *extent, size_t *offset) 413c2f99d7cSDavid van Moolenbroek { 414b1d06847SJean-Baptiste Boric panic("read_inode_extents() isn't implemented yet!"); 415b1d06847SJean-Baptiste Boric } 416b1d06847SJean-Baptiste Boric 417b1d06847SJean-Baptiste Boric #endif 418b1d06847SJean-Baptiste Boric 419b1d06847SJean-Baptiste Boric int check_dir_record(const struct iso9660_dir_record *d, size_t offset) { 420c2f99d7cSDavid van Moolenbroek /* Run some consistency check on a directory entry. */ 421c2f99d7cSDavid van Moolenbroek if ((d->length < 33) || (d->length_file_id < 1)) 422c2f99d7cSDavid van Moolenbroek return EINVAL; 423c2f99d7cSDavid van Moolenbroek if (d->length_file_id + 32 > d->length) 424c2f99d7cSDavid van Moolenbroek return EINVAL; 425c2f99d7cSDavid van Moolenbroek if (offset + d->length > v_pri.logical_block_size_l) 426c2f99d7cSDavid van Moolenbroek return EINVAL; 427c2f99d7cSDavid van Moolenbroek 428c2f99d7cSDavid van Moolenbroek return OK; 429c2f99d7cSDavid van Moolenbroek } 430