UnixDirectoryImpl.mesa
Copyright Ó 1988, 1989, 1991 by Xerox Corporation. All rights reserved.
Eduardo Pelegri-Llopart,November 29, 1988 12:19:27 pm PST
Willie-Sue Orr, March 11, 1989 1:26 pm PST
An implementation of some Unix (tm) directory functions using UnixSysCalls.
Willie-s, August 13, 1991 1:27 pm PDT
~
BEGIN
ROPE: TYPE ~ Rope.ROPE;
CHARPtr: TYPE ~ UnixTypes.CHARPtr;
FD: TYPE ~ UnixTypes.FD;
RES: TYPE ~ UnixTypes.RES;
DirPtr: TYPE ~ REF DirRep;
DirRep:
PUBLIC
TYPE ~ RECORD [
buffer: CStrings.CString, -- character buffer where to place data --
bsize: INT, -- size of the buffer --
fd: FD, -- file descriptor of the directory --
loc: INT, -- the next directory entry in buffer --
size: INT, -- the first nonvalid character in buffer --
offset: INT -- the offset of DirEnt in the directory file --
];
DirEnt: TYPE ~ UnixDirectory.DirEnt;
DirEntPtr: TYPE ~ POINTER TO DirEnt;
UnixSysCalls.GetDEnts: UNSAFE PROC [fd: FD, buf: CHARPtr, nBytes: INT] RETURNS [INT];
OpenDir:
PUBLIC PROC [fileName: CHARPtr]
RETURNS [dirp: DirPtr] ~
TRUSTED {
flags: UnixTypes.FileFlags ~ [access: RDONLY];
mode: UnixTypes.Mode;
fd: FD ~ UnixSysCalls.Open[path: fileName, flags: flags, mode: mode];
stat: UnixTypes.Stat;
buf: UnixTypes.StatPtr ~ @stat;
IF fd = error THEN RETURN [NIL];
IF UnixSysCalls.FStat[fd, buf] = failure
THEN {
[] ¬ UnixSysCalls.Close[fd];
RETURN [NIL];
};
IF buf.mode.fmt # dir
THEN {
UnixErrno.SetErrno[ENOTDIR];
[] ¬ UnixSysCalls.Close[fd];
RETURN [NIL];
};
dirp ¬
NEW [DirRep ¬ [
buffer: UXStrings.CreateSpace[buf.blksize],
bsize: buf.blksize,
fd: fd,
size: 0,
loc: 0,
offset: 0]];
RETURN [dirp];
};
CloseDir:
PUBLIC
PROC [dirp: DirPtr]
RETURNS [
RES] ~ {
fd: FD ~ dirp.fd;
dirp.buffer.anchor ← NIL; -- free now --
dirp.fd ¬ error;
dirp.loc ¬ 0;
RETURN [UnixSysCalls.Close[fd]];
};
ReadDir:
PUBLIC
PROC [dirp: DirPtr]
RETURNS [DirEntPtr] ~ {
dp: DirEntPtr;
fd: FD ~ dirp.fd;
buffer: CHARPtr ~ dirp.buffer;
bsize: INT ~ dirp.bsize;
saveloc: INT ¬ 0;
recLen: CARD;
fileNo: CARD;
WHILE
TRUE
DO
IF dirp.size # 0
THEN {
saveloc ¬ dirp.loc;
TRUSTED {
dp ¬ LOOPHOLE[buffer + saveloc];
recLen ¬ dp.recLen;
};
dirp.loc ¬ saveloc + recLen;
};
IF dirp.loc >= dirp.size
THEN {
dirp.loc ¬ dirp.size ¬ 0;
};
IF dirp.size = 0
THEN {
TRUSTED {dirp.size ¬ UnixSysCalls.GetDEnts[fd, buffer, bsize]};
IF dirp.size = 0 THEN dirp.loc ¬ saveloc;
IF dirp.size <=0 THEN RETURN [NIL];
};
TRUSTED {
dp ¬ LOOPHOLE[buffer + dirp.loc];
recLen ¬ dp.recLen;
fileNo ¬ dp.fileNo;
};
IF recLen <= 0 THEN RETURN [NIL];
IF fileNo # 0 THEN EXIT;
ENDLOOP;
TRUSTED {dirp.offset ¬ dp.offset} ;
RETURN [dp];
};
TellDir:
PUBLIC
PROC [dirp: DirPtr]
RETURNS [
INT] ~ {
RETURN [dirp.offset];
};
SeekDir:
PUBLIC
PROC [dirp: DirPtr, loc:
INT] ~ {
currentLocation: INT ~ dirp.offset;
fd: FD ~ dirp.fd;
IF (currentLocation = loc) THEN RETURN;
dirp.loc ¬ 0;
dirp.size ¬ 0;
[] ¬ UnixSysCalls.LSeek[d: fd, offset: loc, whence: set];
dirp.offset ¬ loc;
};
RewindDir:
PUBLIC
PROC [dirp: DirPtr] ~ {
startOffset: INT ~ 0;
SeekDir[dirp, startOffset];
};
NameFromDirEntP:
PUBLIC PROC [dp: DirEntPtr]
RETURNS [name:
ROPE] ~
TRUSTED {
name ¬ UXStrings.ToRope[LOOPHOLE[@(dp.name)]];
};