Annotation of qemu/roms/openbios/fs/grubfs/fsys_iso9660.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  *  ISO 9660 filesystem backend for GRUB (GRand Unified Bootloader)
                      3:  *  including Rock Ridge Extensions support
                      4:  *
                      5:  *  Copyright (C) 1998, 1999  Kousuke Takai  <[email protected]>
                      6:  *
                      7:  *  This program is free software; you can redistribute it and/or modify
                      8:  *  it under the terms of the GNU General Public License as published by
                      9:  *  the Free Software Foundation; either version 2 of the License, or
                     10:  *  (at your option) any later version.
                     11:  *
                     12:  *  This program is distributed in the hope that it will be useful,
                     13:  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
                     14:  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     15:  *  GNU General Public License for more details.
                     16:  *
                     17:  *  You should have received a copy of the GNU General Public License
                     18:  *  along with this program; if not, write to the Free Software
                     19:  *  Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
                     20:  *  MA 02110-1301, USA.
                     21:  */
                     22: /*
                     23:  *  References:
                     24:  *     linux/fs/isofs/rock.[ch]
                     25:  *     mkisofs-1.11.1/diag/isoinfo.c
                     26:  *     mkisofs-1.11.1/iso9660.h
                     27:  *             (all are written by Eric Youngdale)
                     28:  *
                     29:  *  Modifications by:
                     30:  *     Leonid Lisovskiy   <[email protected]>      2003
                     31:  */
                     32: 
                     33: /*
                     34:  * Modified to make it work with FILO
                     35:  * 2003-10 by SONE Takeshi
                     36:  */
                     37: 
                     38: #ifdef FSYS_ISO9660
                     39: 
                     40: #include "shared.h"
                     41: #include "filesys.h"
                     42: #include "iso9660.h"
                     43: #include "debug.h"
                     44: 
                     45: #if defined(__sparc__) || defined(__PPC__)
                     46: #define ENDIAN b
                     47: #else
                     48: #define ENDIAN l
                     49: #endif
                     50: 
                     51: struct iso_superblock {
                     52:     unsigned long vol_sector;
                     53: 
                     54:     unsigned long file_start;
                     55: };
                     56: 
                     57: #define ISO_SUPER      ((struct iso_superblock *)(FSYS_BUF))
                     58: #define PRIMDESC        ((struct iso_primary_descriptor *)(FSYS_BUF + 2048))
                     59: #define DIRREC          ((struct iso_directory_record *)(FSYS_BUF + 4096))
                     60: #define RRCONT_BUF      ((unsigned char *)(FSYS_BUF + 6144))
                     61: #define NAME_BUF        ((unsigned char *)(FSYS_BUF + 8192))
                     62: 
                     63: static int
                     64: iso9660_devread (int sector, int byte_offset, int byte_len, char *buf)
                     65: {
                     66:   /* FILO uses 512-byte "soft" sector, and ISO-9660 uses 2048-byte
                     67:    * CD-ROM sector */
                     68:   return devread(sector<<2, byte_offset, byte_len, buf);
                     69: }
                     70: 
                     71: int
                     72: iso9660_mount (void)
                     73: {
                     74:   unsigned int sector;
                     75: 
                     76:   /*
                     77:    *  Because there is no defined slice type ID for ISO-9660 filesystem,
                     78:    *  this test will pass only either (1) if entire disk is used, or
                     79:    *  (2) if current partition is BSD style sub-partition whose ID is
                     80:    *  ISO-9660.
                     81:    */
                     82:   /*if ((current_partition != 0xFFFFFF)
                     83:       && !IS_PC_SLICE_TYPE_BSD_WITH_FS(current_slice, FS_ISO9660))
                     84:     return 0;*/
                     85: 
                     86:   /*
                     87:    *  Currently, only FIRST session of MultiSession disks are supported !!!
                     88:    */
                     89:   for (sector = 16 ; sector < 32 ; sector++)
                     90:     {
                     91:       if (!iso9660_devread(sector, 0, sizeof(*PRIMDESC), (char *)PRIMDESC))
                     92:        break;
                     93:       /* check ISO_VD_PRIMARY and ISO_STANDARD_ID */
                     94:       if (CHECK4(&PRIMDESC->type, ISO_VD_PRIMARY, 'C', 'D', '0')
                     95:          && CHECK2(PRIMDESC->id + 3, '0', '1'))
                     96:        {
                     97:          ISO_SUPER->vol_sector = sector;
                     98:          ISO_SUPER->file_start = 0;
                     99:           fsmax = PRIMDESC->volume_space_size.ENDIAN;
                    100:          return 1;
                    101:        }
                    102:     }
                    103: 
                    104:   return 0;
                    105: }
                    106: 
                    107: int
                    108: iso9660_dir (char *dirname)
                    109: {
                    110:   struct iso_directory_record *idr;
                    111:   RR_ptr_t rr_ptr;
                    112:   struct rock_ridge *ce_ptr;
                    113:   unsigned int pathlen;
                    114:   int size;
                    115:   unsigned int extent;
                    116:   unsigned int rr_len;
                    117:   unsigned char file_type;
                    118:   unsigned char rr_flag;
                    119: 
                    120:   idr = &PRIMDESC->root_directory_record;
                    121:   ISO_SUPER->file_start = 0;
                    122: 
                    123:   do
                    124:   {
                    125:       while (*dirname == '/')  /* skip leading slashes */
                    126:          dirname++;
                    127:       /* pathlen = strcspn(dirname, "/\n\t "); */
                    128:       for (pathlen = 0 ;
                    129:          dirname[pathlen]
                    130:             && !isspace(dirname[pathlen]) && dirname[pathlen] != '/' ;
                    131:          pathlen++)
                    132:        ;
                    133: 
                    134:       size = idr->size.ENDIAN;
                    135:       extent = idr->extent.ENDIAN;
                    136: 
                    137:       while (size > 0)
                    138:       {
                    139:          if (!iso9660_devread(extent, 0, ISO_SECTOR_SIZE, (char *)DIRREC))
                    140:          {
                    141:              errnum = ERR_FSYS_CORRUPT;
                    142:              return 0;
                    143:          }
                    144:          extent++;
                    145: 
                    146:          idr = (struct iso_directory_record *)DIRREC;
                    147:          for (; idr->length.ENDIAN > 0;
                    148:                  idr = (struct iso_directory_record *)((char *)idr + idr->length.ENDIAN) )
                    149:          {
                    150:               const char *name = (char *)idr->name;
                    151:               unsigned int name_len = idr->name_len.ENDIAN;
                    152: 
                    153:               file_type = (idr->flags.ENDIAN & 2) ? ISO_DIRECTORY : ISO_REGULAR;
                    154:              if (name_len == 1)
                    155:              {
                    156:                  if ((name[0] == 0) || /* self */
                    157:                      (name[0] == 1))   /* parent */
                    158:                    continue;
                    159:              }
                    160:              if (name_len > 2 && CHECK2(name + name_len - 2, ';', '1'))
                    161:              {
                    162:                  name_len -= 2;        /* truncate trailing file version */
                    163:                  if (name_len > 1 && name[name_len - 1] == '.')
                    164:                    name_len--;         /* truncate trailing dot */
                    165:              }
                    166: 
                    167:              /*
                    168:               *  Parse Rock-Ridge extension
                    169:               */
                    170:               rr_len = (idr->length.ENDIAN - idr->name_len.ENDIAN
                    171:                        - (unsigned char)sizeof(struct iso_directory_record)
                    172:                        + (unsigned char)sizeof(idr->name));
                    173:               rr_ptr.ptr = ((char *)idr + idr->name_len.ENDIAN
                    174:                            + sizeof(struct iso_directory_record)
                    175:                            - sizeof(idr->name));
                    176:              if (rr_len & 1)
                    177:                rr_ptr.ptr++, rr_len--;
                    178:              ce_ptr = NULL;
                    179:              rr_flag = RR_FLAG_NM | RR_FLAG_PX;
                    180: 
                    181:              while (rr_len >= 4)
                    182:              {
                    183:                  if (rr_ptr.rr->version != 1)
                    184:                  {
                    185: #ifndef STAGE1_5
                    186:                    if (debug)
                    187:                      printf(
                    188:                            "Non-supported version (%d) RockRidge chunk "
                    189:                            "`%c%c'\n", rr_ptr.rr->version,
                    190:                            rr_ptr.rr->signature & 0xFF,
                    191:                            rr_ptr.rr->signature >> 8);
                    192: #endif
                    193:                  }
                    194:                   else if (CHECK2(&rr_ptr.rr->signature, 'R', 'R')
                    195:                           && rr_ptr.rr->len >= 5)
                    196:                       rr_flag &= rr_ptr.rr->u.rr.flags.ENDIAN;
                    197:                   else if (CHECK2(&rr_ptr.rr->signature, 'N', 'M'))
                    198:                  {
                    199:                      name = (char *)rr_ptr.rr->u.nm.name;
                    200:                      name_len = rr_ptr.rr->len - 5;
                    201:                      rr_flag &= ~RR_FLAG_NM;
                    202:                  }
                    203:                   else if (CHECK2(&rr_ptr.rr->signature, 'P', 'X')
                    204:                           && rr_ptr.rr->len >= 36)
                    205:                  {
                    206:                       file_type = ((rr_ptr.rr->u.px.mode.ENDIAN & POSIX_S_IFMT)
                    207:                                   == POSIX_S_IFREG
                    208:                                   ? ISO_REGULAR
                    209:                                    : ((rr_ptr.rr->u.px.mode.ENDIAN & POSIX_S_IFMT)
                    210:                                      == POSIX_S_IFDIR
                    211:                                      ? ISO_DIRECTORY : ISO_OTHER));
                    212:                      rr_flag &= ~RR_FLAG_PX;
                    213:                  }
                    214:                   else if (CHECK2(&rr_ptr.rr->signature, 'C', 'E')
                    215:                           && rr_ptr.rr->len >= 28)
                    216:                    ce_ptr = rr_ptr.rr;
                    217:                  if (!rr_flag)
                    218:                    /*
                    219:                     * There is no more extension we expects...
                    220:                     */
                    221:                    break;
                    222:                  rr_len -= rr_ptr.rr->len;
                    223:                  rr_ptr.ptr += rr_ptr.rr->len;
                    224:                  if (rr_len < 4 && ce_ptr != NULL)
                    225:                  {
                    226:                      /* preserve name before loading new extent. */
                    227:                      if( RRCONT_BUF <= (unsigned char *)name
                    228:                          && (unsigned char *)name < RRCONT_BUF + ISO_SECTOR_SIZE )
                    229:                      {
                    230:                          memcpy(NAME_BUF, name, name_len);
                    231:                          name = (char *)NAME_BUF;
                    232:                      }
                    233:                       rr_ptr.ptr = (char *)(RRCONT_BUF + ce_ptr->u.ce.offset.ENDIAN);
                    234:                       rr_len = ce_ptr->u.ce.size.ENDIAN;
                    235:                       if (!iso9660_devread(ce_ptr->u.ce.extent.ENDIAN, 0,
                    236:                                            ISO_SECTOR_SIZE, (char *)RRCONT_BUF))
                    237:                      {
                    238:                          errnum = 0;   /* this is not fatal. */
                    239:                          break;
                    240:                      }
                    241:                      ce_ptr = NULL;
                    242:                   }
                    243:              } /* rr_len >= 4 */
                    244: 
                    245:              filemax = MAXINT;
                    246:              if (name_len >= pathlen
                    247:                   && !strnicmp(name, dirname, pathlen))
                    248:              {
                    249:                 if (dirname[pathlen] == '/' || !print_possibilities)
                    250:                {
                    251:                  /*
                    252:                   *  DIRNAME is directory component of pathname,
                    253:                   *  or we are to open a file.
                    254:                   */
                    255:                  if (pathlen == name_len)
                    256:                  {
                    257:                      if (dirname[pathlen] == '/')
                    258:                      {
                    259:                          if (file_type != ISO_DIRECTORY)
                    260:                          {
                    261:                              errnum = ERR_BAD_FILETYPE;
                    262:                              return 0;
                    263:                          }
                    264:                           goto next_dir_level;
                    265:                      }
                    266:                      if (file_type != ISO_REGULAR)
                    267:                      {
                    268:                          errnum = ERR_BAD_FILETYPE;
                    269:                          return 0;
                    270:                      }
                    271:                       ISO_SUPER->file_start = idr->extent.ENDIAN;
                    272:                      filepos = 0;
                    273:                       filemax = idr->size.ENDIAN;
                    274:                      return 1;
                    275:                  }
                    276:                }
                    277:                else    /* Completion */
                    278:                {
                    279: #ifndef STAGE1_5
                    280:                  if (print_possibilities > 0)
                    281:                      print_possibilities = -print_possibilities;
                    282:                  memcpy(NAME_BUF, name, name_len);
                    283:                  NAME_BUF[name_len] = '\0';
                    284:                  print_a_completion (NAME_BUF);
                    285: #endif
                    286:                }
                    287:              }
                    288:          } /* for */
                    289: 
                    290:          size -= ISO_SECTOR_SIZE;
                    291:       } /* size>0 */
                    292: 
                    293:       if (dirname[pathlen] == '/' || print_possibilities >= 0)
                    294:       {
                    295:          errnum = ERR_FILE_NOT_FOUND;
                    296:          return 0;
                    297:       }
                    298: 
                    299: next_dir_level:
                    300:       dirname += pathlen;
                    301: 
                    302:   } while (*dirname == '/');
                    303: 
                    304:   return 1;
                    305: }
                    306: 
                    307: int
                    308: iso9660_read (char *buf, int len)
                    309: {
                    310:   int sector, blkoffset, size, ret;
                    311: 
                    312:   if (ISO_SUPER->file_start == 0)
                    313:     return 0;
                    314: 
                    315:   ret = 0;
                    316:   blkoffset = filepos & (ISO_SECTOR_SIZE - 1);
                    317:   sector = filepos >> ISO_SECTOR_BITS;
                    318:   while (len > 0)
                    319:   {
                    320:     size = ISO_SECTOR_SIZE - blkoffset;
                    321:     if (size > len)
                    322:         size = len;
                    323: 
                    324:     disk_read_func = disk_read_hook;
                    325: 
                    326:     if (!iso9660_devread(ISO_SUPER->file_start + sector, blkoffset, size, buf))
                    327:        return 0;
                    328: 
                    329:     disk_read_func = NULL;
                    330: 
                    331:     len -= size;
                    332:     buf += size;
                    333:     ret += size;
                    334:     filepos += size;
                    335:     sector++;
                    336:     blkoffset = 0;
                    337:   }
                    338: 
                    339:   return ret;
                    340: }
                    341: 
                    342: #endif /* FSYS_ISO9660 */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.