_INSIDE THE ISO-966 FILESYSTEM FORMAT_ 
by William Frederick Jolitz and Lynne Greer Jolitz 
 
[LISTING ONE] 
 
/* cdromcheck: A simple program to check what kind of CDROM we have, and to  
 * list the volume descriptors that are present, if any. */ 
 
#include <stdio.h> 
#include "primary_descriptor" 
#include "directory_entry" 
 
#define VD_LSN       16   /* first logical sector of volume descriptor table */ 
#define CDROM_LSECSZ 2048 /* initial logical sector size of a CDROM */ 
 
char buffer[CDROM_LBS]; 
static hsffmt, isofmt; 
void doiso(struct iso_primary_descriptor *, int); 
void dohsf(struct hsf_primary_descriptor *, int); 
 
#define HSF 1 
#define ISO 2 
int cdromfmt; 
 
char *cdromfmtnames[] = { 
    "unknown format", 
    "High Sierra", 
    "ISO - 9660" 
}; 
char *voltypenames[] = { 
    "Boot Record", 
    "Standard File Structure", 
    "Coded Character Set File Structure", 
    "Unspecified File Structure", 
}; 
#define NVOLTYPENAMES   (sizeof(voltypenames)/sizeof(char *)) 
int 
main(int argc, char *argv[]) 
{ 
    struct iso_primary_descriptor *ipd; 
    struct hsf_primary_descriptor *hpd; 
    int cdfd; 
 
    cdfd = open("/dev/ras2d", 0); 
    /* locate at the beginning of the descriptor table */ 
    lseek(cdfd, VD_LSN*CDROM_LSECSZ, SEEK_SET); 
    ipd = (struct iso_primary_descriptor *) buffer; 
    hpd = (struct hsf_primary_descriptor *) buffer; 
    /* walk descriptor table */ 
    for(;;) { 
        unsigned char type; 
        read(cdfd, buffer, sizeof(buffer)); 
        /* determine ISO or HSF format of CDROM */ 
        if (cdromfmt == 0) { 
          if (strncmp (ipd->id, ISO_STANDARD_ID, sizeof(ipd->id)) == 0) 
                cdromfmt = ISO; 
          if (strncmp (hpd->id, HSF_STANDARD_ID, sizeof(hpd->id)) == 0) 
                cdromfmt = HSF; 
          if (cdromfmt) 
           printf("%s Volume Descriptors:\n", cdromfmtnames[cdromfmt]); 
            else { 
                printf("%s\n", cdromfmtnames[0]); 
                exit(0); 
            } 
        } 
        /* type of descriptor */ 
        if (cdromfmt == ISO) 
            type = (unsigned char)ipd->type[0]; 
        else 
            type = (unsigned char)hpd->type[0]; 
 
        /* type of volume */ 
        if (type < NVOLTYPENAMES) 
            printf("\t%s\n", voltypenames[type]); 
        else if (type != VD_END) 
            printf("\t Reserved - %d\n", type); 
 
        /* terminating volume */ 
        if (type == VD_END) 
            break; 
        /* ISO 9660 filestructure */ 
        if (cdromfmt == ISO && type == VD_PRIMARY 
         && strncmp (ipd->id, ISO_STANDARD_ID, sizeof(ipd->id)) == 0) { 
            doiso(ipd, cdfd); 
            isofmt++; 
            continue; 
        } 
        /* (obselete) High Sierra filestructure */ 
        if (cdromfmt == HSF && type == VD_PRIMARY 
         && strncmp (hpd->id, HSF_STANDARD_ID, sizeof(hpd->id)) == 0) { 
            dohsf(hpd, cdfd); 
            hsffmt++; 
            continue; 
        } 
        printf("\n"); 
    } 
    return (0); 
} 
char *iso_astring(char *, int len); 
/* rude translation routines for interpreting strings, words, halfwords */ 
#define ISO_AS(s)   (iso_astring(s, sizeof(s))) 
#define ISO_WD(s)   (*(unsigned *)(s)) 
#define ISO_HWD(s)  (*(unsigned short *)(s)) 
/* dig out the details of a ISO - 9660 descriptor */ 
void 
doiso(struct iso_primary_descriptor *ipd, int fd) { 
   printf(" Volume ID:\t\t%s\n", ISO_AS(ipd->volume_id)); 
   printf(" Logical Block Size:\t%d\n", ISO_HWD(ipd->logical_block_size)); 
   printf(" Volume Set ID:\t\t%s\n", ISO_AS(ipd->volume_set_id)); 
   printf(" Publisher ID:\t\t%s\n", ISO_AS(ipd->publisher_id)); 
   printf(" Preparer ID:\t\t%s\n", ISO_AS(ipd->preparer_id)); 
   printf(" Application ID:\t\t%s\n", ISO_AS(ipd->application_id)); 
   printf(" Copyright File ID:\t%s\n", ISO_AS(ipd->copyright_file_id)); 
   printf(" Abstract File ID:\t%s\n", ISO_AS(ipd->abstract_file_id)); 
   printf(" Bibliographic File ID:\t%s\n", ISO_AS(ipd->bibliographic_file_id)); 
   printf(" Creation Date:\t\t%s\n", ISO_AS(ipd->creation_date)); 
   printf(" Modification Date:\t%s\n", ISO_AS(ipd->modification_date)); 
   printf(" Expiration Date:\t%s\n", ISO_AS(ipd->expiration_date)); 
   printf(" Effective Date:\t%s\n", ISO_AS(ipd->effective_date)); 
} 
/* dig out the details of a High Sierra Descriptor */ 
void 
dohsf(struct hsf_primary_descriptor *hpd, int fd) { 
    printf(" Volume Logical Block Number:\t%d\n", ISO_WD(hpd->volume_lbn)); 
    printf(" Volume ID:\t\t%s\n", ISO_AS(hpd->volume_id)); 
    printf(" Logical Block Size:\t%d\n", ISO_HWD(hpd->logical_block_size)); 
    printf(" Volume Set ID:\t\t%s\n", ISO_AS(hpd->volume_set_id)); 
    printf(" Publisher ID:\t\t%s\n", ISO_AS(hpd->publisher_id)); 
    printf(" Preparer ID:\t\t%s\n", ISO_AS(hpd->preparer_id)); 
    printf(" Application ID:\t\t%s\n", ISO_AS(hpd->application_id)); 
    printf(" Copyright File ID:\t%s\n", ISO_AS(hpd->copyright_file_id)); 
    printf(" Abstract File ID:\t%s\n", ISO_AS(hpd->abstract_file_id)); 
    printf(" Creation Date:\t\t%s\n", ISO_AS(hpd->creation_date)); 
    printf(" Modification Date:\t%s\n", ISO_AS(hpd->modification_date)); 
    printf(" Expiration Date:\t%s\n", ISO_AS(hpd->expiration_date)); 
    printf(" Effective Date:\t%s\n", ISO_AS(hpd->effective_date)); 
} 
static char __strbuf[200]; 
/* turn a blank padded character feild into the null terminated strings 
   that POSIX/UNIX/WHATSIX likes so much */ 
char *iso_astring(char *sp, int len) { 
    bcopy(sp, __strbuf, len); 
    __strbuf[len] = 0; 
    for (sp = __strbuf + len - 1; sp > __strbuf ; sp--) 
        if (*sp == ' ') 
            *sp = 0; 
    return(__strbuf); 
} 
 
 
[LISTING TWO] 
 
From Rich Morin's "Prime Time Freeware", Vol 1.1 CDROM: 
 
ISO - 9660 Volume Descriptors: Standard File Structure 
 Volume ID:     PTF_1_1 
 Logical Block Size:    2048 
 Volume Set ID:       
 Publisher ID:        
 Preparer ID:       MERIDIAN_DATA_CD_PUBLISHER 
 Application ID:          
 Copyright File ID:   
 Abstract File ID:    
 Bibliographic File ID:   
 Creation Date:     1992011101452700 
 Modification Date: 1992011101452700 
 Expiration Date:   0000000000000000 
 Effective Date:    1992011101452700 
 
 
From Discovery System's CD-ROM Sampler: 
 
High Sierra Volume Descriptors: 
 
    Standard File Structure 
 Volume Logical Block Number:   16 
 Volume ID:     CDROM_SAMP1 
 Logical Block Size:    2048 
 Volume Set ID:     CDROM_SAMP1 
 Publisher ID:      DISCOVERY 
 Preparer ID:       DISCOVERY 
 Application ID:          
 Copyright File ID:   
 Abstract File ID:    
 Creation Date:     1987111215553400 
 Modification Date: 1987111215553400 
 Expiration Date:   0000000000000000 
 Effective Date:    0000000000000000 
 
    Standard File Structure 
 Volume Logical Block Number:   17 
 Volume ID:     CDROM_SAMP1 
 Logical Block Size:    2048 
 Volume Set ID:     CDROM_SAMP1 
 Publisher ID:      DISCOVERY 
 Preparer ID:       DISCOVERY 
 Application ID:          
 Copyright File ID:   
 Abstract File ID:    
 Creation Date:     1987111215553400 
 Modification Date: 1987111215553400 
 Expiration Date:   0000000000000000 
 Effective Date:    0000000000000000 
 
 
[LISTING THREE] 
 
/* cdromfs.h: various definitions for CDROM filesystems. */ 
 
#define VD_LSN        16  /* first logical sector of volume descriptor table */ 
#define CDROM_LSECSZ  2048 /* initial logical sector size of a CDROM */ 
 
#define HSF 1 
#define ISO 2 
 
char *cdromfmtnames[] = { 
    "unknown format", 
    "High Sierra", 
    "ISO - 9660" 
}; 
char *voltypenames[] = { 
    "Boot Record", 
    "Standard File Structure", 
    "Coded Character Set File Structure", 
    "Unspecified File Structure", 
}; 
/* rude translation routines for interpreting strings, words, halfwords */ 
#define ISO_AS(s)   (iso_astring(s, sizeof(s))) 
#define ISO_WD(s)   (*(unsigned *)(s)) 
#define ISO_HWD(s)  (*(unsigned short *)(s)) 
#define ISO_BY(s)   (*(unsigned char *)(s)) 
 
#define NVOLTYPENAMES   (sizeof(voltypenames)/sizeof(char *)) 
struct cdromtime { 
    unsigned char years;    /* number of years since 1900 */ 
    unsigned char month;    /* month of the year */ 
    unsigned char day;  /* day of month */ 
    unsigned char hour; /* hour of day */ 
    unsigned char min;  /* minute of the hour */ 
    unsigned char sec;  /* second of the minute */ 
    unsigned char tz;   /* timezones, in quarter hour increments */ 
                /* or, longitude in 3.75 of a degree */ 
}; 
#define CD_FLAGBITS "vdaEp  m"  /* file flag bits */ 
/* Handy macro's for block calculation */ 
#define lbntob(fs, n)   ((fs)->lbs * (n)) 
#define btolbn(fs, n)   ((fs)->lbs * (n)) 
#define trunc_lbn(fs, n)    ((n) - ((n) % (fs)->lbs) 
#define roundup(n, d)   ((((n) + (d)) / (d)) * (d)) 
 
 
 
[LISTING FOUR] 
 
/* cdromcat -- A simple program to interpret the CDROM filesystem, and return. 
 * the contents of the file (directories are formatted and printed, files are  
 * returned untranslated).  */ 
 
#include <sys/types.h> 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <time.h> 
#include "primary_descriptor" 
#include "directory_entry" 
#include "cdromfs.h" 
 
/* per filesystem information */ 
struct fs { 
    char *name; /* kind of cdrom filesystem */ 
    int fd;     /* open file descriptor */ 
    int lbs;    /* logical block size */ 
    int type;   /* which flavor */ 
} fsd; 
/* filesystem directory entry */ 
struct directent { 
    union fsdir { 
        struct iso_directory_record iso_dir; 
        struct hsf_directory_record hsf_dir; 
    } fsd; 
    /* actually, name contains name, reserved field, and extensions area */ 
    char name[255 - sizeof(union fsdir)]; 
}   rootent; 
/* filesystem volume descriptors */ 
union voldesc { 
    struct iso_primary_descriptor  iso_desc; 
    struct hsf_primary_descriptor  hsf_desc; 
}; 
char *iso_astring(char *, int len); 
char *cdrom_time(struct cdromtime *, int); 
void printdirent(struct directent *, struct fs *); 
void printdirents(struct directent *, struct fs *); 
void printdirentheader(char *p); 
int searchdirent(struct directent *, struct directent *, struct directent *, 
    struct fs *); 
void extractdirent(struct directent *, struct fs *); 
int lookup(struct directent *, struct directent *, char *, struct fs *); 
/* "fetch directory value" */ 
#define FDV(b, f, t)    (((t) == ISO) ? (b)->fsd.iso_dir.##f \ 
                : (b)->fsd.hsf_dir.##f) 
/* "fetch primary descriptor value" */ 
#define FPDV(b, f, t)   (((t) == ISO) ? (b)->iso_desc.##f \ 
                : (b)->hsf_desc.##f) 
/* user "application" program */ 
int 
main(int argc, char *argv[]) 
{ 
    struct directent openfile; 
    char pathname[80]; 
    /* open the CDROM device */ 
    if ((fsd.fd = open("/dev/ras2d", 0)) < 0) { 
        perror("cdromcat"); 
        exit(1); 
    } 
    /* is there a filesystem we can understand here? */ 
    if (iscdromfs(&rootent, &fsd) == 0) { 
        fprintf(stderr, "cdromcat: %s\n", fsd.name); 
        exit(1); 
    } 
    /* print the contents of the root directory to give user a start */ 
    printf("Root Directory Listing:\n"); 
    printdirentheader("/"); 
    printdirents(&rootent, &fsd); 
    /* print files on demand from user */ 
    for(;;){ 
        /* prompt user for name to locate */ 
        printf("Pathname to open? : "); 
        fflush(stdout); 
        /* obtain, if none, exit, else trim newline off */ 
        if (fgets(pathname, sizeof(pathname), stdin) == NULL) 
            exit(0); 
        pathname[strlen(pathname) - 1] = '\0'; 
        if (strlen(pathname) == 0) 
            exit(0); 
        /* lookup filename on CDROM */ 
        if (lookup(&rootent, &openfile, pathname, &fsd)){ 
            /* if a directory, format and list it */ 
            if (ISO_BY(FDV(&openfile, flags, fsd.type)) 
                & CD_DIRECTORY) { 
                printdirentheader(pathname); 
                printdirents(&openfile, &fsd); 
            }  
            /* if a file, print it on standard output */ 
            else 
                extractdirent(&openfile, &fsd); 
        } else 
            printf("Not found.\n"); 
    } 
    /* NOTREACHED */ 
} 
/* ----------- Filesystem primatives ------------------- */ 
/* Check for the presence of a cdrom filesystem. If present, pass back  
 * parameters for initialization, otherwise, pass back error. */ 
int 
iscdromfs(struct directent *dp, struct fs *fs) { 
    char buffer[CDROM_LSECSZ]; 
    union voldesc *vdp = (union voldesc *) buffer; 
    /* locate at the beginning of the descriptor table */ 
    lseek(fs->fd, VD_LSN*CDROM_LSECSZ, SEEK_SET); 
    /* walk descriptor table */ 
    for(;;) { 
        unsigned char type; 
        /* obtain a descriptor */ 
        read(fs->fd, buffer, sizeof(buffer)); 
        /* determine ISO or HSF format of CDROM */ 
        if (fs->type == 0) { 
            if (strncmp (vdp->iso_desc.id, ISO_STANDARD_ID, 
                sizeof(vdp->iso_desc.id)) == 0) 
                fs->type = ISO; 
            if (strncmp (vdp->hsf_desc.id, HSF_STANDARD_ID, 
                sizeof(vdp->hsf_desc.id)) == 0) 
                fs->type = HSF; 
        }  
        /* if determined, obtain root directory entry */ 
        if (fs->type) { 
            type = ISO_BY(FPDV(vdp, type, fs->type)); 
            if (type == VD_PRIMARY) { 
                bcopy ( 
            (caddr_t) FPDV(vdp, root_directory_record, fs->type), 
                (caddr_t)dp, sizeof (union fsdir)); 
            fs->lbs = 
                  ISO_HWD(FPDV(vdp, logical_block_size, fs->type)); 
            } 
        } 
        /* terminating volume */ 
        if (type == VD_END) 
            break; 
    } 
    fs->name = cdromfmtnames[fs->type]; 
    return (fs->type); 
} 
/* Obtain a "logical", i.e. relative to the directory entries beginning 
 * (or extent), block from the CDROM. */ 
int 
getblkdirent(struct directent *dp, char *contents, long lbn, struct fs *fs) { 
    long    filesize = ISO_WD(FDV(dp, size, fs->type)), 
        extent = ISO_WD(FDV(dp, extent, fs->type)); 
    if (lbntob(fs, lbn) > roundup(filesize, fs->lbs)) 
        return (0); 
    /* perform logical to physical translation */ 
    (void) lseek(fs->fd, lbntob(fs, extent + lbn), SEEK_SET); 
    /* obtain block */ 
    return (read(fs->fd, contents, fs->lbs) == fs->lbs); 
} 
/* Search the contents of this directory entry, known to be a directory itself, 
 * looking for a component. If found, return directory entry associated with  
 * the component. */ 
int 
searchdirent(struct directent *dp, struct directent *fdp, 
    struct directent *compdp, struct fs *fs) { 
    struct directent *ldp; 
    long    filesize =  ISO_WD(FDV(dp, size, fs->type)), 
        comp_namelen =  ISO_BY(FDV(compdp, name_len, fs->type)), 
        lbn = 0, cnt; 
    char    *buffer = (char *) malloc(fs->lbs); 
    while (getblkdirent(dp, buffer, lbn, fs)) { 
        cnt = filesize > fs->lbs ? fs->lbs : filesize; 
        filesize -= cnt; 
        ldp = (struct directent *) buffer; 
        /* have we a record to match? */ 
        while (cnt > sizeof (union fsdir)) { 
            long    entlen, namelen; 
            /* match against component's name and name length */ 
            entlen = ISO_BY(FDV(ldp, length, fs->type)); 
            namelen = ISO_BY(FDV(ldp, name_len, fs->type)); 
    if (entlen >= comp_namelen + sizeof(union fsdir) && namelen == comp_namelen 
                && strncmp(FDV(ldp,name,fs->type), 
                FDV(compdp,name,fs->type), namelen) == 0) { 
                bcopy ((caddr_t)ldp, (caddr_t)fdp, entlen); 
                bcopy ((caddr_t)ldp, (caddr_t)compdp, entlen); 
                free(buffer); 
                return 1; 
            } else { 
                cnt -= entlen; 
                ldp = (struct directent *) 
                    (((char *) ldp) + entlen); 
            } 
        } 
        if (filesize == 0) break; 
        lbn++; 
    } 
    free(buffer); 
    return 0; 
} 
/* Lookup the pathname by interpreting the directory structure of the CDROM  
 * element by element, returning a directory entry if found. Name translation  
 * occurs here, out of the null terminated path name string. This routine  
 * works by recursion. */ 
int 
lookup(struct directent *dp, struct directent *fdp, char *pathname, 
    struct fs *fs) { 
    struct directent *ldp; 
    struct directent thiscomp; 
    char *nextcomp; 
    unsigned len; 
    /* break off the next component of the pathname */ 
    if ((nextcomp = strrchr(pathname, '/'))  == NULL) 
        nextcomp = strrchr(pathname, '\0'); 
    /* construct an entry for this component to match */ 
    ISO_BY(FDV(&thiscomp, name_len, fs->type)) = len = nextcomp - pathname; 
    bcopy(pathname, thiscomp.name, len); 
    /* attempt a match, returning component if found */ 
    if (searchdirent(dp, fdp, &thiscomp, fs)){ 
        /* if no more components, return found value */ 
        if (*nextcomp == '\0') 
            return 1; 
        /* otherwise, if this component is a directory, 
         * recursively satisfy lookup */ 
        else if (ISO_BY(FDV(dp, flags, fs->type)) & CD_DIRECTORY) 
            return (lookup(&thiscomp, fdp, nextcomp + 1, fs)); 
    } 
    /* if no match return fail */ 
    else 
        return(0); 
} 
/* --------------- object output routines for application ------------ */ 
/* Extract the entire contents of a directory entry and write this on 
 * standard output. */ 
void 
extractdirent(struct directent *dp, struct fs *fs) { 
    long    filesize = ISO_WD(FDV(dp, size, fs->type)), 
        lbn = 0, cnt; 
    char    *buffer = (char *) malloc(fs->lbs); 
    /* iterate over all contents of the directory entry */ 
    while (getblkdirent(dp, buffer, lbn, fs)) { 
        /* write out the valid portion of this logical block */ 
        cnt = filesize > fs->lbs ? fs->lbs : filesize; 
        (void) write (1, buffer,  cnt); 
        /* next one? */ 
        lbn++; 
        filesize -= cnt; 
        if (filesize == 0) break; 
    } 
    free(buffer); 
} 
/* Print directory header */ 
void 
printdirentheader(char *path) { 
    printf("Directory(%s):\n", path); 
    printf("Flags:\tsize date sysa name\n"); 
} 
/* Print all entries in the directory. */ 
void 
printdirents(struct directent *dp, struct fs *fs) { 
    struct directent *ldp; 
    long    filesize = ISO_WD(FDV(dp, size, fs->type)), 
        lbn = 0, cnt; 
    char    *buffer = (char *) malloc(fs->lbs); 
    while (getblkdirent(dp, buffer, lbn, fs)) { 
        long    entlen, namelen; 
        cnt = filesize > fs->lbs ? fs->lbs : filesize; 
        filesize -= cnt; 
        ldp = (struct directent *) buffer; 
        entlen = ISO_BY(FDV(ldp, length, fs->type)); 
        namelen = ISO_BY(FDV(ldp, name_len, fs->type)); 
        /* have we a record to match? */ 
        while (cnt > sizeof (union fsdir) && entlen && namelen) { 
            printdirent(ldp, fs); 
            /* next entry? */ 
            cnt -= entlen; 
            ldp = (struct directent *) (((char *) ldp) + entlen); 
            entlen = ISO_BY(FDV(ldp, length, fs->type)); 
            namelen = ISO_BY(FDV(ldp, name_len, fs->type)); 
        } 
        if (filesize == 0) break; 
        lbn++; 
    } 
    free(buffer); 
} 
/* Print a directent on output, formatted. */ 
void 
printdirent(struct directent *dp, struct fs *fs) { 
    unsigned extattlen; 
    unsigned fbname, name_len, entlen, enttaken; 
    /* mode flags */ 
    prmodes(ISO_BY(FDV(dp, flags, fs->type))); 
/* Note: this feature of HSF is not used because of lack of semantic def. */ 
#ifdef whybother 
    extattlen = ISO_BY(FDV(dp, ext_attr_length, fs->type)); 
    if (extattlen) 
        printf(" E%3d", extattlen); 
    else 
        printf("     "); 
#endif 
    /* size */ 
    printf("\t%6d", ISO_WD(FDV(dp, size, fs->type))); 
    /* time */ 
    printf(" %s", 
       cdrom_time((struct cdromtime *) FDV(dp, date, fs->type),fs->type)); 
    /* compensate for reserved field used to word align directory entry */ 
    entlen = ISO_BY(FDV(dp, length, fs->type)); 
    name_len = ISO_BY(FDV(dp, name_len, fs->type)); 
    enttaken = sizeof(union fsdir) + name_len; 
    if (enttaken & 1) 
        enttaken++; 
    fbname = ISO_BY(FDV(dp, name, fs->type)); 
    entlen -= enttaken; 
    /* print size of CDROM Extensions field if present */ 
    if (entlen) 
        printf(" %3d", entlen); 
    else 
        printf("    "); 
    /* finally print name. compensate for unprintable names */ 
    if (name_len == 1 && fbname <= 1) { 
        printf("\t%s\n", (fbname == 0) ? "." : ".."); 
    } else 
        printf("\t%s\n", 
            iso_astring(FDV(dp, name, fs->type), name_len)); 
}; 
/* print CDROM file modes */ 
prmodes(f) { 
    int i; 
    for(i=0; i < 8; i++) { 
        if(CD_FLAGBITS[i] == ' ')  
            continue; 
        if(f & (1<<i)) 
            putchar(CD_FLAGBITS[i]); 
        else 
            putchar('-'); 
    } 
    putchar(' '); 
} 
/* attempt to print a CDROM file's creation time */ 
char * 
cdrom_time(struct cdromtime *crt, int type) { 
    struct tm tm; 
    static char buf[32]; 
    char *fmt; 
    /* step 1. convert into a ANSI C time description */ 
    tm.tm_sec = crt->sec; 
    tm.tm_min = crt->min; 
    tm.tm_hour = crt->hour; 
    tm.tm_mday = crt->day; 
    /* month starts with 1 */ 
    tm.tm_mon = crt->month - 1; 
    tm.tm_year = crt->years; 
    tm.tm_isdst = 0; 
/* Note: not all ISO-9660 disks have correct timezone field */ 
#ifdef whybother 
    /* ISO has time zone as 7th octet, HSF does not */ 
    if (type == ISO) { 
        tm.tm_gmtoff = crt->tz*15*60; 
        tm.tm_zone = timezone(crt->tz*15, 0); 
        fmt = "%b %e %H:%M:%S %Z %Y"; 
    } else 
#endif 
        fmt = "%b %e %H:%M:%S %Y"; 
    /* step 2. use ANSI C standard function to format time properly */ 
    (void)strftime(buf, sizeof(buf), fmt, &tm); 
    return (buf); 
} 
static char __strbuf[200]; 
/* turn a blank padded character field into the null terminated strings 
   that POSIX/UNIX/WHATSIX likes so much */ 
char *iso_astring(char *sp, int len) { 
    bcopy(sp, __strbuf, len); 
    __strbuf[len] = 0; 
    for (sp = __strbuf + len - 1; sp > __strbuf ; sp--) 
        if (*sp == ' ') 
            *sp = 0; 
    return(__strbuf); 
} 
 
 
 
 
[LISTING FIVE] 
 
bill 1 % cdromcat 
Root Directory Listing: 
Directory(/): 
Flags:	size date sysa name 
-d---- 	  2048 Jul 27 12:49:16 1992    	. 
-d---- 	  2048 Jul 27 12:49:16 1992    	.. 
------ 	394127 Jul 24 01:21:06 1992    	0.ALL;1 
------ 	289565 Jul 24 01:21:06 1992    	0.ASK;1 
------ 	  2454 Jul 23 23:57:56 1992    	0.DOC;1 
-d---- 	  2048 Jul 27 12:50:06 1992    	A2Z 
-d---- 	  2048 Jul 27 12:50:07 1992    	AI 
-d---- 	  2048 Jul 27 12:50:07 1992    	ARCHIVE 
-d---- 	  2048 Jul 27 12:50:08 1992    	CAD 
-d---- 	  2048 Jul 27 12:50:08 1992    	DATABASE 
-d---- 	  2048 Jul 27 12:50:08 1992    	DATACOMM 
-d---- 	  2048 Jul 27 12:50:10 1992    	DESKTOP 
-d---- 	  2048 Jul 27 12:50:10 1992    	DOCPREP 
-d---- 	  2048 Jul 27 12:50:13 1992    	GAME 
-d---- 	  2048 Jul 27 12:50:13 1992    	GRAPHICS 
-d---- 	  2048 Jul 27 12:50:16 1992    	LANGUAGE 
-d---- 	  2048 Jul 27 12:50:27 1992    	MATH 
-d---- 	  2048 Jul 27 12:50:27 1992    	MISC 
-d---- 	  2048 Jul 27 12:50:28 1992    	MUSIC 
-d---- 	  2048 Jul 27 12:50:29 1992    	OS 
-d---- 	  2048 Jul 27 12:50:29 1992    	PGM_TOOL 
-d---- 	  2048 Jul 27 12:50:30 1992    	SCIENCE 
Pathname to open? : 0.DOC;1 
Topic:		(/) 
 
Description:	This is the top level directory of the PTF disc. 
 
Notes: 
<... contents of file ... > 
 
Pathname to open? : OS 
Directory(OS): 
Flags:	size date sysa name 
-d---- 	  2048 Jul 27 12:50:29 1992    	. 
-d---- 	  2048 Jul 27 12:49:16 1992    	.. 
------ 	   593 Jul 23 23:53:40 1992    	0.DOC;1 
-d---- 	  2048 Jul 27 12:50:29 1992    	CONDOR 
-d---- 	  2048 Jul 27 12:50:29 1992    	MACH 
-d---- 	  2048 Jul 27 12:50:29 1992    	MDQS 
-d---- 	  2048 Jul 27 12:50:29 1992    	PLAN_9 
Pathname to open? : OS/PLAN_9 
Directory(OS/PLAN_9): 
Flags:	size date sysa name 
-d---- 	  2048 Jul 27 12:50:29 1992    	. 
-d---- 	  2048 Jul 27 12:50:29 1992    	.. 
------ 	   732 Jul 23 23:41:38 1992    	0.DOC;1 
------ 	    31 Jul 23 23:03:30 1992    	0.LST;1 
------ 	230093 Jul 23 23:03:30 1992    	PAPERS.ATZ;1 
------ 	   472 Jul 23 23:03:30 1992    	PAPERS.LTV;1 
Pathname to open? :  
bill 2 % 
 
 
 
 
