(*
  Title:	Dir - Unix Implementation
  $Header: Dir.mod,v 1.4 88/02/26 16:13:51 dm Exp $
  		Copyright (C) 1984 by Acorn Research Centre
*)

IMPLEMENTATION MODULE Dir;

FROM SYSTEM IMPORT CALLEXTPROC, CALLEXTFUNC, ADR, WORD;
FROM Storage IMPORT ALLOCATE, DEALLOCATE;
IMPORT Streams, FileStream, Strings;
FROM Strings IMPORT String, CopyCS, ExtractCC;
FROM Fields IMPORT ExtractShort;
IMPORT Endian;
IMPORT UnixLibCall;
FROM UnixIOXtra IMPORT Stat, StatBuf;

CONST
	MAXNAMLEN=255;

TYPE
	DirHandle = POINTER TO Dir;
	Dir = RECORD
		ddFd:	INTEGER;
		ddLoc:	INTEGER;
		ddSize:	INTEGER;
		ddBbase:	INTEGER;
		ddEntno:	INTEGER;
		ddBsize:	INTEGER;
		ddBuf:	String;
	END;

	PtrDirect = POINTER TO Direct;
	Direct = RECORD
		dFileno: INTEGER;		(* file number of entry *)
		kludge: CARDINAL;
(* Kludge includes these two fields. *)
(* u_short *d_reclen;		(* length of this record *)*)
(* u_short *d_namlen;		(* length of string in d_name *)*)

		(* name (up to MAXNAMLEN + 1) *)
		dName: ARRAY [0..MAXNAMLEN + 1] OF CHAR;
	END;

VAR
  dotS: ARRAY [0..0] OF CHAR;

PROCEDURE DirExists(name: ARRAY OF CHAR; VAR id: INTEGER): BOOLEAN;
  VAR
    statBuf: StatBuf;
  BEGIN
    IF Stat(name, statBuf) < 0 THEN
      RETURN FALSE
    ELSE
      id := statBuf.ino;
      RETURN TRUE;
    END;
  END DirExists;

PROCEDURE OpenDir(name: ARRAY OF CHAR): DirHandle;
VAR
	d: DirHandle;
	tmpStr: String;
BEGIN
	tmpStr := CopyCS( name );
	d := DirHandle( CALLEXTFUNC( UnixLibCall.opendir, WORD(tmpStr) ) );
	IF CARDINAL( d ) = 0 THEN
		RETURN NIL;
	ELSE
		RETURN d;
	END;
END OpenDir;

(*
PROCEDURE RdShort(d: DirHandle): CARDINAL;
  VAR
    msb: CARDINAL;
  BEGIN
    msb := CARDINAL(Streams.Get(d));
    RETURN CARDINAL(Streams.Get(d)) + msb * 256;
  END RdShort;

PROCEDURE RdInt(d: DirHandle): INTEGER;
  VAR
    mss : CARDINAL;
  BEGIN
    mss := RdShort(d);
    RETURN INTEGER( RdShort(d) + mss * 65536);
  END RdInt;
*)

PROCEDURE NextDirEntry(d: DirHandle; VAR name: ARRAY OF CHAR): BOOLEAN;
  VAR
    n: INTEGER;
    discard: CHAR;
    reclen, namlen, ino: INTEGER;
	direct: PtrDirect;

  BEGIN
	direct := PtrDirect( CALLEXTFUNC( UnixLibCall.readdir, WORD(d) ) );
	IF CARDINAL( direct) = 0 THEN
		RETURN( FALSE );
	END;
        reclen := ExtractShort(direct^.kludge,0);
	namlen := ExtractShort(direct^.kludge,1);
	ExtractCC( direct^.dName, 0, namlen+1, name );
    RETURN TRUE;
END NextDirEntry;

PROCEDURE CloseDir(d: DirHandle);
VAR
	i: INTEGER;
BEGIN
	i := INTEGER( CALLEXTFUNC( UnixLibCall.closedir, WORD(d) ) );
END CloseDir;

PROCEDURE NullDir(d: DirHandle): BOOLEAN;
  BEGIN
    RETURN d = NIL;
  END NullDir;

PROCEDURE IsCurrentDirectoryName(name: Strings.String): BOOLEAN;
  BEGIN
    RETURN Strings.EqualCS(dotS, name);
  END IsCurrentDirectoryName;

BEGIN
  dotS[0] := '.';
END Dir.

(*
$Log:	Dir.mod,v $
Revision 1.4  88/02/26  16:13:51  dm
Fields now deals with endian things

Revision 1.3  88/01/26  13:13:32  dm
Uses opendir and readdir and closedir now.

Revision 1.1  84/11/30  16:00:35  mjj
Initial revision

*)

