|
|
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 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.