Annotation of qemu/roms/openbios/fs/grubfs/fsys_iso9660.c, revision 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.