executor/src/fileAccess.c

1782 lines
42 KiB
C

/* Copyright 1986-1996 by Abacus Research and
* Development, Inc. All rights reserved.
*/
#if !defined (OMIT_RCSID_STRINGS)
char ROMlib_rcsid_fileAccess[] =
"$Id: fileAccess.c 86 2005-05-25 00:47:12Z ctm $";
#endif
/* Forward declarations in FileMgr.h (DO NOT DELETE THIS LINE) */
#include "rsys/common.h"
#include "FileMgr.h"
#include "OSEvent.h"
#include "VRetraceMgr.h"
#include "OSUtil.h"
#include "DeviceMgr.h"
#include "MemoryMgr.h"
#include "rsys/hfs.h"
#include "rsys/file.h"
#include "rsys/glue.h"
#include "rsys/filedouble.h"
#include "rsys/segment.h"
#include "rsys/string.h"
#include "rsys/file.h"
#include "rsys/suffix_maps.h"
#include "rsys/lockunlock.h"
#include <ctype.h>
#if defined (CYGWIN32)
#include "winfs.h"
#endif
int ROMlib_nosync = 0; /* if non-zero, we don't call sync () or fsync () */
#if !defined(NDEBUG)
PUBLIC void fs_err_hook (OSErr err)
{
}
#endif
PUBLIC int ROMlib_lasterrnomapped;
#define MAX_ERRNO 50
#define install_errno(uerr, merr) \
do \
{ \
gui_assert(uerr < NELEM(xtable)); \
xtable[uerr] = merr; \
} \
while (FALSE);
A0(PUBLIC, OSErr, ROMlib_maperrno) /* INTERNAL */
{
OSErr retval;
static OSErr xtable[MAX_ERRNO + 1];
static char been_here = FALSE;
int errno_save;
if (!been_here)
{
int i;
for (i = 0; i < (int) NELEM(xtable); ++i)
xtable[i] = fsDSIntErr;
install_errno(0, noErr);
install_errno(EPERM, permErr);
install_errno(ENOENT, fnfErr);
install_errno(EIO, ioErr);
install_errno(ENXIO, paramErr);
install_errno(EBADF, fnOpnErr);
install_errno(EAGAIN, fLckdErr);
install_errno(ENOMEM, memFullErr);
install_errno(EACCES, permErr);
install_errno(EFAULT, paramErr);
install_errno(EBUSY, fBsyErr);
install_errno(EEXIST, dupFNErr);
install_errno(EXDEV, fsRnErr);
install_errno(ENODEV, nsvErr);
install_errno(ENOTDIR, dirNFErr);
install_errno(EINVAL, paramErr);
install_errno(ENFILE, tmfoErr);
install_errno(EMFILE, tmfoErr);
install_errno(EFBIG, dskFulErr);
install_errno(ENOSPC, dskFulErr);
install_errno(ESPIPE, posErr);
install_errno(EROFS, wPrErr);
install_errno(EMLINK, dirFulErr);
#if !defined(MSDOS) && !defined(CYGWIN32)
install_errno(ETXTBSY, fBsyErr);
install_errno(EWOULDBLOCK,permErr);
#endif
been_here = TRUE;
}
errno_save = errno;
ROMlib_lasterrnomapped = errno_save;
if (errno_save < 0 || errno_save >= (int) NELEM(xtable))
retval = fsDSIntErr;
else
retval = xtable[errno_save];
if (retval == fsDSIntErr)
warning_unexpected ("fsDSIntErr errno = %d", errno_save);
if (retval == dirNFErr)
warning_trace_info ("dirNFErr errno = %d", errno_save);
fs_err_hook (retval);
return retval;
}
A3(PUBLIC, OSErr, FSOpen, StringPtr, filen, INTEGER, vrn, /* IMIV-109 */
INTEGER *, rn)
{
ParamBlockRec pbr;
OSErr temp;
pbr.ioParam.ioNamePtr = RM(filen);
pbr.ioParam.ioVRefNum = CW(vrn);
pbr.ioParam.ioVersNum = 0;
pbr.ioParam.ioPermssn = fsCurPerm;
pbr.ioParam.ioMisc = 0;
temp = PBOpen(&pbr, 0);
*rn = CW(pbr.ioParam.ioRefNum);
fs_err_hook (temp);
return(temp);
}
A3(PUBLIC, OSErr, OpenRF, StringPtr, filen, INTEGER, vrn, /* IMIV-109 */
INTEGER *, rn)
{
ParamBlockRec pbr;
OSErr temp;
pbr.ioParam.ioNamePtr = RM(filen);
pbr.ioParam.ioVRefNum = CW(vrn);
pbr.ioParam.ioVersNum = 0;
pbr.ioParam.ioPermssn = fsCurPerm;
pbr.ioParam.ioMisc = 0;
temp = PBOpenRF(&pbr, 0);
*rn = CW(pbr.ioParam.ioRefNum);
fs_err_hook (temp);
return(temp);
}
A3(PUBLIC, OSErr, FSRead, INTEGER, rn, LONGINT *, count, /* IMIV-109 */
Ptr, buffp)
{
ParamBlockRec pbr;
OSErr temp;
pbr.ioParam.ioRefNum = CW(rn);
pbr.ioParam.ioBuffer = RM(buffp);
pbr.ioParam.ioReqCount = CL(*count);
pbr.ioParam.ioPosMode = CWC(fsAtMark);
temp = PBRead(&pbr, 0);
*count = CL(pbr.ioParam.ioActCount);
fs_err_hook (temp);
return(temp);
}
PUBLIC OSErr
FSReadAll (INTEGER rn, LONGINT *countp, Ptr buffp)
{
LONGINT orig_count;
OSErr retval;
orig_count = *countp;
retval = FSRead (rn, countp, buffp);
if (retval == noErr && *countp != orig_count)
retval = eofErr;
return retval;
}
A3(PUBLIC, OSErr, FSWrite, INTEGER, rn, LONGINT *, count, /* IMIV-110 */
Ptr, buffp)
{
ParamBlockRec pbr;
OSErr temp;
pbr.ioParam.ioRefNum = CW(rn);
pbr.ioParam.ioBuffer = RM(buffp);
pbr.ioParam.ioReqCount = CL(*count);
pbr.ioParam.ioPosMode = CWC(fsAtMark);
temp = PBWrite(&pbr, 0);
*count = CL(pbr.ioParam.ioActCount);
fs_err_hook (temp);
return(temp);
}
PUBLIC OSErr
FSWriteAll (INTEGER rn, LONGINT *countp, Ptr buffp)
{
LONGINT orig_count;
OSErr retval;
orig_count = *countp;
retval = FSWrite (rn, countp, buffp);
if (retval == noErr && *countp != orig_count)
retval = ioErr;
return retval;
}
A2(PUBLIC, OSErr, GetFPos, INTEGER, rn, LONGINT *, filep) /* IMIV-110 */
{
ParamBlockRec pbr;
OSErr temp;
pbr.ioParam.ioRefNum = CW(rn);
temp = PBGetFPos(&pbr, 0);
*filep = CL(pbr.ioParam.ioPosOffset);
fs_err_hook (temp);
return(temp);
}
A3(PUBLIC, OSErr, SetFPos, INTEGER, rn, INTEGER, posmode, /* IMIV-110 */
LONGINT, possoff)
{
ParamBlockRec pbr;
OSErr err;
pbr.ioParam.ioRefNum = CW(rn);
pbr.ioParam.ioPosMode = CW(posmode);
pbr.ioParam.ioPosOffset = Cx(possoff);
err = PBSetFPos(&pbr, 0);
fs_err_hook (err);
return err;
}
A2(PUBLIC, OSErr, GetEOF, INTEGER, rn, LONGINT *, eof) /* IMIV-111 */
{
ParamBlockRec pbr;
OSErr temp;
pbr.ioParam.ioRefNum = Cx(rn);
temp = PBGetEOF(&pbr, 0);
*eof = CL(pbr.ioParam.ioMisc);
fs_err_hook (temp);
return(temp);
}
A2(PUBLIC, OSErr, SetEOF, INTEGER, rn, LONGINT, eof) /* IMIV-111 */
{
ParamBlockRec pbr;
OSErr err;
pbr.ioParam.ioRefNum = Cx(rn);
pbr.ioParam.ioMisc = Cx(eof);
err = PBSetEOF(&pbr, 0);
fs_err_hook (err);
return (err);
}
A2(PUBLIC, OSErr, Allocate, INTEGER, rn, LONGINT *, count) /* IMIV-112 */
{
ParamBlockRec pbr;
OSErr temp;
pbr.ioParam.ioRefNum = Cx(rn);
pbr.ioParam.ioReqCount = *count;
temp = PBAllocate(&pbr, 0);
*count = CL(pbr.ioParam.ioActCount);
fs_err_hook (temp);
return(temp);
}
A2(PUBLIC, OSErr, AllocContig, INTEGER, rn, LONGINT *, count)
{
ParamBlockRec pbr;
OSErr temp;
pbr.ioParam.ioRefNum = Cx(rn);
pbr.ioParam.ioReqCount = *count;
temp = PBAllocContig(&pbr, 0);
*count = CL(pbr.ioParam.ioActCount);
fs_err_hook (temp);
return(temp);
}
A1(PUBLIC, OSErr, FSClose, INTEGER, rn) /* IMIV-112 */
{
ParamBlockRec pbr;
OSErr err;
pbr.ioParam.ioRefNum = Cx(rn);
err = PBClose(&pbr, 0);
fs_err_hook (err);
return err;
}
A2(PUBLIC, VCB *, vlookupbyname, const char *, namep, const char *, endp)
{
VCB *retval;
int n;
n = endp - namep;
for (retval = (VCB *)MR(VCBQHdr.qHead); retval;
retval = (VCB *) MR(retval->qLink))
if (n == retval->vcbVN[0] &&
strncmp(namep, (char *) retval->vcbVN+1, n) == 0)
return retval;
#if defined (MSDOS) || defined (CYGWIN32)
for (retval = (VCB *)MR(VCBQHdr.qHead); retval;
retval = (VCB *) MR(retval->qLink))
if (n == retval->vcbVN[0] &&
strncasecmp(namep, (char *) retval->vcbVN+1, n) == 0)
return retval;
#endif
return 0;
}
A1(PRIVATE, VCB *, vlookupbydrive, INTEGER, drive)
{
VCB *retval;
for (retval = (VCB *)MR(VCBQHdr.qHead); retval;
retval = (VCB *) MR(retval->qLink))
if (drive == Cx(retval->vcbDrvNum))
return retval;
return 0;
}
PRIVATE LONGINT cacheindex = 0x7fffffff;
A0(PUBLIC, void, ROMlib_rewinddir)
{
cacheindex = 0x7fffffff;
}
/*
* Blech! I've finally caved in and am going to look for the magic
* number in the obnoxious case of a file that starts with %XX where XX
* are two upper case hex digits.
*/
PUBLIC BOOLEAN ROMlib_isresourcefork(const char *fullname)
{
LONGINT fd;
LONGINT magic;
BOOLEAN retval;
const char *filename;
/* netatalk_conventions_p means we never see resource forks, because
they're stored in a subdirectory */
if (netatalk_conventions_p)
retval = FALSE;
else
{
filename = strrchr(fullname, '/');
if (!filename)
filename = fullname;
else
++filename;
if (filename[0] != '%')
retval = FALSE;
else if (!isxdigit(filename[1]) || !isxdigit(filename[2]))
retval = TRUE;
else {
fd = -1;
retval = (fd = Uopen(fullname, O_BINARY|O_RDONLY, 0)) >= 0 &&
read(fd, (void *) &magic, sizeof(magic)) == sizeof(magic) &&
(magic == CLC(DOUBLEMAGIC)
|| magic == DOUBLEMAGIC);
if (fd >= 0)
Uclose(fd);
}
}
return retval;
}
int ROMlib_no_dot_files = FALSE;
static boolean_t
dislike_name (char *namep)
{
boolean_t retval;
if (strcmp (namep, ".") == 0
|| strcmp (namep, "..") == 0
|| strcmp (namep, ".AppleDouble") == 0
|| strcmp (namep, ".AppleDesktop") == 0
|| (ROMlib_no_dot_files && namep[0] == '.'))
retval = TRUE;
else
{
char *buf;
int namelen;
namelen = strlen (namep);
buf = alloca (namelen);
memcpy (buf, namep, namelen);
namelen -= ROMlib_UNIX7_to_Mac (buf, namelen);
retval = namelen > 31;
}
return retval;
}
A4(PRIVATE, char *, dirindex, char *, dir, LONGINT, index, BOOLEAN, nodirectories,
struct stat *, sbufp)
{
THz saveZone;
static char *cachedir = 0, *cachedirend;
static DIR *dirp = 0;
#if defined (USE_STRUCT_DIRECT)
struct direct *dp;
#else
struct dirent *dp;
#endif
int dirnamelen;
struct stat sbuf;
#if defined(MSDOS) || defined (CYGWIN32)
while (dir[0] == '/' && dir[1] == '/')
++dir;
#endif
if (!sbufp)
sbufp = &sbuf;
if (index <= cacheindex || !cachedir || strcmp(dir, cachedir) != 0) {
if (cachedir)
free (cachedir);
if (dirp)
closedir(dirp);
dirp = Uopendir(dir);
if (!dirp) {
dp = 0;
goto DONE;
}
cacheindex = 0;
dirnamelen = strlen(dir);
#if !defined(MAXNAMLEN)
#define MAXNAMLEN 1024
#endif /* !defined(MAXNAMLEN) */
saveZone = TheZone;
TheZone = SysZone;
cachedir = malloc (dirnamelen+1+MAXNAMLEN+1);
TheZone = saveZone;
if (!cachedir)
/*-->*/ return 0;
strcpy(cachedir, dir);
cachedirend = cachedir + dirnamelen;
}
*cachedirend = '/';
do {
if ((dp = readdir(dirp))) {
strcpy(cachedirend+1, dp->d_name);
if (!dislike_name (dp->d_name)
&& !ROMlib_isresourcefork(cachedir)
&& Ustat(cachedir, sbufp) == 0) {
if (!nodirectories || !S_ISDIR (sbufp->st_mode))
++cacheindex;
}
}
} while (dp && cacheindex != index);
*cachedirend = 0;
DONE:
return dp ? dp->d_name : 0;
}
/*
* NOTE: we must use capital letters in tohex below. Code depends on it.
*/
A1(PRIVATE, unsigned char, tohex, unsigned char, c)
{
unsigned char retval;
retval = (unsigned char) (netatalk_conventions_p ?
"0123456789abcdef"
:
"0123456789ABCDEF")[c & 0xF];
return retval;
}
A3(PRIVATE, INTEGER, Mac_to_UNIX7, unsigned char *, name, INTEGER, length,
unsigned char *, out)
{
unsigned char c;
INTEGER retval;
boolean_t last_character_was_colon;
retval = length;
last_character_was_colon = TRUE;
while (--length >= 0) {
c = *name++;
if (NEEDTOMAP(c)) {
*out++ = apple_double_quote_char;
*out++ = tohex(c >> 4);
*out++ = tohex(c);
retval += 2;
} else if (c == ':') {
if (last_character_was_colon)
{
*out++ = '.';
*out++ = '.';
retval += 2;
}
*out++ = '/';
} else
*out++ = c;
last_character_was_colon = c == ':';
}
return retval;
}
A2(PUBLIC, char *, ROMlib_newunixfrommac, char *, ip, INTEGER, n)
{
char *retval;
if ((retval = malloc (3*n+1))) /* worst case numbers */
retval[Mac_to_UNIX7((unsigned char *) ip, n,
(unsigned char *) retval)] = 0;
return retval;
}
/*
* ROMlib_breakoutioname's role is to examine ioNamePtr and vRefNum
* to determine the vcbp, but since it has to look at ioNamePtr
* anyway it makes sense to make a unix partial pathname for the
* rest. While we're at it, if we get passed in a working-director
* instead of a TRUE vrn we might as well note the directory id
* that is associated with it.
*/
/*
* BUG Fix TODO: newunixfrommac needs to be more complex; specifically
* it needs to handle :: properly (which is to go up
* a directory, UNLESS it's already at the top).
*/
A5(PUBLIC, VCB *, ROMlib_breakoutioname, ParmBlkPtr, pb, /* INTERNAL */
LONGINT *, diridp, char **, therestp, BOOLEAN *, fullpathp,
BOOLEAN, usedefault)
{
VCB *retval;
char *colon;
unsigned char *p;
INTEGER v;
wdentry *wdp;
retval = 0;
*diridp = 0;
*therestp = 0;
if (fullpathp)
*fullpathp = FALSE;
if ((p = (unsigned char *) MR(pb->ioParam.ioNamePtr))) {
if (p[0] > 1 && p[1] != ':') {
if ((colon = pstr_index_after(p, ':', SLASH_CHAR_OFFSET))) {
retval = vlookupbyname((char *) p+1, colon);
if (colon - ((char *)p+1) < p[0])
*therestp =
ROMlib_newunixfrommac(colon+1,
p[0] + (char *) p - colon);
if (fullpathp)
*fullpathp = TRUE;
} else
*therestp = ROMlib_newunixfrommac((char *) p+1, p[0]);
} else if (p[0] > 0) {
if (p[1] == ':' || (p[0] == 1 && p[1] == '/'))
*therestp = ROMlib_newunixfrommac((char *)p+2, p[0]-1);
else
*therestp = ROMlib_newunixfrommac((char *)p+1, p[0]);
}
}
if (!retval) {
if ((v = Cx(pb->ioParam.ioVRefNum)) > 0) /* drive number */
retval = vlookupbydrive(v);
else if (v < 0) {
if (ISWDNUM(v)) {
wdp = WDNUMTOWDP(v);
*diridp = CL(wdp->dirid);
retval = MR(wdp->vcbp);
} else
retval = ROMlib_vcbbyvrn(v);
}
if (!retval && (usedefault ||
(!pb->ioParam.ioNamePtr && !pb->ioParam.ioVRefNum))) {
retval = MR(DefVCBPtr);
*diridp = CL(DefDirID);
}
}
return retval;
}
/*
* myscandir looks through a directory for a filename match with case not
* significant. It returns TRUE if a match was found; FALSE
* otherwise. Note, the filename specified in "rest" starts
* out smashed and needs the character stored in "save" to
* be filled in before it can be used, but this has to be
* done after "dirname" has been used.
*/
A4(PRIVATE, BOOLEAN, myscandir, char *, dirname, char, save, char *, rest,
INTEGER, restlen)
{
DIR *dirp;
#if defined (USE_STRUCT_DIRECT)
struct direct *directp;
#else
struct dirent *directp;
#endif
int retval;
LONGINT d0;
#if defined(MSDOS) || defined (CYGWIN32)
while (dirname[0] == '/' && dirname[1] == '/')
++dirname;
#endif
retval = FALSE;
if ((dirp = Uopendir(dirname))) {
*rest = save;
d0 = ((LONGINT) restlen << 16) | (unsigned short) restlen;
while ((directp = readdir(dirp)))
if (restlen == (INTEGER) strlen (directp->d_name) &&
ROMlib_RelString((unsigned char *) rest,
(unsigned char *) directp->d_name, FALSE, TRUE, d0) == 0) {
retval = TRUE;
memcpy(rest, directp->d_name, restlen);
/*-->*/ break;
}
closedir(dirp);
} else
*rest = save;
return retval;
}
A2(PRIVATE, LONGINT, weasel, char *, fullpathname, struct stat *, sbufp)
{
char *start, *nextslash, save;
INTEGER length;
LONGINT retval;
#if 1
gui_assert(fullpathname[SLASH_CHAR_OFFSET] == '/');
#else
if (fullpathname[SLASH_CHAR_OFFSET] != '/')
{
DEBUG_OUT("weasel surprise %s", fullpathname);
*(long *) -1 = -1;
}
#endif
if (Ustat(fullpathname, sbufp) < 0) {
switch(errno) {
#if !defined (CYGWIN32)
case ENOENT:
#if 0
/* this will only work on systems that distinguish
between ENOENT and ENOTDIR ... maybe it won't work
at all. It doesn't work under Linux, so omit it
for now */
start = strrchr(fullpathname, '/') + 1;
break;
#endif
case ENOTDIR:
start = fullpathname + SLASH_CHAR_OFFSET + 1;
break;
#endif
default:
return errno;
break;
}
} else
return 0;
do {
nextslash = strchr(start, '/');
if (nextslash)
length = nextslash - start;
else
length = strlen(start);
save = *start;
*start = 0;
if (!myscandir(fullpathname, save, start, length)) {
return nextslash ? ENOTDIR : ENOENT;
}
start = nextslash + 1;
} while (nextslash);
if (Ustat(fullpathname, sbufp) < 0)
{
retval = errno;
return retval;
}
else
return 0;
}
/*
* NOTE: As of today, ROMlib_nami always either returns an error, or leaves
* a valid result in *sbufp (if sbufp is non-zero). That means that
* you can call ROMlib_nami and not have to do a stat afterward.
*/
A9(PUBLIC, OSErr, ROMlib_nami, ParmBlkPtr, pb, LONGINT, dir, /* INTERNAL */
IndexType, indextype, char **, pathname, char **, filename,
char **, endname, BOOLEAN, nodirs, VCBExtra **, vcbpp, struct stat *, sbufp)
{
char *temp1, *temp2, *temp3;
INTEGER index;
StringPtr fnamep;
Str255 fname;
LONGINT dirid;
char *therest;
char *fn;
VCBExtra *vcbp;
datum content;
char *vcbanddir;
int vcbstrlen, therestlen;
StringPtr savenamep;
BOOLEAN fullp;
struct stat sbuf;
INTEGER badness;
OSErr err;
ALLOCABEGIN
if (!pathname)
pathname = &temp1;
if (!filename)
filename = &temp2;
if (!endname)
endname = &temp3;
fnamep = 0;
if (indextype != NoIndex) {
savenamep = MR(pb->ioParam.ioNamePtr);
pb->ioParam.ioNamePtr = 0;
}
#if !defined (LETGCCWAIL)
else
savenamep = (StringPtr) -1;
#endif /* LETGCCWAIL */
vcbp = (VCBExtra *) ROMlib_breakoutioname(pb, &dirid, &therest, &fullp,
TRUE);
if (vcbpp)
*vcbpp = vcbp;
if (fullp)
dir = 0;
else {
if (dir <= 0)
dir = dirid;
}
content.dsize = 0;
/*
* Retry strategy:
* first time things don't work we try closing and reopening
* the database (badness == 1); second time we try closing,
* rebuilding and reopening the database (badness == 2).
*/
badness = 0;
/* do { */
loop:
if (dir > 2) {
content = ROMlib_dbm_fetch(vcbp, dir);
if (!content.dptr)
{
content.dsize = 0;
}
}
vcbstrlen = strlen(vcbp->unixname);
vcbanddir = ALLOCA(vcbstrlen + content.dsize + 2);
BlockMove((Ptr) vcbp->unixname, (Ptr) vcbanddir, (Size) vcbstrlen+1);
if (content.dsize) {
if (vcbanddir[vcbstrlen-1] != '/')
{
vcbanddir[vcbstrlen] = '/';
++vcbstrlen;
}
BlockMove((Ptr) content.dptr, (Ptr) vcbanddir+vcbstrlen,
(Size) content.dsize);
vcbanddir[vcbstrlen+content.dsize] = 0;
if (Ustat(vcbanddir, &sbuf) < 0)
{
warning_unexpected ("vcbanddir = '%s', dir = 0x%x",
vcbanddir, dir);
ROMlib_dbm_delete_inode(vcbp, dir);
/*-->*/ goto loop;
}
else if (ST_INO(sbuf) != dir)
{
#if 1
warning_unexpected ("ST_INO(sbuf) = 0x%lx, dir = 0x%x",
(unsigned long) ST_INO(sbuf), dir);
ROMlib_dbm_delete_inode(vcbp, dir);
{
LONGINT templong;
templong = ST_INO(sbuf);
ROMlib_dbm_store(vcbp, vcbanddir, &templong, TRUE);
}
/*-->*/ goto loop;
#else
fprintf(stderr, "ino mismatch %s %ld %d\n", vcbanddir,
(long)ST_INO(sbuf), dir);
++badness;
#endif
}
else
badness = 0;
} else if (dir > 2)
++badness;
if (badness == 1 && dirid)
{
dir = dirid;
badness = 2;
goto loop;
}
if (badness && badness <= 1)
goto loop;
/* } while (badness && badness <= 1); */
if (badness)
{
err = dirNFErr;
warning_trace_info ("badness = %d, dirid = %d, dir = %d, "
"vcbp->unixname = '%s', therest = '%s', "
"fullp = %d, vcbanddir = '%s'",
badness, dirid, dir,
vcbp->unixname, therest, fullp, vcbanddir);
fs_err_hook (err);
free (therest);
/*-->*/ return err;
}
if (indextype != NoIndex)
pb->ioParam.ioNamePtr = RM(savenamep);
if (indextype == FDirIndex && (index = Cx(pb->fileParam.ioFDirIndex)) > 0) {
free (therest);
therest = 0;
if (!(fn = dirindex(vcbanddir, index, nodirs, sbufp))) {
ALLOCAEND
err = fnfErr;
fs_err_hook (err);
/*-->*/ return err;
}
if (pb->ioParam.ioNamePtr)
fnamep = MR(pb->ioParam.ioNamePtr);
else
fnamep = fname;
fnamep[0] = strlen(fn);
strcpy((char *) fnamep+1, fn);
#if 0
therest = ROMlib_newunixfrommac((char *) fnamep+1, fnamep[0]);
#else
therest = malloc ((Size) fnamep[0] + 1);
BlockMove((Ptr) fnamep+1, (Ptr) therest, (Size) fnamep[0]);
therest[fnamep[0]] = 0;
#endif
}
therestlen = therest ? strlen(therest) : 0;
*pathname = malloc (therestlen + strlen(vcbanddir)+2);
*filename = *pathname + strlen(vcbanddir) +1;
*endname = *filename + therestlen + 1;
BlockMove((Ptr) vcbanddir, (Ptr) *pathname, (Size) strlen(vcbanddir));
if (therest) {
if (vcbanddir[1 + SLASH_CHAR_OFFSET]) /* i.e. test for "/" */
(*filename)[-1] = '/';
else {
--*filename;
--*endname;
}
BlockMove((Ptr) therest, (Ptr) *filename, (Size) therestlen);
(*endname)[-1] = 0;
} else {
*endname = *filename;
(*endname)[-1] = 0;
}
if (strcmp(*pathname + SLASH_CHAR_OFFSET, "/") != 0) {
while ((*endname)[-2] == '/') { /* remove trailing slashes */
(*endname)[-2] = 0;
--*endname;
}
if ((*filename = strrchr(*pathname, '/')))
++*filename;
else
*filename = *pathname;
} else
*filename = *pathname;
if (therest)
free (therest);
ALLOCAEND
if (indextype == NoIndex && sbufp) {
errno = weasel(*pathname, sbufp);
err = ROMlib_maperrno();
} else if (indextype == IGNORENAME && sbufp)
{
if (Ustat(*pathname, sbufp) < 0)
{
err = ROMlib_maperrno();
}
else
err = noErr;
}
else
err = noErr;
fs_err_hook (err);
if (err == noErr && fullp)
ROMlib_automount (*pathname);
return err;
}
/*
* Old algorithm:
*
* The new code is a little bit tricky; it would be just prepend a %, except
* if someone has a name that begins with two hex digits ("feed me") you would
* get something that could be a data fork, so we make sure that if the first
* char is a % and the next two are hex and the hex would make something that
* we would have wanted to map then we map the second character even though
* we normally wouldn't map it.
*
* New algorithm:
*
* We just prepend the bloody "%" -- We get into trouble with other providers
* of Apple Double if we do it differently. What a crock.
*/
#define ROOTS_PERCENT_FILE "%%2F"
A3(PUBLIC, char *, ROMlib_resname, char *, pathname, /* INTERNAL */
char *, filename, char *, endname)
{
int pathnamesize, filenamesize, newsize;
char *newname;
pathnamesize = filename - pathname;
filenamesize = endname - filename;
if (pathnamesize)
{
newsize = pathnamesize + filenamesize
+ apple_double_fork_prefix_length;
newname = malloc (newsize);
memcpy (newname, pathname, pathnamesize);
strcpy (&newname[pathnamesize], apple_double_fork_prefix);
memcpy (newname + pathnamesize + apple_double_fork_prefix_length,
filename, filenamesize);
}
else
{
/* "E:/" --> "E:/%%2F" */
newsize = filenamesize + sizeof (ROOTS_PERCENT_FILE);
newname = malloc (newsize);
sprintf (newname, "%s%s", filename, ROOTS_PERCENT_FILE);
}
return newname;
}
/*
* macopen opens the file using mac permissions, returning an OSErr
* the file descriptor of the opened file is filled in where fdp points
*/
A5(PRIVATE, OSErr, macopen, char *, file, short, perm, LONGINT *, fdp,
BOOLEAN, isres, Byte *,flagp)
{
int newperm;
int flockret;
boolean_t open_should_fail_p;
OSErr err;
switch (perm) {
default:
warning_unexpected ("perm = %d", perm);
/* FALL THROUGH */
case fsCurPerm:
newperm = O_RDWR; /* start out here, downgrade if necessary */
*flagp |= fcwriteperm;
break;
case fsRdPerm:
newperm = O_RDONLY;
break;
case fsWrPerm:
*flagp |= fcwriteperm;
newperm = isres ? O_RDWR : O_WRONLY;
break;
case fsRdWrPerm:
*flagp |= fcwriteperm;
newperm = O_RDWR;
break;
case fsRdWrShPerm:
*flagp |= fcwriteperm;
newperm = O_RDWR;
break;
}
#if defined(MSDOS)
#define BROKEN_OPEN
#endif
#if defined(BROKEN_OPEN)
{
struct stat sbuf;
open_should_fail_p = ((newperm == O_WRONLY || newperm == O_RDWR)
&& Ustat(file, &sbuf) == 0
&& (!(sbuf.st_mode & S_IWUSR)));
}
#else
open_should_fail_p = FALSE;
#endif
if (open_should_fail_p)
*fdp = -1;
else
*fdp = Uopen(file, O_BINARY|newperm, 0);
if (*fdp == -1 && perm == fsCurPerm) {
*fdp = Uopen(file, O_BINARY|O_RDONLY, 0);
*flagp &= ~fcwriteperm;
}
flockret = 0;
#if !defined(AVIION) && !defined(MACBLITZ) && 0
if (*fdp != -1) {
if (perm == fsCurPerm || perm == fsRdWrPerm)
flockret = flock(*fdp, LOCK_EX|LOCK_NB);
if (perm == fsRdWrShPerm || (perm == fsCurPerm && flockret == -1))
flockret = flock(*fdp, LOCK_SH|LOCK_NB);
if (flockret == -1 && perm != fsCurPerm) {
Uclose(*fdp);
*fdp = flockret;
}
}
#endif /* !defined(AVIION) */
err = *fdp == -1 ? ROMlib_maperrno(): noErr;
fs_err_hook (err);
return err;
}
A1(PRIVATE, void, freeprn, fcbrec *, fp)
{
fp->fdfnum = 0;
}
A1(PRIVATE, OSErr, getprn, INTEGER *, pprn)
{
INTEGER length;
fcbrec *fcbp, *efcbp;
OSErr err;
/* #define NASTYTEMPHAXK */
#if defined(NASTYTEMPHAXK) && defined(MSDOS)
static int n = 0;
*pprn = 2 + 94 * n++;
return noErr;
#endif
length =CW( *(short *)MR(FCBSPtr));
fcbp = (fcbrec *) ((short *)MR(FCBSPtr)+1);
efcbp = (fcbrec *) ((char *)MR(FCBSPtr) + length);
for (;fcbp < efcbp && fcbp->fdfnum;
fcbp = (fcbrec *) ((char *)fcbp + Cx(FSFCBLen)))
;
if (fcbp < efcbp) {
*pprn = (char *) fcbp - (char *) MR(FCBSPtr);
err = noErr;
} else
err = tmfoErr;
fs_err_hook (err);
return err;
}
A4(PRIVATE, OSErr, PBOpenForkD, ParmBlkPtr, pb, BOOLEAN, a,
ForkType, fork, LONGINT, dir)
{
OSErr err;
int temp;
INTEGER prn;
char *pathname, *filename, *endname, *newname;
struct stat sbuf;
VCBExtra *vcbp;
int namelen;
fcbrec *fp;
THz savezone;
int save_index;
char save_char;
char *need_to_free;
need_to_free = 0;
pb->ioParam.ioRefNum = CWC(0); /* in case some goofy program,
like StuffIt Lite decides to
ignore error codes */
savezone = TheZone;
TheZone = SysZone;
pathname = 0;
/*
* We have to pass in sbuf below or we won't be weaseled like we should be.
*/
if ((err = ROMlib_nami(pb, dir, NoIndex, &pathname, &filename, &endname,
TRUE, &vcbp, (struct stat *) &sbuf)) == noErr) {
err = getprn(&prn);
if (err == noErr) {
fp = (fcbrec *) (MR(FCBSPtr) + prn);
fp->fdfnum = CL((LONGINT) ST_INO(sbuf));
fp->fcfd = -1;
fp->fcflags = 0;
fp->fcbTypByt = 0;
fp->fcbCrPs = 0;
if ((filename == pathname + 1) ||
(filename == pathname + SLASH_CHAR_OFFSET + 1))
save_index = 0; /* root ... don't scorch leading "/" */
else
save_index = -1;
save_char = filename[save_index];
filename[save_index] = 0;
if (Ustat(pathname, &sbuf) < 0) /* NOTE: this is a stat of */
err = ROMlib_maperrno(); /* the parent's directory, */
else { /* so ROMlib_nami won't do */
if (ST_INO(sbuf) == vcbp->u.ufs.ino) /* the stat for us */
fp->fcparid = CLC (2);
else
fp->fcparid = CL((LONGINT) ST_INO(sbuf));
filename[save_index] = save_char;
if (fork == ResourceFork) {
newname = ROMlib_resname(pathname, filename, endname);
temp = Ustat(newname, &sbuf);
if (temp < 0 && errno != ENOENT)
err = ioErr;
need_to_free = pathname; /* can't free it now, because
filename is drawn from
here */
pathname = newname;
}
}
if (err == noErr) {
err = macopen(pathname, pb->ioParam.ioPermssn,
&fp->fcfd, fork == ResourceFork, &fp->fcflags);
if (err != noErr
&& (fork != ResourceFork ||
(err = ROMlib_newresfork(pathname, &fp->fcfd, TRUE))))
freeprn(fp);
else {
if (fork == ResourceFork)
{
fp->fcflags |= fcfisres;
fp->hiddenfd = fp->fcfd;
lseek(fp->fcfd, ROMlib_FORKOFFSET(fp), L_SET);
}
else
{
newname = ROMlib_resname (pathname, filename,
endname);
fp->hiddenfd = Uopen (newname, O_BINARY|O_RDWR, 0666L);
if (fp->hiddenfd < 0)
{
Byte dummy_byte = -1;
if (errno == ENOENT)
{
if ((fp->fcflags & fcwriteperm) &&
!ROMlib_creator_and_type_from_filename
(strlen (filename), filename, NULL, NULL))
err = ROMlib_newresfork(newname,
&fp->hiddenfd, TRUE);
else
{
err = noErr;
fp->hiddenfd = -1;
}
}
else
macopen(newname, pb->ioParam.ioPermssn,
&fp->hiddenfd, TRUE, &dummy_byte);
}
free (newname);
}
if (err == noErr)
err = ROMlib_geteofostype(fp);
fp->fcvptr = RM((VCB *) vcbp);
pb->ioParam.ioRefNum = CW(prn);
namelen = strlen (filename);
namelen -= ROMlib_UNIX7_to_Mac (filename, namelen);
namelen = MIN(namelen, 31);
fp->fcname[0] = namelen;
BlockMove((Ptr) filename,
(Ptr) fp->fcname+1, (Size) namelen);
}
}
}
}
if (need_to_free)
free (need_to_free);
if (pathname)
free (pathname);
TheZone = savezone;
fs_err_hook (err);
return err;
}
A2(PUBLIC, OSErr, ufsPBOpen, ParmBlkPtr, pb, BOOLEAN, a) /* INTERNAL */
{
OSErr err;
err = PBOpenForkD(pb, a, DataFork, 0);
fs_err_hook (err);
return err;
}
A2(PUBLIC, OSErr, ufsPBHOpen, HParmBlkPtr, pb, /* INTERNAL */
BOOLEAN, a) /* IMIV-136 */
{
OSErr err;
err = PBOpenForkD((ParmBlkPtr) pb, a, DataFork, CL(pb->fileParam.ioDirID));
fs_err_hook (err);
return err;
}
A2(PUBLIC trap, OSErrRET, OpenDeny, HParmBlkPtr, pb, /* IMV-397 */
BOOLEAN, a)
{ /* HACK */
HParamBlockRec block;
OSErr retval;
block.ioParam.ioCompletion = pb->ioParam.ioCompletion;
block.ioParam.ioNamePtr = pb->ioParam.ioNamePtr;
block.ioParam.ioVRefNum = pb->ioParam.ioVRefNum;
block.ioParam.ioVersNum = 0;
switch (pb->ioParam.ioPermssn & 3) {
case 0:
block.ioParam.ioPermssn = fsCurPerm;
break;
case 1:
block.ioParam.ioPermssn = fsRdPerm;
break;
case 2:
block.ioParam.ioPermssn = fsWrPerm;
break;
case 3:
block.ioParam.ioPermssn = fsRdWrPerm;
break;
}
block.ioParam.ioMisc = 0;
block.fileParam.ioDirID = pb->fileParam.ioDirID;
retval = PBHOpen(&block, a);
pb->ioParam.ioResult = block.ioParam.ioResult;
pb->ioParam.ioRefNum = block.ioParam.ioRefNum;
fs_err_hook (retval);
return retval;
}
A2(PUBLIC, OSErr, ufsPBOpenRF, ParmBlkPtr, pb, /* INTERNAL */
BOOLEAN, a)
{
OSErr err;
err = PBOpenForkD(pb, a, ResourceFork, 0);
fs_err_hook (err);
return err;
}
A2(PUBLIC, OSErr, ufsPBHOpenRF, HParmBlkPtr, pb, /* INTERNAL */
BOOLEAN, a)
{
OSErr err;
err = PBOpenForkD((ParmBlkPtr) pb, a, ResourceFork,
CL(pb->fileParam.ioDirID));
fs_err_hook (err);
return err;
}
#define POSMASK 0x3 /* IMIV-121 */
PRIVATE OSErr
pbfpos (ParmBlkPtr pb, LONGINT *toseekp, boolean_t can_go_past_eof)
{
OSErr err;
LONGINT leof;
INTEGER forkoffset;
LONGINT pos;
int fd;
fcbrec *fp;
fp = PRNTOFPERR(Cx(pb->ioParam.ioRefNum), &err);
if (err == noErr) {
forkoffset = FORKOFFSET(fp);
leof = Cx(fp->fcleof);
fd = fp->fcfd;
switch (Cx(pb->ioParam.ioPosMode) & POSMASK) {
case fsAtMark:
if ((pos = lseek(fd, 0L, L_INCR)) == -1) {
switch(errno) {
case EBADF:
err = fnOpnErr;
break;
case EINVAL:
err = paramErr;
break;
default:
err = ioErr;
}
} else
*toseekp = pos - forkoffset;
break;
case fsFromStart:
*toseekp = Cx(pb->ioParam.ioPosOffset);
break;
case fsFromLEOF:
*toseekp = leof + Cx(pb->ioParam.ioPosOffset);
break;
case fsFromMark:
if ((pos = lseek(fd, 0L, L_INCR)) == -1) {
switch(errno) {
case EBADF:
err = fnOpnErr;
break;
case EINVAL:
err = paramErr;
break;
default:
err = ioErr;
}
} else
*toseekp = pos + Cx(pb->ioParam.ioPosOffset) - forkoffset;
break;
}
if (*toseekp + forkoffset < 0) {
err = posErr;
*toseekp = 0;
} else if ((*toseekp > leof) && !can_go_past_eof) {
err = eofErr;
*toseekp = leof;
}
*toseekp += forkoffset;
}
fs_err_hook (err);
return err;
}
A3(PRIVATE, OSErr, PBLockUnlockRange, ParmBlkPtr, pb, BOOLEAN, a,
lockunlock_t, op)
{
OSErr err;
LONGINT toseek;
int fd;
LONGINT curseek;
fcbrec *fp;
err = noErr;
fp = PRNTOFPERR(Cx(pb->ioParam.ioRefNum), &err);
if (err == noErr) {
if ((err = pbfpos(pb, &toseek, TRUE)) == noErr) {
OSErr (*verify ) (int fd, uint32 start, uint32 count);
OSErr (*cleanup) (int fd, uint32 start, uint32 count);
fd = fp->fcfd;
curseek = lseek(fd, 0, L_SET);
if (op == lock)
{
verify = ROMlib_fd_range_overlap;
cleanup = ROMlib_fd_add_range;
}
else
{
verify = ROMlib_find_fd_start_count;
cleanup = ROMlib_fd_remove_range;
}
err = verify (fd, toseek, CL (pb->ioParam.ioReqCount));
if (err == noErr && lseek(fd, toseek, L_SET) == -1)
err = ROMlib_maperrno();
if (err == noErr)
err = ROMlib_lockunlockrange (fd, toseek,
CL (pb->ioParam.ioReqCount), op);
if (err == noErr)
err = cleanup (fd, toseek, CL (pb->ioParam.ioReqCount));
lseek(fd, curseek, L_SET);
}
}
fs_err_hook (err);
return err;
}
A2(PUBLIC, OSErr, ufsPBLockRange, ParmBlkPtr, pb, /* INTERNAL */
BOOLEAN, a)
{
OSErr err;
err = PBLockUnlockRange(pb, a, lock);
fs_err_hook (err);
return err;
}
A2(PUBLIC, OSErr, ufsPBUnlockRange, ParmBlkPtr, pb, /* INTERNAL */
BOOLEAN, a)
{
OSErr err;
err = PBLockUnlockRange(pb, a, unlock);
fs_err_hook (err);
return err;
}
PRIVATE OSErr
pbsetfpos (ParmBlkPtr pb, boolean_t can_go_past_eof)
{
OSErr err;
INTEGER forkoffset;
LONGINT toseek;
int fd;
fcbrec *fp;
fp = PRNTOFPERR(Cx(pb->ioParam.ioRefNum), &err);
if (err == noErr) {
forkoffset = FORKOFFSET(fp);
err = pbfpos(pb, &toseek, can_go_past_eof);
fd = fp->fcfd;
pb->ioParam.ioPosOffset = CL(lseek(fd, toseek, L_SET) - forkoffset);
}
fs_err_hook (err);
return err;
}
PUBLIC int ROMlib_newlinetocr = TRUE;
/*
* NOTE: ROMlib_destroy_blocks is a wrapper routine that either destroys
* a limited range or flushes the entire cache. Apple's semantics
* say that you must flush the entire cache in certain circumstances.
* However, 99% of all programs need to destroy only a range of
* addresses.
*/
PUBLIC int ROMlib_flushoften = 0;
PUBLIC unsigned long ROMlib_destroy_blocks(syn68k_addr_t start, uint32 count,
BOOLEAN flush_only_faulty_checksums)
{
unsigned long num_blocks_destroyed;
if (ROMlib_flushoften)
{
start = 0;
count = ~0;
}
if (count)
{
if (flush_only_faulty_checksums)
num_blocks_destroyed =
destroy_blocks_with_checksum_mismatch (start, count);
else
num_blocks_destroyed = destroy_blocks (start, count);
}
else
num_blocks_destroyed = 0;
return num_blocks_destroyed;
}
A2(PUBLIC, OSErr, ufsPBRead, ParmBlkPtr, pb, BOOLEAN, a) /* INTERNAL */
{
OSErr err;
LONGINT nread;
INTEGER forkoffset;
fcbrec *fp;
#if 0
if (pb->ioParam.ioRefNum == 0x5003)
{
printf ("read IN mode = %d, offset = %5d, req = %5d\n",
CW (pb->ioParam.ioPosMode),
CL (pb->ioParam.ioPosOffset), CL (pb->ioParam.ioReqCount));
}
#endif
if (Cx(pb->ioParam.ioRefNum) < 0)
{
err = ROMlib_dispatch(pb, a, Prime, aRdCmd);
fs_err_hook (err);
return err;
}
fp = PRNTOFPERR(Cx(pb->ioParam.ioRefNum), &err);
if (err == noErr && ((err = pbsetfpos(pb, FALSE)) == noErr || err == eofErr)) {
forkoffset = FORKOFFSET(fp);
if (Cx(pb->ioParam.ioReqCount) < 0)
err = paramErr;
else {
int fd = fp->fcfd;
LONGINT rc = Cx(pb->ioParam.ioReqCount);
if (Cx(pb->ioParam.ioPosOffset) + rc > Cx(fp->fcleof))
rc = Cx(fp->fcleof) - Cx(pb->ioParam.ioPosOffset);
nread = read(fd, (char *)(MR(pb->ioParam.ioBuffer)), rc);
ROMlib_destroy_blocks((syn68k_addr_t)
(long) US_TO_SYN68K(MR(pb->ioParam.ioBuffer)),
rc, TRUE);
if (nread == -1) {
pb->ioParam.ioActCount = 0;
err = ioErr;
} else {
pb->ioParam.ioActCount = CL(nread);
pb->ioParam.ioPosOffset = CL(lseek(fd, 0L, L_INCR) -
forkoffset);
if (rc != Cx(pb->ioParam.ioReqCount))
err = eofErr;
}
}
}
fs_err_hook (err);
#if 0
if (pb->ioParam.ioRefNum == 0x5003)
{
printf ("read OUT mode = %d, offset = %5d, req = %5d, act = %d, err = %d\n",
CW (pb->ioParam.ioPosMode),
CL (pb->ioParam.ioPosOffset), CL (pb->ioParam.ioReqCount),
CL (pb->ioParam.ioActCount),
err);
}
#endif
return err;
}
A2(PUBLIC, OSErr, ufsPBWrite, ParmBlkPtr, pb, BOOLEAN, a) /* INTERNAL */
{
OSErr err;
LONGINT nwrite, rc;
INTEGER forkoffset;
fcbrec *fp;
if (Cx(pb->ioParam.ioRefNum) < 0)
{
err = ROMlib_dispatch(pb, a, Prime, aWrCmd);
fs_err_hook (err);
return err;
}
fp = PRNTOFPERR(Cx(pb->ioParam.ioRefNum), &err);
if (err == noErr && ((err = pbsetfpos(pb, TRUE)) == noErr || err == eofErr)) {
forkoffset = FORKOFFSET(fp);
if ((rc = Cx(pb->ioParam.ioReqCount)) < 0)
err = paramErr;
else {
int fd = fp->fcfd;
#if defined (WEHAVEENOUGHSWAPSPACETORUNSUNSGOOFYLITTLERPCTHINGYS)
#if defined (SUN)
if (lockf(fd, F_TLOCK, rc))
err = fLckdErr;
#endif /* SUN */
#endif /* WEHAVEENOUGHSWAPSPACETORUNSUNSGOOFYLITTLERPCTHINGYS */
if (err == noErr && Cx(pb->ioParam.ioPosOffset) + rc > Cx(fp->fcleof)) {
fp->fcleof = CL(CL(pb->ioParam.ioPosOffset) + rc);
err = ROMlib_seteof(fp);
}
if (err == noErr) {
nwrite = write(fd, (char *)(MR(pb->ioParam.ioBuffer)), rc);
if (nwrite == -1) {
pb->ioParam.ioActCount = 0;
err = ioErr;
} else {
err = noErr;
pb->ioParam.ioActCount = CL(nwrite);
pb->ioParam.ioPosOffset = CL(lseek(fd, 0L, L_INCR) -
forkoffset);
if (Cx(pb->ioParam.ioPosOffset) > Cx(fp->fcleof)) {
fp->fcleof = pb->ioParam.ioPosOffset;
err = ROMlib_seteof(fp);
}
}
}
#if defined (WEHAVEENOUGHSWAPSPACETORUNSUNSGOOFYLITTLERPCTHINGYS)
#if defined (SUN)
lockf(fd, F_ULOCK, Cx(pb->ioParam.ioReqCount));
#endif /* SUN */
#endif /* WEHAVEENOUGHSWAPSPACETORUNSUNSGOOFYLITTLERPCTHINGYS */
}
}
fs_err_hook (err);
return err;
}
A2(PUBLIC, OSErr, ufsPBGetFPos, ParmBlkPtr, pb, /* INTERNAL */
BOOLEAN, a)
{
OSErr err;
INTEGER forkoffset;
fcbrec *fp;
fp = PRNTOFPERR(Cx(pb->ioParam.ioRefNum), &err);
if (err == noErr) {
forkoffset = FORKOFFSET(fp);
pb->ioParam.ioPosOffset = CL(lseek(fp->fcfd, 0L, L_INCR) -
forkoffset);
pb->ioParam.ioReqCount = pb->ioParam.ioActCount =
pb->ioParam.ioPosMode = 0;
}
fs_err_hook (err);
return err;
}
A2(PUBLIC, OSErr, ufsPBSetFPos, ParmBlkPtr, pb, /* INTERNAL */
BOOLEAN, a)
{
OSErr err = pbsetfpos(pb, FALSE);
#if 0
if (pb->ioParam.ioRefNum == 0x5003)
{
printf ("seek IN mode = %d, offset = %5d\n",
CW (pb->ioParam.ioPosMode),
CL (pb->ioParam.ioPosOffset));
}
#endif
if (err == noErr)
pb->ioParam.ioReqCount = pb->ioParam.ioActCount = 0;
fs_err_hook (err);
#if 0
if (pb->ioParam.ioRefNum == 0x5003)
{
printf ("seek OUT mode = %d, offset = %5d, err = %d\n",
CW (pb->ioParam.ioPosMode),
CL (pb->ioParam.ioPosOffset), err);
}
#endif
return err;
}
A2(PUBLIC, OSErr, ufsPBGetEOF, ParmBlkPtr, pb, BOOLEAN, a) /* INTERNAL */
{
fcbrec *fp;
OSErr err;
fp = PRNTOFPERR(Cx(pb->ioParam.ioRefNum), &err);
if (err == noErr)
pb->ioParam.ioMisc = fp->fcleof;
fs_err_hook (err);
return err;
}
A2(PUBLIC, OSErr, ufsPBSetEOF, ParmBlkPtr, pb, BOOLEAN, a) /* INTERNAL */
{
fcbrec *fp;
OSErr err;
fp = PRNTOFPERR(Cx(pb->ioParam.ioRefNum), &err);
if (err == noErr) {
fp->fcleof = pb->ioParam.ioMisc;
err = ROMlib_seteof(fp);
}
fs_err_hook (err);
return err;
}
A2(PUBLIC, OSErr, ufsPBAllocate, ParmBlkPtr, pb, /* INTERNAL */
BOOLEAN, a)
{
fcbrec *fp;
OSErr err;
fp = PRNTOFPERR(Cx(pb->ioParam.ioRefNum), &err);
if (err == noErr) {
fp->fcleof = CL(CL(fp->fcleof) + CL(pb->ioParam.ioReqCount));
err = ROMlib_seteof(fp);
pb->ioParam.ioActCount = pb->ioParam.ioReqCount;
}
fs_err_hook (err);
return err;
}
A2(PUBLIC, OSErr, ufsPBAllocContig, ParmBlkPtr, pb, /* INTERNAL */
BOOLEAN, a)
{
OSErr err;
/* WARN that calling this might be a sign of a non-portable program */
err = PBAllocate(pb, a); /* o.k. a lie, but wtf */
fs_err_hook (err);
return err;
}
A2(PUBLIC, OSErr, ufsPBFlushFile, ParmBlkPtr, pb, /* INTERNAL */
BOOLEAN, a)
{
fcbrec *fp;
OSErr err;
fp = PRNTOFPERR(Cx(pb->ioParam.ioRefNum), &err);
if (!ROMlib_nosync)
sync ();
fs_err_hook (err);
return err;
}
A2(PUBLIC, OSErr, ufsPBClose, ParmBlkPtr, pb, BOOLEAN, a)/* INTERNAL */
{
OSErr err;
fcbrec *fp;
if (Cx(pb->ioParam.ioRefNum) < 0)
{
err = ROMlib_dispatch(pb, a, Close, 0);
fs_err_hook (err);
return err;
}
fp = PRNTOFPERR(Cx(pb->ioParam.ioRefNum), &err);
if (err == noErr) {
if (Uclose(fp->fcfd) < 0)
{
err = ioErr;
}
Uclose(fp->hiddenfd);
freeprn(fp);
}
fs_err_hook (err);
return err;
}
A2(PUBLIC trap, OSErrRET, PBHGetLogInInfo, HParmBlkPtr, pb, BOOLEAN, a)
{
OSErrRET retval;
warning_unimplemented (NULL_STRING);
retval = paramErr;
return retval;
}
A2(PUBLIC trap, OSErrRET, PBHGetDirAccess, HParmBlkPtr, pb, BOOLEAN, a)
{
OSErrRET retval;
warning_unimplemented (NULL_STRING);
retval = paramErr;
return retval;
}
A2(PUBLIC trap, OSErrRET, PBHCopyFile, HParmBlkPtr, pb, BOOLEAN, a)
{
OSErrRET retval;
warning_unimplemented (NULL_STRING);
retval = paramErr;
return retval;
}
A2(PUBLIC trap, OSErrRET, PBHMapName, HParmBlkPtr, pb, BOOLEAN, a)
{
OSErrRET retval;
warning_unimplemented (NULL_STRING);
retval = paramErr;
return retval;
}
A2(PUBLIC trap, OSErrRET, PBHMapID, HParmBlkPtr, pb, BOOLEAN, a)
{
OSErrRET retval;
warning_unimplemented (NULL_STRING);
retval = paramErr;
return retval;
}
A2(PUBLIC trap, OSErrRET, PBHSetDirAccess, HParmBlkPtr, pb, BOOLEAN, a)
{
OSErrRET retval;
warning_unimplemented (NULL_STRING);
retval = paramErr;
return retval;
}
A2(PUBLIC trap, OSErrRET, PBHMoveRename, HParmBlkPtr, pb, BOOLEAN, a)
{
OSErrRET retval;
warning_unimplemented (NULL_STRING);
retval = paramErr;
return retval;
}