Examples


This section provides code listings of programs that use the File folio and the file system.

Using NVRAM

Example 1 is a program listing that demonstrates how to save data to a file in NVRAM or to any other writable device.

The SaveDataFile() function takes a name, a data pointer, and a size indicator, and creates a file with that name and size, containing the supplied data.

Writing data to a file requires a bit of finesse. Data can only be written in blocks, not bytes. So if the data being written out is not a multiple of the target device's block size, the last chunk of data must be copied to a buffer which is the size of a block, and the block can then be written out.

Example 1: Saving data to a file in NVRAM (nvram.c).

#include "types.h"
#include "filesystem.h"
#include "filefunctions.h"
#include "io.h"
#include "string.h"
#include "mem.h"
#include "stdio.h"
#include "operror.h"


/*****************************************************************************/


Err SaveDataFile(const char *name, void *data, uint32 dataSize)
{
Item       fileItem;
Item       ioReqItem;
IOInfo     ioInfo;
void      *temp;
Err        result;
uint32     numBlocks;
uint32     blockSize;
uint32     roundedSize;
FileStatus status;

    /* get rid of the file if it was already there */
    DeleteFile((char *)name);

    /* create the file again... */
    result = CreateFile((char *)name);
    if (result >= 0)
    {
        /* open the file for access */
        fileItem = OpenDiskFile((char *)name);
        if (fileItem >= 0)
        {
            /* create an IOReq to communicate with the file */
            ioReqItem = CreateIOReq(NULL, 0, fileItem, 0);
            if (ioReqItem >= 0)
            {
                /* get the block size of the file */
                memset(&ioInfo, 0, sizeof(IOInfo));
                ioInfo.ioi_Command         = CMD_STATUS;
                ioInfo.ioi_Recv.iob_Buffer = &status;
                ioInfo.ioi_Recv.iob_Len    = sizeof(FileStatus);
                result = DoIO(ioReqItem, &ioInfo);
                if (result >= 0)
                {
                    blockSize = status.fs.ds_DeviceBlockSize;
                    numBlocks = (dataSize + blockSize - 1) / blockSize;

                    /* allocate the blocks we need for this file */
                    ioInfo.ioi_Command         = FILECMD_ALLOCBLOCKS;
                    ioInfo.ioi_Recv.iob_Buffer = NULL;
                    ioInfo.ioi_Recv.iob_Len    = 0;
                    ioInfo.ioi_Offset          = numBlocks;
                    result = DoIO(ioReqItem, &ioInfo);
                    if (result >= 0)
                    {
                        /* tell the system how many bytes for this file */
                        memset(&ioInfo,0,sizeof(IOInfo));
                        ioInfo.ioi_Command         = FILECMD_SETEOF;
                        ioInfo.ioi_Offset          = dataSize;
                        result = DoIO(ioReqItem, &ioInfo);
                        if (result >= 0)
                        {
                            roundedSize = 0;
                            if (dataSize >= blockSize)
                            {
                                /* If we have more than one block's worth of
                                 * data, write as much of it as possible.
                                 */

                                roundedSize = (dataSize / blockSize) * blockSize;
                                ioInfo.ioi_Command         = CMD_WRITE;
                                ioInfo.ioi_Send.iob_Buffer = (void *)data;
                                ioInfo.ioi_Send.iob_Len    = roundedSize;
                                ioInfo.ioi_Offset          = 0;
                                result = DoIO(ioReqItem, &ioInfo);

                                data      = (void *)((uint32)data + roundedSize);
                                dataSize -= roundedSize;
                            }

                            if ((result >= 0) && dataSize)
                            {
                                /* If the amount of data left isn't as large
                                 * as a whole block, we must allocate a memory
                                 * buffer of the size of the block, copy the
                                 * rest of the data into it, and write the
                                 * buffer to disk.
                                 */

                                temp = AllocMem(blockSize,MEMTYPE_DMA | 

                                              MEMTYPE_FILL);
                                if (temp)
                                {
                                    memcpy(temp,data,dataSize);
                                    ioInfo.ioi_Command         = CMD_WRITE;
                                    ioInfo.ioi_Send.iob_Buffer = temp;
                                    ioInfo.ioi_Send.iob_Len    = blockSize;
                                    ioInfo.ioi_Offset          = roundedSize;
                                    result = DoIO(ioReqItem, &ioInfo);

                                    FreeMem(temp,blockSize);
                                }
                                else
                                {
                                    result = NOMEM;
                                }
                            }
                        }
                    }
                }
                DeleteIOReq(ioReqItem);
            }
            else
            {
                result = ioReqItem;
            }
            CloseDiskFile(fileItem);
        }
        else
        {
            result = fileItem;
        }

        /* don't leave a potentially corrupt file around... */
        if (result < 0)
            DeleteFile((char *)name);
    }

    return (result);
}


/*****************************************************************************/


static char testData[] = "This is some test data to save out";

int main(int32 argc, char **argv)
{
Err err;

    err = SaveDataFile("/NVRAM/test",testData,sizeof(testData));
    if (err < 0)
    {
        printf("Could not save data: ");
        PrintfSysErr(err);
    }
}

Displaying Contents of a File

Example 2 is a program listing that demonstrates how to read a file using the byte stream calls, and output its contents to the debugging terminal.

Example 2: Displaying the contents of a 3DO file (type.c)

#include "types.h"
#include "stdio.h"
#include "filestream.h"
#include "filestreamfunctions.h"


/*****************************************************************************/


#define MAXLINE 1024

static void Type(const char *path)
{
Stream *stream;
char    c;
char    line[MAXLINE];
int32   linelen;
int32   lines;
int32   endOfLine, endOfFile;

    /* Open the file as a byte-stream. A buffer size of zero is
     * specified, which permits the File folio to choose an appropriate
     * amount of buffer space based on the file's actual block size.
     */

    stream = OpenDiskStream((char *)path, 0);
    if (!stream)
    {
        printf("File '%s' could not be opened\n", path);
        return;
    }

    lines     = 0;
    linelen   = 0;
    endOfLine = FALSE;
    endOfFile = FALSE;

    /* Spin through a loop, grabbing one byte each time.
     *
     * A more efficient implementation would grab bytes
     * in larger batches (e.g. 128 bytes at a time) and parse them in a
     * more reasonable fashion.
     */

    while (!endOfFile)
    {
        if (ReadDiskStream(stream, &c, 1) < 1)
        {
            endOfFile = TRUE;
            endOfLine = TRUE;
            line[linelen] = '\0';
        }
        else if (c == '\r' || c == '\n')
        {
            endOfLine = TRUE;
            line[linelen] = '\0';
        }
        else if (linelen < MAXLINE-1)
        {
            line[linelen++] = c;
        }

        if (endOfLine)
        {
            printf("%s\n", line);
            linelen = 0;
            lines++;
            endOfLine = FALSE;
        }
    }

    printf("\n%d lines processed\n\n", lines);

    /* close the file */
    CloseDiskStream(stream);
}


/*****************************************************************************/


int main(int32 argc, char **argv)
{
int32 i;

    if (argc < 2)
    {
        printf("Usage: type file1 [file2] [file3] [...]\n");
    }
    else
    {
        /* go through all the arguments */
        for (i = 1; i < argc; i++)
            Type(argv[i]);
    }

    return 0;
}

Scanning the File System

Example 3 is a program listing of an application that scans the file system.

Example 3: Scanning the file system (Walker.c).

#include "types.h"
#include "io.h"
#include "stdio.h"
#include "operror.h"
#include "filesystem.h"
#include "directory.h"
#include "directoryfunctions.h"
#include "filefunctions.h"


/*****************************************************************************/


static void TraverseDirectory(Item dirItem)
{
Directory      *dir;
DirectoryEntry  de;
Item            subDirItem;
int32           entry;

    dir = OpenDirectoryItem(dirItem);
    if (dir)
    {
        entry = 1;
        while (ReadDirectory(dir, &de) >= 0)
        {
            printf("Entry #%d:\n", entry);
            printf("  file '%s', type 0x%lx, ID 0x%lx",
                    de.de_FileName, de.de_Type,
                    de.de_UniqueIdentifier);
            printf(", flags 0x%lx\n", de.de_Flags);
            printf("  %d bytes, %d block(s) of %d byte(s) each\n",
                    de.de_ByteCount,
                    de.de_BlockCount, de.de_BlockSize);
            printf("  %d avatar(s)", de.de_AvatarCount);
            printf("\n\n");

            if (de.de_Flags & FILE_IS_DIRECTORY)
            {
                subDirItem = OpenDiskFileInDir(dirItem, de.de_FileName);
                if (subDirItem >= 0)
                {
                    printf("********** RECURSE **********\n\n");
                    TraverseDirectory(subDirItem);
                    printf("******* END RECURSION *******\n\n");
                }
                else
                {
                    printf("***  RECURSION FAILED  ***\n\n");
                }
            }
            entry++;
        }
        CloseDirectory(dir);
    }
    else
    {
        printf("OpenDirectoryItem() failed\n");
        CloseDiskFile(dirItem);
    }
}


/*****************************************************************************/


static Err Walk(const char *path)
{
Item startItem;

    startItem = OpenDiskFile((char *)path);
    if (startItem >= 0)
    {
        printf("\nRecursive directory scan from %s\n\n", path);
        TraverseDirectory(startItem);
        printf("End of %s has been reached\n\n", path);
        return 0;
    }
    else
    {
        printf("OpenDiskFile(\"%s\") failed: ",path);
        PrintfSysErr(startItem);
        return startItem;
    }
}


/*****************************************************************************/


int main(int32 argc, char **argv)
{
int i;

    if (argc <= 1)
    {
        /* if no directory name was given, scan the current directory */
        Walk(".");
    }
    else
    {
        for (i = 1; i < argc; i++)
            Walk(argv[i]);
    }

    return 0;
}


Listing the Contents of a Directory

Example 4 is a code listing that list the contents of a directory.

Example 4: Listing a directory (ls.c)

**/

#include "types.h"
#include "stdio.h"
#include "string.h"
#include "io.h"
#include "operror.h"
#include "filesystem.h"
#include "filefunctions.h"
#include "directory.h"
#include "directoryfunctions.h"


/*****************************************************************************/


static void ListDirectory(const char *path)
{
Directory      *dir;
DirectoryEntry  de;
Item            ioReqItem;
int32           entry;
int32           err;
char            fullPath[FILESYSTEM_MAX_PATH_LEN];
IOInfo          ioInfo;
Item            dirItem;

    /* open the directory for access */
    dirItem = OpenDiskFile((char *)path);
    if (dirItem >= 0)
    {
        /* create an IOReq for the directory */
        ioReqItem = CreateIOReq(NULL, 0, dirItem, 0);
        if (ioReqItem >= 0)
        {
            /* Ask the directory its full name. This will expand any aliases
             * given on the command-line into fully qualified pathnames.
             */
            memset(&ioInfo, 0, sizeof(ioInfo));
            ioInfo.ioi_Command         = FILECMD_GETPATH;
            ioInfo.ioi_Recv.iob_Buffer = fullPath;
            ioInfo.ioi_Recv.iob_Len    = sizeof(fullPath);
            err = DoIO(ioReqItem, &ioInfo);
            if (err >= 0)
            {
                /* now open the directory for scanning */
                dir = OpenDirectoryPath((char *)path);
                if (dir)
                {
                    printf("\nContents of directory %s:\n\n", fullPath);
                    entry = 1;
                    while (ReadDirectory(dir, &de) >= 0)
                    {
                        printf("%5s", (char *) &de.de_Type);
                        printf(" %8d", de.de_ByteCount);
                        printf(" %4d*%4d", de.de_BlockCount, de.de_BlockSize);
                        printf(" %3d", de.de_AvatarCount);
                        printf(" %8x", de.de_Flags);
                        printf(" %s\n", de.de_FileName);
                        entry++;
                    }
                    CloseDirectory(dir);

                    printf("\nEnd of directory\n\n");
                }
                else
                {
                    printf("OpenDirectory(\"%s\") failed\n",fullPath);
                }
            }
            else
            {
                printf("Unable to get full path name for '%s': ",path);
                PrintfSysErr(err);
            }
            DeleteIOReq(ioReqItem);
        }
        else
        {
            printf("CreateIOReq() failed: ");
            PrintfSysErr(ioReqItem);
        }
        CloseDiskFile(dirItem);
    }
    else
    {
        printf("OpenDiskFile(\"%s\") failed: ",path);
        PrintfSysErr(dirItem);
    }
}


/*****************************************************************************/


int main(int32 argc, char **argv)
{
int32 i;

    if (argc <= 1)
    {
        /* if no directory name was given, scan the current directory */
        ListDirectory(".");
    }
    else
    {
        /* go through all the arguments */
        for (i = 1; i < argc; i++)
            ListDirectory(argv[i]);
    }

    return 0;
}