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
DIRECTORY
CStrings,
Rope,
UnixSysCalls,
UnixErrno,
UnixTypes,
UnixDirectory,
UXStrings;
UnixDirectoryImpl: CEDAR PROGRAM
IMPORTS UnixErrno, UnixSysCalls, UXStrings
EXPORTS UnixDirectory
~ 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)]];
};
END.