home *** CD-ROM | disk | FTP | other *** search
/ ftp.cdrom.com/pub/cdrom/ / cdrom.tar / cdrom / textinfo / cdrom.asc < prev    next >
Text File  |  1993-03-19  |  24KB  |  687 lines

  1. _INSIDE THE ISO-966 FILESYSTEM FORMAT_
  2. by William Frederick Jolitz and Lynne Greer Jolitz
  3.  
  4. [LISTING ONE]
  5.  
  6. /* cdromcheck: A simple program to check what kind of CDROM we have, and to 
  7.  * list the volume descriptors that are present, if any. */
  8.  
  9. #include <stdio.h>
  10. #include "primary_descriptor"
  11. #include "directory_entry"
  12.  
  13. #define VD_LSN       16   /* first logical sector of volume descriptor table */
  14. #define CDROM_LSECSZ 2048 /* initial logical sector size of a CDROM */
  15.  
  16. char buffer[CDROM_LBS];
  17. static hsffmt, isofmt;
  18. void doiso(struct iso_primary_descriptor *, int);
  19. void dohsf(struct hsf_primary_descriptor *, int);
  20.  
  21. #define HSF 1
  22. #define ISO 2
  23. int cdromfmt;
  24.  
  25. char *cdromfmtnames[] = {
  26.     "unknown format",
  27.     "High Sierra",
  28.     "ISO - 9660"
  29. };
  30. char *voltypenames[] = {
  31.     "Boot Record",
  32.     "Standard File Structure",
  33.     "Coded Character Set File Structure",
  34.     "Unspecified File Structure",
  35. };
  36. #define NVOLTYPENAMES   (sizeof(voltypenames)/sizeof(char *))
  37. int
  38. main(int argc, char *argv[])
  39. {
  40.     struct iso_primary_descriptor *ipd;
  41.     struct hsf_primary_descriptor *hpd;
  42.     int cdfd;
  43.  
  44.     cdfd = open("/dev/ras2d", 0);
  45.     /* locate at the beginning of the descriptor table */
  46.     lseek(cdfd, VD_LSN*CDROM_LSECSZ, SEEK_SET);
  47.     ipd = (struct iso_primary_descriptor *) buffer;
  48.     hpd = (struct hsf_primary_descriptor *) buffer;
  49.     /* walk descriptor table */
  50.     for(;;) {
  51.         unsigned char type;
  52.         read(cdfd, buffer, sizeof(buffer));
  53.         /* determine ISO or HSF format of CDROM */
  54.         if (cdromfmt == 0) {
  55.           if (strncmp (ipd->id, ISO_STANDARD_ID, sizeof(ipd->id)) == 0)
  56.                 cdromfmt = ISO;
  57.           if (strncmp (hpd->id, HSF_STANDARD_ID, sizeof(hpd->id)) == 0)
  58.                 cdromfmt = HSF;
  59.           if (cdromfmt)
  60.            printf("%s Volume Descriptors:\n", cdromfmtnames[cdromfmt]);
  61.             else {
  62.                 printf("%s\n", cdromfmtnames[0]);
  63.                 exit(0);
  64.             }
  65.         }
  66.         /* type of descriptor */
  67.         if (cdromfmt == ISO)
  68.             type = (unsigned char)ipd->type[0];
  69.         else
  70.             type = (unsigned char)hpd->type[0];
  71.  
  72.         /* type of volume */
  73.         if (type < NVOLTYPENAMES)
  74.             printf("\t%s\n", voltypenames[type]);
  75.         else if (type != VD_END)
  76.             printf("\t Reserved - %d\n", type);
  77.  
  78.         /* terminating volume */
  79.         if (type == VD_END)
  80.             break;
  81.         /* ISO 9660 filestructure */
  82.         if (cdromfmt == ISO && type == VD_PRIMARY
  83.          && strncmp (ipd->id, ISO_STANDARD_ID, sizeof(ipd->id)) == 0) {
  84.             doiso(ipd, cdfd);
  85.             isofmt++;
  86.             continue;
  87.         }
  88.         /* (obselete) High Sierra filestructure */
  89.         if (cdromfmt == HSF && type == VD_PRIMARY
  90.          && strncmp (hpd->id, HSF_STANDARD_ID, sizeof(hpd->id)) == 0) {
  91.             dohsf(hpd, cdfd);
  92.             hsffmt++;
  93.             continue;
  94.         }
  95.         printf("\n");
  96.     }
  97.     return (0);
  98. }
  99. char *iso_astring(char *, int len);
  100. /* rude translation routines for interpreting strings, words, halfwords */
  101. #define ISO_AS(s)   (iso_astring(s, sizeof(s)))
  102. #define ISO_WD(s)   (*(unsigned *)(s))
  103. #define ISO_HWD(s)  (*(unsigned short *)(s))
  104. /* dig out the details of a ISO - 9660 descriptor */
  105. void
  106. doiso(struct iso_primary_descriptor *ipd, int fd) {
  107.    printf(" Volume ID:\t\t%s\n", ISO_AS(ipd->volume_id));
  108.    printf(" Logical Block Size:\t%d\n", ISO_HWD(ipd->logical_block_size));
  109.    printf(" Volume Set ID:\t\t%s\n", ISO_AS(ipd->volume_set_id));
  110.    printf(" Publisher ID:\t\t%s\n", ISO_AS(ipd->publisher_id));
  111.    printf(" Preparer ID:\t\t%s\n", ISO_AS(ipd->preparer_id));
  112.    printf(" Application ID:\t\t%s\n", ISO_AS(ipd->application_id));
  113.    printf(" Copyright File ID:\t%s\n", ISO_AS(ipd->copyright_file_id));
  114.    printf(" Abstract File ID:\t%s\n", ISO_AS(ipd->abstract_file_id));
  115.    printf(" Bibliographic File ID:\t%s\n", ISO_AS(ipd->bibliographic_file_id));
  116.    printf(" Creation Date:\t\t%s\n", ISO_AS(ipd->creation_date));
  117.    printf(" Modification Date:\t%s\n", ISO_AS(ipd->modification_date));
  118.    printf(" Expiration Date:\t%s\n", ISO_AS(ipd->expiration_date));
  119.    printf(" Effective Date:\t%s\n", ISO_AS(ipd->effective_date));
  120. }
  121. /* dig out the details of a High Sierra Descriptor */
  122. void
  123. dohsf(struct hsf_primary_descriptor *hpd, int fd) {
  124.     printf(" Volume Logical Block Number:\t%d\n", ISO_WD(hpd->volume_lbn));
  125.     printf(" Volume ID:\t\t%s\n", ISO_AS(hpd->volume_id));
  126.     printf(" Logical Block Size:\t%d\n", ISO_HWD(hpd->logical_block_size));
  127.     printf(" Volume Set ID:\t\t%s\n", ISO_AS(hpd->volume_set_id));
  128.     printf(" Publisher ID:\t\t%s\n", ISO_AS(hpd->publisher_id));
  129.     printf(" Preparer ID:\t\t%s\n", ISO_AS(hpd->preparer_id));
  130.     printf(" Application ID:\t\t%s\n", ISO_AS(hpd->application_id));
  131.     printf(" Copyright File ID:\t%s\n", ISO_AS(hpd->copyright_file_id));
  132.     printf(" Abstract File ID:\t%s\n", ISO_AS(hpd->abstract_file_id));
  133.     printf(" Creation Date:\t\t%s\n", ISO_AS(hpd->creation_date));
  134.     printf(" Modification Date:\t%s\n", ISO_AS(hpd->modification_date));
  135.     printf(" Expiration Date:\t%s\n", ISO_AS(hpd->expiration_date));
  136.     printf(" Effective Date:\t%s\n", ISO_AS(hpd->effective_date));
  137. }
  138. static char __strbuf[200];
  139. /* turn a blank padded character feild into the null terminated strings
  140.    that POSIX/UNIX/WHATSIX likes so much */
  141. char *iso_astring(char *sp, int len) {
  142.     bcopy(sp, __strbuf, len);
  143.     __strbuf[len] = 0;
  144.     for (sp = __strbuf + len - 1; sp > __strbuf ; sp--)
  145.         if (*sp == ' ')
  146.             *sp = 0;
  147.     return(__strbuf);
  148. }
  149.  
  150.  
  151. [LISTING TWO]
  152.  
  153. From Rich Morin's "Prime Time Freeware", Vol 1.1 CDROM:
  154.  
  155. ISO - 9660 Volume Descriptors: Standard File Structure
  156.  Volume ID:     PTF_1_1
  157.  Logical Block Size:    2048
  158.  Volume Set ID:      
  159.  Publisher ID:       
  160.  Preparer ID:       MERIDIAN_DATA_CD_PUBLISHER
  161.  Application ID:         
  162.  Copyright File ID:  
  163.  Abstract File ID:   
  164.  Bibliographic File ID:  
  165.  Creation Date:     1992011101452700
  166.  Modification Date: 1992011101452700
  167.  Expiration Date:   0000000000000000
  168.  Effective Date:    1992011101452700
  169.  
  170.  
  171. From Discovery System's CD-ROM Sampler:
  172.  
  173. High Sierra Volume Descriptors:
  174.  
  175.     Standard File Structure
  176.  Volume Logical Block Number:   16
  177.  Volume ID:     CDROM_SAMP1
  178.  Logical Block Size:    2048
  179.  Volume Set ID:     CDROM_SAMP1
  180.  Publisher ID:      DISCOVERY
  181.  Preparer ID:       DISCOVERY
  182.  Application ID:         
  183.  Copyright File ID:  
  184.  Abstract File ID:   
  185.  Creation Date:     1987111215553400
  186.  Modification Date: 1987111215553400
  187.  Expiration Date:   0000000000000000
  188.  Effective Date:    0000000000000000
  189.  
  190.     Standard File Structure
  191.  Volume Logical Block Number:   17
  192.  Volume ID:     CDROM_SAMP1
  193.  Logical Block Size:    2048
  194.  Volume Set ID:     CDROM_SAMP1
  195.  Publisher ID:      DISCOVERY
  196.  Preparer ID:       DISCOVERY
  197.  Application ID:         
  198.  Copyright File ID:  
  199.  Abstract File ID:   
  200.  Creation Date:     1987111215553400
  201.  Modification Date: 1987111215553400
  202.  Expiration Date:   0000000000000000
  203.  Effective Date:    0000000000000000
  204.  
  205.  
  206. [LISTING THREE]
  207.  
  208. /* cdromfs.h: various definitions for CDROM filesystems. */
  209.  
  210. #define VD_LSN        16  /* first logical sector of volume descriptor table */
  211. #define CDROM_LSECSZ  2048 /* initial logical sector size of a CDROM */
  212.  
  213. #define HSF 1
  214. #define ISO 2
  215.  
  216. char *cdromfmtnames[] = {
  217.     "unknown format",
  218.     "High Sierra",
  219.     "ISO - 9660"
  220. };
  221. char *voltypenames[] = {
  222.     "Boot Record",
  223.     "Standard File Structure",
  224.     "Coded Character Set File Structure",
  225.     "Unspecified File Structure",
  226. };
  227. /* rude translation routines for interpreting strings, words, halfwords */
  228. #define ISO_AS(s)   (iso_astring(s, sizeof(s)))
  229. #define ISO_WD(s)   (*(unsigned *)(s))
  230. #define ISO_HWD(s)  (*(unsigned short *)(s))
  231. #define ISO_BY(s)   (*(unsigned char *)(s))
  232.  
  233. #define NVOLTYPENAMES   (sizeof(voltypenames)/sizeof(char *))
  234. struct cdromtime {
  235.     unsigned char years;    /* number of years since 1900 */
  236.     unsigned char month;    /* month of the year */
  237.     unsigned char day;  /* day of month */
  238.     unsigned char hour; /* hour of day */
  239.     unsigned char min;  /* minute of the hour */
  240.     unsigned char sec;  /* second of the minute */
  241.     unsigned char tz;   /* timezones, in quarter hour increments */
  242.                 /* or, longitude in 3.75 of a degree */
  243. };
  244. #define CD_FLAGBITS "vdaEp  m"  /* file flag bits */
  245. /* Handy macro's for block calculation */
  246. #define lbntob(fs, n)   ((fs)->lbs * (n))
  247. #define btolbn(fs, n)   ((fs)->lbs * (n))
  248. #define trunc_lbn(fs, n)    ((n) - ((n) % (fs)->lbs)
  249. #define roundup(n, d)   ((((n) + (d)) / (d)) * (d))
  250.  
  251.  
  252.  
  253. [LISTING FOUR]
  254.  
  255. /* cdromcat -- A simple program to interpret the CDROM filesystem, and return.
  256.  * the contents of the file (directories are formatted and printed, files are 
  257.  * returned untranslated).  */
  258.  
  259. #include <sys/types.h>
  260. #include <stdio.h>
  261. #include <stdlib.h>
  262. #include <string.h>
  263. #include <time.h>
  264. #include "primary_descriptor"
  265. #include "directory_entry"
  266. #include "cdromfs.h"
  267.  
  268. /* per filesystem information */
  269. struct fs {
  270.     char *name; /* kind of cdrom filesystem */
  271.     int fd;     /* open file descriptor */
  272.     int lbs;    /* logical block size */
  273.     int type;   /* which flavor */
  274. } fsd;
  275. /* filesystem directory entry */
  276. struct directent {
  277.     union fsdir {
  278.         struct iso_directory_record iso_dir;
  279.         struct hsf_directory_record hsf_dir;
  280.     } fsd;
  281.     /* actually, name contains name, reserved field, and extensions area */
  282.     char name[255 - sizeof(union fsdir)];
  283. }   rootent;
  284. /* filesystem volume descriptors */
  285. union voldesc {
  286.     struct iso_primary_descriptor  iso_desc;
  287.     struct hsf_primary_descriptor  hsf_desc;
  288. };
  289. char *iso_astring(char *, int len);
  290. char *cdrom_time(struct cdromtime *, int);
  291. void printdirent(struct directent *, struct fs *);
  292. void printdirents(struct directent *, struct fs *);
  293. void printdirentheader(char *p);
  294. int searchdirent(struct directent *, struct directent *, struct directent *,
  295.     struct fs *);
  296. void extractdirent(struct directent *, struct fs *);
  297. int lookup(struct directent *, struct directent *, char *, struct fs *);
  298. /* "fetch directory value" */
  299. #define FDV(b, f, t)    (((t) == ISO) ? (b)->fsd.iso_dir.##f \
  300.                 : (b)->fsd.hsf_dir.##f)
  301. /* "fetch primary descriptor value" */
  302. #define FPDV(b, f, t)   (((t) == ISO) ? (b)->iso_desc.##f \
  303.                 : (b)->hsf_desc.##f)
  304. /* user "application" program */
  305. int
  306. main(int argc, char *argv[])
  307. {
  308.     struct directent openfile;
  309.     char pathname[80];
  310.     /* open the CDROM device */
  311.     if ((fsd.fd = open("/dev/ras2d", 0)) < 0) {
  312.         perror("cdromcat");
  313.         exit(1);
  314.     }
  315.     /* is there a filesystem we can understand here? */
  316.     if (iscdromfs(&rootent, &fsd) == 0) {
  317.         fprintf(stderr, "cdromcat: %s\n", fsd.name);
  318.         exit(1);
  319.     }
  320.     /* print the contents of the root directory to give user a start */
  321.     printf("Root Directory Listing:\n");
  322.     printdirentheader("/");
  323.     printdirents(&rootent, &fsd);
  324.     /* print files on demand from user */
  325.     for(;;){
  326.         /* prompt user for name to locate */
  327.         printf("Pathname to open? : ");
  328.         fflush(stdout);
  329.         /* obtain, if none, exit, else trim newline off */
  330.         if (fgets(pathname, sizeof(pathname), stdin) == NULL)
  331.             exit(0);
  332.         pathname[strlen(pathname) - 1] = '\0';
  333.         if (strlen(pathname) == 0)
  334.             exit(0);
  335.         /* lookup filename on CDROM */
  336.         if (lookup(&rootent, &openfile, pathname, &fsd)){
  337.             /* if a directory, format and list it */
  338.             if (ISO_BY(FDV(&openfile, flags, fsd.type))
  339.                 & CD_DIRECTORY) {
  340.                 printdirentheader(pathname);
  341.                 printdirents(&openfile, &fsd);
  342.             } 
  343.             /* if a file, print it on standard output */
  344.             else
  345.                 extractdirent(&openfile, &fsd);
  346.         } else
  347.             printf("Not found.\n");
  348.     }
  349.     /* NOTREACHED */
  350. }
  351. /* ----------- Filesystem primatives ------------------- */
  352. /* Check for the presence of a cdrom filesystem. If present, pass back 
  353.  * parameters for initialization, otherwise, pass back error. */
  354. int
  355. iscdromfs(struct directent *dp, struct fs *fs) {
  356.     char buffer[CDROM_LSECSZ];
  357.     union voldesc *vdp = (union voldesc *) buffer;
  358.     /* locate at the beginning of the descriptor table */
  359.     lseek(fs->fd, VD_LSN*CDROM_LSECSZ, SEEK_SET);
  360.     /* walk descriptor table */
  361.     for(;;) {
  362.         unsigned char type;
  363.         /* obtain a descriptor */
  364.         read(fs->fd, buffer, sizeof(buffer));
  365.         /* determine ISO or HSF format of CDROM */
  366.         if (fs->type == 0) {
  367.             if (strncmp (vdp->iso_desc.id, ISO_STANDARD_ID,
  368.                 sizeof(vdp->iso_desc.id)) == 0)
  369.                 fs->type = ISO;
  370.             if (strncmp (vdp->hsf_desc.id, HSF_STANDARD_ID,
  371.                 sizeof(vdp->hsf_desc.id)) == 0)
  372.                 fs->type = HSF;
  373.         } 
  374.         /* if determined, obtain root directory entry */
  375.         if (fs->type) {
  376.             type = ISO_BY(FPDV(vdp, type, fs->type));
  377.             if (type == VD_PRIMARY) {
  378.                 bcopy (
  379.             (caddr_t) FPDV(vdp, root_directory_record, fs->type),
  380.                 (caddr_t)dp, sizeof (union fsdir));
  381.             fs->lbs =
  382.                   ISO_HWD(FPDV(vdp, logical_block_size, fs->type));
  383.             }
  384.         }
  385.         /* terminating volume */
  386.         if (type == VD_END)
  387.             break;
  388.     }
  389.     fs->name = cdromfmtnames[fs->type];
  390.     return (fs->type);
  391. }
  392. /* Obtain a "logical", i.e. relative to the directory entries beginning
  393.  * (or extent), block from the CDROM. */
  394. int
  395. getblkdirent(struct directent *dp, char *contents, long lbn, struct fs *fs) {
  396.     long    filesize = ISO_WD(FDV(dp, size, fs->type)),
  397.         extent = ISO_WD(FDV(dp, extent, fs->type));
  398.     if (lbntob(fs, lbn) > roundup(filesize, fs->lbs))
  399.         return (0);
  400.     /* perform logical to physical translation */
  401.     (void) lseek(fs->fd, lbntob(fs, extent + lbn), SEEK_SET);
  402.     /* obtain block */
  403.     return (read(fs->fd, contents, fs->lbs) == fs->lbs);
  404. }
  405. /* Search the contents of this directory entry, known to be a directory itself,
  406.  * looking for a component. If found, return directory entry associated with 
  407.  * the component. */
  408. int
  409. searchdirent(struct directent *dp, struct directent *fdp,
  410.     struct directent *compdp, struct fs *fs) {
  411.     struct directent *ldp;
  412.     long    filesize =  ISO_WD(FDV(dp, size, fs->type)),
  413.         comp_namelen =  ISO_BY(FDV(compdp, name_len, fs->type)),
  414.         lbn = 0, cnt;
  415.     char    *buffer = (char *) malloc(fs->lbs);
  416.     while (getblkdirent(dp, buffer, lbn, fs)) {
  417.         cnt = filesize > fs->lbs ? fs->lbs : filesize;
  418.         filesize -= cnt;
  419.         ldp = (struct directent *) buffer;
  420.         /* have we a record to match? */
  421.         while (cnt > sizeof (union fsdir)) {
  422.             long    entlen, namelen;
  423.             /* match against component's name and name length */
  424.             entlen = ISO_BY(FDV(ldp, length, fs->type));
  425.             namelen = ISO_BY(FDV(ldp, name_len, fs->type));
  426.     if (entlen >= comp_namelen + sizeof(union fsdir) && namelen == comp_namelen
  427.                 && strncmp(FDV(ldp,name,fs->type),
  428.                 FDV(compdp,name,fs->type), namelen) == 0) {
  429.                 bcopy ((caddr_t)ldp, (caddr_t)fdp, entlen);
  430.                 bcopy ((caddr_t)ldp, (caddr_t)compdp, entlen);
  431.                 free(buffer);
  432.                 return 1;
  433.             } else {
  434.                 cnt -= entlen;
  435.                 ldp = (struct directent *)
  436.                     (((char *) ldp) + entlen);
  437.             }
  438.         }
  439.         if (filesize == 0) break;
  440.         lbn++;
  441.     }
  442.     free(buffer);
  443.     return 0;
  444. }
  445. /* Lookup the pathname by interpreting the directory structure of the CDROM 
  446.  * element by element, returning a directory entry if found. Name translation 
  447.  * occurs here, out of the null terminated path name string. This routine 
  448.  * works by recursion. */
  449. int
  450. lookup(struct directent *dp, struct directent *fdp, char *pathname,
  451.     struct fs *fs) {
  452.     struct directent *ldp;
  453.     struct directent thiscomp;
  454.     char *nextcomp;
  455.     unsigned len;
  456.     /* break off the next component of the pathname */
  457.     if ((nextcomp = strrchr(pathname, '/'))  == NULL)
  458.         nextcomp = strrchr(pathname, '\0');
  459.     /* construct an entry for this component to match */
  460.     ISO_BY(FDV(&thiscomp, name_len, fs->type)) = len = nextcomp - pathname;
  461.     bcopy(pathname, thiscomp.name, len);
  462.     /* attempt a match, returning component if found */
  463.     if (searchdirent(dp, fdp, &thiscomp, fs)){
  464.         /* if no more components, return found value */
  465.         if (*nextcomp == '\0')
  466.             return 1;
  467.         /* otherwise, if this component is a directory,
  468.          * recursively satisfy lookup */
  469.         else if (ISO_BY(FDV(dp, flags, fs->type)) & CD_DIRECTORY)
  470.             return (lookup(&thiscomp, fdp, nextcomp + 1, fs));
  471.     }
  472.     /* if no match return fail */
  473.     else
  474.         return(0);
  475. }
  476. /* --------------- object output routines for application ------------ */
  477. /* Extract the entire contents of a directory entry and write this on
  478.  * standard output. */
  479. void
  480. extractdirent(struct directent *dp, struct fs *fs) {
  481.     long    filesize = ISO_WD(FDV(dp, size, fs->type)),
  482.         lbn = 0, cnt;
  483.     char    *buffer = (char *) malloc(fs->lbs);
  484.     /* iterate over all contents of the directory entry */
  485.     while (getblkdirent(dp, buffer, lbn, fs)) {
  486.         /* write out the valid portion of this logical block */
  487.         cnt = filesize > fs->lbs ? fs->lbs : filesize;
  488.         (void) write (1, buffer,  cnt);
  489.         /* next one? */
  490.         lbn++;
  491.         filesize -= cnt;
  492.         if (filesize == 0) break;
  493.     }
  494.     free(buffer);
  495. }
  496. /* Print directory header */
  497. void
  498. printdirentheader(char *path) {
  499.     printf("Directory(%s):\n", path);
  500.     printf("Flags:\tsize date sysa name\n");
  501. }
  502. /* Print all entries in the directory. */
  503. void
  504. printdirents(struct directent *dp, struct fs *fs) {
  505.     struct directent *ldp;
  506.     long    filesize = ISO_WD(FDV(dp, size, fs->type)),
  507.         lbn = 0, cnt;
  508.     char    *buffer = (char *) malloc(fs->lbs);
  509.     while (getblkdirent(dp, buffer, lbn, fs)) {
  510.         long    entlen, namelen;
  511.         cnt = filesize > fs->lbs ? fs->lbs : filesize;
  512.         filesize -= cnt;
  513.         ldp = (struct directent *) buffer;
  514.         entlen = ISO_BY(FDV(ldp, length, fs->type));
  515.         namelen = ISO_BY(FDV(ldp, name_len, fs->type));
  516.         /* have we a record to match? */
  517.         while (cnt > sizeof (union fsdir) && entlen && namelen) {
  518.             printdirent(ldp, fs);
  519.             /* next entry? */
  520.             cnt -= entlen;
  521.             ldp = (struct directent *) (((char *) ldp) + entlen);
  522.             entlen = ISO_BY(FDV(ldp, length, fs->type));
  523.             namelen = ISO_BY(FDV(ldp, name_len, fs->type));
  524.         }
  525.         if (filesize == 0) break;
  526.         lbn++;
  527.     }
  528.     free(buffer);
  529. }
  530. /* Print a directent on output, formatted. */
  531. void
  532. printdirent(struct directent *dp, struct fs *fs) {
  533.     unsigned extattlen;
  534.     unsigned fbname, name_len, entlen, enttaken;
  535.     /* mode flags */
  536.     prmodes(ISO_BY(FDV(dp, flags, fs->type)));
  537. /* Note: this feature of HSF is not used because of lack of semantic def. */
  538. #ifdef whybother
  539.     extattlen = ISO_BY(FDV(dp, ext_attr_length, fs->type));
  540.     if (extattlen)
  541.         printf(" E%3d", extattlen);
  542.     else
  543.         printf("     ");
  544. #endif
  545.     /* size */
  546.     printf("\t%6d", ISO_WD(FDV(dp, size, fs->type)));
  547.     /* time */
  548.     printf(" %s",
  549.        cdrom_time((struct cdromtime *) FDV(dp, date, fs->type),fs->type));
  550.     /* compensate for reserved field used to word align directory entry */
  551.     entlen = ISO_BY(FDV(dp, length, fs->type));
  552.     name_len = ISO_BY(FDV(dp, name_len, fs->type));
  553.     enttaken = sizeof(union fsdir) + name_len;
  554.     if (enttaken & 1)
  555.         enttaken++;
  556.     fbname = ISO_BY(FDV(dp, name, fs->type));
  557.     entlen -= enttaken;
  558.     /* print size of CDROM Extensions field if present */
  559.     if (entlen)
  560.         printf(" %3d", entlen);
  561.     else
  562.         printf("    ");
  563.     /* finally print name. compensate for unprintable names */
  564.     if (name_len == 1 && fbname <= 1) {
  565.         printf("\t%s\n", (fbname == 0) ? "." : "..");
  566.     } else
  567.         printf("\t%s\n",
  568.             iso_astring(FDV(dp, name, fs->type), name_len));
  569. };
  570. /* print CDROM file modes */
  571. prmodes(f) {
  572.     int i;
  573.     for(i=0; i < 8; i++) {
  574.         if(CD_FLAGBITS[i] == ' ') 
  575.             continue;
  576.         if(f & (1<<i))
  577.             putchar(CD_FLAGBITS[i]);
  578.         else
  579.             putchar('-');
  580.     }
  581.     putchar(' ');
  582. }
  583. /* attempt to print a CDROM file's creation time */
  584. char *
  585. cdrom_time(struct cdromtime *crt, int type) {
  586.     struct tm tm;
  587.     static char buf[32];
  588.     char *fmt;
  589.     /* step 1. convert into a ANSI C time description */
  590.     tm.tm_sec = crt->sec;
  591.     tm.tm_min = crt->min;
  592.     tm.tm_hour = crt->hour;
  593.     tm.tm_mday = crt->day;
  594.     /* month starts with 1 */
  595.     tm.tm_mon = crt->month - 1;
  596.     tm.tm_year = crt->years;
  597.     tm.tm_isdst = 0;
  598. /* Note: not all ISO-9660 disks have correct timezone field */
  599. #ifdef whybother
  600.     /* ISO has time zone as 7th octet, HSF does not */
  601.     if (type == ISO) {
  602.         tm.tm_gmtoff = crt->tz*15*60;
  603.         tm.tm_zone = timezone(crt->tz*15, 0);
  604.         fmt = "%b %e %H:%M:%S %Z %Y";
  605.     } else
  606. #endif
  607.         fmt = "%b %e %H:%M:%S %Y";
  608.     /* step 2. use ANSI C standard function to format time properly */
  609.     (void)strftime(buf, sizeof(buf), fmt, &tm);
  610.     return (buf);
  611. }
  612. static char __strbuf[200];
  613. /* turn a blank padded character field into the null terminated strings
  614.    that POSIX/UNIX/WHATSIX likes so much */
  615. char *iso_astring(char *sp, int len) {
  616.     bcopy(sp, __strbuf, len);
  617.     __strbuf[len] = 0;
  618.     for (sp = __strbuf + len - 1; sp > __strbuf ; sp--)
  619.         if (*sp == ' ')
  620.             *sp = 0;
  621.     return(__strbuf);
  622. }
  623.  
  624.  
  625.  
  626.  
  627. [LISTING FIVE]
  628.  
  629. bill 1 % cdromcat
  630. Root Directory Listing:
  631. Directory(/):
  632. Flags:    size date sysa name
  633. -d----       2048 Jul 27 12:49:16 1992        .
  634. -d----       2048 Jul 27 12:49:16 1992        ..
  635. ------     394127 Jul 24 01:21:06 1992        0.ALL;1
  636. ------     289565 Jul 24 01:21:06 1992        0.ASK;1
  637. ------       2454 Jul 23 23:57:56 1992        0.DOC;1
  638. -d----       2048 Jul 27 12:50:06 1992        A2Z
  639. -d----       2048 Jul 27 12:50:07 1992        AI
  640. -d----       2048 Jul 27 12:50:07 1992        ARCHIVE
  641. -d----       2048 Jul 27 12:50:08 1992        CAD
  642. -d----       2048 Jul 27 12:50:08 1992        DATABASE
  643. -d----       2048 Jul 27 12:50:08 1992        DATACOMM
  644. -d----       2048 Jul 27 12:50:10 1992        DESKTOP
  645. -d----       2048 Jul 27 12:50:10 1992        DOCPREP
  646. -d----       2048 Jul 27 12:50:13 1992        GAME
  647. -d----       2048 Jul 27 12:50:13 1992        GRAPHICS
  648. -d----       2048 Jul 27 12:50:16 1992        LANGUAGE
  649. -d----       2048 Jul 27 12:50:27 1992        MATH
  650. -d----       2048 Jul 27 12:50:27 1992        MISC
  651. -d----       2048 Jul 27 12:50:28 1992        MUSIC
  652. -d----       2048 Jul 27 12:50:29 1992        OS
  653. -d----       2048 Jul 27 12:50:29 1992        PGM_TOOL
  654. -d----       2048 Jul 27 12:50:30 1992        SCIENCE
  655. Pathname to open? : 0.DOC;1
  656. Topic:        (/)
  657.  
  658. Description:    This is the top level directory of the PTF disc.
  659.  
  660. Notes:
  661. <... contents of file ... >
  662.  
  663. Pathname to open? : OS
  664. Directory(OS):
  665. Flags:    size date sysa name
  666. -d----       2048 Jul 27 12:50:29 1992        .
  667. -d----       2048 Jul 27 12:49:16 1992        ..
  668. ------        593 Jul 23 23:53:40 1992        0.DOC;1
  669. -d----       2048 Jul 27 12:50:29 1992        CONDOR
  670. -d----       2048 Jul 27 12:50:29 1992        MACH
  671. -d----       2048 Jul 27 12:50:29 1992        MDQS
  672. -d----       2048 Jul 27 12:50:29 1992        PLAN_9
  673. Pathname to open? : OS/PLAN_9
  674. Directory(OS/PLAN_9):
  675. Flags:    size date sysa name
  676. -d----       2048 Jul 27 12:50:29 1992        .
  677. -d----       2048 Jul 27 12:50:29 1992        ..
  678. ------        732 Jul 23 23:41:38 1992        0.DOC;1
  679. ------         31 Jul 23 23:03:30 1992        0.LST;1
  680. ------     230093 Jul 23 23:03:30 1992        PAPERS.ATZ;1
  681. ------        472 Jul 23 23:03:30 1992        PAPERS.LTV;1
  682. Pathname to open? : 
  683. bill 2 %
  684.  
  685.  
  686.  
  687.