# the File API

# Data structures

Warning! None of the fields of the structure below can be modified directly from the user code. If they are modified directly, the behaviour of the library is undefined.
Unless specified otherwise, read access is of course allowed.

The dynamic memory allocation/releasing is done by the library (assuming that `adfFileOpen()` is followed by `adfFileClose()`).

    struct AdfFile {
        struct AdfVolume *        volume;           // pointer to the volume

        struct bFileHeaderBlock * fileHdr;          // the header block
        void *                    currentData;      // current data block
        struct bFileExtBlock *    currentExt;       // current data extension block

        unsigned                  nDataBlock;       // number of current data block
        SECTNUM                   curDataPtr;       // pointer to the current data block
        unsigned long             pos;              // file pos

        int                       posInDataBlk;     // index in a datablock
        int                       posInExtBlk;      // index in a file header or file extension block
        BOOL                      eof;              // TRUE is the last byte has been read, use adfEndOfFile()
        BOOL                      modeRead,         // TRUE if the file is opened in read mode
                                  modeWrite;        // TRUE if the file is opened in write mode
        BOOL                      currentDataBlockChanged;   // in write mode, set if the datablock currently in memory has changed
    };

adfFileOpen()

## Syntax

struct AdfFile* adfFileOpen(struct adfVolume* vol, char* name, AdfFileMode mode);

## Description

Opens the file with the name name which is located in the current working directory of the vol volume.
The allowed modes are:

- `ADF_FILE_MODE_READ`
- `ADF_FILE_MODE_WRITE`
- `ADF_FILE_MODE_READ | ADF_FILE_MODE_WRITE`

If the mode is `ADF_FILE_MODE_WRITE` then:

- if the file does not exist, it will be created
- if it already exists, it will be overwritten (from the beginning) but not truncated (`adfFileTruncate()` must be used for that)

Some basic access permissions are just checked for now.

## Return values

A pointer to the newly created `AdfFile` structure, which can be used for further file operations (read/write/truncate).
`NULL` if an error occurs, ie.

- for read: file not found or no permissions to read
- for write: no permissions to write or a directory with the same name already exists

## Internals

adfFlushFile()

## Syntax

void adfFlushFile(struct AdfFile* file);

## Description

Flushes the datablocks on disk.

adfFileClose()

## Syntax

void adfFileClose(struct AdfFile* file)

## Description

Calls adfFileFlush() and frees the file structure.

adfFileRealSize()

## Syntax

long adfFileRealSize(unsigned long size, int blockSize, long* dataN, long* extN);

## Description

Returns the real size in blocks of a file which the given size. It does not taking into account the new dircache that -may- be allocated.

The blockSize must be 488 or 512. This information is located in the datablockSize of the Volume structure.

If the pointers dataN and extN aren't NULL, the number of data blocks and file extension blocks are returned.

adfFileRead()

## Syntax

long adfFileRead(struct AdfFile* file, long n, unsigned char* buffer)

## Description

Read n bytes from the given file into the buffer buffer.

Use adfEndOfFile() to check if the end of the file is reached or not.

## Example

    #include "adflib.h"

    const unsigned BUFSIZE = 600;
    unsigned char buf[BUFSIZE];

    /* a device and a volume 'vol' has been successfully mounted */

    /* opens the Amiga file */
    struct AdfFile * const file = adfFileFile(vol, "mod.and.distantcall", ADF_FILE_MORE_READ);
    if ( file == NULL ) { /* free resources and exit */  };

    /* opens the output classic file */
    FILE * const out = fopen("mod.distant","wb");
    if ( out == NULL ) { adfCloseFile(file); /* ... */ };

    /* copy the Amiga file into the standard file, 600 bytes per 600 bytes */
    long n = adfFileRead(file, BUFSIZE, buf);
    while ( ! adfEndOfFile(file) ) {
        fwrite(buf, sizeof(unsigned char), n, out);
        n = adfFileRead(file, BUFSIZE, buf);
    }
    /* after the EOF is reached, some bytes may need to be written */
    if ( n > 0 )
        fwrite(buf, sizeof(unsigned char), n, out);

    /* closes the standard file */
    fclose(out);

    /* closes the Amiga file */
    adfFileClose(file);

## Returned values

The number of bytes read.

adfEndOfFile()

## Syntax

BOOL adfEndOfFile(struct AdfFile* file)

## Description

TRUE if the end of the file file is reached.

adfFileWrite()

## Syntax

long adfWriteWrite(struct AdfFile* file, long n, unsigned char* buffer)

## Description

Writes n bytes from the given buffer into the file file.

## Example

    #include"adflib.h"

    const unsigned BUFSIZE = 600;
    unsigned char buf[BUFSIZE];

    /* a device and a volume 'vol' has been successfully mounted */

    struct AdfFile * file = adfFileOpen(vol, "moon_gif", ADF_FILE_MODE_READWRITE);
    if ( file == NULL ) { /* error handling */ };

    FILE * in = fopen(argv[2], "rb");
    if ( out == NULL ) { adfFileClose(file); /* error handling */ };

    n = fread(buf, sizeof(unsigned char), BUFSIZE, out);
    while ( ! feof(out) ) {
        adfFileWrite(file, n, buf);
        n = fread(buf, sizeof(unsigned char), BUFSIZE, out);
    }
    if ( n > 0 )
        adfFileWrite(file, n, buf);

    fclose(out);

    adfFileClose(file);

## Returned values

The number of bytes written.