~ubuntu-branches/ubuntu/precise/krusader/precise

« back to all changes in this revision

Viewing changes to iso/libisofs/isofs.c

  • Committer: Bazaar Package Importer
  • Author(s): Scott Kitterman
  • Date: 2010-05-05 22:26:37 UTC
  • mfrom: (3.1.4 squeeze)
  • Revision ID: james.westby@ubuntu.com-20100505222637-ydv3cwjwy365on2r
Tags: 1:2.1.0~beta1-1ubuntu1
* Merge from Debian Unstable.  Remaining changes:
  - Retain Kubuntu doc path

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/***************************************************************************
2
 
                        isofs.c  -  libisofs
3
 
 implementation
4
 
                             -------------------
5
 
    begin                : Oct 25 2002
6
 
    copyright            : (C) 2002 by Szombathelyi Gy�gy
7
 
    email                : gyurco@users.sourceforge.net
8
 
 ***************************************************************************/
9
 
 
10
 
/***************************************************************************
11
 
 *                                                                         *
12
 
 *   This program is free software; you can redistribute it and/or modify  *
13
 
 *   it under the terms of the GNU General Public License as published by  *
14
 
 *   the Free Software Foundation; either version 2 of the License, or     *
15
 
 *   (at your option) any later version.                                   *
16
 
 *                                                                         *
17
 
 ***************************************************************************/
18
 
 
19
 
#include <errno.h>
20
 
#include <stdlib.h>
21
 
#include <string.h>
22
 
 
23
 
#include "isofs.h"
24
 
#include "iso_fs.h"
25
 
 
26
 
/**************************************************************/
27
 
 
28
 
 
29
 
/* internal function from the linux kernel (isofs fs) */
30
 
static time_t getisotime(int year,int month,int day,int hour,
31
 
                                                 int minute,int second,int tz) {
32
 
 
33
 
        int days, i;
34
 
        time_t crtime;
35
 
 
36
 
        year-=1970;
37
 
        
38
 
        if (year < 0) {
39
 
                crtime = 0;
40
 
        } else {
41
 
                int monlen[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
42
 
 
43
 
                days = year * 365;
44
 
                if (year > 2)
45
 
                        days += (year+1) / 4;
46
 
                for (i = 1; i < month; i++)
47
 
                        days += monlen[i-1];
48
 
                if (((year+2) % 4) == 0 && month > 2)
49
 
                        days++;
50
 
                days += day - 1;
51
 
                crtime = ((((days * 24) + hour) * 60 + minute) * 60)
52
 
                        + second;
53
 
 
54
 
                /* sign extend */
55
 
                if (tz & 0x80)
56
 
                        tz |= (-1 << 8);
57
 
                        
58
 
                /* 
59
 
                 * The timezone offset is unreliable on some disks,
60
 
                 * so we make a sanity check.  In no case is it ever
61
 
                 * more than 13 hours from GMT, which is 52*15min.
62
 
                 * The time is always stored in localtime with the
63
 
                 * timezone offset being what get added to GMT to
64
 
                 * get to localtime.  Thus we need to subtract the offset
65
 
                 * to get to true GMT, which is what we store the time
66
 
                 * as internally.  On the local system, the user may set
67
 
                 * their timezone any way they wish, of course, so GMT
68
 
                 * gets converted back to localtime on the receiving
69
 
                 * system.
70
 
                 *
71
 
                 * NOTE: mkisofs in versions prior to mkisofs-1.10 had
72
 
                 * the sign wrong on the timezone offset.  This has now
73
 
                 * been corrected there too, but if you are getting screwy
74
 
                 * results this may be the explanation.  If enough people
75
 
                 * complain, a user configuration option could be added
76
 
                 * to add the timezone offset in with the wrong sign
77
 
                 * for 'compatibility' with older discs, but I cannot see how
78
 
                 * it will matter that much.
79
 
                 *
80
 
                 * Thanks to kuhlmav@elec.canterbury.ac.nz (Volker Kuhlmann)
81
 
                 * for pointing out the sign error.
82
 
                 */
83
 
                if (-52 <= tz && tz <= 52)
84
 
                        crtime -= tz * 15 * 60;
85
 
        }
86
 
        return crtime;
87
 
 
88
 
}
89
 
 
90
 
/**
91
 
 * Returns the Unix from the ISO9660 9.1.5 time format
92
 
 */
93
 
time_t isodate_915(char * p, int hs) {
94
 
 
95
 
        return getisotime(1900+p[0],p[1],p[2],p[3],p[4],p[5],hs==0 ? p[6] : 0);
96
 
}               
97
 
 
98
 
/**
99
 
 * Returns the Unix from the ISO9660 8.4.26.1 time format
100
 
 * BUG: hundredth of seconds are ignored, because Unix time_t has one second
101
 
 * resolution (I think it's no problem at all)
102
 
 */
103
 
time_t isodate_84261(char * p, int hs) {
104
 
        int year,month,day,hour,minute,second;
105
 
        year=(p[0]-'0')*1000 + (p[1]-'0')*100 + (p[2]-'0')*10 + p[3]-'0';
106
 
        month=(p[4]-'0')*10 + (p[5]-'0');
107
 
        day=(p[6]-'0')*10 + (p[7]-'0');
108
 
        hour=(p[8]-'0')*10 + (p[9]-'0');
109
 
        minute=(p[10]-'0')*10 + (p[11]-'0');
110
 
        second=(p[12]-'0')*10 + (p[13]-'0');
111
 
        return getisotime(year,month,day,hour,minute,second,hs==0 ? p[16] : 0);
112
 
}
113
 
 
114
 
void FreeBootTable(boot_head *boot) {
115
 
        boot_entry *be,*next;
116
 
 
117
 
        be=boot->defentry;
118
 
        while (be) {
119
 
                next=be->next;
120
 
                free(be);
121
 
                be=next;        
122
 
        }
123
 
        boot->defentry=NULL;
124
 
}
125
 
 
126
 
long long BootImageSize(int media,unsigned int len) {
127
 
        long long ret;
128
 
 
129
 
        switch(media & 0xf) {
130
 
                case 0:
131
 
                        ret=len; /* No emulation */
132
 
                        break;
133
 
                case 1:
134
 
                        ret=80*2*15; /* 1.2 MB */
135
 
                        break;
136
 
                case 2:
137
 
                        ret=80*2*18; /* 1.44 MB */
138
 
                        break;
139
 
                case 3:
140
 
                        ret=80*2*36; /* 2.88 MB */
141
 
                        break;
142
 
                case 4:
143
 
                        /* FIXME!!! */
144
 
                        ret=len; /* Hard Disk */
145
 
                        break;
146
 
                default:
147
 
                        ret=len;
148
 
        }       
149
 
        return ret;
150
 
}
151
 
 
152
 
static boot_entry *CreateBootEntry(char *be) {
153
 
        boot_entry *entry;
154
 
        
155
 
        entry = (boot_entry*) malloc(sizeof(boot_entry));
156
 
        if (!entry) return NULL;
157
 
        memset(entry, 0, sizeof(boot_entry));
158
 
        memcpy(entry->data,be,0x20);
159
 
        return entry;
160
 
}
161
 
 
162
 
int ReadBootTable(readfunc *read,unsigned int sector, boot_head *head, void *udata) {
163
 
 
164
 
        char buf[2048], *c, *be;
165
 
        int i,end=0;
166
 
        unsigned short sum;
167
 
        boot_entry *defcur=NULL,*deflast=NULL;
168
 
        register struct validation_entry *ventry=NULL;
169
 
        
170
 
        head->sections=NULL;
171
 
        head->defentry=NULL;
172
 
        while (1) {
173
 
                be = (char*) &buf;
174
 
                if ( read(be, sector, 1, udata) != 1 ) goto err;
175
 
 
176
 
                /* first entry needs to be a validation entry */
177
 
                if (!ventry) {
178
 
                        ventry=(struct validation_entry *) be;
179
 
                        if ( isonum_711(ventry->type) !=1 ) goto err;
180
 
                        sum=0;
181
 
                        c = (char*) ventry;
182
 
                        for (i=0;i<16;i++) { sum += isonum_721(c); c+=2; }
183
 
                        if (sum) goto err;
184
 
                        memcpy(&head->ventry,be,0x20);
185
 
                        be += 0x20;
186
 
                }
187
 
 
188
 
                while (!end && (be < (char *)(&buf+1))) {
189
 
                        switch (isonum_711(be)) {
190
 
                                case 0x88:
191
 
                                        defcur=CreateBootEntry(be);
192
 
                                        if (!defcur) goto err;
193
 
                                        if (deflast)
194
 
                                                deflast->next=defcur;
195
 
                                        else
196
 
                                                head->defentry=defcur;
197
 
                                        defcur->prev=deflast;
198
 
                                        deflast=defcur;
199
 
                                        break;  
200
 
                                case 0x90:
201
 
                                case 0x91:
202
 
                                        break;
203
 
                                default:
204
 
                                        end=1;
205
 
                                        break;
206
 
                        }
207
 
                        be += 0x20;
208
 
                }
209
 
                if (end) break;
210
 
 
211
 
                sector ++;              
212
 
        }
213
 
 
214
 
        return 0;
215
 
 
216
 
err:
217
 
        FreeBootTable(head);
218
 
        return -1;
219
 
}
220
 
 
221
 
 
222
 
/**
223
 
 * Creates the linked list of the volume descriptors
224
 
 */
225
 
iso_vol_desc *ReadISO9660(readfunc *read,unsigned int sector,void *udata) {
226
 
                                
227
 
        int i;
228
 
        struct iso_volume_descriptor buf;
229
 
        iso_vol_desc *first=NULL,*current=NULL,*prev=NULL;
230
 
 
231
 
        for (i=0;i<100;i++) {
232
 
                if (read( (char*) &buf, sector+i+16, 1, udata) != 1 ) {
233
 
                        FreeISO9660(first);
234
 
                        return NULL;
235
 
                }
236
 
                if (!memcmp(ISO_STANDARD_ID,&buf.id,5)) {
237
 
                        switch ( isonum_711(&buf.type[0]) ) {
238
 
 
239
 
                                case ISO_VD_BOOT:
240
 
                                case ISO_VD_PRIMARY:
241
 
                                case ISO_VD_SUPPLEMENTARY:
242
 
                                        current=(iso_vol_desc*) malloc(sizeof(iso_vol_desc));
243
 
                                        if (!current) {
244
 
                                                FreeISO9660(first);
245
 
                                                return NULL;
246
 
                                        }
247
 
                                        current->prev=prev;
248
 
                                        current->next=NULL;
249
 
                                        if (prev) prev->next=current;
250
 
                                        memcpy(&(current->data),&buf,2048);
251
 
                                        if (!first) first=current;
252
 
                                        prev=current;
253
 
                                        break;
254
 
 
255
 
                                case ISO_VD_END:
256
 
                                        return first;
257
 
                                        break;
258
 
                        }
259
 
                } else if (!memcmp(HS_STANDARD_ID,(struct hs_volume_descriptor*) &buf,5)) {
260
 
                        /* High Sierra format not supported (yet) */
261
 
                }
262
 
        }
263
 
        
264
 
        return first;
265
 
}
266
 
 
267
 
/**
268
 
 * Frees the linked list of volume descriptors
269
 
 */
270
 
void FreeISO9660(iso_vol_desc *data) {
271
 
 
272
 
        iso_vol_desc *current;
273
 
 
274
 
        
275
 
        while (data) {
276
 
                current=data;   
277
 
                data=current->next;
278
 
                free(current);
279
 
        }
280
 
}
281
 
 
282
 
/**
283
 
 * Frees the strings in 'rrentry'
284
 
 */
285
 
void FreeRR(rr_entry *rrentry) {
286
 
        if (rrentry->name) {
287
 
                free(rrentry->name);
288
 
                rrentry->name=NULL;
289
 
        }
290
 
        if (rrentry->sl) {
291
 
                free(rrentry->sl);
292
 
                rrentry->name=NULL;
293
 
        }
294
 
}
295
 
 
296
 
static int str_nappend(char **d,char *s,int n) {
297
 
        int i=0;
298
 
        char *c;
299
 
        
300
 
/*      i=strnlen(s,n)+1; */
301
 
        while (i<n && s[i]) i++;
302
 
        i++;
303
 
        if (*d) i+=(strlen(*d)+1);
304
 
        c=(char*) malloc(i);
305
 
        if (!c) return -ENOMEM;
306
 
        if (*d) {
307
 
                strcpy(c,*d);
308
 
                strncat(c,s,n);
309
 
 
310
 
                free(*d);
311
 
        } else
312
 
                strncpy(c,s,n);
313
 
        c[i-1]=0;
314
 
        *d=c;
315
 
        return 0;
316
 
}
317
 
 
318
 
static int str_append(char **d,char *s) {
319
 
        int i;
320
 
        char *c;
321
 
        
322
 
        i=strlen(s)+1;
323
 
        if (*d) i+=(strlen(*d)+1);
324
 
        c=(char*) malloc(i);
325
 
        if (!c) return -ENOMEM;
326
 
        if (*d) {
327
 
                strcpy(c,*d);
328
 
                strcat(c,s);
329
 
                free(*d);
330
 
        } else
331
 
                strcpy(c,s);
332
 
        c[i-1]=0;
333
 
        *d=c;
334
 
        return 0;
335
 
}
336
 
 
337
 
#define rrtlen(c) (((unsigned char) c & 0x80) ? 17 : 7)
338
 
#define rrctime(f,c) ((unsigned char) f & 0x80) ? isodate_84261(c,0) : isodate_915(c,0)
339
 
/**
340
 
 * Parses the System Use area and fills rr_entry with values
341
 
 */
342
 
int ParseRR(struct iso_directory_record *idr, rr_entry *rrentry) {
343
 
 
344
 
        int suspoffs,susplen,i,f,ret=0;
345
 
        char *r, *c;
346
 
        struct rock_ridge *rr;
347
 
 
348
 
        suspoffs=33+isonum_711(idr->name_len);
349
 
        if (!(isonum_711(idr->name_len) & 1)) suspoffs++;
350
 
        susplen=isonum_711(idr->length)-suspoffs;
351
 
        r= & (((char*) idr)[suspoffs]);
352
 
        rr = (struct rock_ridge*) r;
353
 
 
354
 
        memset(rrentry,0,sizeof(rr_entry));
355
 
        rrentry->len = sizeof(rr_entry);        
356
 
 
357
 
        while (susplen > 0) {
358
 
                if (isonum_711(&rr->len) > susplen || rr->len == 0) break;
359
 
                if (rr->signature[0]=='N' && rr->signature[1]=='M') {
360
 
                        if (!(rr->u.NM.flags & 0x26) && rr->len>5 && !rrentry->name) {
361
 
                                
362
 
                                if (str_nappend(&rrentry->name,rr->u.NM.name,isonum_711(&rr->len)-5)) {
363
 
                                        FreeRR(rrentry); return -ENOMEM;
364
 
                                }
365
 
                                ret++;
366
 
                        }
367
 
                } else if (rr->signature[0]=='P' && rr->signature[1]=='X' && 
368
 
                        (isonum_711(&rr->len)==44 || isonum_711(&rr->len)==36)) {
369
 
                                rrentry->mode=isonum_733(rr->u.PX.mode);
370
 
                                rrentry->nlink=isonum_733(rr->u.PX.n_links);
371
 
                                rrentry->uid=isonum_733(rr->u.PX.uid);
372
 
                                rrentry->gid=isonum_733(rr->u.PX.gid);
373
 
                                if (isonum_711(&rr->len)==44) rrentry->serno=isonum_733(rr->u.PX.serno);
374
 
                                ret++;
375
 
                } else if (rr->signature[0]=='P' && rr->signature[1]=='N' && 
376
 
                        isonum_711(&rr->len)==20) {
377
 
                                rrentry->dev_major=isonum_733(rr->u.PN.dev_high);
378
 
                                rrentry->dev_minor=isonum_733(rr->u.PN.dev_low);
379
 
                                ret++;
380
 
                } else if (rr->signature[0]=='P' && rr->signature[1]=='L' && 
381
 
                        isonum_711(&rr->len)==12) {
382
 
                                rrentry->pl=isonum_733(rr->u.PL.location);
383
 
                                ret++;
384
 
                } else if (rr->signature[0]=='C' && rr->signature[1]=='L' && 
385
 
                        isonum_711(&rr->len)==12) {
386
 
                                rrentry->cl=isonum_733(rr->u.CL.location);
387
 
                                ret++;
388
 
                } else if (rr->signature[0]=='R' && rr->signature[1]=='E' && 
389
 
                        isonum_711(&rr->len)==4) {
390
 
                                rrentry->re=1;
391
 
                                ret++;
392
 
                } else if (rr->signature[0]=='S' && rr->signature[1]=='L' &&
393
 
                        isonum_711(&rr->len)>7) {
394
 
                        i = isonum_711(&rr->len)-5;
395
 
                        c = (char*) rr;
396
 
                        c += 5;
397
 
                        while (i>0) {
398
 
                                switch(c[0] & ~1) {
399
 
                                        case 0x2:
400
 
                                                if (str_append(&rrentry->sl,(char *)".")) {
401
 
                                                        FreeRR(rrentry); return -ENOMEM;
402
 
                                                }
403
 
                                                break;
404
 
                                        case 0x4:
405
 
                                                if (str_append(&rrentry->sl,(char *)"..")) {
406
 
                                                        FreeRR(rrentry); return -ENOMEM;
407
 
                                                }
408
 
                                                break;
409
 
                                }
410
 
                                if ( (c[0] & 0x08) == 0x08 || (c[1] && rrentry->sl && 
411
 
                                         strlen(rrentry->sl)>1) ) {
412
 
                                        if (str_append(&rrentry->sl,(char *) DIR_SEPARATOR )) {
413
 
                                                FreeRR(rrentry); return -ENOMEM;
414
 
                                        }
415
 
                                }
416
 
 
417
 
                                if ((unsigned char)c[1]>0) {
418
 
                                        if (str_nappend(&rrentry->sl,c+2,(unsigned char)c[1])) {
419
 
                                                FreeRR(rrentry); return -ENOMEM;
420
 
                                        }
421
 
                                }
422
 
                                i -= ((unsigned char)c[1] + 2);
423
 
                                c += ((unsigned char)c[1] + 2);
424
 
                        }
425
 
                        ret++;
426
 
                } else if (rr->signature[0]=='T' && rr->signature[1]=='F' && 
427
 
                        isonum_711(&rr->len)>5) {
428
 
 
429
 
                        i = isonum_711(&rr->len)-5;
430
 
                        f = rr->u.TF.flags;
431
 
                        c = (char*) rr;
432
 
                        c += 5;
433
 
 
434
 
                        while (i >= rrtlen(f)) {
435
 
                                if (f & 1) {
436
 
                                        rrentry->t_creat=rrctime(f,c);
437
 
                                        f &= ~1;
438
 
                                } else if (f & 2) {
439
 
                                        rrentry->t_mtime=rrctime(f,c);
440
 
                                        f &= ~2;
441
 
                                } else if (f & 4) {
442
 
                                        rrentry->t_atime=rrctime(f,c);
443
 
                                        f &= ~4;
444
 
                                } else if (f & 8) {
445
 
                                        rrentry->t_ctime=rrctime(f,c);
446
 
                                        f &= ~8;
447
 
                                } else if (f & 16) {
448
 
                                        rrentry->t_backup=rrctime(f,c);
449
 
                                        f &= ~16;
450
 
                                } else if (f & 32) {
451
 
                                        rrentry->t_expire=rrctime(f,c);
452
 
                                        f &= ~32;
453
 
                                } else if (f & 64) {
454
 
                                        rrentry->t_effect=rrctime(f,c);
455
 
                                        f &= ~64;
456
 
                                }
457
 
 
458
 
                                i -= rrtlen(f);
459
 
                                c += rrtlen(f);
460
 
                        }
461
 
                        ret++;
462
 
 
463
 
                } else if (rr->signature[0]=='Z' && rr->signature[1]=='F' && 
464
 
                        isonum_711(&rr->len)==16) {
465
 
                                /* Linux-specific extension: transparent decompression */
466
 
                                rrentry->z_algo[0]=rr->u.ZF.algorithm[0];
467
 
                                rrentry->z_algo[1]=rr->u.ZF.algorithm[1];
468
 
                                rrentry->z_params[0]=rr->u.ZF.parms[0];
469
 
                                rrentry->z_params[1]=rr->u.ZF.parms[1];
470
 
                                rrentry->z_size=isonum_733(rr->u.ZF.real_size);
471
 
                                ret++;
472
 
                } else {
473
 
/*                      printf("SUSP sign: %c%c\n",rr->signature[0],rr->signature[1]); */
474
 
                }
475
 
                
476
 
                susplen -= isonum_711(&rr->len);
477
 
                r += isonum_711(&rr->len);
478
 
                rr = (struct rock_ridge*) r;
479
 
        }
480
 
 
481
 
        return ret;
482
 
}
483
 
 
484
 
/**
485
 
 * Iterates over the directory entries. The directory is in 'buf',
486
 
 * the size of the directory is 'size'. 'callback' is called for each
487
 
 * directory entry with the parameter 'udata'.
488
 
 */
489
 
int ProcessDir(readfunc *read,int extent,int size,dircallback *callback,void *udata) {
490
 
 
491
 
        int pos=0,ret=0,siz;
492
 
        char *buf;
493
 
        struct iso_directory_record *idr;
494
 
 
495
 
        if (size & 2047) {
496
 
                siz=((size>>11)+1)<<11;
497
 
        } else {
498
 
                siz=size;
499
 
        }
500
 
 
501
 
        buf=(char*) malloc(siz);
502
 
        if (!buf) return -ENOMEM;
503
 
        if (read(buf,extent,siz>>11,udata)!=siz>>11) {
504
 
                free(buf);
505
 
                return -EIO;
506
 
        }
507
 
 
508
 
        while (size>0) {
509
 
                idr=(struct iso_directory_record*) &buf[pos];
510
 
                if (isonum_711(idr->length)==0) {
511
 
 
512
 
                        size-=(2048 - (pos & 0x7ff));
513
 
                        if (size<=2) break;
514
 
                        pos+=0x800;
515
 
                        pos&=0xfffff800;
516
 
                        idr=(struct iso_directory_record*) &buf[pos];
517
 
                }
518
 
                pos+=isonum_711(idr->length);
519
 
                pos+=isonum_711(idr->ext_attr_length);
520
 
                size-=isonum_711(idr->length);
521
 
                size-=isonum_711(idr->ext_attr_length);
522
 
                if (size<0) break;
523
 
                
524
 
                if (isonum_711(idr->length)
525
 
<33 ||
526
 
                        isonum_711(idr->length)<33+isonum_711(idr->name_len)) {
527
 
                        /* Invalid directory entry */                   
528
 
                        continue;
529
 
                }
530
 
                if ((ret=callback(idr,udata))) break;
531
 
        }
532
 
 
533
 
        free(buf);
534
 
        return ret;     
535
 
}
536
 
 
537
 
/**
538
 
 * returns the joliet level from the volume descriptor
539
 
 */
540
 
int JolietLevel(struct iso_volume_descriptor *ivd) {
541
 
        int ret=0;
542
 
        register struct iso_supplementary_descriptor *isd;
543
 
        
544
 
        isd = (struct iso_supplementary_descriptor *) ivd;
545
 
        
546
 
        if (isonum_711(ivd->type)==ISO_VD_SUPPLEMENTARY) {
547
 
                if (isd->escape[0]==0x25 && 
548
 
                        isd->escape[1]==0x2f) {
549
 
 
550
 
                        switch (isd->escape[2]) {
551
 
                                case 0x40:
552
 
                                        ret=1;
553
 
                                        break;
554
 
                                case 0x43:
555
 
                                        ret=2;
556
 
                                        break;
557
 
                                case 0x45:
558
 
                                        ret=3;
559
 
                                        break;
560
 
                        }
561
 
                }
562
 
        }
563
 
        return ret;
564
 
}
565
 
 
566
 
/********************************************************************/
567
 
#ifdef ISOFS_MAIN
568
 
 
569
 
#include <time.h>
570
 
#include <fcntl.h>
571
 
#include <stdio.h>
572
 
#include <unistd.h>
573
 
#include <sys/types.h>
574
 
#include <sys/stat.h>
575
 
#include <iconv.h>
576
 
 
577
 
int level=0,joliet=0,dirs,files;
578
 
iconv_t iconv_d;
579
 
int fd;
580
 
 
581
 
int readf(char *buf, unsigned int start, unsigned int len,void *udata) {
582
 
        int ret;
583
 
        
584
 
        if ((ret=lseek64(fd, (long long)start << (long long)11, SEEK_SET))<0) return ret;
585
 
        ret=read(fd, buf, len << 11u);
586
 
        if (ret<0) return ret;
587
 
        return (ret >> 11u);
588
 
}
589
 
 
590
 
void dumpchars(char *c,int len) {
591
 
        while (len>0) {
592
 
                printf("%c",*c);
593
 
                len--;
594
 
                c++;
595
 
        }       
596
 
}
597
 
 
598
 
void sp(int num) {
599
 
        int i;
600
 
        for (i=0;i<num*5;i++) { printf(" "); };
601
 
}
602
 
 
603
 
void dumpflags(char flags) {
604
 
        if (flags & 1) printf("HIDDEN ");
605
 
        if (flags & 2) printf("DIR ");
606
 
        if (flags & 4) printf("ASF ");
607
 
}
608
 
 
609
 
void dumpjoliet(char *c,int len) {
610
 
 
611
 
        char outbuf[255];
612
 
        size_t out;
613
 
        int ret;
614
 
        char *outptr;
615
 
        
616
 
        outptr=(char*) &outbuf;
617
 
        out=255;
618
 
        if ((iconv(iconv_d,&c,&len,&outptr,&out))<0) {
619
 
                printf("conversion error=%d",errno);
620
 
                return;
621
 
        }
622
 
        ret=255-out;
623
 
        dumpchars((char*) &outbuf,ret);
624
 
}
625
 
 
626
 
void dumpchardesc(char *c,int len) {
627
 
 
628
 
        if (joliet) 
629
 
                dumpjoliet(c,len);
630
 
        else {
631
 
                dumpchars(c,len);
632
 
        }
633
 
}
634
 
 
635
 
void dumpiso915time(char *t, int hs) {
636
 
        
637
 
        time_t time;
638
 
        char *c;
639
 
        
640
 
        time=isodate_915(t,hs);
641
 
        c=(char*) ctime(&time);
642
 
        if (c && c[strlen(c)-1]==0x0a) c[strlen(c)-1]=0;
643
 
        if (c) printf("%s",c);
644
 
}
645
 
 
646
 
void dumpiso84261time(char *t, int hs) {
647
 
        
648
 
        time_t time;
649
 
        char *c;
650
 
        
651
 
        time=isodate_84261(t,hs);
652
 
        c=(char*) ctime(&time);
653
 
        if (c && c[strlen(c)-1]==0x0a) c[strlen(c)-1]=0;
654
 
        if (c) printf("%s",c);
655
 
}
656
 
 
657
 
void dumpdirrec(struct iso_directory_record *dir) {
658
 
        
659
 
        if (isonum_711(dir->name_len)==1) {
660
 
                switch (dir->name[0]) {
661
 
                case 0:
662
 
                        printf(".");
663
 
                        break;
664
 
                case 1:
665
 
                        printf("..");
666
 
                        break;
667
 
                default:
668
 
                        printf("%c",dir->name[0]);      
669
 
                        break;
670
 
                }
671
 
        }
672
 
        dumpchardesc(dir->name,isonum_711(dir->name_len));
673
 
        printf(" size=%d",isonum_733(dir->size));
674
 
        printf(" extent=%d ",isonum_733(dir->extent));
675
 
        dumpflags(isonum_711(dir->flags));
676
 
        dumpiso915time((char*) &(dir->date),0);
677
 
}
678
 
 
679
 
void dumprrentry(rr_entry *rr) {
680
 
        printf("  NM=[%s] uid=%d gid=%d nlink=%d mode=%o ",
681
 
                rr->name,rr->uid,rr->gid,rr->nlink,rr->mode);
682
 
        if (S_ISCHR(rr->mode) || S_ISBLK(rr->mode))
683
 
                printf("major=%d minor=%d ",rr->dev_major,rr->dev_minor);
684
 
        if (rr->mode & S_IFLNK && rr->sl) printf("slink=%s ",rr->sl);
685
 
/*
686
 
        printf("\n");
687
 
        if (rr->t_creat) printf("t_creat: %s",ctime(&rr->t_creat));
688
 
        if (rr->st_mtime) printf("st_mtime: %s",ctime(&rr->st_mtime));
689
 
        if (rr->st_atime) printf("st_atime: %s",ctime(&rr->st_atime));
690
 
        if (rr->st_ctime) printf("st_ctime: %s",ctime(&rr->st_ctime));
691
 
        if (rr->t_backup) printf("t_backup: %s",ctime(&rr->t_backup));
692
 
        if (rr->t_expire) printf("t_expire: %s",ctime(&rr->t_expire));
693
 
        if (rr->t_effect) printf("t_effect: %s",ctime(&rr->t_effect));
694
 
*/
695
 
}
696
 
 
697
 
void dumpsusp(char *c, int len) {
698
 
        dumpchars(c,len);
699
 
}
700
 
 
701
 
void dumpboot(struct el_torito_boot_descriptor *ebd) {
702
 
        printf("version: %d\n",isonum_711(ebd->version));
703
 
        printf("system id: ");dumpchars(ebd->system_id,ISODCL(8,39));printf("\n");
704
 
        printf("boot catalog start: %d\n",isonum_731(ebd->boot_catalog));
705
 
}
706
 
 
707
 
void dumpdefentry(struct default_entry *de) {
708
 
        printf("Default entry: \n");
709
 
        printf("  bootid=%x\n",isonum_711(de->bootid));
710
 
        printf("  media emulation=%d (",isonum_711(de->media));
711
 
        switch(isonum_711(de->media) & 0xf) {
712
 
                case 0:
713
 
                        printf("No emulation");
714
 
                        break;
715
 
                case 1:
716
 
                        printf("1.2 Mb floppy");
717
 
                        break;
718
 
                case 2:
719
 
                        printf("1.44 Mb floppy");
720
 
                        break;
721
 
                case 3:
722
 
                        printf("2.88 Mb floppy");
723
 
                        break;
724
 
                case 4:
725
 
                        printf("Hard Disk");
726
 
                        break;
727
 
                default:
728
 
                        printf("Unknown/Invalid");
729
 
                        break;
730
 
        }       
731
 
        printf(")\n");
732
 
        printf("  loadseg=%d\n",isonum_721(de->loadseg));
733
 
        printf("  systype=%d\n",isonum_711(de->systype));
734
 
        printf("  start lba=%d count=%d\n",isonum_731(de->start),
735
 
                isonum_721(de->seccount));
736
 
}
737
 
 
738
 
void dumpbootcat(boot_head *bh) {
739
 
        boot_entry *be;
740
 
 
741
 
        printf("System id: ");dumpchars(bh->ventry.id,ISODCL(28,5));printf("\n");
742
 
        be=bh->defentry;
743
 
        while (be) {
744
 
                dumpdefentry(be->data);
745
 
                be=be->next;
746
 
        }
747
 
}
748
 
 
749
 
void dumpdesc(struct iso_primary_descriptor *ipd) {
750
 
 
751
 
        printf("system id: ");dumpchardesc(ipd->system_id,ISODCL(9,40));printf("\n");
752
 
        printf("volume id: ");dumpchardesc(ipd->volume_id,ISODCL(41,72));printf("\n");
753
 
        printf("volume space size: %d\n",isonum_733(ipd->volume_space_size));
754
 
        printf("volume set size: %d\n",isonum_723(ipd->volume_set_size));
755
 
        printf("volume seq num: %d\n",isonum_723(ipd->volume_set_size));
756
 
        printf("logical block size: %d\n",isonum_723(ipd->logical_block_size));
757
 
        printf("path table size: %d\n",isonum_733(ipd->path_table_size));
758
 
        printf("location of type_l path table: %d\n",isonum_731(ipd->type_l_path_table));
759
 
        printf("location of optional type_l path table: %d\n",isonum_731(ipd->opt_type_l_path_table));
760
 
        printf("location of type_m path table: %d\n",isonum_732(ipd->type_m_path_table));               
761
 
        printf("location of optional type_m path table: %d\n",isonum_732(ipd->opt_type_m_path_table));          
762
 
/*
763
 
        printf("Root dir record:\n");dumpdirrec((struct iso_directory_record*) &ipd->root_directory_record);
764
 
*/
765
 
        printf("Volume set id: ");dumpchardesc(ipd->volume_set_id,ISODCL(191,318));printf("\n");
766
 
        printf("Publisher id: ");dumpchardesc(ipd->publisher_id,ISODCL(319,446));printf("\n");
767
 
        printf("Preparer id: ");dumpchardesc(ipd->preparer_id,ISODCL(447,574));printf("\n");
768
 
        printf("Application id: ");dumpchardesc(ipd->application_id,ISODCL(575,702));printf("\n");
769
 
        printf("Copyright id: ");dumpchardesc(ipd->copyright_file_id,ISODCL(703,739));printf("\n");
770
 
        printf("Abstract file id: ");dumpchardesc(ipd->abstract_file_id,ISODCL(740,776));printf("\n");
771
 
        printf("Bibliographic file id: ");dumpchardesc(ipd->bibliographic_file_id,ISODCL(777,813));printf("\n");
772
 
        printf("Volume creation date: ");dumpiso84261time(ipd->creation_date,0);printf("\n");
773
 
        printf("Volume modification date: ");dumpiso84261time(ipd->modification_date,0);printf("\n");
774
 
        printf("Volume expiration date: ");dumpiso84261time(ipd->expiration_date,0);printf("\n");
775
 
        printf("Volume effective date: ");dumpiso84261time(ipd->effective_date,0);printf("\n");
776
 
        printf("File structure version: %d\n",isonum_711(ipd->file_structure_version));
777
 
}
778
 
 
779
 
int mycallb(struct iso_directory_record *idr,void *udata) {
780
 
        rr_entry rrentry;
781
 
 
782
 
        sp(level);dumpdirrec(idr);
783
 
        if (level==0) printf(" (Root directory) ");
784
 
        printf("\n");
785
 
        
786
 
        if (ParseRR(idr,&rrentry)>0) {
787
 
                sp(level);printf("  ");dumprrentry(&rrentry);printf("\n");
788
 
        }
789
 
        FreeRR(&rrentry);
790
 
        if ( !(idr->flags[0] & 2) ) files++;
791
 
        if ( (idr->flags[0] & 2) && (level==0 || isonum_711(idr->name_len)>1) ) {
792
 
                level++;
793
 
                dirs++;
794
 
                ProcessDir(&readf,isonum_733(idr->extent),isonum_733(idr->size),&mycallb,udata);
795
 
                level--;
796
 
        }
797
 
        return 0;
798
 
}
799
 
 
800
 
/************************************************/
801
 
 
802
 
int main(int argc, char *argv[]) {
803
 
        
804
 
        int i=1,sector=0;
805
 
        iso_vol_desc *desc;
806
 
        boot_head boot;
807
 
        
808
 
        if (argc<2) {
809
 
                fprintf(stderr,"\nUsage: %s iso-file-name or device [starting sector]\n\n",argv[0]);
810
 
                return 0;
811
 
        }
812
 
        if (argc>=3) {
813
 
                sector=atoi(argv[2]);
814
 
                printf("Using starting sector number %d\n",sector);
815
 
        }
816
 
        fd=open(argv[1],O_RDONLY);
817
 
        if (fd<0) {
818
 
                fprintf(stderr,"open error\n");
819
 
                return -1;
820
 
        }
821
 
        iconv_d=iconv_open("ISO8859-2","UTF16BE");
822
 
        if (iconv_d==0) {
823
 
                fprintf(stderr,"iconv open error\n");
824
 
                return -1;
825
 
        }
826
 
        
827
 
        desc=ReadISO9660(&readf,sector,NULL);
828
 
        if (!desc) {
829
 
                printf("No volume descriptors\n");
830
 
                return -1;
831
 
        }
832
 
        while (desc) {
833
 
                
834
 
                printf("\n\n--------------- Volume descriptor (%d.) type %d: ---------------\n\n",
835
 
                        i,isonum_711(desc->data.type));
836
 
                switch (isonum_711(desc->data.type)) {
837
 
                        case ISO_VD_BOOT: {
838
 
 
839
 
                                struct el_torito_boot_descriptor* bootdesc;
840
 
                                bootdesc=&(desc->data);
841
 
                                dumpboot(bootdesc);
842
 
                                if ( !memcmp(EL_TORITO_ID,bootdesc->system_id,ISODCL(8,39)) ) {
843
 
                                        
844
 
                                        if (ReadBootTable(&readf,isonum_731(bootdesc->boot_catalog),&boot,NULL)) {
845
 
                                                printf("Boot Catalog Error\n");
846
 
                                        } else {
847
 
                                                dumpbootcat(&boot);
848
 
                                                FreeBootTable(&boot);
849
 
                                        }
850
 
                                }
851
 
                        }
852
 
                                break;
853
 
 
854
 
                        case ISO_VD_PRIMARY:
855
 
                        case ISO_VD_SUPPLEMENTARY:
856
 
                                joliet=0;
857
 
                                joliet = JolietLevel(&desc->data);
858
 
                                printf("Joliet level: %d\n",joliet);
859
 
                                dumpdesc((struct iso_primary_descriptor*) &desc->data);
860
 
                                printf("\n\n--------------- Directory structure: -------------------\n\n");
861
 
                                dirs=0;files=0;
862
 
                                mycallb( &( ((struct iso_primary_descriptor*) &desc->data)->root_directory_record), NULL );
863
 
                                printf("\nnumber of directories: %d\n",dirs);
864
 
                                printf("\nnumber of files: %d\n",files);
865
 
                                break;
866
 
 
867
 
                }
868
 
                desc=desc->next;
869
 
                i++;
870
 
        }
871
 
        iconv_close(iconv_d);
872
 
        close(fd);
873
 
        FreeISO9660(desc);
874
 
        return 0;
875
 
}
876
 
 
877
 
#endif /* ISOFS_MAIN */
 
1
/*****************************************************************************
 
2
 * Copyright (C) 2002 Szombathelyi György <gyurco@users.sourceforge.net>     *
 
3
 *                                                                           *
 
4
 * This program is free software; you can redistribute it and/or modify      *
 
5
 * it under the terms of the GNU General Public License as published by      *
 
6
 * the Free Software Foundation; either version 2 of the License, or         *
 
7
 * (at your option) any later version.                                       *
 
8
 *                                                                           *
 
9
 * This package is distributed in the hope that it will be useful,           *
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of            *
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
 
12
 * GNU General Public License for more details.                              *
 
13
 *                                                                           *
 
14
 * You should have received a copy of the GNU General Public License         *
 
15
 * along with this package; if not, write to the Free Software               *
 
16
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA *
 
17
 *****************************************************************************/
 
18
 
 
19
#include <errno.h>
 
20
#include <stdlib.h>
 
21
#include <string.h>
 
22
 
 
23
#include "isofs.h"
 
24
#include "iso_fs.h"
 
25
 
 
26
/**************************************************************/
 
27
 
 
28
 
 
29
/* internal function from the linux kernel (isofs fs) */
 
30
static time_t getisotime(int year, int month, int day, int hour,
 
31
                         int minute, int second, int tz)
 
32
{
 
33
 
 
34
    int days, i;
 
35
    time_t crtime;
 
36
 
 
37
    year -= 1970;
 
38
 
 
39
    if (year < 0) {
 
40
        crtime = 0;
 
41
    } else {
 
42
        int monlen[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
 
43
 
 
44
        days = year * 365;
 
45
        if (year > 2)
 
46
            days += (year + 1) / 4;
 
47
        for (i = 1; i < month; i++)
 
48
            days += monlen[i-1];
 
49
        if (((year + 2) % 4) == 0 && month > 2)
 
50
            days++;
 
51
        days += day - 1;
 
52
        crtime = ((((days * 24) + hour) * 60 + minute) * 60)
 
53
                 + second;
 
54
 
 
55
        /* sign extend */
 
56
        if (tz & 0x80)
 
57
            tz |= (-1 << 8);
 
58
 
 
59
        /*
 
60
         * The timezone offset is unreliable on some disks,
 
61
         * so we make a sanity check.  In no case is it ever
 
62
         * more than 13 hours from GMT, which is 52*15min.
 
63
         * The time is always stored in localtime with the
 
64
         * timezone offset being what get added to GMT to
 
65
         * get to localtime.  Thus we need to subtract the offset
 
66
         * to get to true GMT, which is what we store the time
 
67
         * as internally.  On the local system, the user may set
 
68
         * their timezone any way they wish, of course, so GMT
 
69
         * gets converted back to localtime on the receiving
 
70
         * system.
 
71
         *
 
72
         * NOTE: mkisofs in versions prior to mkisofs-1.10 had
 
73
         * the sign wrong on the timezone offset.  This has now
 
74
         * been corrected there too, but if you are getting screwy
 
75
         * results this may be the explanation.  If enough people
 
76
         * complain, a user configuration option could be added
 
77
         * to add the timezone offset in with the wrong sign
 
78
         * for 'compatibility' with older discs, but I cannot see how
 
79
         * it will matter that much.
 
80
         *
 
81
         * Thanks to kuhlmav@elec.canterbury.ac.nz (Volker Kuhlmann)
 
82
         * for pointing out the sign error.
 
83
         */
 
84
        if (-52 <= tz && tz <= 52)
 
85
            crtime -= tz * 15 * 60;
 
86
    }
 
87
    return crtime;
 
88
 
 
89
}
 
90
 
 
91
/**
 
92
 * Returns the Unix from the ISO9660 9.1.5 time format
 
93
 */
 
94
time_t isodate_915(char * p, int hs)
 
95
{
 
96
 
 
97
    return getisotime(1900 + p[0], p[1], p[2], p[3], p[4], p[5], hs == 0 ? p[6] : 0);
 
98
}
 
99
 
 
100
/**
 
101
 * Returns the Unix from the ISO9660 8.4.26.1 time format
 
102
 * BUG: hundredth of seconds are ignored, because Unix time_t has one second
 
103
 * resolution (I think it's no problem at all)
 
104
 */
 
105
time_t isodate_84261(char * p, int hs)
 
106
{
 
107
    int year, month, day, hour, minute, second;
 
108
    year = (p[0] - '0') * 1000 + (p[1] - '0') * 100 + (p[2] - '0') * 10 + p[3] - '0';
 
109
    month = (p[4] - '0') * 10 + (p[5] - '0');
 
110
    day = (p[6] - '0') * 10 + (p[7] - '0');
 
111
    hour = (p[8] - '0') * 10 + (p[9] - '0');
 
112
    minute = (p[10] - '0') * 10 + (p[11] - '0');
 
113
    second = (p[12] - '0') * 10 + (p[13] - '0');
 
114
    return getisotime(year, month, day, hour, minute, second, hs == 0 ? p[16] : 0);
 
115
}
 
116
 
 
117
void FreeBootTable(boot_head *boot)
 
118
{
 
119
    boot_entry *be, *next;
 
120
 
 
121
    be = boot->defentry;
 
122
    while (be) {
 
123
        next = be->next;
 
124
        free(be);
 
125
        be = next;
 
126
    }
 
127
    boot->defentry = NULL;
 
128
}
 
129
 
 
130
long long BootImageSize(int media, unsigned int len)
 
131
{
 
132
    long long ret;
 
133
 
 
134
    switch (media & 0xf) {
 
135
    case 0:
 
136
        ret = len; /* No emulation */
 
137
        break;
 
138
    case 1:
 
139
        ret = 80 * 2 * 15; /* 1.2 MB */
 
140
        break;
 
141
    case 2:
 
142
        ret = 80 * 2 * 18; /* 1.44 MB */
 
143
        break;
 
144
    case 3:
 
145
        ret = 80 * 2 * 36; /* 2.88 MB */
 
146
        break;
 
147
    case 4:
 
148
        /* FIXME!!! */
 
149
        ret = len; /* Hard Disk */
 
150
        break;
 
151
    default:
 
152
        ret = len;
 
153
    }
 
154
    return ret;
 
155
}
 
156
 
 
157
static boot_entry *CreateBootEntry(char *be)
 
158
{
 
159
    boot_entry *entry;
 
160
 
 
161
    entry = (boot_entry*) malloc(sizeof(boot_entry));
 
162
    if (!entry) return NULL;
 
163
    memset(entry, 0, sizeof(boot_entry));
 
164
    memcpy(entry->data, be, 0x20);
 
165
    return entry;
 
166
}
 
167
 
 
168
int ReadBootTable(readfunc *read, unsigned int sector, boot_head *head, void *udata)
 
169
{
 
170
 
 
171
    char buf[2048], *c, *be;
 
172
    int i, end = 0;
 
173
    unsigned short sum;
 
174
    boot_entry *defcur = NULL, *deflast = NULL;
 
175
    register struct validation_entry *ventry = NULL;
 
176
 
 
177
    head->sections = NULL;
 
178
    head->defentry = NULL;
 
179
    while (1) {
 
180
        be = (char*) & buf;
 
181
        if (read(be, sector, 1, udata) != 1) goto err;
 
182
 
 
183
        /* first entry needs to be a validation entry */
 
184
        if (!ventry) {
 
185
            ventry = (struct validation_entry *) be;
 
186
            if (isonum_711(ventry->type) != 1) goto err;
 
187
            sum = 0;
 
188
            c = (char*) ventry;
 
189
            for (i = 0;i < 16;i++) {
 
190
                sum += isonum_721(c); c += 2;
 
191
            }
 
192
            if (sum) goto err;
 
193
            memcpy(&head->ventry, be, 0x20);
 
194
            be += 0x20;
 
195
        }
 
196
 
 
197
        while (!end && (be < (char *)(&buf + 1))) {
 
198
            switch (isonum_711(be)) {
 
199
            case 0x88:
 
200
                defcur = CreateBootEntry(be);
 
201
                if (!defcur) goto err;
 
202
                if (deflast)
 
203
                    deflast->next = defcur;
 
204
                else
 
205
                    head->defentry = defcur;
 
206
                defcur->prev = deflast;
 
207
                deflast = defcur;
 
208
                break;
 
209
            case 0x90:
 
210
            case 0x91:
 
211
                break;
 
212
            default:
 
213
                end = 1;
 
214
                break;
 
215
            }
 
216
            be += 0x20;
 
217
        }
 
218
        if (end) break;
 
219
 
 
220
        sector ++;
 
221
    }
 
222
 
 
223
    return 0;
 
224
 
 
225
err:
 
226
    FreeBootTable(head);
 
227
    return -1;
 
228
}
 
229
 
 
230
 
 
231
/**
 
232
 * Creates the linked list of the volume descriptors
 
233
 */
 
234
iso_vol_desc *ReadISO9660(readfunc *read, unsigned int sector, void *udata)
 
235
{
 
236
 
 
237
    int i;
 
238
    struct iso_volume_descriptor buf;
 
239
    iso_vol_desc *first = NULL, *current = NULL, *prev = NULL;
 
240
 
 
241
    for (i = 0;i < 100;i++) {
 
242
        if (read((char*) &buf, sector + i + 16, 1, udata) != 1) {
 
243
            FreeISO9660(first);
 
244
            return NULL;
 
245
        }
 
246
        if (!memcmp(ISO_STANDARD_ID, &buf.id, 5)) {
 
247
            switch (isonum_711(&buf.type[0])) {
 
248
 
 
249
            case ISO_VD_BOOT:
 
250
            case ISO_VD_PRIMARY:
 
251
            case ISO_VD_SUPPLEMENTARY:
 
252
                current = (iso_vol_desc*) malloc(sizeof(iso_vol_desc));
 
253
                if (!current) {
 
254
                    FreeISO9660(first);
 
255
                    return NULL;
 
256
                }
 
257
                current->prev = prev;
 
258
                current->next = NULL;
 
259
                if (prev) prev->next = current;
 
260
                memcpy(&(current->data), &buf, 2048);
 
261
                if (!first) first = current;
 
262
                prev = current;
 
263
                break;
 
264
 
 
265
            case ISO_VD_END:
 
266
                return first;
 
267
                break;
 
268
            }
 
269
        } else if (!memcmp(HS_STANDARD_ID, (struct hs_volume_descriptor*) &buf, 5)) {
 
270
            /* High Sierra format not supported (yet) */
 
271
        }
 
272
    }
 
273
 
 
274
    return first;
 
275
}
 
276
 
 
277
/**
 
278
 * Frees the linked list of volume descriptors
 
279
 */
 
280
void FreeISO9660(iso_vol_desc *data)
 
281
{
 
282
 
 
283
    iso_vol_desc *current;
 
284
 
 
285
 
 
286
    while (data) {
 
287
        current = data;
 
288
        data = current->next;
 
289
        free(current);
 
290
    }
 
291
}
 
292
 
 
293
/**
 
294
 * Frees the strings in 'rrentry'
 
295
 */
 
296
void FreeRR(rr_entry *rrentry)
 
297
{
 
298
    if (rrentry->name) {
 
299
        free(rrentry->name);
 
300
        rrentry->name = NULL;
 
301
    }
 
302
    if (rrentry->sl) {
 
303
        free(rrentry->sl);
 
304
        rrentry->name = NULL;
 
305
    }
 
306
}
 
307
 
 
308
static int str_nappend(char **d, char *s, int n)
 
309
{
 
310
    int i = 0;
 
311
    char *c;
 
312
 
 
313
    /* i=strnlen(s,n)+1; */
 
314
    while (i < n && s[i]) i++;
 
315
    i++;
 
316
    if (*d) i += (strlen(*d) + 1);
 
317
    c = (char*) malloc(i);
 
318
    if (!c) return -ENOMEM;
 
319
    if (*d) {
 
320
        strcpy(c, *d);
 
321
        strncat(c, s, n);
 
322
 
 
323
        free(*d);
 
324
    } else
 
325
        strncpy(c, s, n);
 
326
    c[i-1] = 0;
 
327
    *d = c;
 
328
    return 0;
 
329
}
 
330
 
 
331
static int str_append(char **d, char *s)
 
332
{
 
333
    int i;
 
334
    char *c;
 
335
 
 
336
    i = strlen(s) + 1;
 
337
    if (*d) i += (strlen(*d) + 1);
 
338
    c = (char*) malloc(i);
 
339
    if (!c) return -ENOMEM;
 
340
    if (*d) {
 
341
        strcpy(c, *d);
 
342
        strcat(c, s);
 
343
        free(*d);
 
344
    } else
 
345
        strcpy(c, s);
 
346
    c[i-1] = 0;
 
347
    *d = c;
 
348
    return 0;
 
349
}
 
350
 
 
351
#define rrtlen(c) (((unsigned char) c & 0x80) ? 17 : 7)
 
352
#define rrctime(f,c) ((unsigned char) f & 0x80) ? isodate_84261(c,0) : isodate_915(c,0)
 
353
/**
 
354
 * Parses the System Use area and fills rr_entry with values
 
355
 */
 
356
int ParseRR(struct iso_directory_record *idr, rr_entry *rrentry)
 
357
{
 
358
 
 
359
    int suspoffs, susplen, i, f, ret = 0;
 
360
    char *r, *c;
 
361
    struct rock_ridge *rr;
 
362
 
 
363
    suspoffs = 33 + isonum_711(idr->name_len);
 
364
    if (!(isonum_711(idr->name_len) & 1)) suspoffs++;
 
365
    susplen = isonum_711(idr->length) - suspoffs;
 
366
    r = & (((char*) idr)[suspoffs]);
 
367
    rr = (struct rock_ridge*) r;
 
368
 
 
369
    memset(rrentry, 0, sizeof(rr_entry));
 
370
    rrentry->len = sizeof(rr_entry);
 
371
 
 
372
    while (susplen > 0) {
 
373
        if (isonum_711(&rr->len) > susplen || rr->len == 0) break;
 
374
        if (rr->signature[0] == 'N' && rr->signature[1] == 'M') {
 
375
            if (!(rr->u.NM.flags & 0x26) && rr->len > 5 && !rrentry->name) {
 
376
 
 
377
                if (str_nappend(&rrentry->name, rr->u.NM.name, isonum_711(&rr->len) - 5)) {
 
378
                    FreeRR(rrentry); return -ENOMEM;
 
379
                }
 
380
                ret++;
 
381
            }
 
382
        } else if (rr->signature[0] == 'P' && rr->signature[1] == 'X' &&
 
383
                   (isonum_711(&rr->len) == 44 || isonum_711(&rr->len) == 36)) {
 
384
            rrentry->mode = isonum_733(rr->u.PX.mode);
 
385
            rrentry->nlink = isonum_733(rr->u.PX.n_links);
 
386
            rrentry->uid = isonum_733(rr->u.PX.uid);
 
387
            rrentry->gid = isonum_733(rr->u.PX.gid);
 
388
            if (isonum_711(&rr->len) == 44) rrentry->serno = isonum_733(rr->u.PX.serno);
 
389
            ret++;
 
390
        } else if (rr->signature[0] == 'P' && rr->signature[1] == 'N' &&
 
391
                   isonum_711(&rr->len) == 20) {
 
392
            rrentry->dev_major = isonum_733(rr->u.PN.dev_high);
 
393
            rrentry->dev_minor = isonum_733(rr->u.PN.dev_low);
 
394
            ret++;
 
395
        } else if (rr->signature[0] == 'P' && rr->signature[1] == 'L' &&
 
396
                   isonum_711(&rr->len) == 12) {
 
397
            rrentry->pl = isonum_733(rr->u.PL.location);
 
398
            ret++;
 
399
        } else if (rr->signature[0] == 'C' && rr->signature[1] == 'L' &&
 
400
                   isonum_711(&rr->len) == 12) {
 
401
            rrentry->cl = isonum_733(rr->u.CL.location);
 
402
            ret++;
 
403
        } else if (rr->signature[0] == 'R' && rr->signature[1] == 'E' &&
 
404
                   isonum_711(&rr->len) == 4) {
 
405
            rrentry->re = 1;
 
406
            ret++;
 
407
        } else if (rr->signature[0] == 'S' && rr->signature[1] == 'L' &&
 
408
                   isonum_711(&rr->len) > 7) {
 
409
            i = isonum_711(&rr->len) - 5;
 
410
            c = (char*) rr;
 
411
            c += 5;
 
412
            while (i > 0) {
 
413
                switch (c[0] & ~1) {
 
414
                case 0x2:
 
415
                    if (str_append(&rrentry->sl, (char *)".")) {
 
416
                        FreeRR(rrentry); return -ENOMEM;
 
417
                    }
 
418
                    break;
 
419
                case 0x4:
 
420
                    if (str_append(&rrentry->sl, (char *)"..")) {
 
421
                        FreeRR(rrentry); return -ENOMEM;
 
422
                    }
 
423
                    break;
 
424
                }
 
425
                if ((c[0] & 0x08) == 0x08 || (c[1] && rrentry->sl &&
 
426
                                              strlen(rrentry->sl) > 1)) {
 
427
                    if (str_append(&rrentry->sl, (char *) DIR_SEPARATOR)) {
 
428
                        FreeRR(rrentry); return -ENOMEM;
 
429
                    }
 
430
                }
 
431
 
 
432
                if ((unsigned char)c[1] > 0) {
 
433
                    if (str_nappend(&rrentry->sl, c + 2, (unsigned char)c[1])) {
 
434
                        FreeRR(rrentry); return -ENOMEM;
 
435
                    }
 
436
                }
 
437
                i -= ((unsigned char)c[1] + 2);
 
438
                c += ((unsigned char)c[1] + 2);
 
439
            }
 
440
            ret++;
 
441
        } else if (rr->signature[0] == 'T' && rr->signature[1] == 'F' &&
 
442
                   isonum_711(&rr->len) > 5) {
 
443
 
 
444
            i = isonum_711(&rr->len) - 5;
 
445
            f = rr->u.TF.flags;
 
446
            c = (char*) rr;
 
447
            c += 5;
 
448
 
 
449
            while (i >= rrtlen(f)) {
 
450
                if (f & 1) {
 
451
                    rrentry->t_creat = rrctime(f, c);
 
452
                    f &= ~1;
 
453
                } else if (f & 2) {
 
454
                    rrentry->t_mtime = rrctime(f, c);
 
455
                    f &= ~2;
 
456
                } else if (f & 4) {
 
457
                    rrentry->t_atime = rrctime(f, c);
 
458
                    f &= ~4;
 
459
                } else if (f & 8) {
 
460
                    rrentry->t_ctime = rrctime(f, c);
 
461
                    f &= ~8;
 
462
                } else if (f & 16) {
 
463
                    rrentry->t_backup = rrctime(f, c);
 
464
                    f &= ~16;
 
465
                } else if (f & 32) {
 
466
                    rrentry->t_expire = rrctime(f, c);
 
467
                    f &= ~32;
 
468
                } else if (f & 64) {
 
469
                    rrentry->t_effect = rrctime(f, c);
 
470
                    f &= ~64;
 
471
                }
 
472
 
 
473
                i -= rrtlen(f);
 
474
                c += rrtlen(f);
 
475
            }
 
476
            ret++;
 
477
 
 
478
        } else if (rr->signature[0] == 'Z' && rr->signature[1] == 'F' &&
 
479
                   isonum_711(&rr->len) == 16) {
 
480
            /* Linux-specific extension: transparent decompression */
 
481
            rrentry->z_algo[0] = rr->u.ZF.algorithm[0];
 
482
            rrentry->z_algo[1] = rr->u.ZF.algorithm[1];
 
483
            rrentry->z_params[0] = rr->u.ZF.parms[0];
 
484
            rrentry->z_params[1] = rr->u.ZF.parms[1];
 
485
            rrentry->z_size = isonum_733(rr->u.ZF.real_size);
 
486
            ret++;
 
487
        } else {
 
488
            /*   printf("SUSP sign: %c%c\n",rr->signature[0],rr->signature[1]); */
 
489
        }
 
490
 
 
491
        susplen -= isonum_711(&rr->len);
 
492
        r += isonum_711(&rr->len);
 
493
        rr = (struct rock_ridge*) r;
 
494
    }
 
495
 
 
496
    return ret;
 
497
}
 
498
 
 
499
/**
 
500
 * Iterates over the directory entries. The directory is in 'buf',
 
501
 * the size of the directory is 'size'. 'callback' is called for each
 
502
 * directory entry with the parameter 'udata'.
 
503
 */
 
504
int ProcessDir(readfunc *read, int extent, int size, dircallback *callback, void *udata)
 
505
{
 
506
 
 
507
    int pos = 0, ret = 0, siz;
 
508
    char *buf;
 
509
    struct iso_directory_record *idr;
 
510
 
 
511
    if (size & 2047) {
 
512
        siz = ((size >> 11) + 1) << 11;
 
513
    } else {
 
514
        siz = size;
 
515
    }
 
516
 
 
517
    buf = (char*) malloc(siz);
 
518
    if (!buf) return -ENOMEM;
 
519
    if (read(buf, extent, siz >> 11, udata) != siz >> 11) {
 
520
        free(buf);
 
521
        return -EIO;
 
522
    }
 
523
 
 
524
    while (size > 0) {
 
525
        idr = (struct iso_directory_record*) & buf[pos];
 
526
        if (isonum_711(idr->length) == 0) {
 
527
 
 
528
            size -= (2048 - (pos & 0x7ff));
 
529
            if (size <= 2) break;
 
530
            pos += 0x800;
 
531
            pos &= 0xfffff800;
 
532
            idr = (struct iso_directory_record*) & buf[pos];
 
533
        }
 
534
        pos += isonum_711(idr->length);
 
535
        pos += isonum_711(idr->ext_attr_length);
 
536
        size -= isonum_711(idr->length);
 
537
        size -= isonum_711(idr->ext_attr_length);
 
538
        if (size < 0) break;
 
539
 
 
540
        if (isonum_711(idr->length)
 
541
                < 33 ||
 
542
                isonum_711(idr->length) < 33 + isonum_711(idr->name_len)) {
 
543
            /* Invalid directory entry */
 
544
            continue;
 
545
        }
 
546
        if ((ret = callback(idr, udata))) break;
 
547
    }
 
548
 
 
549
    free(buf);
 
550
    return ret;
 
551
}
 
552
 
 
553
/**
 
554
 * returns the joliet level from the volume descriptor
 
555
 */
 
556
int JolietLevel(struct iso_volume_descriptor *ivd)
 
557
{
 
558
    int ret = 0;
 
559
    register struct iso_supplementary_descriptor *isd;
 
560
 
 
561
    isd = (struct iso_supplementary_descriptor *) ivd;
 
562
 
 
563
    if (isonum_711(ivd->type) == ISO_VD_SUPPLEMENTARY) {
 
564
        if (isd->escape[0] == 0x25 &&
 
565
                isd->escape[1] == 0x2f) {
 
566
 
 
567
            switch (isd->escape[2]) {
 
568
            case 0x40:
 
569
                ret = 1;
 
570
                break;
 
571
            case 0x43:
 
572
                ret = 2;
 
573
                break;
 
574
            case 0x45:
 
575
                ret = 3;
 
576
                break;
 
577
            }
 
578
        }
 
579
    }
 
580
    return ret;
 
581
}
 
582
 
 
583
/********************************************************************/
 
584
#ifdef ISOFS_MAIN
 
585
 
 
586
#include <time.h>
 
587
#include <fcntl.h>
 
588
#include <stdio.h>
 
589
#include <unistd.h>
 
590
#include <sys/types.h>
 
591
#include <sys/stat.h>
 
592
#include <iconv.h>
 
593
 
 
594
int level = 0, joliet = 0, dirs, files;
 
595
iconv_t iconv_d;
 
596
int fd;
 
597
 
 
598
int readf(char *buf, unsigned int start, unsigned int len, void *udata)
 
599
{
 
600
    int ret;
 
601
 
 
602
    if ((ret = lseek64(fd, (long long)start << (long long)11, SEEK_SET)) < 0) return ret;
 
603
    ret = read(fd, buf, len << 11u);
 
604
    if (ret < 0) return ret;
 
605
    return (ret >> 11u);
 
606
}
 
607
 
 
608
void dumpchars(char *c, int len)
 
609
{
 
610
    while (len > 0) {
 
611
        printf("%c", *c);
 
612
        len--;
 
613
        c++;
 
614
    }
 
615
}
 
616
 
 
617
void sp(int num)
 
618
{
 
619
    int i;
 
620
    for (i = 0;i < num*5;i++) {
 
621
        printf(" ");
 
622
    };
 
623
}
 
624
 
 
625
void dumpflags(char flags)
 
626
{
 
627
    if (flags & 1) printf("HIDDEN ");
 
628
    if (flags & 2) printf("DIR ");
 
629
    if (flags & 4) printf("ASF ");
 
630
}
 
631
 
 
632
void dumpjoliet(char *c, int len)
 
633
{
 
634
 
 
635
    char outbuf[255];
 
636
    size_t out;
 
637
    int ret;
 
638
    char *outptr;
 
639
 
 
640
    outptr = (char*) & outbuf;
 
641
    out = 255;
 
642
    if ((iconv(iconv_d, &c, &len, &outptr, &out)) < 0) {
 
643
        printf("conversion error=%d", errno);
 
644
        return;
 
645
    }
 
646
    ret = 255 - out;
 
647
    dumpchars((char*) &outbuf, ret);
 
648
}
 
649
 
 
650
void dumpchardesc(char *c, int len)
 
651
{
 
652
 
 
653
    if (joliet)
 
654
        dumpjoliet(c, len);
 
655
    else {
 
656
        dumpchars(c, len);
 
657
    }
 
658
}
 
659
 
 
660
void dumpiso915time(char *t, int hs)
 
661
{
 
662
 
 
663
    time_t time;
 
664
    char *c;
 
665
 
 
666
    time = isodate_915(t, hs);
 
667
    c = (char*) ctime(&time);
 
668
    if (c && c[strlen(c)-1] == 0x0a) c[strlen(c)-1] = 0;
 
669
    if (c) printf("%s", c);
 
670
}
 
671
 
 
672
void dumpiso84261time(char *t, int hs)
 
673
{
 
674
 
 
675
    time_t time;
 
676
    char *c;
 
677
 
 
678
    time = isodate_84261(t, hs);
 
679
    c = (char*) ctime(&time);
 
680
    if (c && c[strlen(c)-1] == 0x0a) c[strlen(c)-1] = 0;
 
681
    if (c) printf("%s", c);
 
682
}
 
683
 
 
684
void dumpdirrec(struct iso_directory_record *dir)
 
685
{
 
686
 
 
687
    if (isonum_711(dir->name_len) == 1) {
 
688
        switch (dir->name[0]) {
 
689
        case 0:
 
690
            printf(".");
 
691
            break;
 
692
        case 1:
 
693
            printf("..");
 
694
            break;
 
695
        default:
 
696
            printf("%c", dir->name[0]);
 
697
            break;
 
698
        }
 
699
    }
 
700
    dumpchardesc(dir->name, isonum_711(dir->name_len));
 
701
    printf(" size=%d", isonum_733(dir->size));
 
702
    printf(" extent=%d ", isonum_733(dir->extent));
 
703
    dumpflags(isonum_711(dir->flags));
 
704
    dumpiso915time((char*) &(dir->date), 0);
 
705
}
 
706
 
 
707
void dumprrentry(rr_entry *rr)
 
708
{
 
709
    printf("  NM=[%s] uid=%d gid=%d nlink=%d mode=%o ",
 
710
           rr->name, rr->uid, rr->gid, rr->nlink, rr->mode);
 
711
    if (S_ISCHR(rr->mode) || S_ISBLK(rr->mode))
 
712
        printf("major=%d minor=%d ", rr->dev_major, rr->dev_minor);
 
713
    if (rr->mode & S_IFLNK && rr->sl) printf("slink=%s ", rr->sl);
 
714
    /*
 
715
     printf("\n");
 
716
     if (rr->t_creat) printf("t_creat: %s",ctime(&rr->t_creat));
 
717
     if (rr->st_mtime) printf("st_mtime: %s",ctime(&rr->st_mtime));
 
718
     if (rr->st_atime) printf("st_atime: %s",ctime(&rr->st_atime));
 
719
     if (rr->st_ctime) printf("st_ctime: %s",ctime(&rr->st_ctime));
 
720
     if (rr->t_backup) printf("t_backup: %s",ctime(&rr->t_backup));
 
721
     if (rr->t_expire) printf("t_expire: %s",ctime(&rr->t_expire));
 
722
     if (rr->t_effect) printf("t_effect: %s",ctime(&rr->t_effect));
 
723
    */
 
724
}
 
725
 
 
726
void dumpsusp(char *c, int len)
 
727
{
 
728
    dumpchars(c, len);
 
729
}
 
730
 
 
731
void dumpboot(struct el_torito_boot_descriptor *ebd)
 
732
{
 
733
    printf("version: %d\n", isonum_711(ebd->version));
 
734
    printf("system id: ");dumpchars(ebd->system_id, ISODCL(8, 39));printf("\n");
 
735
    printf("boot catalog start: %d\n", isonum_731(ebd->boot_catalog));
 
736
}
 
737
 
 
738
void dumpdefentry(struct default_entry *de)
 
739
{
 
740
    printf("Default entry: \n");
 
741
    printf("  bootid=%x\n", isonum_711(de->bootid));
 
742
    printf("  media emulation=%d (", isonum_711(de->media));
 
743
    switch (isonum_711(de->media) & 0xf) {
 
744
    case 0:
 
745
        printf("No emulation");
 
746
        break;
 
747
    case 1:
 
748
        printf("1.2 Mb floppy");
 
749
        break;
 
750
    case 2:
 
751
        printf("1.44 Mb floppy");
 
752
        break;
 
753
    case 3:
 
754
        printf("2.88 Mb floppy");
 
755
        break;
 
756
    case 4:
 
757
        printf("Hard Disk");
 
758
        break;
 
759
    default:
 
760
        printf("Unknown/Invalid");
 
761
        break;
 
762
    }
 
763
    printf(")\n");
 
764
    printf("  loadseg=%d\n", isonum_721(de->loadseg));
 
765
    printf("  systype=%d\n", isonum_711(de->systype));
 
766
    printf("  start lba=%d count=%d\n", isonum_731(de->start),
 
767
           isonum_721(de->seccount));
 
768
}
 
769
 
 
770
void dumpbootcat(boot_head *bh)
 
771
{
 
772
    boot_entry *be;
 
773
 
 
774
    printf("System id: ");dumpchars(bh->ventry.id, ISODCL(28, 5));printf("\n");
 
775
    be = bh->defentry;
 
776
    while (be) {
 
777
        dumpdefentry(be->data);
 
778
        be = be->next;
 
779
    }
 
780
}
 
781
 
 
782
void dumpdesc(struct iso_primary_descriptor *ipd)
 
783
{
 
784
 
 
785
    printf("system id: ");dumpchardesc(ipd->system_id, ISODCL(9, 40));printf("\n");
 
786
    printf("volume id: ");dumpchardesc(ipd->volume_id, ISODCL(41, 72));printf("\n");
 
787
    printf("volume space size: %d\n", isonum_733(ipd->volume_space_size));
 
788
    printf("volume set size: %d\n", isonum_723(ipd->volume_set_size));
 
789
    printf("volume seq num: %d\n", isonum_723(ipd->volume_set_size));
 
790
    printf("logical block size: %d\n", isonum_723(ipd->logical_block_size));
 
791
    printf("path table size: %d\n", isonum_733(ipd->path_table_size));
 
792
    printf("location of type_l path table: %d\n", isonum_731(ipd->type_l_path_table));
 
793
    printf("location of optional type_l path table: %d\n", isonum_731(ipd->opt_type_l_path_table));
 
794
    printf("location of type_m path table: %d\n", isonum_732(ipd->type_m_path_table));
 
795
    printf("location of optional type_m path table: %d\n", isonum_732(ipd->opt_type_m_path_table));
 
796
    /*
 
797
     printf("Root dir record:\n");dumpdirrec((struct iso_directory_record*) &ipd->root_directory_record);
 
798
    */
 
799
    printf("Volume set id: ");dumpchardesc(ipd->volume_set_id, ISODCL(191, 318));printf("\n");
 
800
    printf("Publisher id: ");dumpchardesc(ipd->publisher_id, ISODCL(319, 446));printf("\n");
 
801
    printf("Preparer id: ");dumpchardesc(ipd->preparer_id, ISODCL(447, 574));printf("\n");
 
802
    printf("Application id: ");dumpchardesc(ipd->application_id, ISODCL(575, 702));printf("\n");
 
803
    printf("Copyright id: ");dumpchardesc(ipd->copyright_file_id, ISODCL(703, 739));printf("\n");
 
804
    printf("Abstract file id: ");dumpchardesc(ipd->abstract_file_id, ISODCL(740, 776));printf("\n");
 
805
    printf("Bibliographic file id: ");dumpchardesc(ipd->bibliographic_file_id, ISODCL(777, 813));printf("\n");
 
806
    printf("Volume creation date: ");dumpiso84261time(ipd->creation_date, 0);printf("\n");
 
807
    printf("Volume modification date: ");dumpiso84261time(ipd->modification_date, 0);printf("\n");
 
808
    printf("Volume expiration date: ");dumpiso84261time(ipd->expiration_date, 0);printf("\n");
 
809
    printf("Volume effective date: ");dumpiso84261time(ipd->effective_date, 0);printf("\n");
 
810
    printf("File structure version: %d\n", isonum_711(ipd->file_structure_version));
 
811
}
 
812
 
 
813
int mycallb(struct iso_directory_record *idr, void *udata)
 
814
{
 
815
    rr_entry rrentry;
 
816
 
 
817
    sp(level);dumpdirrec(idr);
 
818
    if (level == 0) printf(" (Root directory) ");
 
819
    printf("\n");
 
820
 
 
821
    if (ParseRR(idr, &rrentry) > 0) {
 
822
        sp(level);printf("  ");dumprrentry(&rrentry);printf("\n");
 
823
    }
 
824
    FreeRR(&rrentry);
 
825
    if (!(idr->flags[0] & 2)) files++;
 
826
    if ((idr->flags[0] & 2) && (level == 0 || isonum_711(idr->name_len) > 1)) {
 
827
        level++;
 
828
        dirs++;
 
829
        ProcessDir(&readf, isonum_733(idr->extent), isonum_733(idr->size), &mycallb, udata);
 
830
        level--;
 
831
    }
 
832
    return 0;
 
833
}
 
834
 
 
835
/************************************************/
 
836
 
 
837
int main(int argc, char *argv[])
 
838
{
 
839
 
 
840
    int i = 1, sector = 0;
 
841
    iso_vol_desc *desc;
 
842
    boot_head boot;
 
843
 
 
844
    if (argc < 2) {
 
845
        fprintf(stderr, "\nUsage: %s iso-file-name or device [starting sector]\n\n", argv[0]);
 
846
        return 0;
 
847
    }
 
848
    if (argc >= 3) {
 
849
        sector = atoi(argv[2]);
 
850
        printf("Using starting sector number %d\n", sector);
 
851
    }
 
852
    fd = open(argv[1], O_RDONLY);
 
853
    if (fd < 0) {
 
854
        fprintf(stderr, "open error\n");
 
855
        return -1;
 
856
    }
 
857
    iconv_d = iconv_open("ISO8859-2", "UTF16BE");
 
858
    if (iconv_d == 0) {
 
859
        fprintf(stderr, "iconv open error\n");
 
860
        return -1;
 
861
    }
 
862
 
 
863
    desc = ReadISO9660(&readf, sector, NULL);
 
864
    if (!desc) {
 
865
        printf("No volume descriptors\n");
 
866
        return -1;
 
867
    }
 
868
    while (desc) {
 
869
 
 
870
        printf("\n\n--------------- Volume descriptor (%d.) type %d: ---------------\n\n",
 
871
               i, isonum_711(desc->data.type));
 
872
        switch (isonum_711(desc->data.type)) {
 
873
        case ISO_VD_BOOT: {
 
874
 
 
875
            struct el_torito_boot_descriptor* bootdesc;
 
876
            bootdesc = &(desc->data);
 
877
            dumpboot(bootdesc);
 
878
            if (!memcmp(EL_TORITO_ID, bootdesc->system_id, ISODCL(8, 39))) {
 
879
 
 
880
                if (ReadBootTable(&readf, isonum_731(bootdesc->boot_catalog), &boot, NULL)) {
 
881
                    printf("Boot Catalog Error\n");
 
882
                } else {
 
883
                    dumpbootcat(&boot);
 
884
                    FreeBootTable(&boot);
 
885
                }
 
886
            }
 
887
        }
 
888
        break;
 
889
 
 
890
        case ISO_VD_PRIMARY:
 
891
        case ISO_VD_SUPPLEMENTARY:
 
892
            joliet = 0;
 
893
            joliet = JolietLevel(&desc->data);
 
894
            printf("Joliet level: %d\n", joliet);
 
895
            dumpdesc((struct iso_primary_descriptor*) &desc->data);
 
896
            printf("\n\n--------------- Directory structure: -------------------\n\n");
 
897
            dirs = 0;files = 0;
 
898
            mycallb(&(((struct iso_primary_descriptor*) &desc->data)->root_directory_record), NULL);
 
899
            printf("\nnumber of directories: %d\n", dirs);
 
900
            printf("\nnumber of files: %d\n", files);
 
901
            break;
 
902
 
 
903
        }
 
904
        desc = desc->next;
 
905
        i++;
 
906
    }
 
907
    iconv_close(iconv_d);
 
908
    close(fd);
 
909
    FreeISO9660(desc);
 
910
    return 0;
 
911
}
 
912
 
 
913
#endif /* ISOFS_MAIN */