mirror of
https://github.com/ksherlock/mpw.git
synced 2024-12-22 00:29:18 +00:00
open, write (O_BINARY)
This commit is contained in:
parent
58ab56e35e
commit
2290d22e24
196
mpw/mpw.cpp
196
mpw/mpw.cpp
@ -1,44 +1,170 @@
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cerrno>
|
||||
|
||||
#include <cpu/defs.h>
|
||||
#include <cpu/fmem.h>
|
||||
#include <cpu/cpuModule.h>
|
||||
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/paths.h>
|
||||
|
||||
|
||||
|
||||
#include "mpw.h"
|
||||
|
||||
#include "mpw_errno.h"
|
||||
|
||||
namespace {
|
||||
|
||||
using namespace MPW;
|
||||
|
||||
|
||||
int remap_errno(int xerrno)
|
||||
{
|
||||
switch (xerrno)
|
||||
{
|
||||
case EPERM: return kEPERM;
|
||||
case ENOENT: return kENOENT;
|
||||
|
||||
#ifdef ENORSRC
|
||||
case ENORSRC: return kENORSRC;
|
||||
#endif
|
||||
|
||||
case EINTR: return kEINTR;
|
||||
case EIO: return kEIO;
|
||||
case ENXIO: return kENXIO;
|
||||
case E2BIG: return kE2BIG;
|
||||
case ENOEXEC: return kENOEXEC;
|
||||
case EBADF: return kEBADF;
|
||||
case ECHILD: return kECHILD;
|
||||
case EAGAIN: return kEAGAIN;
|
||||
case ENOMEM: return kENOMEM;
|
||||
case EACCES: return kEACCES;
|
||||
case EFAULT: return kEFAULT;
|
||||
case ENOTBLK: return kENOTBLK;
|
||||
case EBUSY: return kEBUSY;
|
||||
case EEXIST: return kEEXIST;
|
||||
case EXDEV: return kEXDEV;
|
||||
case ENODEV: return kENODEV;
|
||||
case ENOTDIR: return kENOTDIR;
|
||||
case EISDIR: return kEISDIR;
|
||||
case EINVAL: return kEINVAL;
|
||||
case ENFILE: return kENFILE;
|
||||
case EMFILE: return kEMFILE;
|
||||
case ENOTTY: return kENOTTY;
|
||||
case ETXTBSY: return kETXTBSY;
|
||||
case EFBIG: return kEFBIG;
|
||||
case ENOSPC: return kENOSPC;
|
||||
case ESPIPE: return kESPIPE;
|
||||
case EROFS: return kEROFS;
|
||||
case EMLINK: return kEMLINK;
|
||||
case EPIPE: return kEPIPE;
|
||||
case EDOM: return kEDOM;
|
||||
case ERANGE: return kERANGE;
|
||||
}
|
||||
return kEINVAL;
|
||||
|
||||
}
|
||||
|
||||
uint32_t ftrap_open(uint32_t name, uint32_t parm)
|
||||
{
|
||||
uint32_t d0;
|
||||
int fd;
|
||||
std::string sname;
|
||||
|
||||
MPWFile f;
|
||||
int nativeFlags;
|
||||
std::memset(&f, 0, sizeof(f));
|
||||
|
||||
f.flags = memoryReadWord(parm);
|
||||
|
||||
|
||||
nativeFlags = 0;
|
||||
switch (f.flags & 0x03)
|
||||
{
|
||||
case 0x01:
|
||||
nativeFlags = O_RDONLY;
|
||||
break;
|
||||
case 0x02:
|
||||
nativeFlags = O_WRONLY;
|
||||
break;
|
||||
case 0x00: // ????
|
||||
case 0x03:
|
||||
nativeFlags = O_RDWR;
|
||||
break;
|
||||
}
|
||||
|
||||
if (f.flags & kO_APPEND) nativeFlags |= O_APPEND;
|
||||
if (f.flags & kO_CREAT) nativeFlags |= O_CREAT;
|
||||
if (f.flags & kO_TRUNC) nativeFlags |= O_TRUNC;
|
||||
if (f.flags & kO_EXCL) nativeFlags |= O_EXCL;
|
||||
|
||||
|
||||
const char *cp = (const char *)memoryPointer(name);
|
||||
sname.assign(cp);
|
||||
|
||||
if (f.flags & kO_RSRC)
|
||||
sname.append(_PATH_RSRCFORKSPEC);
|
||||
|
||||
if (f.flags & kO_CREAT) fd = ::open(sname.c_str(), nativeFlags, 0666);
|
||||
else fd = ::open(sname.c_str(), nativeFlags);
|
||||
|
||||
if (fd < 0)
|
||||
{
|
||||
d0 = 0x40000000 | remap_errno(errno);
|
||||
f.error = -36; // ioErr ... whatever.
|
||||
f.cookie = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
d0 = 0;
|
||||
f.error = 0;
|
||||
f.cookie = fd;
|
||||
// todo -- keep a separate array of fd/counts for dup/close?
|
||||
|
||||
// ... do I need to create the buffer?
|
||||
}
|
||||
|
||||
memoryWriteWord(f.error, parm + 2);
|
||||
memoryWriteLong(f.cookie, parm + 8);
|
||||
|
||||
return d0;
|
||||
}
|
||||
|
||||
void ftrap_access(uint16_t trap)
|
||||
{
|
||||
// open a file, rename a file, or delete a file.
|
||||
std::string sname;
|
||||
uint32_t d0;
|
||||
|
||||
uint32_t sp = cpuGetAReg(7);
|
||||
|
||||
// hmmm not sure if 3 or 4 parameters.
|
||||
|
||||
uint32_pt name = memoryReadLong(sp + 4);
|
||||
|
||||
uint32_t name = memoryReadLong(sp + 4);
|
||||
uint32_t op = memoryReadLong(sp + 8);
|
||||
uint32_t parm = memoryReadLong(sp + 12);
|
||||
|
||||
fprintf(stderr, "%04x Access(%08x, %04x, %08x)\n", trap, name, op, parm);
|
||||
|
||||
MPWFile f;
|
||||
switch (op)
|
||||
{
|
||||
case kF_OPEN:
|
||||
d0 = ftrap_open(name, parm);
|
||||
break;
|
||||
default:
|
||||
d0 = 0x40000000 | kEINVAL;
|
||||
fprintf(stderr, "faccess - unsupported op %04x\n", op);
|
||||
}
|
||||
|
||||
|
||||
fprintf(stderr, "%04x Access()\n", trap);
|
||||
cpuSetDReg(0, 0);
|
||||
cpuSetDReg(0, d0);
|
||||
}
|
||||
|
||||
void ftrap_close(uint16_t trap)
|
||||
@ -56,6 +182,8 @@ namespace {
|
||||
|
||||
void ftrap_write(uint16_t trap)
|
||||
{
|
||||
uint32_t d0;
|
||||
|
||||
uint32_t sp = cpuGetAReg(7);
|
||||
uint32_t parm = memoryReadLong(sp + 4);
|
||||
|
||||
@ -73,30 +201,52 @@ namespace {
|
||||
// hmmm how to handle crlf?
|
||||
|
||||
|
||||
d0 = 0;
|
||||
if (f.count)
|
||||
{
|
||||
std::unique_ptr<uint8_t[]> buffer(new uint8_t[f.count]);
|
||||
uint8_t *ptr = memoryPointer(f.buffer);
|
||||
|
||||
|
||||
std::transform(ptr, ptr + f.count, buffer.get(),
|
||||
[](uint8_t c) { return c == '\r' ? '\n' : c; }
|
||||
);
|
||||
ssize_t size;
|
||||
|
||||
int fd = f.cookie;
|
||||
|
||||
::write(fd, buffer.get(), f.count);
|
||||
if (f.flags & kO_BINARY)
|
||||
{
|
||||
size = ::write(fd, memoryPointer(f.buffer), f.count);
|
||||
}
|
||||
else
|
||||
{
|
||||
std::unique_ptr<uint8_t[]> buffer(new uint8_t[f.count]);
|
||||
uint8_t *ptr = memoryPointer(f.buffer);
|
||||
|
||||
// hmm, also needs to update the count actually transferred?
|
||||
std::transform(ptr, ptr + f.count, buffer.get(),
|
||||
[](uint8_t c) { return c == '\r' ? '\n' : c; }
|
||||
);
|
||||
|
||||
size = ::write(fd, buffer.get(), f.count);
|
||||
}
|
||||
|
||||
if (size < 0)
|
||||
{
|
||||
f.count = 0;
|
||||
f.error = -36; // ioErr
|
||||
d0 = 0x40000000 | remap_errno(errno);
|
||||
}
|
||||
else
|
||||
{
|
||||
f.count = size;
|
||||
f.error = 0;
|
||||
}
|
||||
|
||||
// write back...
|
||||
memoryWriteWord(f.error, parm + 2);
|
||||
memoryWriteLong(f.count, parm + 12);
|
||||
}
|
||||
cpuSetDReg(0, 0);
|
||||
cpuSetDReg(0, d0);
|
||||
}
|
||||
|
||||
void ftrap_ioctl(uint16_t trap)
|
||||
{
|
||||
// int ioctl(int fildes, unsigned int cmd, long *arg);
|
||||
|
||||
uint32_t d0;
|
||||
uint32_t sp = cpuGetAReg(7);
|
||||
|
||||
uint32_t fd = memoryReadLong(sp + 4);
|
||||
@ -105,7 +255,11 @@ namespace {
|
||||
|
||||
fprintf(stderr, "%04x IOCtl(%08x, %08x, %08x)\n", trap, fd, cmd, arg);
|
||||
|
||||
cpuSetDReg(0, 0);
|
||||
// dup doesn't appear to dup so much as increment a refCount
|
||||
// close decrements this refCount and doesn't close until it hits 0.
|
||||
d0 = 0;
|
||||
|
||||
cpuSetDReg(0, d0);
|
||||
}
|
||||
|
||||
void ftrap_quit(uint16_t trap)
|
||||
|
41
mpw/mpw.h
41
mpw/mpw.h
@ -16,6 +16,47 @@ namespace MPW {
|
||||
uint32_t buffer;
|
||||
};
|
||||
|
||||
// from MPW's FCntl.h
|
||||
enum
|
||||
{
|
||||
kF_OPEN = (('d' << 8)| 0x00),
|
||||
kF_DELETE = (('d' << 8) | 0x01),
|
||||
kF_RENAME = (('d' << 8) | 0x02),
|
||||
};
|
||||
|
||||
// from MPW's IOCtl.h
|
||||
enum
|
||||
{
|
||||
kFIOLSEEK = (('f' << 8) | 0x00), /* Apple internal use only */
|
||||
kFIODUPFD = (('f' << 8) | 0x01), /* Apple internal use only */
|
||||
kFIOINTERACTIVE = (('f' << 8) | 0x02), /* If device is interactive */
|
||||
kFIOBUFSIZE = (('f' << 8) | 0x03), /* Return optimal buffer size */
|
||||
kFIOFNAME = (('f' << 8) | 0x04), /* Return filename */
|
||||
kFIOREFNUM = (('f' << 8) | 0x05), /* Return fs refnum */
|
||||
kFIOSETEOF = (('f' << 8) | 0x06), /* Set file length */
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
kSEEK_CUR = 1,
|
||||
kSEEK_END = 2,
|
||||
kSEEK_SET = 0,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
// despite these constants, 0x01 seems to be read, 0x02 is write, 0x03 is read/write.
|
||||
kO_RDONLY = 0, /* Bits 0 and 1 are used internally */
|
||||
kO_WRONLY = 1, /* Values 0..2 are historical */
|
||||
kO_RDWR = 2, /* NOTE: it goes 0, 1, 2, *!* 8, 16, 32, ... */
|
||||
kO_APPEND = (1 << 3), /* append (writes guaranteed at the end) */
|
||||
kO_RSRC = (1 << 4), /* Open the resource fork */
|
||||
kO_CREAT = (1 << 8), /* Open with file create */
|
||||
kO_TRUNC = (1 << 9), /* Open with truncation */
|
||||
kO_EXCL = (1 << 10), /* w/ O_CREAT Exclusive "create-only" */
|
||||
kO_BINARY = (1 << 11), /* Open as a binary stream */
|
||||
};
|
||||
|
||||
enum {
|
||||
fQuit = 0xf000,
|
||||
fAccess,
|
||||
|
46
mpw/mpw_errno.h
Normal file
46
mpw/mpw_errno.h
Normal file
@ -0,0 +1,46 @@
|
||||
#ifndef __mpw_errno_h__
|
||||
#define __mpw_errno_h__
|
||||
|
||||
namespace MPW {
|
||||
|
||||
// from MPW errno.h
|
||||
enum {
|
||||
kEPERM = 1, /* Permission denied */
|
||||
kENOENT = 2, /* No such file or directory */
|
||||
kENORSRC = 3, /* No such resource */
|
||||
kEINTR = 4, /* Interrupted system service */
|
||||
kEIO = 5, /* I/O error */
|
||||
kENXIO = 6, /* No such device or address */
|
||||
kE2BIG = 7, /* Argument list too long */
|
||||
kENOEXEC = 8, /* Exec format error */
|
||||
kEBADF = 9, /* Bad file number */
|
||||
kECHILD = 10, /* No children processes */
|
||||
kEAGAIN = 11, /* Resource temporarily unavailable, try again later */
|
||||
kENOMEM = 12, /* Not enough space */
|
||||
kEACCES = 13, /* Permission denied */
|
||||
kEFAULT = 14, /* Bad address */
|
||||
kENOTBLK = 15, /* Block device required */
|
||||
kEBUSY = 16, /* Device or resource busy */
|
||||
kEEXIST = 17, /* File exists */
|
||||
kEXDEV = 18, /* Cross-device link */
|
||||
kENODEV = 19, /* No such device */
|
||||
kENOTDIR = 20, /* Not a directory */
|
||||
kEISDIR = 21, /* Is a directory */
|
||||
kEINVAL = 22, /* Invalid argument */
|
||||
kENFILE = 23, /* File table overflow */
|
||||
kEMFILE = 24, /* Too many open files */
|
||||
kENOTTY = 25, /* Not a character device */
|
||||
kETXTBSY = 26, /* Text file busy */
|
||||
kEFBIG = 27, /* File too large */
|
||||
kENOSPC = 28, /* No space left on device */
|
||||
kESPIPE = 29, /* Illegal seek */
|
||||
kEROFS = 30, /* Read only file system */
|
||||
kEMLINK = 31, /* Too many links */
|
||||
kEPIPE = 32, /* Broken pipe */
|
||||
kEDOM = 33, /* Math arg out of domain of func */
|
||||
kERANGE = 34, /* Math result not representable */
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user