Fork me on GitHub

root/fs/iso9660/inode.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. read_pathtable
  2. get_parent_dir_size
  3. iso9660_read_inode
  4. iso9660_bmap

   1 /*
   2  * fiwix/fs/iso9660/inode.c
   3  *
   4  * Copyright 2018-2021, Jordi Sanfeliu. All rights reserved.
   5  * Distributed under the terms of the Fiwix License.
   6  */
   7 
   8 #include <fiwix/kernel.h>
   9 #include <fiwix/types.h>
  10 #include <fiwix/errno.h>
  11 #include <fiwix/fs.h>
  12 #include <fiwix/filesystems.h>
  13 #include <fiwix/fs_iso9660.h>
  14 #include <fiwix/fs_pipe.h>
  15 #include <fiwix/buffer.h>
  16 #include <fiwix/stat.h>
  17 #include <fiwix/mm.h>
  18 #include <fiwix/sched.h>
  19 #include <fiwix/stdio.h>
  20 #include <fiwix/string.h>
  21 
  22 static int read_pathtable(struct inode *i)
  23 {
  24         int n, offset, pt_len, pt_blk;
  25         struct iso9660_sb_info *sbi;
  26         struct iso9660_pathtable_record *ptr;
  27         struct buffer *buf;
  28 
  29         sbi = (struct iso9660_sb_info *)&i->sb->u.iso9660;
  30         pt_len = isonum_733(sbi->sb->path_table_size);
  31         pt_blk = isonum_731(sbi->sb->type_l_path_table);
  32 
  33         if(pt_len > PAGE_SIZE) {
  34                 printk("WARNING: %s(): path table record size (%d) > 4096, not supported yet.\n", __FUNCTION__, pt_len);
  35                 return -EINVAL;
  36         }
  37 
  38         if(!(sbi->pathtable_raw = (void *)kmalloc())) {
  39                 return -ENOMEM;
  40         }
  41         offset = 0;
  42         while(offset < pt_len) {
  43                 if(!(buf = bread(i->dev, pt_blk++, BLKSIZE_2K))) {
  44                         kfree((unsigned int)sbi->pathtable_raw);
  45                         return -EIO;
  46                 }
  47                 memcpy_b(sbi->pathtable_raw + offset, (void *)buf->data, MIN(pt_len - offset, BLKSIZE_2K));
  48                 offset += MIN(pt_len - offset, BLKSIZE_2K);
  49                 brelse(buf);
  50         }
  51 
  52         /* allocate and count the number of records in the Path Table */
  53         offset = n = 0;
  54         if(!(sbi->pathtable = (struct iso9660_pathtable_record **)kmalloc())) {
  55                 kfree((unsigned int)sbi->pathtable_raw);
  56                 return -ENOMEM;
  57         }
  58         sbi->pathtable[n] = NULL;
  59         while(offset < pt_len) {
  60                 ptr = (struct iso9660_pathtable_record *)(sbi->pathtable_raw + offset);
  61                 sbi->pathtable[++n] = ptr;
  62                 offset += sizeof(struct iso9660_pathtable_record) + isonum_711(ptr->length) + (isonum_711(ptr->length) & 1);
  63         }
  64         sbi->paths = n;
  65 
  66         return 0;
  67 }
  68 
  69 static int get_parent_dir_size(struct superblock *sb, __blk_t extent)
  70 {
  71         int n;
  72         struct iso9660_pathtable_record *ptr;
  73         __blk_t parent;
  74 
  75         for(n = 0; n < sb->u.iso9660.paths; n++) {
  76                 ptr = (struct iso9660_pathtable_record *)sb->u.iso9660.pathtable[n];
  77                 if(isonum_731(ptr->extent) == extent) {
  78                         
  79                         parent = isonum_723(ptr->parent);
  80                         ptr = (struct iso9660_pathtable_record *)sb->u.iso9660.pathtable[parent];
  81                         parent = isonum_731(ptr->extent);
  82                         return parent;
  83                 }
  84         }
  85         printk("WARNING: %s(): unable to locate extent '%d' in path table.\n", __FUNCTION__, extent);
  86         return 0;
  87 }
  88 
  89 int iso9660_read_inode(struct inode *i)
  90 {
  91         int errno;
  92         __u32 blksize;
  93         struct superblock *sb;
  94         struct iso9660_directory_record *d;
  95         struct buffer *buf;
  96         __blk_t dblock;
  97         __off_t doffset;
  98 
  99         sb = (struct superblock *)i->sb;
 100         if(!sb->u.iso9660.pathtable) {
 101                 if((errno = read_pathtable(i))) {
 102                         return errno;
 103                 }
 104         }
 105 
 106         dblock = (i->inode & ~ISO9660_INODE_MASK) >> ISO9660_INODE_BITS;
 107         doffset = i->inode & ISO9660_INODE_MASK;
 108         blksize = i->sb->s_blocksize;
 109 
 110         /* FIXME: it only looks in one directory block */
 111         if(!(buf = bread(i->dev, dblock, blksize))) {
 112                 return -EIO;
 113         }
 114 
 115         if(doffset >= blksize) {
 116                 printk("WARNING: %s(): inode %d (dblock=%d, doffset=%d) not found in directory entry.\n", __FUNCTION__, i->inode, dblock, doffset);
 117                 brelse(buf);
 118                 return -EIO;
 119         }
 120         d = (struct iso9660_directory_record *)(buf->data + doffset);
 121 
 122         i->i_mode = S_IFREG;
 123         if((char)d->flags[0] & ISO9660_FILE_ISDIR) {
 124                 i->i_mode = S_IFDIR;
 125         }
 126         if(!((char)d->flags[0] & ISO9660_FILE_HASOWNER)) {
 127                 i->i_mode |= S_IRUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
 128         }
 129         i->i_uid = 0;
 130         i->i_size = isonum_733(d->size);
 131         i->i_atime = isodate(d->date);
 132         i->i_ctime = isodate(d->date);
 133         i->i_mtime = isodate(d->date);
 134         i->i_gid = 0;
 135         i->i_nlink = 1;
 136         i->count = 1;
 137 
 138         i->u.iso9660.i_extent = isonum_733(d->extent);
 139         check_rrip_inode(d, i);
 140         brelse(buf);
 141 
 142         switch(i->i_mode & S_IFMT) {
 143                 case S_IFCHR:
 144                         i->fsop = &def_chr_fsop;
 145                         break;
 146                 case S_IFBLK:
 147                         i->fsop = &def_blk_fsop;
 148                         break;
 149                 case S_IFIFO:
 150                         i->fsop = &pipefs_fsop;
 151                         /* it's a union so we need to clear pipefs_inode */
 152                         memset_b(&i->u.pipefs, NULL, sizeof(struct pipefs_inode));
 153                         break;
 154                 case S_IFDIR:
 155                         i->fsop = &iso9660_dir_fsop;
 156                         i->i_nlink++;
 157                         break;
 158                 case S_IFREG:
 159                         i->fsop = &iso9660_file_fsop;
 160                         break;
 161                 case S_IFLNK:
 162                         i->fsop = &iso9660_symlink_fsop;
 163                         break;
 164                 case S_IFSOCK:
 165                         i->fsop = NULL;
 166                         break;
 167                 default:
 168                         PANIC("invalid inode (%d) mode %08o.\n", i->inode, i->i_mode);
 169         }
 170         return 0;
 171 }
 172 
 173 int iso9660_bmap(struct inode *i, __off_t offset, int mode)
 174 {
 175         __blk_t block;
 176 
 177         block = i->u.iso9660.i_extent + (offset / i->sb->s_blocksize);
 178         return block;
 179 }

/* [previous][next][first][last][top][bottom][index][help] */