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