executor/src/hfsHelper.c

810 lines
21 KiB
C

/* Copyright 1992 - 1996 by Abacus Research and
* Development, Inc. All rights reserved.
*/
#if !defined (OMIT_RCSID_STRINGS)
char ROMlib_rcsid_hfsHelper[] =
"$Id: hfsHelper.c 63 2004-12-24 18:19:43Z ctm $";
#endif
#include "rsys/common.h"
#include "OSUtil.h"
#include "FileMgr.h"
#include "SegmentLdr.h"
#include "ToolboxEvent.h"
#include "MemoryMgr.h"
#include "ThinkC.h"
#include "SysErr.h"
#include "DialogMgr.h"
#include "ResourceMgr.h"
#include "rsys/hfs.h"
#include "rsys/file.h"
#include "rsys/setuid.h"
#include "rsys/partition.h"
#if defined (MSDOS) || defined (CYGWIN32)
#include "dosdisk.h"
#include "aspi.h"
#endif
#if !defined(MAC)
#define FLOPPYWORKSFS "/usr/filesystems/macintosh.fs"
#define NEWFLOPPYWORKSFS "/usr/filesystems/macintosh.fs.SAVE"
#define MAC30FS "/usr/filesystems/mac.fs"
#define NEWMAC30FS "/usr/filesystems/mac.fs.SAVE"
#define OURSOCK "/dev/HFS_XFer"
#define HFSXFERDOTFS "/usr/filesystems/HFS_XFer.fs"
#define HFSXFERUTIL HFSXFERDOTFS "/HFS_XFer.util"
#if defined (NEXT)
PRIVATE LONGINT pipefd[2];
#endif /* NEXT */
PUBLIC LONGINT ROMlib_sock;
PUBLIC void ROMlib_hfsinit( void )
{
#if defined (NEXT)
struct stat sbuf;
struct sockaddr sockname;
LONGINT i;
char device[DEVNAMELEN];
LONGINT nread, nwritten;
LONGINT err;
LONGINT savemask;
LONGINT myfd;
LONGINT mode;
if (geteuid())
mustbesetuid();
if (Ustat(HFSXFERDOTFS, &sbuf) < 0) {
savemask = umask(0);
Umkdir(HFSXFERDOTFS, 0755);
umask(savemask);
}
if (((Ustat(HFSXFERUTIL, &sbuf) < 0) || (sbuf.st_mtime < ROMlib_ourmtime))
&& ROMlib_xfervmsize) {
myfd = Uopen(HFSXFERUTIL, O_BINARY|O_CREAT|O_WRONLY, 000);
if (myfd >= 0) {
nwritten = write(myfd, ROMlib_xfervmaddr, ROMlib_xfervmsize);
err = close(myfd);
if (nwritten == ROMlib_xfervmsize && err == 0)
Uchmod(HFSXFERUTIL, 04711);
else
Uunlink(HFSXFERUTIL);
}
}
if (Ustat(FLOPPYWORKSFS, &sbuf) >= 0)
Urename(FLOPPYWORKSFS, NEWFLOPPYWORKSFS);
if (Ustat(MAC30FS, &sbuf) >= 0)
Urename(MAC30FS, NEWMAC30FS);
pipefd[1] = -1;
pipe((void *) pipefd);
if (fork() == 0) {
setpgrp(0, 0);
for (i = 1; i < NSIG; ++i)
signal(i, SIG_IGN);
close(pipefd[1]);
do {
nread = read(pipefd[0], device, sizeof(device));
if (nread > 1) {
sscanf(device+strlen(device)+1, "%o", &mode);
Uchmod(device, mode);
}
} while (nread > 0);
Urename(NEWFLOPPYWORKSFS, FLOPPYWORKSFS);
Urename(NEWMAC30FS, MAC30FS);
Uunlink(OURSOCK);
exit(0);
} else
close(pipefd[0]);
ROMlib_sock = socket(AF_UNIX, SOCK_STREAM, 0);
gui_assert(ROMlib_sock >= 0);
sockname.sa_family = AF_UNIX;
memmove(sockname.sa_data, OURSOCK, sizeof(OURSOCK));
Uunlink(OURSOCK);
err = bind(ROMlib_sock, &sockname, sizeof(sockname));
if (err < 0)
someoneelseonfloppy();
/* gui_assert(err >= 0); */
ROMlib_setuid(getuid());
err = fcntl(ROMlib_sock, F_SETFL, FNDELAY);
/* gui_assert(err >= 0); */
err = listen(ROMlib_sock, 1);
/* gui_assert(err >= 0); */
#endif /* NEXT */
}
/*
* NOTE: The weird name constructed below is inherited from HFS_XFer.util.c,
* which is an ARDI written NEXTSTEP atrocity.
*/
#if !defined(LINUX) && !defined (MACOSX)
#define EJECTABLE(buf) FALSE
#else
/* #warning this is not the proper way to tell if something is ejectable */
#define EJECTABLE(buf) (buf[strlen(buf)-3] == 'f' && buf[strlen(buf)-2] == 'd')
#endif
#define ASSIGN_NAME_MODE_STRING(buf, lenp, filename, sbuf) \
do { \
char ejectable; \
\
ejectable = EJECTABLE(filename); \
*(lenp) = strlen((filename)) + 1 + 6 + 1 + 1 + 1; \
(buf) = alloca(*(lenp)); \
sprintf((buf), "%s%c%06o%c%c", (filename), 0, (sbuf).st_mode & 07777, 0, \
ejectable);\
} while (0)
#define NRETRIES 5
#if defined (NEXT)
PUBLIC long ROMlib_priv_open(const char *filename, long mode)
{
long retval;
struct stat sbuf;
long savemode;
char *dname;
long len;
int count;
if (Ustat(filename, &sbuf) < 0)
retval = ROMlib_maperrno();
else {
savemode = sbuf.st_mode;
sbuf.st_mode = 0666;
ASSIGN_NAME_MODE_STRING(dname, &len, filename, sbuf);
write(pipefd[1], dname, len);
count = NRETRIES;
do {
if (count != NRETRIES)
Delay(60, (LONGINT *) 0);
retval = Uopen(filename, mode);
} while ((retval < 0) && (errno == EACCES) && --count);
if (retval < 0)
retval = ROMlib_maperrno();
sbuf.st_mode = savemode;
ASSIGN_NAME_MODE_STRING(dname, &len, filename, sbuf);
write(pipefd[1], dname, len);
}
return retval;
}
#else
PUBLIC long
ROMlib_priv_open (const char *filename, long mode)
{
long retval;
retval = Uopen(filename, mode, 0);
if (retval < 0)
retval = ROMlib_maperrno();
return retval;
}
#endif
PRIVATE void eject_floppy_notify( void )
{
/*
* We make the test for 'ALRT' because when Executor shuts down, an ejectable
* volume may be unmounted after the volume with the System file has already
* been unmounted. In the past, this caused a crash. It may make sense to
* deliberately unmount last the volume containing System, but that's a fix
* for another day.
*/
if (WWExist == EXIST_YES && GetResource(TICK("ALRT"), EJECTALERTID))
Alert(EJECTALERTID, (ProcPtr) 0);
}
PUBLIC OSErr ROMlib_ejectfloppy( LONGINT floppyfd )
{
OSErr err;
err = noErr;
#if defined(MSDOS) || defined (CYGWIN32)
if (floppyfd == -1 || (floppyfd & (DOSFDBIT|ASPIFDBIT))) {
if (floppyfd != -1)
{
if (floppyfd & DOSFDBIT)
{
floppyfd &= ~DOSFDBIT;
dosdisk_close(floppyfd, TRUE);
}
#if defined (MSDOS)
else
{
floppyfd &= ~ASPIFDBIT;
aspi_disk_close(floppyfd, TRUE);
}
#endif
}
eject_floppy_notify();
} else {
#endif
#if defined(NEXTSTEP) || defined (MACOSX)
if (floppyfd != -1 && ioctl(floppyfd, DKIOCEJECT, (char *) 0) < 0) {
fprintf(stderr, "couldn't eject disk\n");
err = ioErr;
}
#endif
if (floppyfd != -1)
close(floppyfd);
#if defined(LINUX) || defined (MACOSX)
eject_floppy_notify();
#endif
#if defined(MSDOS) || defined (CYGWIN32)
}
#endif
return err;
}
PUBLIC void ROMlib_OurClose( void )
{
HVCB *vcbp, *next;
ParamBlockRec pbr;
for (vcbp = (HVCB *) MR(VCBQHdr.qHead); vcbp; vcbp = next) {
next = (HVCB *) MR(vcbp->qLink);
pbr.ioParam.ioNamePtr = 0;
if (Cx(vcbp->vcbCTRef)) {
pbr.ioParam.ioVRefNum = vcbp->vcbVRefNum;
PBUnmountVol(&pbr);
#if defined (NEXTSTEP) || defined (MACOSX)
if (!(Cx(vcbp->vcbAtrb) & VNONEJECTABLEBIT) && Cx(vcbp->vcbDrvNum))
ROMlib_ejectfloppy(((VCBExtra *) vcbp)->u.hfs.fd);
#endif
} else
ROMlib_dbm_close((VCBExtra *) vcbp);
}
}
#if 0
PRIVATE BOOLEAN isejectable( const charCx( *dname), LONGINT fd )
{
BOOLEAN retval;
#if defined(NEXTSTEP) || defined (MACOSX)
struct scsi_req sr;
char inqbuf[sizeof(struct inquiry_reply) + 3];
struct inquiry_replyCx( *inqp);
const charCx( *p);
#endif
/* look for rfd[0-9] */
retval = FALSE;
#if defined(NEXTSTEP) || defined (MACOSX)
for (p = dname; p = index(p, 'r'); ++p) {
if (p[1] == 'f' && p[2] == 'd' && isdigit(p[3])) {
retval = TRUE;
/*-->*/ break;
}
}
if (!retval) {
inqp = (struct inquiry_reply *) (((LONGINT) inqbuf + 3) / 4Cx( * 4));
bzero (&sr, sizeof(sr));
sr.sr_cdb.cdb_c6.c6_opcode = C6OP_INQUIRY;
sr.sr_cdb.cdb_c6.c6_len = sizeofCx((*inqp));
sr.sr_dma_dir = SR_DMA_RD;
sr.sr_addr = (caddr_t) inqp;
sr.sr_dma_max = sr.sr_cdb.cdb_c6.c6_len;
sr.sr_ioto = 1;
if (ioctl(fd, SGIOCREQ, &sr) == 0 && sr.sr_io_status == 0 &&
Cx(inqp->ir_removable))
retval = TRUE;
}
#endif
return retval;
}
#endif
/*
* NOTE: messp below points to the longint that will be filled in with
* the status of the first disk insert event that we create, but
* because we can have multiple drives mounted on one physical
* drive, we wind put using PostEvent for all but the first.
*
* The above method sounds pretty hacky to me, and should probably
* be replaced once we find a cheaper way to be notified that
* a disk can be read (probably use a signal on the pipe).
*/
PRIVATE LONGINT try_to_open_disk( const char *dname,
LONGINT *bsizep, LONGINT *maxbytesp, drive_flags_t *flagsp,
uint32 *offsetp)
{
LONGINT floppyfd;
int len;
#if defined(NEXTSTEP)
struct drive_info drvinfo;
#endif
*flagsp = 0;
len = strlen(dname)+1; /* first component: name */
len += strlen(dname+len)+1; /* second component: permission */
if (!dname[len])
*flagsp |= DRIVE_FLAGS_FIXED; /* third component: ejectable */
#if defined (NEXT)
if (pipefd[1] != -1)
write(pipefd[1], dname, len);
#endif /* NEXT */
#if !defined (CYGWIN32)
#define EXTRA_BITS O_EXCL
#else
#define EXTRA_BITS 0
#endif
if ((floppyfd = Uopen(dname, O_BINARY|O_RDWR|EXTRA_BITS, 0000)) < 0 &&
(*flagsp |= DRIVE_FLAGS_LOCKED,
(floppyfd = Uopen(dname, O_BINARY|O_RDONLY|EXTRA_BITS,
0000)) < 0))
/* fprintf(stderr, "can't open %s\n", dname) */;
else {
#if defined(NEXTSTEP)
if (ioctl(floppyfd, DKIOCINFO, &drvinfo) == 0) {
*bsizep = drvinfo.di_devblklen;
*maxbytesp = drvinfo.di_maxbcount / *bsizep * *bsizep;
} else {
*bsizep = PHYSBSIZE;
*maxbytesp = 1024L * 1024;
}
#else
*bsizep = PHYSBSIZE;
*maxbytesp = 1024L * 1024;
#endif
}
if (floppyfd >= 0)
{
struct stat sbuf;
if (fstat (floppyfd, &sbuf) >= 0 && (S_IFREG & sbuf.st_mode))
*offsetp = sbuf.st_size % PHYSBSIZE;
else
*offsetp = 0;
}
return floppyfd;
}
PRIVATE LONGINT
read_driver_block_size (LONGINT fd, LONGINT bsize, LONGINT maxbytes,
char aligned_buf[])
{
LONGINT retval;
retval = PHYSBSIZE;
if (ROMlib_readwrite (fd, aligned_buf, PHYSBSIZE, 0, reading, bsize,
maxbytes) == noErr)
{
if (aligned_buf[0] == 0x45 && aligned_buf[1] == 0x52)
{
retval = (unsigned short) CW (*(unsigned short *) &aligned_buf[2]);
warning_fs_log ("fd = 0x%x, block size = %d", fd, retval);
}
}
return retval;
}
PUBLIC void
try_to_mount_disk (const char *dname, LONGINT floppyfd, LONGINT *messp,
LONGINT bsize, LONGINT maxbytes, drive_flags_t flags,
uint32 offset_in)
{
INTEGER partition;
ParamBlockRec pb;
char *tbuf, *buf;
INTEGER drivenum;
LONGINT offset;
BOOLEAN foundmap, first;
oldblock1_t *oldmapp;
partmapentry_t *partp;
int i;
LONGINT mess;
OSErr err;
DrvQExtra *dqp;
hfs_access_t hfs;
LONGINT driver_block_size;
*messp = 0;
tbuf = alloca (bsize + 3);
buf = (char *) (((long)tbuf +3)&~3);
partition = 0;
if (floppyfd >= 0)
driver_block_size = read_driver_block_size (floppyfd, bsize, maxbytes,
buf);
else
driver_block_size = PHYSBSIZE;
hfs.fd = (flags & DRIVE_FLAGS_FLOPPY) ? floppyfd : -1;
hfs.offset = offset_in;
hfs.bsize = bsize;
hfs.maxbytes = maxbytes;
dqp = ROMlib_addtodq (2048L * 2, dname, partition, OURHFSDREF, flags,
&hfs);
if (floppyfd < 0)
/*-->*/return;
drivenum = CW(dqp->dq.dQDrive);
pb.ioParam.ioVRefNum = CW(drivenum);
foundmap = FALSE;
first = TRUE;
offset = hfs.offset + PARTOFFSET * driver_block_size;
if (ROMlib_readwrite(floppyfd, buf, PHYSBSIZE, offset, reading,
bsize, maxbytes) == noErr) {
if (buf[0] == PARMAPSIG0 && buf[1] == PARMAPSIG1) {
warning_fs_log ("found partition sig at %d, floppyfd = 0x%x",
offset, floppyfd);
partp = (partmapentry_t *) buf;
do {
if (strncmp((char *) partp->pmPartType, HFSPARTTYPE, 32)
== 0) {
foundmap = TRUE;
if (!first) {
++partition;
dqp = ROMlib_addtodq (2048L * 2, dname,
partition, OURHFSDREF, flags,
&hfs);
drivenum = CW(dqp->dq.dQDrive);
pb.ioParam.ioVRefNum = CW(drivenum);
}
dqp->hfs.offset = hfs.offset + (CL (partp->pmPyPartStart)
* driver_block_size);
err = hfsPBMountVol(&pb, floppyfd, dqp->hfs.offset, bsize,
maxbytes, flags, dqp);
mess = ((LONGINT) err << 16) | drivenum;
if (first) {
*messp = CL(mess);
first = FALSE;
} else
PPostEvent(diskEvt, mess, (HIDDEN_EvQElPtr *) 0);
}
offset += driver_block_size;
} while (ROMlib_readwrite(floppyfd, buf, PHYSBSIZE, offset,
reading, bsize, maxbytes) == noErr &&
buf[0] == PARMAPSIG0 && buf[1] == PARMAPSIG1);
} else if (buf[0] == OLDMAPSIG0 && buf[1] == OLDMAPSIG1) {
oldmapp = (oldblock1_t *) buf;
for (i = 0; i < NOLDENTRIES &&
(Cx(oldmapp->oldmapentry[i].pdStart) != 0 ||
Cx(oldmapp->oldmapentry[i].pdSize) != 0 ||
Cx(oldmapp->oldmapentry[i].pdFSID) != 0) ; ++i) {
/*
* NOTE: We initially tried looking for 'TFS1' in pdFSID, but our Cirrus 80
* didn't use that id.
*/
if (!first) {
++partition;
dqp = ROMlib_addtodq (2048L * 2, dname, partition,
OURHFSDREF, flags, &hfs);
drivenum = CW(dqp->dq.dQDrive);
pb.ioParam.ioVRefNum = CW(drivenum);
}
dqp->hfs.offset = hfs.offset +
(CL (oldmapp->oldmapentry[i].pdStart)
* driver_block_size);
err = hfsPBMountVol(&pb, floppyfd, dqp->hfs.offset,
bsize, maxbytes, flags, dqp);
mess = ((LONGINT) err << 16) | drivenum;
if (first) {
*messp = CL(mess);
first = FALSE;
} else
PPostEvent(diskEvt, mess, (HIDDEN_EvQElPtr *) 0);
}
foundmap = TRUE;
}
}
if (!foundmap) {
for (offset = hfs.offset + VOLUMEINFOBLOCKNO * PHYSBSIZE, i = 4;
--i >= 0 ; offset += PHYSBSIZE) {
if (i == 0)
{
if (ROMlib_magic_offset == -1)
/*-->*/ continue;
else
offset = ROMlib_magic_offset;
}
err = ROMlib_readwrite(floppyfd, buf, PHYSBSIZE, offset, reading,
bsize, maxbytes);
if (err != noErr)
{
warning_unexpected ("fd = 0x%x err = %d, offset = %d, "
"bsize = %d, maxbytes = %d", floppyfd,
err, offset, bsize, maxbytes);
/*-->*/ break;
}
if (buf[0] == 'B' && buf[1] == 'D') {
warning_fs_log ("Found HFS volume on 0x%x %d", floppyfd,
offset);
offset -= VOLUMEINFOBLOCKNO * PHYSBSIZE;
foundmap = TRUE;
/*-->*/ break;
} else if (buf[0] == 'H' && buf[1] == '+') {
warning_fs_log ("Found HFS+ volume on 0x%x %d", floppyfd,
offset);
} else {
warning_fs_log ("fd = 0x%x, offset = %d, sig = 0x%02x%02x",
floppyfd, offset, buf[0], buf[1]);
}
}
if (foundmap) {
dqp->hfs.offset = offset;
err = hfsPBMountVol(&pb, floppyfd, offset, bsize, maxbytes,
flags, dqp);
*messp = CL(((LONGINT) err << 16) | drivenum);
}
}
}
PUBLIC void ROMlib_openfloppy( const char *dname, LONGINT *messp)
{
LONGINT floppyfd;
LONGINT bsize, maxbytes;
drive_flags_t flags;
uint32 offset;
*messp = 0;
floppyfd = try_to_open_disk (dname, &bsize, &maxbytes, &flags, &offset);
if (floppyfd >= 0)
try_to_mount_disk (dname, floppyfd, messp, bsize, maxbytes, flags,
offset);
}
PUBLIC void ROMlib_openharddisk( const char *dname, LONGINT *messp )
{
char *newbuf;
long len;
struct stat sbuf;
*messp = 0;
if (Ustat(dname, &sbuf) == 0) {
ASSIGN_NAME_MODE_STRING(newbuf, &len, dname, sbuf);
ROMlib_openfloppy(newbuf, messp);
}
}
#endif
#define JUMPTODONEIF(x) if ((x)) { err = ioErr; goto DONE; }
PUBLIC OSErr ROMlib_readwrite(LONGINT fd, char *buffer, LONGINT count, LONGINT offset,
accesstype rw, LONGINT blocksize, LONGINT maxtransfer)
{
char *newbuffer;
LONGINT remainder, totransfer;
BOOLEAN needlseek;
OSErr err;
int (* readfp)(int fd, void *buf, int nbytes);
int (*writefp)(int fd, const void *buf, int nbytes);
off_t (*seekfp)(int fd, off_t where, int how);
if (blocksize > 18 * 1024)
{
warning_unexpected ("fd = 0x%x, block size = %d", fd, blocksize);
return fsDSIntErr;
}
if (blocksize == 0)
{
blocksize = 2048;
warning_unexpected ("fd = 0x%x, zero block size", fd);
}
#if defined(MSDOS) || defined (CYGWIN32)
if (fd & DOSFDBIT)
{
fd &= ~DOSFDBIT;
seekfp = dosdisk_seek;
readfp = dosdisk_read;
writefp = dosdisk_write;
}
#if defined (MSDOS)
else if (fd & ASPIFDBIT)
{
fd &= ~ASPIFDBIT;
seekfp = aspi_disk_seek;
readfp = aspi_disk_read;
writefp = aspi_disk_write;
}
#endif
else
{
#endif
seekfp = (off_t (*)(int, off_t, int)) lseek;
readfp = (int (*)(int, void *, int)) read;
writefp = (int (*)(int, const void *, int)) write;
#if defined(MSDOS) || defined (CYGWIN32)
}
#endif
err = noErr;
newbuffer = 0;
needlseek = TRUE;
if ((remainder = offset % blocksize)) { /* |xxxDATA| */
remainder = blocksize - remainder;
totransfer = MIN(count, remainder);
newbuffer = (char *) (((long) alloca(blocksize + 3)+3) & ~3);
offset = offset / blocksize * blocksize;
JUMPTODONEIF(seekfp(fd, offset, L_SET) < 0)
needlseek = FALSE;
JUMPTODONEIF(readfp(fd, newbuffer, blocksize) != blocksize)
if (rw == reading) {
memmove(buffer, newbuffer+blocksize-remainder, totransfer);
} else {
memmove(newbuffer+blocksize-remainder, buffer, totransfer);
JUMPTODONEIF(seekfp(fd, offset, L_SET) < 0)
JUMPTODONEIF(writefp(fd, newbuffer, blocksize) != blocksize)
}
buffer += totransfer;
count -= totransfer;
offset += blocksize;
}
if (count >= blocksize) { /* |DATADATADATA...| */
remainder = count % blocksize;
count -= remainder;
if (needlseek) {
JUMPTODONEIF(seekfp(fd, offset, L_SET) < 0)
needlseek = FALSE;
}
while (count) {
totransfer = MIN(maxtransfer, count);
if (rw == reading) {
JUMPTODONEIF(readfp(fd, buffer, totransfer) != totransfer)
} else {
JUMPTODONEIF(writefp(fd, buffer, totransfer) != totransfer)
}
buffer += totransfer;
count -= totransfer;
offset += totransfer;
}
count = remainder;
}
if (count) { /* |DATAxxx| */
if (!newbuffer)
newbuffer = (char *) (((long) alloca(blocksize+3)+3) & ~3);
if (needlseek)
JUMPTODONEIF(seekfp(fd, offset, L_SET) < 0)
JUMPTODONEIF(readfp(fd, newbuffer, blocksize) != blocksize)
if (rw == reading) {
memmove(buffer, newbuffer, count);
} else {
memmove(newbuffer, buffer, count);
JUMPTODONEIF(seekfp(fd, offset, L_SET) < 0)
JUMPTODONEIF(writefp(fd, newbuffer, blocksize) != blocksize)
}
}
DONE:
return err;
}
PUBLIC OSErr
ROMlib_transphysblk (hfs_access_t *hfsp, LONGINT physblock, short nphysblocks,
Ptr bufp, accesstype rw, LONGINT *actp)
{
LONGINT fd;
OSErr err;
Ptr newbufp;
#if defined(MAC)
ioParam pb;
pb.ioVRefNum = vcbp->vcbDrvNum;
pb.ioRefNum = vcbp->vcbDRefNum;
pb.ioBuffer = CL(bufp);
pb.ioReqCount = CL(PHYSBSIZE * (LONGINT nphysblocks));
pb.ioPosMode = CW(fsFromStart);
pb.ioPosOffset = CL(physblock);
err = rw == reading ? PBRead ((ParmBlkPtr) &pb, FALSE) :
PBWrite((ParmBlkPtr) &pb, FALSE);
if (actp)
*actp = pb.ioActCount;
#else
#if defined(NEXTSTEP) || defined (MACOSX)
if ((LONGINT) bufp & 3) {
newbufp = alloca( (LONGINT) nphysblocks * PHYSBSIZE + 4);
newbufp = (Ptr) (((LONGINT) newbufp + 3) & ~3);
if (rw == writing)
memmove(newbufp, bufp, (LONGINT) nphysblocks * PHYSBSIZE);
} else
#endif
newbufp = bufp;
fd = hfsp->fd;
err = ROMlib_readwrite(fd, (char *) newbufp,
(LONGINT) nphysblocks * PHYSBSIZE,
physblock + hfsp->offset, rw, hfsp->bsize,
hfsp->maxbytes);
#if defined(NEXTSTEP) || defined (MACOSX)
if (rw == reading && bufp != newbufp && err == noErr)
memmove(bufp, newbufp, (LONGINT) nphysblocks * PHYSBSIZE);
#endif
if (actp)
*actp = err != noErr ? 0 : CL((LONGINT) nphysblocks * PHYSBSIZE);
#endif
if (err != noErr)
warning_unexpected ("fd = 0x%x, err in transphysblock (err = %d)",
fd, err);
return err;
}
PUBLIC char *ROMlib_indexn(char *str, char tofind, INTEGER length)
{
while (--length >= 0)
if (*str++ == tofind)
return str - 1;
return 0;
}
#if !defined(str255assign)
PUBLIC void str255assign(StringPtr dstp, StringPtr srcp)
{
memmove(dstp, srcp, (size_t) srcp[0]+1);
}
#endif /* !defined(str255assign) */
/*
* ROMlib_indexqueue returns a pointer to the n'th entry on a queue.
* ROMlib_indexqueue is one based; not zero based.
*/
PUBLIC void *ROMlib_indexqueue(QHdr *qp, short index)
{
QElemPtr p;
#if defined(MAC)
for (p = CL(qp->qHead); (--index > 0) && p; p = CL(p->qLink))
;
#else
for (p = MR(qp->qHead); (--index > 0) && p; p = MR(p->vcbQElem.qLink))
;
#endif
return p;
}
PUBLIC OSErr ROMlib_writefcbp(filecontrolblock *fcbp)
{
Byte flags;
OSErr retval;
flags = fcbp->fcbMdRByt;
if (!(flags & WRITEBIT))
retval = wrPermErr;
else if (flags & FLOCKEDBIT)
retval = fLckdErr;
else
retval = noErr;
return retval;
}
PUBLIC OSErr ROMlib_writevcbp(HVCB *vcbp)
{
INTEGER vflags;
OSErr retval;
vflags = Cx(vcbp->vcbAtrb);
if (vflags & VSOFTLOCKBIT)
retval = vLckdErr;
else if (vflags & VHARDLOCKBIT)
retval = wPrErr;
else
retval = noErr;
return retval;
}