Extending Standards for CD-ROM

Although ISO-compliant CD-ROMs are interchangeable and usable on any type of system, the minimalism that made the ISO-9660 standard successful is sometimes too minimal. Consequently, the Rock Ridge Group and others have developed extensions to give new life to CD-ROMs.


July 01, 1993
URL:http://www.drdobbs.com/architecture-and-design/extending-standards-for-cd-rom/184409037

Figure 1


Figure 2


Copyright © 1993, Dr. Dobb's Journal

Figure 3


Copyright © 1993, Dr. Dobb's Journal

Figure 3


Copyright © 1993, Dr. Dobb's Journal

Figure 1


Copyright © 1993, Dr. Dobb's Journal

Figure 2


Copyright © 1993, Dr. Dobb's Journal

Figure 3


Copyright © 1993, Dr. Dobb's Journal

JUL93: Extending Standards for CD-ROM

Extending Standards for CD-ROM

Rock Ridge extends ISO-9660 for POSIX filesystems

Lynne Greer Jolitz

Lynne Jolitz is co-author of 386BSD, a PC implementation of the Berkeley UNIX operating system. She can be contacted on CompuServe at 76704,4266.


Most programmers are aware of the ISO-9660 standard and its significance in sharing CD-ROM data between different platforms. In our article "Inside the ISO-9660 Filesystem Format" (DDJ, December 1992), we examined how this standard has encouraged the use of CD-ROM technology and how a modern ISO-9660 CD-ROM is structured. ISO-compliant CD-ROMs are interchangeable and can be used on any type of system and architecture. However, the minimalism that helped make the ISO-9660 standard successful may sometimes be too minimal for specific applications (such as distributing POSIX-based, bootable CD-ROMs). Because ISO-9660 does not adequately support the POSIX filesystem, the Rock Ridge Group was formed to develop ISO-9660:1988 extensions, which take advantage of the system-use area of the directory record (provided for in ISO-9660) to store complete POSIX filesystem information.

Extensions to ISO-9660 can make a CD-ROM appear like a given target operating system (such as a POSIX-compliant filesystem). By encoding these extensions (using the sharing-use protocols), you can allow for separate sets of attributes for the same filesystem. This lets you organize extended information for different systems (such as VMS, DOS, and UNIX) in a nonconflicting way. Also, any system that only understands ISO-9660 without any extensions can still gain access to the files and obtain the exact same contents of data for a file; you aren't precluding any use of CD-ROM by the use of extensions, you're simply extending the scope of use of the information. You get the best of both worlds: ISO compatibility and interoperability, and POSIX operating-system transparency and functionality.

ISO-9660 Filesystem

A CD-ROM can be mastered with any kind of information on it. Unlike UNIX and DOS (and many other) filesystems which have blocks allocated from a separate list of nonsequential disk blocks, ISO-9660 specifies a dense, sequential arrangement of file information to minimize nonsequential access and, consequently, latency time.

Figure 1 illustrates an ISO-9660 CD-ROM. A reserved field at the beginning of the disk is often used in booting the CD-ROM. Immediately afterwards, a series of volume descriptors detail the contents and kind of information contained on the disk, somewhat akin to the DOS partition table (see the text box entitled, "Structure of the CD-ROM Volume Descriptor"). It's possible to have many different kinds of filesystems and information arrangements on a single CD-ROM. There are also many kinds of descriptors which can be used to optionally record non-ISO defined information contents.

ISO-9660:88 specifies a minimal set of file attributes (directory or ordinary file and time of recording) and name attributes (name, extension, and version) in the directory-entry fields, and has specific restrictions on naming conventions (see the text box entitled "Directory Entries and Filenames"). There are also attributes that make the file appear invisible even though it's still present (existence); allow some systems to store information adjacent to visible files without letting the user note their presence (association); determine whether the file is protected (protection); and determine whether the file is implemented as a group of directory entries to define a more complex multiple-data area (multi-extent).

These attributes allow for a simple hierarchical filesystem, but not for all of the file attributes in modern systems. To that end, ISO-9660 allowed for an optional extended attributes record (XAR) stored at the beginning of the file's extent which can contain additional file-attribute information. The file-attribute information contained in XAR comes at a cost--you must have an exact semantic definition of all fields in the context of each operating system that might use them. Because XAR semantics are designed by committee, they don't exactly match any system. Rather, they attempt to match all systems slightly. To further the problem, XAR information is stored adjacent to file contents on the disk rather than in the directory entry itself. Thus, an additional seek may be required to pick up the file attributes to decide if the file can even be opened in the first place. Even with the XAR present, you still can't record all of the file attributes of any one operating system in its entirety. This failure in the standard is precisely why extensions like Rock Ridge are necessary.

Since the limited set of ISO-9660 directory entries and attributes does not provide sufficient information to transparently reconstruct file attributes for POSIX, Macintosh, Windows NT, and other filesystems, a location for optional extensions called the system-use area was added for each file; see Figure 2. The system-use area is the space between successive ISO-9660 directory entries, denoted by the end of the current entry (fixed, optionally padded offset) and the start of the next entry. (ISO-9660 directory entries have separate name and entry lengths.)

One of the great strengths of ISO-9660 compliance lies in a developer's ability to support many types of filesystems on a single CD-ROM, by selectively using extensions stored in the system-use area. If an ISO-compliant driver or program is not familiar with certain extensions or with a particular type of extension, it will skip the embedded information in the directory entry and continue processing. Thus, many different types of extension attributes can be encoded on a single CD-ROM, although only the extensions pertinent to a particular system need be read. Also, since the information is embedded in the directory entry itself, there will be no additional seeks or data transfers that would slow the file-open process. In effect, ISO-9660 allows for variable-length attributes of an unspecified kind.

Extension Attributes

File attributes can specify anything about that file: graphics, color, a specific model of computer, and so forth. Extension attributes are simply a way to extend the attributes of files. Since attributes vary according to the user, most everyone has a different opinion on what a file attribute should specify. Hence, different extensions have evolved to meet these differing and potentially conflicting standards. In fact, the standards battle in the extension arena--contention for the limited space allocated to extensions and how they are structured--continues. Since attributes and extensions change by their very nature, the standard was actually separated into two parts: the system-use sharing protocol (SUSP) and the actual Rock Ridge extensions.

SUSP dictates the structure of each file extension, much in the same way a directory entry is structured; see Figure 3(a). The system-use area is divided into a number of these extension fields; see Figure 3(b). This approach simply addresses the void in ISO-9660 by providing a mechanism for standards to coexist in the extensions area. In other words, SUSP defines standard "containers" in which the extensions live. Each system-use field is identified by a "system-use field signature word." The signature word field specifies what kind of extension it is; see Table 1(a). This is a universal category, in that you can not only process known types such as SUSP and Rock Ridge extensions, but also specify a proprietary extension, such as one specific to a target piece of hardware and known by the target hardware CD-ROM driver (such as a laser printer). If the driver understands more than one extension entry, then it can use the union of these sets of attributes. The length field of the extension is recorded at the beginning, allowing the system to skip to the next extension entry if the previous one is processed or if the entry itself is not understood by the CD-ROM driver.

One of the most critical of the SUSP extensions mechanisms is the continuation entry, or CE, that allows arbitrary, logical extension of the system-use area to a linked-list chain of sectors. This provides additional room for extension information. Thus, SUSP files can have arbitrary numbers of extensions without fear of overflowing a fixed field size. Basically, SUSP is a filesystem within a filesystem for attributes.

Rock Ridge Extensions

Because ISO-9660 provides insufficient information to reconstruct a UNIX filesystem, most CD-ROM UNIX filesystem implementations have had to fake reasonable file attributes. One method is to inherit attributes, such as directory ownership and permissions, directly from the directory currently mounted (as in SVR4). Another method uses preset values and some type of filesystem translation to obtain file attributes (as in 386BSD Release 0.1 and SUNOS 4.x). However, the Rock Ridge Interchange Protocol (RRIP) provides a way to construct a POSIX filesystem by compacting specific semantics and encoding them in an architecture-independent manner. The semantics of RRIP exactly match those of POSIX. As such, a CD-ROM that understands these extensions will look exactly like a POSIX filesystem, with userid and other expected file attributes present, while still being an ISO-9660 compliant disk. (Non-POSIX systems could still access the files using ordinary ISO-9660 names and attributes.) 386BSD Release 0.2 is such a system.

RRIP is described as a type of SUSP information present within the system-use area of the directory entry, with new signature words specific to RRIP; see Table 1(b). The PX type, which contains the key file information required for reconstruction, is absolutely required for all entries to create a POSIX-style directory or file. All time stamps related to a file are documented in the TS entry. Symbolic links are recorded in SL signature words, and the CL, PL, and RE signature words are used to reconstruct and track deep directories. (ISO-9660 is limited to a fixed eight levels of directory hierarchy due to the limitations of the pathname tables.)

Rock Ridge in a Non-POSIX Environment

While POSIX file attributes and names were the primary point in doing the Rock Ridge extensions, the standard designers wisely chose not to intensely limit these extensions to POSIX. Thus, file-naming records have no "UNIXisms" forced upon them. Since there are no restrictions on filename contents and no embedded filename syntax, you could, for example, use JIS or Unicode in the name octets. Rock Ridge can also be used in a networked situation, since a single CD-ROM can be exported to a variety of different operating systems viewing the same files, while appearing to be in the local system's native file-structure format. In sum, Rock Ridge is heading in the same "universal" direction of other filesystems like NFS.

cdromcat Revisited

In our previous article, we examined a program (cdromcat) that viewed CD-ROM files on the 386/486. This program has been modified to allow for CD-ROMs with Rock Ridge extensions. It will function as before for ISO-only CD-ROMs. If Rock Ridge extensions are present, a UNIX-like directory listing will appear instead. The program now consists of four major components: A main user-application section (Listing One, page 101) which allows the user to interact with the other programs, the filesystem primitives for the CD-ROM filesystem (cdromfs.c), the SUSP and RRIP implementations (susp.c and rrip.c), and the object output routines which format and print the output (printcdromfs.c). Due to space limitations, the entire source code is available electronically; see "Availability," page 5.

Listing One is a minimal applications program that uses the other facilities in this program to interpret multiple CD-ROM filesystems with extensions. The program accepts a pathname, prints the file, and either returns the contents of the file (if the file is ordinary) or provides a directory listing (if it is a directory). The iscdrom() function is used to decipher the CD-ROM filesystem format, which, if successful, returns the root directory entry of the CD-ROMs hierarchical filesystem. For convenience, the program then displays the contents of the root directory as a directory list using printdirents(). Filenames are passed to opencdf() to see if they can be opened; if so, they can be displayed with either printdirents() or extractdirents().

cdromfs.c contains the filesystem primitives to interpret ISO-9660 (and the now obsolete High Sierra) filesystem format, as well as Rock Ridge extensions. It checks for the presence of a known CD-ROM filesystem, probes for known extensions within the filesystem, performs recursive filename lookup in the name hierarchy, and obtains data from CD-ROM files.

The iscdrom() function attempts to locate a valid primary descriptor on the CD-ROM by trying logical sector sizes from 2048 to 65536 octets in size. If it finds the descriptor, it probes the root directory's "." entry to see if the SUSP is present. One oddity of ISO-9660 is that the root-directory entry is in two places: the primary descriptor (with no extensions, it's used to find where the root directory begins) and the first entry of the directory it points to (in this case, with extensions, as any other directory entry). If the SUSP is present, the function continues to check for the presence of the RRIP by looking for a valid SUSP signature record of the correct kind, and sets the USES_RRIP bit. One oddity of Rock Ridge standardization is that the probe for SUSP does not just check the first octet of extensions in the root directory's "dot" entry, it checks for the record throughout the file extensions, for compatibility with CD-ROM XA and any other standard that might insist on "first" billing.

The functions opencdf(), lookup(), searchdirent(), and namematch() implement the filesystem's name-to-file translation mechanism. opencdf() is a wrapper function that implements the operating system's interface semantics and passes off the details to lookup(). lookup() decomposes the syntax of a file pathname and uses searchdirent() to find components of the path on the actual CD-ROM. lookup() recurses if the current component is found and others still remain. While recursion is used in this example, an iterative version can also be used (for example, when inside an operating system with limited stack depth). searchdirent() obtains the contents of a directory (via getblockdirent()) and puzzles apart the directory records so that it can attempt to match them with namematch(). In namematch(), ISO file extensions, if present, are used to obtain the alternative filename and characteristics ahead of matching the actual ISO name in this directory entry. namematch() is where the susp() function is used to scan for Rock Ridge name records (NM).

susp.c contains a single function that scans the ISO system-usage field for valid SUSP entries. rrip.c contains both support code used to obtain POSIX file-status information out of other RRIP records found with the file and a function to translate ISO/Rock Ridge times into POSIX times.

cdrom.c invokes three header files: cdromfs.h, rrip.h, and susp.h. cdromfs.h contains the data structures and definitions of the CD-ROM itself. The susp.h and rrip.h header files contain the fields, constants, and interface definitions for the SUSP implementation and for the RRIP extensions to provide POSIX file attributes to an ISO-9660 CD-ROM, respectively. susp.h also contains an implementation-specific data structure to hold continuation state, so one can iterate through a sequence of SUSP records in a given directory entry. Finally, prtcdromfs.c contains the subroutines to produce formatted output of CD-ROM filesystem files. It prints the directory header, all the entries in the directory, the CD-ROM file modes, and (if available) the creation time of the file.

386BSD Rock Ridge Extensions

A completely new version of the ISO-9660 filesystem format and Rock Ridge extensions are available on the Tiny 386BSD 0.2 installation floppy as part of the DDJ Careware program. This updated floppy can be used to qualify, partition, download, extract, and install the complete 386BSD 0.1 binary distribution released last year (30 Mbytes uncompressed). If you have an extant 386BSD 0.1 system on hard disk, it will automatically update your system without the user having to patch and recompile. (Do not use any "unofficial" patchkits, only the Tiny 386BSD 0.2 and later updates from DDJ.)

To obtain the latest Tiny 386BSD floppy, send a formatted, high-density floppy and a SASE mailer to: Tiny 386BSD, Dr. Dobb's Journal, 411 Borel Avenue, San Mateo, CA 94402. There's no charge for the service, but if you would like, slip in a dollar for the Children's Support League of the East Bay.

Acknowledgments

We'd like to thank Andrew Young, founder and president of Young Minds, a key architect of both SUSP and RRIP, for his assistance while preparing this article and the example programs. You can obtain a copy of the Rock Ridge Technical Specifications through the

CD-ROM forum on CompuServe (GOCDROM).

Figure 1: ISO-9660 CD-ROM

Figure 2: Directory entries with and without extensions.

Table 1: (a) SUSP Standard Signature Word Fields; (b) RRIP Signature Word Fields.

===========================================================================
    Field  Description                Comments
===========================================================================
(a) SP     SUSP Indicator             SUSP in use
    ST     SUSP Terminator            SUSP use terminated
    CE     Continuation Area          Extend SUSP field
    ER     Extension Reference        System-Specific Extension
    PD     Padding Field (optional)   Ignore Field Information

(b) PX     POSIX file attributes      POSIX definition
    PN     POSIX device modes         Character or block
    NM     Alternate name             POSIX or non-ISO-9660 name
    SL     Symbolic link              Contents of symbolic link
    CL     Child link                 Location of relocated directory
    PL     Parent link                Original location of parent directory
    RE     Relocated directory        This directory is a relocated

directory
    TF     Time stamp(s) for a file
    RR     Flags indicating which
           field are recorded (optional)
===========================================================================

Figure 3: (a) System-use field description; (b) SUSP extensions in detail.

Directory Entries and Filenames

A directory entry is a data structure that describes the characteristics of a file or directory, beginning with a length octet describing the size of the entire entry. Entries themselves are of variable length, up to 255 octets in size. File attributes for the file described by the directory entry are stored in the directory entry and optionally, in the extended attribute record. The name-length field specifies how long the name is and is limited to 31 octets (characters). The choice of characters is also limited in scope. A CD-ROM filename may include any combination of numbers, uppercase letters, and underscore characters, optionally followed by a period (.) and another set of numbers and uppercase letters. A version number (optional in the High Sierra format) is delimited by a semicolon. (For example, a legal filename would be FOO_

BAR2.BLECH;1.)

This picture of the filenames is complicated by a few more restrictions. Directories cannot have extensions or version numbers. The two separator characters, period and semicolon, are not strictly in the character set of filenames, as they take up known locations (or values) in the character set. So when the filename match is to be done, they are treated independent of the character set that the CD-ROM is using. (ISO-9660 allows for other character sets for filenames--it remains relative to the files.)

Some gray-zone implementations are also of concern and occur on many of the name-brand ISO-9660 CD-ROMs we've sampled. The period separator can terminate a filename (for instance, a file with no extension), and the mandatory version number on ordinary files is usually missing on "compliant" discs. Worse, null (or blank) padding in names can be present, in clear violation of ISO rules. It is wise for the designer to accommodate these minor technical violations of the standard in a filesystem reader, as long as they don't compromise the standard semantics. However, creators of CD-ROMs that play fast and loose with ISO-9660 semantics should be warned that they are living on borrowed time.

Another problem is that many ISO-compatible systems are not fully compatible with these naming conventions. For example, some MS-DOS CD-ROM programs only allow the filename to be the maximum number of characters that a MS-DOS filename is allowed, because the software cannot differentiate between a MS-DOS filename and a CD-ROM filename. If the name field ends on an odd boundary, a reserve field of one octet is added because some microprocessors (like the 68000) experience a segmentation violation if they fetch a word on an odd boundary. If the name field ends on an even boundary, then this field is not used. The maximum size of a directory entry with no extensions is 58 octets; 197 octets are reserved for attribute extensions.

--L.G.J.

Inside the ISO-9660 Filesystem Format--Some Clarifications

William Frederick Jolitz

We've received a great deal of mail regarding our article discussing the basics of the ISO-9660 CD-ROM standard and sample applications, including some of the people behind the early CD-ROM standards effort, and we're grateful for this thoughtfully provided feedback.

A standard such as ISO-9660 spends as much time discussing areas "defined to be undefined" as it does with areas "defined to be defined" in a certain manner. The system area (beginning of the disk), areas not assigned to the storage of CD-ROM descriptors, directory entries, or other data structures may be used in any fashion. Thus the system area does not need to be used for booting (although that is its common use).

You could, in fact, use the system area to create a CD-ROM that could be mounted as a 386BSD UFS filesystem, as well as an ISO-9660 one, by arranging the filesystem structures of each to be nonconflicting with the other! All file contents would be at the exact same locations on the CD-ROM, just found via the different methods of each filesystem.

ISO-9660 descriptors have the sole function of describing ISO-9660 file systems, and they reserve all field contents for possible future use. Another reserved mechanism is that of making the standard function with certain specific oddities of the CD-ROM. This includes using the 2336-octet, mode-2 sectors instead of the more-standard, 2048-octet sectors that increase data capacity at the expense of error-detection/correction reliability. (Replicated primary descriptors and terminators become necessary to avoid making the disk useless by having a redundant copy of the information.)

File placement, interleaving, multiple extent, and discontiguous "allocation" are possible with ISO-9660, and desirable for certain kinds of applications. But the rules of how to use this to advantage are subtle and weighted toward the application developer and CD-ROM publisher's use. ISO-9660 and its predecessor, High Sierra, provide guidance on structure, not use. Thus, the application of techniques to minimize latency has been inconsistent. This is completely unlike other file systems, such as UFS, where storage policy is fixed within the file system design, and invisible to use.

Using the fine-grain features of ISO-9660 requires considerable "vertical" knowledge--from top (application) to bottom (physical layout), without which a full understanding of CD-ROM standards (even those with only hypothetical impact) is impossible. Fortunately, this type of specialized knowledge is generally not necessary.

Please note that in our December 1992 article the parenthetical comment near the end of the third paragraph at the end of page 82 starting "a variable length_" should read "for example, the volume descriptors constitute a variable length table_". In the page break between the text on page 82 and page 83, a "0x11," was omitted (that is, the byte sequence should be [0x44, 0x33, 0x22, 0x11, 0x11, 0x22, 0x33, 0x44]). Figures 2 and 1 are reversed in the text. To be precise, ISO refers to a file version number instead of a revision number, and while optional in High Sierra, it is mandatory in ISO (see the text box entitled "Directory Entries and Filenames").

High Sierra is a deprecated standard, valuable for reading non-ISO CD-ROMs, so its mention is strictly for reverse compatibility. All multibyte integer fields in ISO-9660 are recorded in both byte orders, even if an application will only use one of them. Filenames have slightly more complicated rules than previously mentioned (see the text box "Directory Entries and Filenames").

The ISO-9660 implementation in 386BSD Release 0.1 and other UNIX-like systems implemented filename translation, since it was inconvenient to use the uppercase filenames and semicolon (;) delimiters in filenames. (The command interpreter, or "shell," uses the semicolon to separate commands, thus filenames must be quoted to avoid misinterpretation.) This technically limits the portability of programs that would depend on the version number being present across different operating systems. In newer versions of 386BSD, an additional flag is added to the mount command to allow strict ISO conformance when desired.

No article can quite replace a copy of the standard itself (only available in printed form via existing sources of ISO standards documents). Finally, thanks to Howard Kaikow and Jim Harper for providing critical feedback.

Structure of the CD-ROM Volume Descriptor

A volume descriptor describes the characteristics of the filesystem information present on a given CD-ROM, or volume. It's divided into two parts: the type of volume descriptor, and the characteristics of the descriptor. The volume descriptor is constructed in this manner so that if a program reading the disk doesn't understand a particular descriptor, it can just skip over it until it finds one it recognizes, thus allowing the use of many different types of information on one CD-ROM. Also, if an error were to render a descriptor unreadable, a subsequent redundant copy of a descriptor could then allow for fault recovery. (Each descriptor is conveniently contained in a single logical sector by itself.) The minimum requirement is that it have a primary descriptor describing the ISO-9660 filesystem and an ending descriptor (a variable-length table that contains information on how many other descriptors are present).

The ISO-9660 primary volume descriptor acts much like the superblock of the UNIX filesystem, providing details on the ISO-9660-compliant portions of the disk. Contained within the primary volume descriptor is the root-directory record describing the location of the contiguous root directory. (As in UNIX, directories appear as files for the operating system's special use.) Directory entries are successively stored within this region. Evaluation of the ISO-9660 filenames is begun at this location. The root directory is stored as an extent, or sequential series of sectors, that contains each of the directory entries appearing in the root. In addition, since ISO-9660 works by segmenting the CD-ROM into logical blocks, the size of these blocks is found in the primary volume descriptor as well.

While we can have many different types of filesystems on a single ISO-9660 CD-ROM, there's always one ISO-9660 primary volume descriptor.

--L.G.J.


[LISTING ONE]

(Text begins on page 74.)

/* Copyright (c) 1992, 1993 William F. Jolitz, TeleMuse
 * All rights reserved.
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met: 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. All advertising materials mentioning features or use of this software
 *    must display the following acknowledgement:
 *  This software is a component of "386BSD" developed by
 *  William F. Jolitz, TeleMuse.
 * 4. Neither the name of the developer nor the name "386BSD"
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 * THIS SOFTWARE IS A COMPONENT OF 386BSD DEVELOPED BY WILLIAM F. JOLITZ
 * AND IS INTENDED FOR RESEARCH AND EDUCATIONAL PURPOSES ONLY. THIS
 * SOFTWARE SHOULD NOT BE CONSIDERED TO BE A COMMERCIAL PRODUCT.
 * THE DEVELOPER URGES THAT USERS WHO REQUIRE A COMMERCIAL PRODUCT
 * NOT MAKE USE OF THIS WORK.
 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPER ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE DEVELOPER BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *  cdrom:
 *  A simple program to interpret the CDROM filesystem, and return
 *  the contents of the file. (Directories are formatted and printed,
 *  and files are returned untranslated).
 *  Allows for the use of Rock Ridge extensions.
 *  main.c: application program to peruse cdrom filesystems.
 *  Written in the Oakland CA. district of Rockridge.
 */

#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/stat.h>
#include "cdromfs.h"
#include "susp.h"
#include "rrip.h"

/* per filesystem information */
struct fs fsd;

/* filesystem directory entry */
struct directent rootent, currentent;

/* user "application" program */
int
main(int argc, char *argv[])
{
    struct directent *dp;
    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);
    }
    currentent = rootent;
    /* print the contents of the root directory to give user a start */
    printf("Root Directory Listing:\n");
    printdirentheader("/", &fsd);
    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 (dp = opencdf(pathname, &fsd)){
            /* if a directory, format and list it */
            if (FDV(dp, flags, fsd.type) & CD_DIRECTORY) {
                printdirentheader(pathname, &fsd);
                printdirents(dp, &fsd);
            }
            /* if a file, print it on standard output */
            else
                extractdirent(dp, &fsd);
        } else
            printf("Not found.\n");
    }
    /* NOTREACHED */
}
/* Extract the entire contents of a directory entry and write this on standard
 * output. (XXX needs to be turned into a readcdf() function call. -wfj ). */
void
extractdirent(struct directent *dp, struct fs *fs) {
    long    datalen = ISO_WD(&FDV(dp, datalen, 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 = datalen > fs->lbs ? fs->lbs : datalen;
        (void) write (1, buffer,  cnt);
        /* next one? */
        lbn++;
        datalen -= cnt;
        if (datalen == 0) break;
    }
    free(buffer);
}
End Listing


Copyright © 1993, Dr. Dobb's Journal

Terms of Service | Privacy Statement | Copyright © 2024 UBM Tech, All rights reserved.