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