Fork me on GitHub

root/fs/iso9660/super.c

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

DEFINITIONS

This source file includes following definitions.
  1. isonum_711
  2. isonum_723
  3. isonum_731
  4. isonum_733
  5. isodate
  6. iso9660_cleanfilename
  7. iso9660_statfs
  8. iso9660_read_superblock
  9. iso9660_release_superblock
  10. iso9660_init

   1 /*
   2  * fiwix/fs/iso9660/super.c
   3  *
   4  * Copyright 2018, Jordi Sanfeliu. All rights reserved.
   5  * Distributed under the terms of the Fiwix License.
   6  */
   7 
   8 #include <fiwix/types.h>
   9 #include <fiwix/errno.h>
  10 #include <fiwix/fs.h>
  11 #include <fiwix/filesystems.h>
  12 #include <fiwix/fs_iso9660.h>
  13 #include <fiwix/buffer.h>
  14 #include <fiwix/time.h>
  15 #include <fiwix/sched.h>
  16 #include <fiwix/mm.h>
  17 #include <fiwix/stdio.h>
  18 #include <fiwix/string.h>
  19 
  20 struct fs_operations iso9660_fsop = {
  21         FSOP_REQUIRES_DEV,
  22         NULL,
  23 
  24         NULL,                   /* open */
  25         NULL,                   /* close */
  26         NULL,                   /* read */
  27         NULL,                   /* write */
  28         NULL,                   /* ioctl */
  29         NULL,                   /* lseek */
  30         NULL,                   /* readdir */
  31         NULL,                   /* mmap */
  32         NULL,                   /* select */
  33 
  34         NULL,                   /* readlink */
  35         NULL,                   /* followlink */
  36         NULL,                   /* bmap */
  37         NULL,                   /* lookup */
  38         NULL,                   /* rmdir */
  39         NULL,                   /* link */
  40         NULL,                   /* unlink */
  41         NULL,                   /* symlink */
  42         NULL,                   /* mkdir */
  43         NULL,                   /* mknod */
  44         NULL,                   /* truncate */
  45         NULL,                   /* create */
  46         NULL,                   /* rename */
  47 
  48         NULL,                   /* read_block */
  49         NULL,                   /* write_block */
  50 
  51         iso9660_read_inode,
  52         NULL,                   /* write_inode */
  53         NULL,                   /* ialloc */
  54         NULL,                   /* ifree */
  55         iso9660_statfs,
  56         iso9660_read_superblock,
  57         NULL,                   /* remount_fs */
  58         NULL,                   /* write_superblock */
  59         iso9660_release_superblock
  60 };
  61 
  62 int isonum_711(char *str)
  63 {
  64         unsigned char *le;
  65 
  66         le = (unsigned char *)str;
  67         return le[0];
  68 }
  69 
  70 /* return a 16bit little-endian number */
  71 int isonum_723(char *str)
  72 {
  73         unsigned char *le;
  74 
  75         le = (unsigned char *)str;
  76         return le[0] | (le[1] << 8);
  77 }
  78 
  79 /* return a 32bit little-endian number */
  80 int isonum_731(char *str)
  81 {
  82         unsigned char *le;
  83 
  84         le = (unsigned char *)str;
  85         return le[0] | (le[1] << 8) | (le[2] << 16) | (le[3] << 24);
  86 }
  87 
  88 /* return a 32bit little-endian number */
  89 int isonum_733(char *p)
  90 {
  91         return isonum_731(p);
  92 }
  93 
  94 /* return a date and time format */
  95 unsigned long int isodate(char *p)
  96 {
  97         struct mt mt;
  98 
  99         if(!p[0]) {
 100                 return 0;
 101         }
 102 
 103         mt.mt_sec = p[5];
 104         mt.mt_min = p[4];
 105         mt.mt_hour = p[3];
 106         mt.mt_day = p[2];
 107         mt.mt_month = p[1];
 108         mt.mt_year = p[0];
 109         mt.mt_year += 1900;
 110         mt.mt_min += p[6] * 15;
 111 
 112         return mktime(&mt);
 113 }
 114 
 115 /* return a clean filename */
 116 int iso9660_cleanfilename(char *filename, int len)
 117 {
 118         int n;
 119         char *p;
 120 
 121         p = filename;
 122         if(len > 2) {
 123                 for(n = 0; n < len; n++) {
 124                         if((len - n) == 2) {
 125                                 if(p[n] == ';' && p[n + 1] == '1') {
 126                                         filename[n] = NULL;
 127                                         if(p[n - 1] == '.') {
 128                                                 filename[n - 1] = NULL;
 129                                         }
 130                                         return 0;
 131                                 }
 132                         }
 133                 }
 134         }
 135         return 1;
 136 }
 137 
 138 void iso9660_statfs(struct superblock *sb, struct statfs *statfsbuf)
 139 {
 140         statfsbuf->f_type = ISO9660_SUPER_MAGIC;
 141         statfsbuf->f_bsize = sb->s_blocksize;
 142         statfsbuf->f_blocks = isonum_733(sb->u.iso9660.sb->volume_space_size);
 143         statfsbuf->f_bfree = 0;
 144         statfsbuf->f_bavail = 0;
 145         statfsbuf->f_files = 0;         /* FIXME */
 146         statfsbuf->f_ffree = 0;
 147         /* statfsbuf->f_fsid = ? */
 148         statfsbuf->f_namelen = NAME_MAX;
 149 }
 150 
 151 int iso9660_read_superblock(__dev_t dev, struct superblock *sb)
 152 {
 153         struct buffer *buf;
 154         struct iso9660_super_block *iso9660sb;
 155         struct iso9660_super_block *pvd;
 156         struct iso9660_directory_record *dr;
 157         __ino_t root_inode;
 158         int n;
 159 
 160         superblock_lock(sb);
 161         pvd = NULL;
 162 
 163         for(n = 0; n < ISO9660_MAX_VD; n++) {
 164                 if(!(buf = bread(dev, ISO9660_SUPERBLOCK + n, BLKSIZE_2K))) {
 165                         superblock_unlock(sb);
 166                         return -EIO;
 167                 }
 168 
 169                 iso9660sb = (struct iso9660_super_block *)buf->data;
 170                 if(strncmp(iso9660sb->id, ISO9660_STANDARD_ID, sizeof(iso9660sb->id)) || (isonum_711(iso9660sb->type) == ISO9660_VD_END)) {
 171                         break;
 172                 }
 173                 if(isonum_711(iso9660sb->type) == ISO9660_VD_PRIMARY) {
 174                         pvd = (struct iso9660_super_block *)buf->data;
 175                         break;
 176                 }
 177                 brelse(buf);
 178         }
 179         if(!pvd) {
 180                 printk("WARNING: %s(): invalid filesystem type or bad superblock on device %d,%d.\n", __FUNCTION__, MAJOR(dev), MINOR(dev));
 181                 superblock_unlock(sb);
 182                 brelse(buf);
 183                 return -EINVAL;
 184         }
 185 
 186         dr = (struct iso9660_directory_record *)pvd->root_directory_record;
 187         root_inode = isonum_711(dr->extent);
 188 
 189         sb->dev = dev;
 190         sb->fsop = &iso9660_fsop;
 191         sb->flags = MS_RDONLY;
 192         sb->s_blocksize = isonum_723(pvd->logical_block_size);
 193         sb->u.iso9660.rrip = 0;
 194         if(!(sb->u.iso9660.sb = (void *)kmalloc())) {
 195                 superblock_unlock(sb);
 196                 brelse(buf);
 197                 return -ENOMEM;
 198         }
 199         memcpy_b(sb->u.iso9660.sb, pvd, sizeof(struct iso9660_super_block));
 200         brelse(buf);
 201 
 202         root_inode = (root_inode << ISO9660_INODE_BITS) + (0 & ISO9660_INODE_MASK);
 203         if(!(sb->root = iget(sb, root_inode))) {
 204                 printk("WARNING: %s(): unable to get root inode.\n", __FUNCTION__);
 205                 superblock_unlock(sb);
 206                 return -EINVAL;
 207         }
 208         sb->u.iso9660.s_root_inode = root_inode;
 209 
 210         superblock_unlock(sb);
 211         return 0;
 212 }
 213 
 214 void iso9660_release_superblock(struct superblock *sb)
 215 {
 216         kfree((unsigned int)sb->u.iso9660.sb);
 217         kfree((unsigned int)sb->u.iso9660.pathtable);
 218         kfree((unsigned int)sb->u.iso9660.pathtable_raw);
 219 }
 220 
 221 int iso9660_init(void)
 222 {
 223         return register_filesystem("iso9660", &iso9660_fsop);
 224 }

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