DEFINITION MODULE Directories;

	(********************************************************)
	(*							*)
	(*		Disk directory lookup.			*)
	(*							*)
	(*  Programmer:		P. Moylan			*)
	(*  Last edited:	13 June 1992			*)
	(*  Status:						*)
	(*	Working, but needs more detailed testing.	*)
	(*	FindRelativeCluster not tested.			*)
	(*							*)
	(********************************************************)

FROM Devices IMPORT
    (* type *)	Device, BlockNumberType;

FROM IOErrorCodes IMPORT
    (* type *)	ErrorCode;

(************************************************************************)

TYPE Handle;	(* is private *)

TYPE Cluster = CARDINAL;

CONST

    (* NoSuchBlock is, by convention, returned to indicate a		*)
    (* nonexistent block.						*)

    NoSuchBlock = 0FFFFFFFFH;

(************************************************************************)
(*									*)
(*  Remark: file space is allocated in clusters, where a cluster is	*)
(*  one or more blocks.  Because the mapping from cluster number to	*)
(*  block number varies from one disk to another (it depends on the	*)
(*  disk capacity and format), and because module Devices does not	*)
(*  know about clusters, it is simplest to keep that mapping private	*)
(*  to this module, and return information to the caller in terms of	*)
(*  block numbers.  However, the caller needs to be told the cluster	*)
(*  size in bytes, in order to know how much data to read or write	*)
(*  at a time.								*)
(*									*)
(************************************************************************)

PROCEDURE SetDefaultDirectory (VAR (*IN*) path: ARRAY OF CHAR): ErrorCode;

    (* Sets the starting point for directory searches in subsequent	*)
    (* file operations.  Each device has a separate default directory.	*)
    (* If parameter path includes a device name, the default is set for	*)
    (* that device; otherwise, the default directory is set for the	*)
    (* current default device.						*)

PROCEDURE Lookup (newfile: BOOLEAN;  name: ARRAY OF CHAR;
		VAR (*OUT*) device: Device;
		VAR (*OUT*) unit: CARDINAL;
		VAR (*OUT*) fileid: Handle;
		VAR (*OUT*) StartingBlock: BlockNumberType;
		VAR (*OUT*) BytesPerCluster: CARDINAL;
		VAR (*OUT*) BytesInFile: LONGCARD): ErrorCode;

    (* Parses the file name, returns the device code and unit number,	*)
    (* and looks up the device directory (which might involve some	*)
    (* subdirectory searches) to find the location of the directory	*)
    (* entry, the starting block number, cluster size in bytes, and	*)
    (* file size in bytes, for the file.  If newfile=TRUE, we create a	*)
    (* new directory entry for this file (or report an error if the	*)
    (* file already exists).  When creating a new file, we pre-allocate	*)
    (* the first cluster; this partially avoids the complication of	*)
    (* having to go back and modify the directory entry when the first	*)
    (* cluster of data is ready to be written (we will still have to	*)
    (* modify the file size part of the entry when the file is closed).	*)

PROCEDURE NextBlockNumber (fileid: Handle;
			   currentblock: BlockNumberType): BlockNumberType;

    (* Given the block number of the current cluster in a file, returns	*)
    (* the block number of the following cluster.			*)

PROCEDURE FindRelativeCluster (fileid: Handle;  N: CARDINAL)
							: BlockNumberType;

    (* Returns the block number of the Nth cluster, where N = 0		*)
    (* corresponds to the starting cluster of the file.			*)

PROCEDURE AllocateBlock (fileid: Handle;
			currentblock: BlockNumberType): BlockNumberType;

    (* Allocates a new free cluster, and returns its block number.  The	*)
    (* variable currentblock shows the block number of the last cluster	*)
    (* used by this file - we need this to update the space allocation	*)
    (* chain.								*)

PROCEDURE UpdateFileSize (fileid: Handle;  NewSize: LONGCARD);

    (* Updates a directory entry to show a modified file size.	*)

PROCEDURE DiscardHandle (VAR (*INOUT*) fileid: Handle);

    (* To be called when a file is no longer going to be accessed.	*)

END Directories.
