
This file documents the libhfs.a library for accessing HFS volumes.
Copyright (C) 1996, 1997 Robert Leslie

$Id: libhfs.txt,v 1.7 1997/08/27 04:35:42 rob Exp $

===============================================================================

Exported Data

  const char *hfs_error;

    This contains a pointer to a C string describing the last HFS error.
    It is generally only valid after an HFS routine has returned an error
    code (-1 or a NULL pointer).

    In all cases when an error occurs, the global variable `errno' is also
    set to an appropriate value.

  unsigned char hfs_charorder[];

    This array contains the relative sorting order of characters in HFS
    filenames according to the semantics of the Macintosh character set
    and the MacOS string comparison routines as used by HFS. The array can
    be indexed by unsigned character quantities; the resulting value can
    be compared to other array values to determine the relative sorting
    order of the corresponding character indices.

Public Routines

  ----- Volume Routines -----

  hfsvol *hfs_mount(const char *path, int pnum, int flags);

    This routine attempts to open an HFS volume from a source pathname. If
    the source medium is partitioned, `pnum' indicates which ordinal HFS
    partition should be mounted, and is usually 1.

    The `flags' argument specifies how the volume should be mounted.
    HFS_MODE_RDONLY means the volume should be mounted read-only.
    HFS_MODE_RDWR means the volume must be opened read/write. HFS_MODE_ANY
    means the volume can be mounted either read-only or read/write, with
    preference for the latter.

    A pointer to a volume structure is returned. This pointer is used
    to access the volume and must eventually be passed to hfs_umount()
    to flush and close the volume and free all associated memory.

  int hfs_flush(hfsvol *vol);

    This routine causes all pending changes to be flushed to an HFS volume.
    If a volume is kept open for a long period of time, it may be
    advantageous to call this periodically to avoid corrupting the volume
    due to unforeseen circumstances (power failure, floppy eject, etc.)

    If an error occurs, this function returns -1. Otherwise it returns 0.

  void hfs_flushall(void);

    This routine is similar to hfs_flush() except that all mounted volumes
    are flushed, and errors are not reported.

  int hfs_umount(hfsvol *vol);

    The specified HFS volume is unmounted; all open files and directories
    on the volume are closed, all pending changes to the volume are
    flushed, and all memory allocated for the volume is freed.

    All volumes opened with hfs_mount() must eventually be closed with
    hfs_umount(), or they will risk corruption.

    If an error occurs, this function returns -1. Otherwise it returns 0.
    In either case, the volume structure pointer will become invalid, as
    will all pointers to open file or directory structures associated with
    the volume.

  void hfs_umountall(void);

    This routine is similar to hfs_umount() except that all mounted volumes
    are closed, and errors are not reported.

    This routine may be useful to call just before a process terminates to
    make sure any remaining open volumes are properly unmounted.

  hfsvol *hfs_getvol(const char *name);

    This routines searches all mounted volumes for one having the given
    name, and returns its volume structure pointer. If more than one volume
    have the same name, the most recently mounted one is returned. If no
    volume matches the given name, a NULL pointer is returned.

    If a NULL pointer is passed to this routine, the current volume is
    returned, if any.

  void hfs_setvol(hfsvol *vol);

    The routine changes the "current" volume. Most HFS routines will accept
    a NULL volume pointer to mean the current volume; by default, the
    current volume is the last one which was mounted.

  int hfs_vstat(hfsvol *vol, hfsvolent *ent);

    This routine fills the volume entity structure `*ent' with information
    about a mounted volume. The fields of the structure are defined in
    the hfs.h header file.

    This routine returns 0 unless a NULL pointer is passed for the volume
    and no volume is current, in which case it returns -1.

  int hfs_vsetattr(hfsvol *vol, hfsvolent *ent);

    This routine allows some attributes of a volume to be changed. The
    attributes which may be changed are: ent->clumpsz, ent->crdate,
    ent->mddate, and ent->bkdate. Note that the default file clump size
    may only be changed to be a multiple of the volume's allocation block
    size. To change the volume's name, use hfs_rename().

    If an error occurs, this function returns -1. Otherwise it returns 0.

  int hfs_format(char *path, int pnum, char *vname)

    This routine writes a new HFS file system to the specified device or
    file pathname. The size of the volume is determined either by the
    maximum size of the device or the size of the existing file.

    If `pnum' is > 0, it selects an ordinal HFS partition in the device
    to receive the file system. The partition must already exist; an error
    will result if it cannot be found. With `pnum' == 0, any partition
    structure on the existing medium will be ignored, and the entire
    device will be used for the new HFS volume.

    The volume is given the name `vname', which must be between 1 and
    HFS_MAX_VLEN (27) characters in length inclusively, and cannot contain
    any colons (':').

    If an error occurs, this function returns -1. Otherwise it returns 0.

  ----- Directory Routines -----

  int hfs_chdir(hfsvol *vol, const char *path);

    The "current working directory" for the given volume is changed.
    `path' can be either a relative or absolute HFS path.

    If an error occurs, this function returns -1. Otherwise it returns 0.

  long hfs_getcwd(hfsvol *vol);

    The internal directory ID of the current working directory for the
    given volume is returned. This value is typically only useful for
    passing to hfs_setcwd() or hfs_dirinfo().

  int hfs_setcwd(hfsvol *vol, long id);

    This routine changes the current working directory for the given
    volume. A directory must exist with the given id.

    If an error occurs, this function returns -1. Otherwise it returns 0.

  int hfs_dirinfo(hfsvol *vol, long *id, char *name);

    This function looks up the given directory ID `*id' and stores in its
    place the directory ID of its parent. If `name' is not NULL, the name
    of the (child) directory is also stored in the buffer pointed to by it,
    which must be at least HFS_MAX_FLEN + 1 (32) bytes long.

    If an error occurs, this function returns -1. Otherwise it returns 0.

    This function can be called repeatedly to construct a full pathname
    to the current working directory. The root directory of a volume
    always has a directory ID of HFS_CNID_ROOTDIR, and a pseudo-parent ID
    of HFS_CNID_ROOTPAR.

  hfsdir *hfs_opendir(hfsvol *vol, const char *path);

    This function prepares to read the contents of a directory. `path'
    must be either an absolute or relative pathname to the desired HFS
    directory. As a special case, if `path' is an empty string, a
    "meta-directory" will be opened containing the root directories from
    all of the currently mounted volumes.

    This function returns a pointer which must be passed to the other
    directory-related routines to read the directory.

    If an error occurs, this function returns a NULL pointer.

  int hfs_readdir(hfsdir *dir, hfsdirent *ent);

    This routine fills the directory entity structure `*ent' with
    information about the next item in the given open directory. The
    fields of the structure are defined in the hfs.h header file.

    If an error occurs, this function returns -1. Otherwise it returns 0.

    When no more items occur in the directory, this function returns -1
    and sets `errno' to ENOENT.

  int hfs_closedir(hfsdir *dir);

    This function closes an open directory and frees all associated
    memory.

    If an error occurs, this function returns -1. Otherwise it returns 0.
    In either case, the directory structure pointer will no longer be valid.

  ----- File Routines -----

  hfsfile *hfs_open(hfsvol *vol, const char *path);

    This function opens an HFS file in preparation for I/O. Both forks of
    the file may be manipulated once the file is opened; hfs_setfork() is
    used to select the current fork. By default, the data fork is current.

    A pointer to a file structure is returned. This pointer should be
    passed to other routines to manipulate the file.

  int hfs_setfork(hfsfile *file, int fork);

    This routine selects the current fork in an open file for I/O. HFS
    files have two forks, data and resource. Resource forks normally contain
    structured data, although these HFS routines make no distinction
    between forks when reading or writing. It is up to higher-level
    applications to make sense of the information read or written from
    either fork.

    If 0 is passed to this routine, the data fork is selected. Otherwise
    the resource fork is selected. The seek pointer for the file is
    automatically reset to the beginning of the newly selected fork.

    As a side effect, this routine causes any excess disk blocks allocated
    for the fork which was current before the call to be freed; normally
    extra blocks are allocated during file writes to promote contiguity.
    This routine will return -1 if an error occurs in this process;
    otherwise it will return 0. The current fork will have been changed
    regardless.

  int hfs_getfork(hfsfile *file);

    This routine returns an indication of which fork is currently active
    for I/O operations on the given file. If 0 is returned, the data fork
    is selected. Otherwise the resource fork is selected.

  long hfs_read(hfsfile *file, void *ptr, unsigned long len);

    This routine reads up to `len' bytes from the current fork of an HFS
    file and places them into the buffer pointed to by `ptr' (which must be
    at least `len' bytes long.) The number of bytes actually read is
    returned, and may be less than `len' if the end of the file is reached.

    If this routine returns 0, there is no more data to be read from the
    file. If an error occurs, this routine will return -1.

    It is most efficient to read data in even blocks of HFS_BLOCKSZ bytes
    at a time.

  long hfs_write(hfsfile *file, const void *ptr, unsigned long len);

    This routine writes up to `len' bytes of data to the current fork of an
    HFS file from the buffer pointed to by `ptr'. The number of bytes
    actually written is returned. If an error occurs, this routine will
    return -1.

    It is most efficient to write data in even blocks of HFS_BLOCKSZ bytes
    at a time.

  int hfs_truncate(hfsfile *file, unsigned long len);

    This routine causes the current fork of the specified open file to be
    truncated to at most `len' bytes.

    The disk blocks associated with the freed portion of the file are not
    actually deallocated until either the current fork is changed or the
    file is closed.

    If an error occurs, this function returns -1. Otherwise it returns 0.

  long hfs_seek(hfsfile *file, long offset, int from);

    This routine changes the current seek pointer for the specified open
    file. This pointer determines where the next call to hfs_read() or
    hfs_write() will read or write data within the current fork.

    If `from' is HFS_SEEK_SET, the pointer is set to the absolute position
    given by `offset'.

    If `from' is HFS_SEEK_CUR, the pointer is offset from its current
    position by the amount `offset'. Positive offsets seek forward; negative
    offsets seek backward.

    If `from' is HFS_SEEK_END, the pointer is offset from the end of the
    file by the amount `offset', which ought to be a non-positive number.

    It is not presently possible to set the seek pointer beyond the logical
    end of the file.

    The new absolute position of the seek pointer is returned, unless an
    invalid argument was specified, in which case -1 is returned.

  int hfs_close(hfsfile *file);

    This routine causes all pending changes to the specified file to be
    flushed, and all storage associated with the file structure to be
    freed. Any excess disk blocks associated with the file are also
    deallocated at this time.

    If an error occurs, this routine returns -1. Otherwise it returns 0.
    In either case, the file structure pointer will no longer be valid.

  ----- Catalog Routines -----

  int hfs_stat(hfsvol *vol, const char *path, hfsdirent *ent);

    This routine fills the directory entity structure `*ent' with
    information about the file or directory specified by `path' on the
    given volume. The fields of the structure are defined in the hfs.h
    header file.

    If there is no such path, or if another error occurs, this routine
    returns -1. Otherwise it returns 0.

  int hfs_fstat(hfsfile *file, hfsdirent *ent);

    This routine is similar to hfs_stat() except it returns information
    about a file that is already open.

    If an error occurs, this routine returns -1. Otherwise it returns 0.

  int hfs_setattr(hfsvol *vol, const char *path, const hfsdirent *ent);

    This routine changes various attributes of an existing file or
    directory. The attributes which may be changed are: ent->crdate,
    ent->mddate, ent->bkdate, ent->fdflags, ent->fdlocation,
    ent->u.file.type, ent->u.file.creator, and ent->u.dir.rect. Also, the
    locked status of a file may be changed with ent->flags & HFS_ISLOCKED.

    If an error occurs, this routine returns -1. Otherwise it returns 0.

  int hfs_fsetattr(hfsfile *file, const hfsdirent *ent);

    This routine is similar to hfs_setattr() except it manipulates a file
    that is already open.

    If an error occurs, this routine returns -1. Otherwise it returns 0.

  int hfs_mkdir(hfsvol *vol, const char *path);

    This routine creates a new, empty directory with the given path.
    All parent directories must already exist, but there must not already
    be a file or directory with the complete given path.

    If an error occurs, this function returns -1. Otherwise it returns 0.

  int hfs_rmdir(hfsvol *vol, const char *path);

    This routine deletes the directory with the given path. The directory
    must be empty.

    If an error occurs, this function returns -1. Otherwise it returns 0.

  int hfs_create(hfsvol *vol, const char *path,
                 const char *type, const char *creator);

    This routine creates a new, empty file with the given path, type, and
    creator. The type and creator must be strings of length 4, and have
    particular meaning under MacOS.

    If an error occurs, this function returns -1. Otherwise it returns 0.

  int hfs_delete(hfsvol *vol, const char *path);

    This routine deletes the file with the given path.

    If an error occurs, this function returns -1. Otherwise it returns 0.

  int hfs_rename(hfsvol *vol, const char *srcpath, const char *dstpath);

    This routine moves and/or renames the given `srcpath' to `dstpath'.
    The source must exist; the destination must not exist, unless it is a
    directory, in which case an attempt will be made to move the source
    into the destination directory without changing its name.

    If both `srcpath' and `dstpath' refer to root directories, the volume
    specified by `srcpath' will be renamed. Note that volume names may
    only have 1-27 (HFS_MAX_VLEN) characters, while all other names may
    have 1-31 (HFS_MAX_FLEN) characters.

    If an error occurs, this function returns -1. Otherwise it returns 0.

===============================================================================

