File indexing completed on 2024-05-19 16:52:41
0001 /* 0002 SPDX-FileCopyrightText: 2002 Szombathelyi György <gyurco@users.sourceforge.net> 0003 SPDX-FileCopyrightText: 2004-2022 Krusader Krew <https://krusader.org> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include "isofs.h" 0009 0010 #include <errno.h> 0011 #include <string.h> 0012 0013 #include "iso_fs.h" 0014 0015 /* internal function from the linux kernel (isofs fs) */ 0016 static time_t getisotime(int year, int month, int day, int hour, 0017 int minute, int second, int tz) 0018 { 0019 0020 int days, i; 0021 time_t crtime; 0022 0023 year -= 1970; 0024 0025 if (year < 0) { 0026 crtime = 0; 0027 } else { 0028 int monlen[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 0029 0030 days = year * 365; 0031 if (year > 2) 0032 days += (year + 1) / 4; 0033 for (i = 1; i < month; i++) 0034 days += monlen[i-1]; 0035 if (((year + 2) % 4) == 0 && month > 2) 0036 days++; 0037 days += day - 1; 0038 crtime = ((((days * 24) + hour) * 60 + minute) * 60) 0039 + second; 0040 0041 /* sign extend */ 0042 if (tz & 0x80) 0043 tz |= (-1 << 8); 0044 0045 /* 0046 * The timezone offset is unreliable on some disks, 0047 * so we make a sanity check. In no case is it ever 0048 * more than 13 hours from GMT, which is 52*15min. 0049 * The time is always stored in localtime with the 0050 * timezone offset being what get added to GMT to 0051 * get to localtime. Thus we need to subtract the offset 0052 * to get to true GMT, which is what we store the time 0053 * as internally. On the local system, the user may set 0054 * their timezone any way they wish, of course, so GMT 0055 * gets converted back to localtime on the receiving 0056 * system. 0057 * 0058 * NOTE: mkisofs in versions prior to mkisofs-1.10 had 0059 * the sign wrong on the timezone offset. This has now 0060 * been corrected there too, but if you are getting screwy 0061 * results this may be the explanation. If enough people 0062 * complain, a user configuration option could be added 0063 * to add the timezone offset in with the wrong sign 0064 * for 'compatibility' with older discs, but I cannot see how 0065 * it will matter that much. 0066 * 0067 * Thanks to kuhlmav@elec.canterbury.ac.nz (Volker Kuhlmann) 0068 * for pointing out the sign error. 0069 */ 0070 if (-52 <= tz && tz <= 52) 0071 crtime -= tz * 15 * 60; 0072 } 0073 return crtime; 0074 0075 } 0076 0077 /** 0078 * Returns the Unix from the ISO9660 9.1.5 time format 0079 */ 0080 time_t isodate_915(char * p, int hs) 0081 { 0082 0083 return getisotime(1900 + p[0], p[1], p[2], p[3], p[4], p[5], hs == 0 ? p[6] : 0); 0084 } 0085 0086 /** 0087 * Returns the Unix from the ISO9660 8.4.26.1 time format 0088 * BUG: hundredth of seconds are ignored, because Unix time_t has one second 0089 * resolution (I think it's no problem at all) 0090 */ 0091 time_t isodate_84261(char * p, int hs) 0092 { 0093 int year, month, day, hour, minute, second; 0094 year = (p[0] - '0') * 1000 + (p[1] - '0') * 100 + (p[2] - '0') * 10 + p[3] - '0'; 0095 month = (p[4] - '0') * 10 + (p[5] - '0'); 0096 day = (p[6] - '0') * 10 + (p[7] - '0'); 0097 hour = (p[8] - '0') * 10 + (p[9] - '0'); 0098 minute = (p[10] - '0') * 10 + (p[11] - '0'); 0099 second = (p[12] - '0') * 10 + (p[13] - '0'); 0100 return getisotime(year, month, day, hour, minute, second, hs == 0 ? p[16] : 0); 0101 } 0102 0103 void FreeBootTable(boot_head *boot) 0104 { 0105 boot_entry *be, *next; 0106 0107 be = boot->defentry; 0108 while (be) { 0109 next = be->next; 0110 free(be); 0111 be = next; 0112 } 0113 boot->defentry = NULL; 0114 } 0115 0116 long long BootImageSize(int media, unsigned int len) 0117 { 0118 long long ret; 0119 0120 switch (media & 0xf) { 0121 case 0: 0122 ret = len; /* No emulation */ 0123 break; 0124 case 1: 0125 ret = 80 * 2 * 15; /* 1.2 MB */ 0126 break; 0127 case 2: 0128 ret = 80 * 2 * 18; /* 1.44 MB */ 0129 break; 0130 case 3: 0131 ret = 80 * 2 * 36; /* 2.88 MB */ 0132 break; 0133 case 4: 0134 /* FIXME!!! */ 0135 ret = len; /* Hard Disk */ 0136 break; 0137 default: 0138 ret = len; 0139 } 0140 return ret; 0141 } 0142 0143 static boot_entry *CreateBootEntry(char *be) 0144 { 0145 boot_entry *entry; 0146 0147 entry = (boot_entry*) malloc(sizeof(boot_entry)); 0148 if (!entry) return NULL; 0149 memset(entry, 0, sizeof(boot_entry)); 0150 memcpy(&(entry->data), be, sizeof(entry->data)); 0151 return entry; 0152 } 0153 0154 int ReadBootTable(readfunc *read, unsigned int sector, boot_head *head, void *udata) 0155 { 0156 0157 char buf[2048], *c, *be; 0158 int i, end = 0; 0159 unsigned short sum; 0160 boot_entry *defcur = NULL, *deflast = NULL; 0161 register struct validation_entry *ventry = NULL; 0162 0163 head->sections = NULL; 0164 head->defentry = NULL; 0165 while (1) { 0166 be = (char*) & buf; 0167 if (read(be, sector, 1, udata) != 1) goto err; 0168 0169 /* first entry needs to be a validation entry */ 0170 if (!ventry) { 0171 ventry = (struct validation_entry *) be; 0172 if (isonum_711(ventry->type) != 1) goto err; 0173 sum = 0; 0174 c = (char*) ventry; 0175 for (i = 0;i < 16;i++) { 0176 sum += isonum_721(c); c += 2; 0177 } 0178 if (sum) goto err; 0179 memcpy(&head->ventry, be, 0x20); 0180 be += 0x20; 0181 } 0182 0183 while (!end && (be < (char *)(&buf + 1))) { 0184 switch (isonum_711(be)) { 0185 case 0x88: 0186 defcur = CreateBootEntry(be); 0187 if (!defcur) goto err; 0188 if (deflast) 0189 deflast->next = defcur; 0190 else 0191 head->defentry = defcur; 0192 defcur->prev = deflast; 0193 deflast = defcur; 0194 break; 0195 case 0x90: 0196 case 0x91: 0197 break; 0198 default: 0199 end = 1; 0200 break; 0201 } 0202 be += 0x20; 0203 } 0204 if (end) break; 0205 0206 sector ++; 0207 } 0208 0209 return 0; 0210 0211 err: 0212 FreeBootTable(head); 0213 return -1; 0214 } 0215 0216 0217 /** 0218 * Creates the linked list of the volume descriptors 0219 */ 0220 iso_vol_desc *ReadISO9660(readfunc *read, unsigned int sector, void *udata) 0221 { 0222 0223 int i; 0224 struct iso_volume_descriptor buf; 0225 iso_vol_desc *first = NULL, *current = NULL, *prev = NULL; 0226 0227 for (i = 0;i < 100;i++) { 0228 if (read((char*) &buf, sector + i + 16, 1, udata) != 1) { 0229 FreeISO9660(first); 0230 return NULL; 0231 } 0232 if (!memcmp(ISO_STANDARD_ID, &buf.id, 5)) { 0233 switch (isonum_711(&buf.type[0])) { 0234 0235 case ISO_VD_BOOT: 0236 case ISO_VD_PRIMARY: 0237 case ISO_VD_SUPPLEMENTARY: 0238 current = (iso_vol_desc*) malloc(sizeof(iso_vol_desc)); 0239 if (!current) { 0240 FreeISO9660(first); 0241 return NULL; 0242 } 0243 current->prev = prev; 0244 current->next = NULL; 0245 if (prev) prev->next = current; 0246 memcpy(&(current->data), &buf, 2048); 0247 if (!first) first = current; 0248 prev = current; 0249 break; 0250 0251 case ISO_VD_END: 0252 return first; 0253 break; 0254 } 0255 } else if (!memcmp(HS_STANDARD_ID, (struct hs_volume_descriptor*) &buf, 5)) { 0256 /* High Sierra format not supported (yet) */ 0257 } 0258 } 0259 0260 return first; 0261 } 0262 0263 /** 0264 * Frees the linked list of volume descriptors 0265 */ 0266 void FreeISO9660(iso_vol_desc *data) 0267 { 0268 0269 iso_vol_desc *current; 0270 0271 0272 while (data) { 0273 current = data; 0274 data = current->next; 0275 free(current); 0276 } 0277 } 0278 0279 /** 0280 * Frees the strings in 'rrentry' 0281 */ 0282 void FreeRR(rr_entry *rrentry) 0283 { 0284 if (rrentry->name) { 0285 free(rrentry->name); 0286 rrentry->name = NULL; 0287 } 0288 if (rrentry->sl) { 0289 free(rrentry->sl); 0290 rrentry->sl = NULL; 0291 } 0292 } 0293 0294 static int str_nappend(char **d, char *s, int n) 0295 { 0296 int i = 0; 0297 char *c; 0298 0299 /* i=strnlen(s,n)+1; */ 0300 while (i < n && s[i]) i++; 0301 i++; 0302 if (*d) i += (strlen(*d) + 1); 0303 c = (char*) malloc(i); 0304 if (!c) return -ENOMEM; 0305 if (*d) { 0306 strcpy(c, *d); 0307 strncat(c, s, n); 0308 0309 free(*d); 0310 } else 0311 strncpy(c, s, n); 0312 c[i-1] = 0; 0313 *d = c; 0314 return 0; 0315 } 0316 0317 static int str_append(char **d, char *s) 0318 { 0319 int i; 0320 char *c; 0321 0322 i = strlen(s) + 1; 0323 if (*d) i += (strlen(*d) + 1); 0324 c = (char*) malloc(i); 0325 if (!c) return -ENOMEM; 0326 if (*d) { 0327 strcpy(c, *d); 0328 strcat(c, s); 0329 free(*d); 0330 } else 0331 strcpy(c, s); 0332 c[i-1] = 0; 0333 *d = c; 0334 return 0; 0335 } 0336 0337 #define rrtlen(c) (((unsigned char) c & 0x80) ? 17 : 7) 0338 #define rrctime(f,c) ((unsigned char) f & 0x80) ? isodate_84261(c,0) : isodate_915(c,0) 0339 /** 0340 * Parses the System Use area and fills rr_entry with values 0341 */ 0342 int ParseRR(struct iso_directory_record *idr, rr_entry *rrentry) 0343 { 0344 0345 int suspoffs, susplen, i, f, ret = 0; 0346 char *r, *c; 0347 struct rock_ridge *rr; 0348 0349 suspoffs = 33 + isonum_711(idr->name_len); 0350 if (!(isonum_711(idr->name_len) & 1)) suspoffs++; 0351 susplen = isonum_711(idr->length) - suspoffs; 0352 r = & (((char*) idr)[suspoffs]); 0353 rr = (struct rock_ridge*) r; 0354 0355 memset(rrentry, 0, sizeof(rr_entry)); 0356 rrentry->len = sizeof(rr_entry); 0357 0358 while (susplen > 0) { 0359 if (isonum_711(&rr->len) > susplen || rr->len == 0) break; 0360 if (rr->signature[0] == 'N' && rr->signature[1] == 'M') { 0361 if (!(rr->u.NM.flags & 0x26) && rr->len > 5 && !rrentry->name) { 0362 0363 if (str_nappend(&rrentry->name, rr->u.NM.name, isonum_711(&rr->len) - 5)) { 0364 FreeRR(rrentry); return -ENOMEM; 0365 } 0366 ret++; 0367 } 0368 } else if (rr->signature[0] == 'P' && rr->signature[1] == 'X' && 0369 (isonum_711(&rr->len) == 44 || isonum_711(&rr->len) == 36)) { 0370 rrentry->mode = isonum_733(rr->u.PX.mode); 0371 rrentry->nlink = isonum_733(rr->u.PX.n_links); 0372 rrentry->uid = isonum_733(rr->u.PX.uid); 0373 rrentry->gid = isonum_733(rr->u.PX.gid); 0374 if (isonum_711(&rr->len) == 44) rrentry->serno = isonum_733(rr->u.PX.serno); 0375 ret++; 0376 } else if (rr->signature[0] == 'P' && rr->signature[1] == 'N' && 0377 isonum_711(&rr->len) == 20) { 0378 rrentry->dev_major = isonum_733(rr->u.PN.dev_high); 0379 rrentry->dev_minor = isonum_733(rr->u.PN.dev_low); 0380 ret++; 0381 } else if (rr->signature[0] == 'P' && rr->signature[1] == 'L' && 0382 isonum_711(&rr->len) == 12) { 0383 rrentry->pl = isonum_733(rr->u.PL.location); 0384 ret++; 0385 } else if (rr->signature[0] == 'C' && rr->signature[1] == 'L' && 0386 isonum_711(&rr->len) == 12) { 0387 rrentry->cl = isonum_733(rr->u.CL.location); 0388 ret++; 0389 } else if (rr->signature[0] == 'R' && rr->signature[1] == 'E' && 0390 isonum_711(&rr->len) == 4) { 0391 rrentry->re = 1; 0392 ret++; 0393 } else if (rr->signature[0] == 'S' && rr->signature[1] == 'L' && 0394 isonum_711(&rr->len) > 7) { 0395 i = isonum_711(&rr->len) - 5; 0396 c = (char*) rr; 0397 c += 5; 0398 while (i > 0) { 0399 switch (c[0] & ~1) { 0400 case 0x2: 0401 if (str_append(&rrentry->sl, (char *)".")) { 0402 FreeRR(rrentry); return -ENOMEM; 0403 } 0404 break; 0405 case 0x4: 0406 if (str_append(&rrentry->sl, (char *)"..")) { 0407 FreeRR(rrentry); return -ENOMEM; 0408 } 0409 break; 0410 } 0411 if ((c[0] & 0x08) == 0x08 || (c[1] && rrentry->sl && 0412 strlen(rrentry->sl) > 1)) { 0413 if (str_append(&rrentry->sl, (char *) DIR_SEPARATOR)) { 0414 FreeRR(rrentry); return -ENOMEM; 0415 } 0416 } 0417 0418 if ((unsigned char)c[1] > 0) { 0419 if (str_nappend(&rrentry->sl, c + 2, (unsigned char)c[1])) { 0420 FreeRR(rrentry); return -ENOMEM; 0421 } 0422 } 0423 i -= ((unsigned char)c[1] + 2); 0424 c += ((unsigned char)c[1] + 2); 0425 } 0426 ret++; 0427 } else if (rr->signature[0] == 'T' && rr->signature[1] == 'F' && 0428 isonum_711(&rr->len) > 5) { 0429 0430 i = isonum_711(&rr->len) - 5; 0431 f = rr->u.TF.flags; 0432 c = (char*) rr; 0433 c += 5; 0434 0435 while (i >= rrtlen(f)) { 0436 if (f & 1) { 0437 rrentry->t_creat = rrctime(f, c); 0438 f &= ~1; 0439 } else if (f & 2) { 0440 rrentry->t_mtime = rrctime(f, c); 0441 f &= ~2; 0442 } else if (f & 4) { 0443 rrentry->t_atime = rrctime(f, c); 0444 f &= ~4; 0445 } else if (f & 8) { 0446 rrentry->t_ctime = rrctime(f, c); 0447 f &= ~8; 0448 } else if (f & 16) { 0449 rrentry->t_backup = rrctime(f, c); 0450 f &= ~16; 0451 } else if (f & 32) { 0452 rrentry->t_expire = rrctime(f, c); 0453 f &= ~32; 0454 } else if (f & 64) { 0455 rrentry->t_effect = rrctime(f, c); 0456 f &= ~64; 0457 } 0458 0459 i -= rrtlen(f); 0460 c += rrtlen(f); 0461 } 0462 ret++; 0463 0464 } else if (rr->signature[0] == 'Z' && rr->signature[1] == 'F' && 0465 isonum_711(&rr->len) == 16) { 0466 /* Linux-specific extension: transparent decompression */ 0467 rrentry->z_algo[0] = rr->u.ZF.algorithm[0]; 0468 rrentry->z_algo[1] = rr->u.ZF.algorithm[1]; 0469 rrentry->z_params[0] = rr->u.ZF.parms[0]; 0470 rrentry->z_params[1] = rr->u.ZF.parms[1]; 0471 rrentry->z_size = isonum_733(rr->u.ZF.real_size); 0472 ret++; 0473 } else { 0474 /* printf("SUSP sign: %c%c\n",rr->signature[0],rr->signature[1]); */ 0475 } 0476 0477 susplen -= isonum_711(&rr->len); 0478 r += isonum_711(&rr->len); 0479 rr = (struct rock_ridge*) r; 0480 } 0481 0482 return ret; 0483 } 0484 0485 /** 0486 * Iterates over the directory entries. The directory is in 'buf', 0487 * the size of the directory is 'size'. 'callback' is called for each 0488 * directory entry with the parameter 'udata'. 0489 */ 0490 int ProcessDir(readfunc *read, int extent, int size, dircallback *callback, void *udata) 0491 { 0492 0493 int pos = 0, ret = 0, siz; 0494 char *buf; 0495 struct iso_directory_record *idr; 0496 0497 if (size & 2047) { 0498 siz = ((size >> 11) + 1) << 11; 0499 } else { 0500 siz = size; 0501 } 0502 0503 buf = (char*) malloc(siz); 0504 if (!buf) return -ENOMEM; 0505 if (read(buf, extent, siz >> 11, udata) != siz >> 11) { 0506 free(buf); 0507 return -EIO; 0508 } 0509 0510 while (size > 0) { 0511 idr = (struct iso_directory_record*) & buf[pos]; 0512 if (isonum_711(idr->length) == 0) { 0513 0514 size -= (2048 - (pos & 0x7ff)); 0515 if (size <= 2) break; 0516 pos += 0x800; 0517 pos &= 0xfffff800; 0518 idr = (struct iso_directory_record*) & buf[pos]; 0519 } 0520 pos += isonum_711(idr->length); 0521 pos += isonum_711(idr->ext_attr_length); 0522 size -= isonum_711(idr->length); 0523 size -= isonum_711(idr->ext_attr_length); 0524 if (size < 0) break; 0525 0526 if (isonum_711(idr->length) 0527 < 33 || 0528 isonum_711(idr->length) < 33 + isonum_711(idr->name_len)) { 0529 /* Invalid directory entry */ 0530 continue; 0531 } 0532 if ((ret = callback(idr, udata))) break; 0533 } 0534 0535 free(buf); 0536 return ret; 0537 } 0538 0539 /** 0540 * returns the joliet level from the volume descriptor 0541 */ 0542 int JolietLevel(struct iso_volume_descriptor *ivd) 0543 { 0544 int ret = 0; 0545 register struct iso_supplementary_descriptor *isd; 0546 0547 isd = (struct iso_supplementary_descriptor *) ivd; 0548 0549 if (isonum_711(ivd->type) == ISO_VD_SUPPLEMENTARY) { 0550 if (isd->escape[0] == 0x25 && 0551 isd->escape[1] == 0x2f) { 0552 0553 switch (isd->escape[2]) { 0554 case 0x40: 0555 ret = 1; 0556 break; 0557 case 0x43: 0558 ret = 2; 0559 break; 0560 case 0x45: 0561 ret = 3; 0562 break; 0563 } 0564 } 0565 } 0566 return ret; 0567 } 0568 0569 /********************************************************************/ 0570 #ifdef ISOFS_MAIN 0571 0572 #include <time.h> 0573 #include <fcntl.h> 0574 #include <stdio.h> 0575 #include <unistd.h> 0576 #include <sys/types.h> 0577 #include <sys/stat.h> 0578 #include <iconv.h> 0579 0580 int level = 0, joliet = 0, dirs, files; 0581 iconv_t iconv_d; 0582 int fd; 0583 0584 int readf(char *buf, unsigned int start, unsigned int len, void *udata) 0585 { 0586 int ret; 0587 0588 if ((ret = lseek64(fd, (long long)start << (long long)11, SEEK_SET)) < 0) return ret; 0589 ret = read(fd, buf, len << 11u); 0590 if (ret < 0) return ret; 0591 return (ret >> 11u); 0592 } 0593 0594 void dumpchars(char *c, int len) 0595 { 0596 while (len > 0) { 0597 printf("%c", *c); 0598 len--; 0599 c++; 0600 } 0601 } 0602 0603 void sp(int num) 0604 { 0605 int i; 0606 for (i = 0;i < num*5;i++) { 0607 printf(" "); 0608 }; 0609 } 0610 0611 void dumpflags(char flags) 0612 { 0613 if (flags & 1) printf("HIDDEN "); 0614 if (flags & 2) printf("DIR "); 0615 if (flags & 4) printf("ASF "); 0616 } 0617 0618 void dumpjoliet(char *c, int len) 0619 { 0620 0621 char outbuf[255]; 0622 size_t out; 0623 int ret; 0624 char *outptr; 0625 0626 outptr = (char*) & outbuf; 0627 out = 255; 0628 if ((iconv(iconv_d, &c, &len, &outptr, &out)) < 0) { 0629 printf("conversion error=%d", errno); 0630 return; 0631 } 0632 ret = 255 - out; 0633 dumpchars((char*) &outbuf, ret); 0634 } 0635 0636 void dumpchardesc(char *c, int len) 0637 { 0638 0639 if (joliet) 0640 dumpjoliet(c, len); 0641 else { 0642 dumpchars(c, len); 0643 } 0644 } 0645 0646 void dumpiso915time(char *t, int hs) 0647 { 0648 0649 time_t time; 0650 char *c; 0651 0652 time = isodate_915(t, hs); 0653 c = (char*) ctime(&time); 0654 if (c && c[strlen(c)-1] == 0x0a) c[strlen(c)-1] = 0; 0655 if (c) printf("%s", c); 0656 } 0657 0658 void dumpiso84261time(char *t, int hs) 0659 { 0660 0661 time_t time; 0662 char *c; 0663 0664 time = isodate_84261(t, hs); 0665 c = (char*) ctime(&time); 0666 if (c && c[strlen(c)-1] == 0x0a) c[strlen(c)-1] = 0; 0667 if (c) printf("%s", c); 0668 } 0669 0670 void dumpdirrec(struct iso_directory_record *dir) 0671 { 0672 0673 if (isonum_711(dir->name_len) == 1) { 0674 switch (dir->name[0]) { 0675 case 0: 0676 printf("."); 0677 break; 0678 case 1: 0679 printf(".."); 0680 break; 0681 default: 0682 printf("%c", dir->name[0]); 0683 break; 0684 } 0685 } 0686 dumpchardesc(dir->name, isonum_711(dir->name_len)); 0687 printf(" size=%d", isonum_733(dir->size)); 0688 printf(" extent=%d ", isonum_733(dir->extent)); 0689 dumpflags(isonum_711(dir->flags)); 0690 dumpiso915time((char*) &(dir->date), 0); 0691 } 0692 0693 void dumprrentry(rr_entry *rr) 0694 { 0695 printf(" NM=[%s] uid=%d gid=%d nlink=%d mode=%o ", 0696 rr->name, rr->uid, rr->gid, rr->nlink, rr->mode); 0697 if (S_ISCHR(rr->mode) || S_ISBLK(rr->mode)) 0698 printf("major=%d minor=%d ", rr->dev_major, rr->dev_minor); 0699 if (rr->mode & S_IFLNK && rr->sl) printf("slink=%s ", rr->sl); 0700 /* 0701 printf("\n"); 0702 if (rr->t_creat) printf("t_creat: %s",ctime(&rr->t_creat)); 0703 if (rr->st_mtime) printf("st_mtime: %s",ctime(&rr->st_mtime)); 0704 if (rr->st_atime) printf("st_atime: %s",ctime(&rr->st_atime)); 0705 if (rr->st_ctime) printf("st_ctime: %s",ctime(&rr->st_ctime)); 0706 if (rr->t_backup) printf("t_backup: %s",ctime(&rr->t_backup)); 0707 if (rr->t_expire) printf("t_expire: %s",ctime(&rr->t_expire)); 0708 if (rr->t_effect) printf("t_effect: %s",ctime(&rr->t_effect)); 0709 */ 0710 } 0711 0712 void dumpsusp(char *c, int len) 0713 { 0714 dumpchars(c, len); 0715 } 0716 0717 void dumpboot(struct el_torito_boot_descriptor *ebd) 0718 { 0719 printf("version: %d\n", isonum_711(ebd->version)); 0720 printf("system id: ");dumpchars(ebd->system_id, ISODCL(8, 39));printf("\n"); 0721 printf("boot catalog start: %d\n", isonum_731(ebd->boot_catalog)); 0722 } 0723 0724 void dumpdefentry(struct default_entry *de) 0725 { 0726 printf("Default entry: \n"); 0727 printf(" bootid=%x\n", isonum_711(de->bootid)); 0728 printf(" media emulation=%d (", isonum_711(de->media)); 0729 switch (isonum_711(de->media) & 0xf) { 0730 case 0: 0731 printf("No emulation"); 0732 break; 0733 case 1: 0734 printf("1.2 Mb floppy"); 0735 break; 0736 case 2: 0737 printf("1.44 Mb floppy"); 0738 break; 0739 case 3: 0740 printf("2.88 Mb floppy"); 0741 break; 0742 case 4: 0743 printf("Hard Disk"); 0744 break; 0745 default: 0746 printf("Unknown/Invalid"); 0747 break; 0748 } 0749 printf(")\n"); 0750 printf(" loadseg=%d\n", isonum_721(de->loadseg)); 0751 printf(" systype=%d\n", isonum_711(de->systype)); 0752 printf(" start lba=%d count=%d\n", isonum_731(de->start), 0753 isonum_721(de->seccount)); 0754 } 0755 0756 void dumpbootcat(boot_head *bh) 0757 { 0758 boot_entry *be; 0759 0760 printf("System id: ");dumpchars(bh->ventry.id, ISODCL(28, 5));printf("\n"); 0761 be = bh->defentry; 0762 while (be) { 0763 dumpdefentry(be->data); 0764 be = be->next; 0765 } 0766 } 0767 0768 void dumpdesc(struct iso_primary_descriptor *ipd) 0769 { 0770 0771 printf("system id: ");dumpchardesc(ipd->system_id, ISODCL(9, 40));printf("\n"); 0772 printf("volume id: ");dumpchardesc(ipd->volume_id, ISODCL(41, 72));printf("\n"); 0773 printf("volume space size: %d\n", isonum_733(ipd->volume_space_size)); 0774 printf("volume set size: %d\n", isonum_723(ipd->volume_set_size)); 0775 printf("volume seq num: %d\n", isonum_723(ipd->volume_set_size)); 0776 printf("logical block size: %d\n", isonum_723(ipd->logical_block_size)); 0777 printf("path table size: %d\n", isonum_733(ipd->path_table_size)); 0778 printf("location of type_l path table: %d\n", isonum_731(ipd->type_l_path_table)); 0779 printf("location of optional type_l path table: %d\n", isonum_731(ipd->opt_type_l_path_table)); 0780 printf("location of type_m path table: %d\n", isonum_732(ipd->type_m_path_table)); 0781 printf("location of optional type_m path table: %d\n", isonum_732(ipd->opt_type_m_path_table)); 0782 /* 0783 printf("Root dir record:\n");dumpdirrec((struct iso_directory_record*) &ipd->root_directory_record); 0784 */ 0785 printf("Volume set id: ");dumpchardesc(ipd->volume_set_id, ISODCL(191, 318));printf("\n"); 0786 printf("Publisher id: ");dumpchardesc(ipd->publisher_id, ISODCL(319, 446));printf("\n"); 0787 printf("Preparer id: ");dumpchardesc(ipd->preparer_id, ISODCL(447, 574));printf("\n"); 0788 printf("Application id: ");dumpchardesc(ipd->application_id, ISODCL(575, 702));printf("\n"); 0789 printf("Copyright id: ");dumpchardesc(ipd->copyright_file_id, ISODCL(703, 739));printf("\n"); 0790 printf("Abstract file id: ");dumpchardesc(ipd->abstract_file_id, ISODCL(740, 776));printf("\n"); 0791 printf("Bibliographic file id: ");dumpchardesc(ipd->bibliographic_file_id, ISODCL(777, 813));printf("\n"); 0792 printf("Volume creation date: ");dumpiso84261time(ipd->creation_date, 0);printf("\n"); 0793 printf("Volume modification date: ");dumpiso84261time(ipd->modification_date, 0);printf("\n"); 0794 printf("Volume expiration date: ");dumpiso84261time(ipd->expiration_date, 0);printf("\n"); 0795 printf("Volume effective date: ");dumpiso84261time(ipd->effective_date, 0);printf("\n"); 0796 printf("File structure version: %d\n", isonum_711(ipd->file_structure_version)); 0797 } 0798 0799 int mycallb(struct iso_directory_record *idr, void *udata) 0800 { 0801 rr_entry rrentry; 0802 0803 sp(level);dumpdirrec(idr); 0804 if (level == 0) printf(" (Root directory) "); 0805 printf("\n"); 0806 0807 if (ParseRR(idr, &rrentry) > 0) { 0808 sp(level);printf(" ");dumprrentry(&rrentry);printf("\n"); 0809 } 0810 FreeRR(&rrentry); 0811 if (!(idr->flags[0] & 2)) files++; 0812 if ((idr->flags[0] & 2) && (level == 0 || isonum_711(idr->name_len) > 1)) { 0813 level++; 0814 dirs++; 0815 ProcessDir(&readf, isonum_733(idr->extent), isonum_733(idr->size), &mycallb, udata); 0816 level--; 0817 } 0818 return 0; 0819 } 0820 0821 /************************************************/ 0822 0823 int main(int argc, char *argv[]) 0824 { 0825 0826 int i = 1, sector = 0; 0827 iso_vol_desc *desc; 0828 boot_head boot; 0829 0830 if (argc < 2) { 0831 fprintf(stderr, "\nUsage: %s iso-file-name or device [starting sector]\n\n", argv[0]); 0832 return 0; 0833 } 0834 if (argc >= 3) { 0835 sector = atoi(argv[2]); 0836 printf("Using starting sector number %d\n", sector); 0837 } 0838 fd = open(argv[1], O_RDONLY); 0839 if (fd < 0) { 0840 fprintf(stderr, "open error\n"); 0841 return -1; 0842 } 0843 iconv_d = iconv_open("ISO8859-2", "UTF16BE"); 0844 if (iconv_d == 0) { 0845 fprintf(stderr, "iconv open error\n"); 0846 return -1; 0847 } 0848 0849 desc = ReadISO9660(&readf, sector, NULL); 0850 if (!desc) { 0851 printf("No volume descriptors\n"); 0852 return -1; 0853 } 0854 while (desc) { 0855 0856 printf("\n\n--------------- Volume descriptor (%d.) type %d: ---------------\n\n", 0857 i, isonum_711(desc->data.type)); 0858 switch (isonum_711(desc->data.type)) { 0859 case ISO_VD_BOOT: { 0860 0861 struct el_torito_boot_descriptor* bootdesc; 0862 bootdesc = &(desc->data); 0863 dumpboot(bootdesc); 0864 if (!memcmp(EL_TORITO_ID, bootdesc->system_id, ISODCL(8, 39))) { 0865 0866 if (ReadBootTable(&readf, isonum_731(bootdesc->boot_catalog), &boot, NULL)) { 0867 printf("Boot Catalog Error\n"); 0868 } else { 0869 dumpbootcat(&boot); 0870 FreeBootTable(&boot); 0871 } 0872 } 0873 } 0874 break; 0875 0876 case ISO_VD_PRIMARY: 0877 case ISO_VD_SUPPLEMENTARY: 0878 joliet = 0; 0879 joliet = JolietLevel(&desc->data); 0880 printf("Joliet level: %d\n", joliet); 0881 dumpdesc((struct iso_primary_descriptor*) &desc->data); 0882 printf("\n\n--------------- Directory structure: -------------------\n\n"); 0883 dirs = 0;files = 0; 0884 mycallb(&(((struct iso_primary_descriptor*) &desc->data)->root_directory_record), NULL); 0885 printf("\nnumber of directories: %d\n", dirs); 0886 printf("\nnumber of files: %d\n", files); 0887 break; 0888 0889 } 0890 desc = desc->next; 0891 i++; 0892 } 0893 iconv_close(iconv_d); 0894 close(fd); 0895 FreeISO9660(desc); 0896 return 0; 0897 } 0898 0899 #endif /* ISOFS_MAIN */