Fork me on GitHub

root/fs/iso9660/rrip.c

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

DEFINITIONS

This source file includes following definitions.
  1. check_rrip_inode
  2. get_rrip_filename
  3. get_rrip_symlink

   1 /*
   2  * fiwix/fs/iso9660/rrip.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/stat.h>
  12 #include <fiwix/filesystems.h>
  13 #include <fiwix/buffer.h>
  14 #include <fiwix/fs_iso9660.h>
  15 #include <fiwix/mm.h>
  16 #include <fiwix/stdio.h>
  17 #include <fiwix/string.h>
  18 
  19 void check_rrip_inode(struct iso9660_directory_record *d, struct inode *i)
  20 {
  21         unsigned int total_len;
  22         unsigned int len;
  23         unsigned int sig;
  24         int n, nm_len, rootflag;
  25         struct susp_rrip *rrip;
  26         unsigned int dev_h, dev_l;
  27         unsigned int ce_block, ce_offset, ce_size;
  28         struct buffer *buf;
  29         unsigned char *sue;
  30         int sl_len;
  31         struct rrip_sl_component *slc;
  32 
  33         ce_block = ce_offset = ce_size = 0;
  34         buf = NULL;
  35         total_len = isonum_711(d->length);
  36         len = isonum_711(d->name_len);
  37         if(!(len % 2)) {
  38                 len++;
  39         }
  40         sue = (unsigned char *)d->name;
  41         nm_len = 0;
  42 
  43 loop:
  44         if(ce_block && ce_size) { 
  45                 /* FIXME: it only looks in one directory block */
  46                 if(!(buf = bread(i->dev, ce_block, i->sb->s_blocksize))) {
  47                         return;
  48                 }
  49                 sue = (unsigned char *)buf->data + ce_offset;
  50                 total_len = ce_size;
  51                 len = 0;
  52         }
  53 
  54         while(len < total_len) {
  55                 rrip = (struct susp_rrip *)(sue + len);
  56                 if(rrip->len == 0) {
  57                         break;
  58                 }
  59                 sig = GET_SIG(rrip->signature[0], rrip->signature[1]);
  60                 switch(sig) {
  61                         case GET_SIG('S', 'P'):
  62                                 if(rrip->u.sp.magic[0] != SP_MAGIC1 || rrip->u.sp.magic[1] != SP_MAGIC2) {
  63                                         if(ce_block) {
  64                                                 brelse(buf);
  65                                         }
  66                                         return;
  67                                 }
  68                                 break;
  69                         case GET_SIG('C', 'E'):
  70                                 if(ce_block) {
  71                                         brelse(buf);
  72                                 }
  73                                 ce_block = isonum_733(rrip->u.ce.block);
  74                                 ce_offset = isonum_733(rrip->u.ce.offset);
  75                                 ce_size = isonum_733(rrip->u.ce.size);
  76                                 goto loop;
  77                                 break;
  78                         case GET_SIG('E', 'R'):
  79                                 i->sb->u.iso9660.rrip = 1;
  80                                 printk("ISO 9660 Extensions: ");
  81                                 for(n = 0; n < rrip->u.er.len_id; n++) {
  82                                         printk("%c", rrip->u.er.data[n]);
  83                                 }
  84                                 printk("\n");
  85                                 break;
  86                         case GET_SIG('P', 'X'):
  87                                 i->i_mode  = isonum_733(rrip->u.px.mode);
  88                                 i->i_nlink = isonum_733(rrip->u.px.nlink);
  89                                 i->i_uid   = isonum_733(rrip->u.px.uid);
  90                                 i->i_gid   = isonum_733(rrip->u.px.gid);
  91                                 break;
  92                         case GET_SIG('P', 'N'):
  93                                 if(S_ISBLK(i->i_mode) || S_ISCHR(i->i_mode)) {
  94                                         dev_h = isonum_733(rrip->u.pn.dev_h);
  95                                         dev_l = isonum_733(rrip->u.pn.dev_l);
  96                                         i->rdev = MKDEV(dev_h, dev_l);
  97                                 }
  98                                 break;
  99                         case GET_SIG('S', 'L'):
 100                                 sl_len = rootflag = 0;
 101                                 slc = (struct rrip_sl_component *)&rrip->u.sl.area;
 102                                 while(sl_len < (rrip->len - 5)) {
 103                                         if(sl_len && !rootflag) {
 104                                                 nm_len++;
 105                                         }
 106                                         rootflag = 0;
 107                                         switch(slc->flags & 0xE) {
 108                                                 case 0:
 109                                                         nm_len += slc->len;
 110                                                         break;
 111                                                 case SL_CURRENT:
 112                                                         nm_len += 1;
 113                                                         break;
 114                                                 case SL_PARENT:
 115                                                         nm_len += 2;
 116                                                         break;
 117                                                 case SL_ROOT:
 118                                                         nm_len += 1;
 119                                                         rootflag = 1;
 120                                                         break;
 121                                                 default:
 122                                                         printk("WARNING: %s(): unsupported RRIP SL flags %d.\n", __FUNCTION__, slc->flags & 0xE);
 123                                         }
 124                                         slc = (struct rrip_sl_component *)(((char *)slc) + slc->len + sizeof(struct rrip_sl_component));
 125                                         sl_len += slc->len + sizeof(struct rrip_sl_component);
 126                                 }
 127                                 i->i_size = nm_len;
 128                                 break;
 129                         case GET_SIG('T', 'F'):
 130                                 n = 0;
 131                                 if(rrip->u.tf.flags & TF_CREATION) {
 132                                         i->i_ctime = isodate(rrip->u.tf.times[n++].time);
 133                                 }
 134                                 if(rrip->u.tf.flags & TF_MODIFY) {
 135                                         i->i_mtime = isodate(rrip->u.tf.times[n++].time);
 136                                 }
 137                                 if(rrip->u.tf.flags & TF_ACCESS) {
 138                                         i->i_atime = isodate(rrip->u.tf.times[n++].time);
 139                                 }
 140                                 if(rrip->u.tf.flags & TF_ATTRIBUTES) {
 141                                         i->i_ctime = isodate(rrip->u.tf.times[n++].time);
 142                                 }
 143                                 break;
 144                 }
 145                 len += rrip->len;
 146         }
 147         if(ce_block) {
 148                 brelse(buf);
 149         }
 150 }
 151 
 152 int get_rrip_filename(struct iso9660_directory_record *d, struct inode *i, char *name)
 153 {
 154         unsigned int total_len;
 155         unsigned int len;
 156         unsigned int sig;
 157         int nm_len;
 158         struct susp_rrip *rrip;
 159         unsigned int ce_block, ce_offset, ce_size;
 160         struct buffer *buf;
 161         unsigned char *sue;
 162 
 163         ce_block = ce_offset = ce_size = 0;
 164         buf = NULL;
 165         total_len = isonum_711(d->length);
 166         len = isonum_711(d->name_len);
 167         if(!(len % 2)) {
 168                 len++;
 169         }
 170         sue = (unsigned char *)d->name;
 171         nm_len = 0;
 172 
 173 loop:
 174         if(ce_block && ce_size) { 
 175                 /* FIXME: it only looks in one directory block */
 176                 if(!(buf = bread(i->dev, ce_block, i->sb->s_blocksize))) {
 177                         return 0;
 178                 }
 179                 sue = (unsigned char *)buf->data + ce_offset;
 180                 total_len = ce_size;
 181                 len = 0;
 182         }
 183 
 184         while(len < total_len) {
 185                 rrip = (struct susp_rrip *)(sue + len);
 186                 if(rrip->len == 0) {
 187                         break;
 188                 }
 189                 sig = GET_SIG(rrip->signature[0], rrip->signature[1]);
 190                 switch(sig) {
 191                         case GET_SIG('S', 'P'):
 192                                 if(rrip->u.sp.magic[0] != SP_MAGIC1 || rrip->u.sp.magic[1] != SP_MAGIC2) {
 193                                         if(ce_block) {
 194                                                 brelse(buf);
 195                                         }
 196                                         return 0;
 197                                 }
 198                                 break;
 199                         case GET_SIG('C', 'E'):
 200                                 if(ce_block) {
 201                                         brelse(buf);
 202                                 }
 203                                 ce_block = isonum_733(rrip->u.ce.block);
 204                                 ce_offset = isonum_733(rrip->u.ce.offset);
 205                                 ce_size = isonum_733(rrip->u.ce.size);
 206                                 goto loop;
 207                         case GET_SIG('N', 'M'):
 208                                 if(rrip->u.nm.flags) { /* FIXME: & ~(NM_CONTINUE | NM_CURRENT | NM_PARENT)) { */
 209                                         printk("WARNING: %s(): unsupported NM flag settings (%d).\n", __FUNCTION__, rrip->u.nm.flags);
 210                                         if(ce_block) {
 211                                                 brelse(buf);
 212                                         }
 213                                         return 0;
 214                                 }
 215                                 nm_len = rrip->len - 5;
 216                                 memcpy_b(name, rrip->u.nm.name, nm_len);
 217                                 name[nm_len] = NULL;
 218                                 break;
 219                 }
 220                 len += rrip->len;
 221         }
 222         if(ce_block) {
 223                 brelse(buf);
 224         }
 225         return nm_len;
 226 }
 227 
 228 int get_rrip_symlink(struct inode *i, char *name)
 229 {
 230         unsigned int total_len;
 231         unsigned int len;
 232         unsigned int sig;
 233         int nm_len;
 234         struct susp_rrip *rrip;
 235         unsigned int ce_block, ce_offset, ce_size;
 236         struct buffer *buf;
 237         struct buffer *buf2;
 238         unsigned char *sue;
 239         struct iso9660_directory_record *d;
 240         __blk_t dblock;
 241         __off_t doffset;
 242         int sl_len, rootflag;
 243         struct rrip_sl_component *slc;
 244 
 245         dblock = (i->inode & ~ISO9660_INODE_MASK) >> ISO9660_INODE_BITS;
 246         doffset = i->inode & ISO9660_INODE_MASK;
 247         /* FIXME: it only looks in one directory block */
 248         if(!(buf = bread(i->dev, dblock, i->sb->s_blocksize))) {
 249                 return -EIO;
 250         }
 251         d = (struct iso9660_directory_record *)(buf->data + doffset);
 252 
 253         ce_block = ce_offset = ce_size = 0;
 254         buf2 = NULL;
 255         total_len = isonum_711(d->length);
 256         len = isonum_711(d->name_len);
 257         if(!(len % 2)) {
 258                 len++;
 259         }
 260         sue = (unsigned char *)d->name;
 261         nm_len = 0;
 262 
 263 loop:
 264         if(ce_block && ce_size) { 
 265                 /* FIXME: it only looks in one directory block */
 266                 if(!(buf2 = bread(i->dev, ce_block, i->sb->s_blocksize))) {
 267                         return 0;
 268                 }
 269                 sue = (unsigned char *)buf2->data + ce_offset;
 270                 total_len = ce_size;
 271                 len = 0;
 272         }
 273 
 274         while(len < total_len) {
 275                 rrip = (struct susp_rrip *)(sue + len);
 276                 if(rrip->len == 0) {
 277                         break;
 278                 }
 279                 sig = GET_SIG(rrip->signature[0], rrip->signature[1]);
 280                 switch(sig) {
 281                         case GET_SIG('S', 'P'):
 282                                 if(rrip->u.sp.magic[0] != SP_MAGIC1 || rrip->u.sp.magic[1] != SP_MAGIC2) {
 283                                         if(ce_block) {
 284                                                 brelse(buf2);
 285                                         }
 286                                         return 0;
 287                                 }
 288                                 break;
 289                         case GET_SIG('C', 'E'):
 290                                 if(ce_block) {
 291                                         brelse(buf2);
 292                                 }
 293                                 ce_block = isonum_733(rrip->u.ce.block);
 294                                 ce_offset = isonum_733(rrip->u.ce.offset);
 295                                 ce_size = isonum_733(rrip->u.ce.size);
 296                                 goto loop;
 297                         case GET_SIG('S', 'L'):
 298                                 sl_len = rootflag = 0;
 299                                 slc = (struct rrip_sl_component *)&rrip->u.sl.area;
 300                                 while(sl_len < (rrip->len - 5)) {
 301                                         if(sl_len && !rootflag) {
 302                                                 strcat(name, "/");
 303                                                 nm_len++;
 304                                         }
 305                                         rootflag = 0;
 306                                         switch(slc->flags & 0xE) {
 307                                                 case 0:
 308                                                         nm_len += slc->len;
 309                                                         strncat(name, slc->name, slc->len);
 310                                                         break;
 311                                                 case SL_CURRENT:
 312                                                         nm_len += 1;
 313                                                         strcat(name, ".");
 314                                                         break;
 315                                                 case SL_PARENT:
 316                                                         nm_len += 2;
 317                                                         strcat(name, "..");
 318                                                         break;
 319                                                 case SL_ROOT:
 320                                                         nm_len += 1;
 321                                                         rootflag = 1;
 322                                                         strcat(name, "/");
 323                                                         break;
 324                                                 default:
 325                                                         printk("WARNING: %s(): unsupported RRIP SL flags %d.\n", __FUNCTION__, slc->flags & 0xE);
 326                                         }
 327                                         slc = (struct rrip_sl_component *)(((char *)slc) + slc->len + sizeof(struct rrip_sl_component));
 328                                         sl_len += slc->len + sizeof(struct rrip_sl_component);
 329                                 }
 330                                 name[nm_len] = NULL;
 331                                 break;
 332                 }
 333                 len += rrip->len;
 334         }
 335         if(ce_block) {
 336                 brelse(buf2);
 337         }
 338         brelse(buf);
 339         return nm_len;
 340 }

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