mirror of
https://github.com/ksherlock/mpw.git
synced 2025-02-26 18:28:59 +00:00
use new file abstraction.
This commit is contained in:
parent
cdd595a812
commit
9d16456b80
@ -40,3 +40,5 @@ set_source_files_properties(
|
|||||||
)
|
)
|
||||||
|
|
||||||
add_library(MPW_LIB ${MPW_SRC})
|
add_library(MPW_LIB ${MPW_SRC})
|
||||||
|
|
||||||
|
target_link_libraries(MPW_LIB MACOS_LIB NATIVE_LIB)
|
||||||
|
35
mpw/mpw.cpp
35
mpw/mpw.cpp
@ -54,6 +54,8 @@
|
|||||||
|
|
||||||
#include <macos/sysequ.h>
|
#include <macos/sysequ.h>
|
||||||
|
|
||||||
|
#include <native/file.h>
|
||||||
|
|
||||||
extern char **environ;
|
extern char **environ;
|
||||||
|
|
||||||
|
|
||||||
@ -74,6 +76,7 @@ namespace MPW
|
|||||||
|
|
||||||
bool Trace = false;
|
bool Trace = false;
|
||||||
|
|
||||||
|
const std::string RootDir();
|
||||||
|
|
||||||
|
|
||||||
static bool isdir(const std::string &path)
|
static bool isdir(const std::string &path)
|
||||||
@ -209,30 +212,24 @@ namespace MPW
|
|||||||
|
|
||||||
uint16_t Init(int argc, char **argv)
|
uint16_t Init(int argc, char **argv)
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
FDTable.resize(16);
|
|
||||||
|
|
||||||
FDTable[STDIN_FILENO] = 1;
|
|
||||||
FDTable[STDOUT_FILENO] = 1;
|
|
||||||
FDTable[STDERR_FILENO] = 1;
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
// stdin/stdout/stderr
|
||||||
OS::Internal::FDTable.resize(3);
|
{
|
||||||
FDTable[STDIN_FILENO].refcount = 1;
|
native::file_ptr io;
|
||||||
FDTable[STDIN_FILENO].text = true;
|
|
||||||
|
|
||||||
FDTable[STDOUT_FILENO].refcount = 1;
|
io.reset(new native::fd_file("<stdin>", STDIN_FILENO));
|
||||||
FDTable[STDOUT_FILENO].text = true;
|
io->text = true;
|
||||||
|
OS::Internal::open_file(std::move(io));
|
||||||
|
|
||||||
FDTable[STDERR_FILENO].refcount = 1;
|
io.reset(new native::fd_file("<stdout>", STDOUT_FILENO));
|
||||||
FDTable[STDERR_FILENO].text = true;
|
io->text = true;
|
||||||
*/
|
OS::Internal::open_file(std::move(io));
|
||||||
|
|
||||||
OS::Internal::FDEntry::allocate(STDIN_FILENO).text = true;
|
|
||||||
OS::Internal::FDEntry::allocate(STDOUT_FILENO).text = true;
|
|
||||||
OS::Internal::FDEntry::allocate(STDERR_FILENO).text = true;
|
|
||||||
|
|
||||||
|
io.reset(new native::fd_file("<stderr>", STDERR_FILENO));
|
||||||
|
io->text = true;
|
||||||
|
OS::Internal::open_file(std::move(io));
|
||||||
|
}
|
||||||
|
|
||||||
std::string command = argv[0];
|
std::string command = argv[0];
|
||||||
|
|
||||||
|
@ -57,7 +57,7 @@
|
|||||||
* may return an errno or an oserr, too, apparently.
|
* may return an errno or an oserr, too, apparently.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* 2016 update -- faccess chedks if the error (16-bit) is negative (tool error)
|
/* 2016 update -- faccess checks if the error (16-bit) is negative (tool error)
|
||||||
* or positive (errno) and calls _uerror(errno, toolerr). toolerr is stored into
|
* or positive (errno) and calls _uerror(errno, toolerr). toolerr is stored into
|
||||||
* the MacOSErr variable and remapped to an errno. if toolerr == 0, errno is stored in
|
* the MacOSErr variable and remapped to an errno. if toolerr == 0, errno is stored in
|
||||||
* errno.
|
* errno.
|
||||||
@ -165,7 +165,6 @@ namespace MPW
|
|||||||
uint32_t ftrap_open(uint32_t name, uint32_t parm)
|
uint32_t ftrap_open(uint32_t name, uint32_t parm)
|
||||||
{
|
{
|
||||||
uint32_t d0;
|
uint32_t d0;
|
||||||
int fd;
|
|
||||||
std::string sname;
|
std::string sname;
|
||||||
|
|
||||||
MPWFile f;
|
MPWFile f;
|
||||||
@ -203,12 +202,12 @@ namespace MPW
|
|||||||
|
|
||||||
// TODO -- can you create a resource file like this?
|
// TODO -- can you create a resource file like this?
|
||||||
|
|
||||||
fd = native::open_fork(sname, f.flags & kO_RSRC, nativeFlags);
|
auto fd = native::open_fork(sname, f.flags & kO_RSRC, nativeFlags);
|
||||||
|
|
||||||
if (fd < 0)
|
if (!fd)
|
||||||
{
|
{
|
||||||
// return a tool error.
|
// return a tool error.
|
||||||
auto e = macos_error_from_errno();
|
auto e = fd.error();
|
||||||
|
|
||||||
d0 = 0x40000000 | (uint16_t)e; /* | mpw_errno_from_errno(); */
|
d0 = 0x40000000 | (uint16_t)e; /* | mpw_errno_from_errno(); */
|
||||||
f.error = (uint16_t)e;
|
f.error = (uint16_t)e;
|
||||||
@ -218,8 +217,9 @@ namespace MPW
|
|||||||
{
|
{
|
||||||
d0 = 0;
|
d0 = 0;
|
||||||
f.error = 0;
|
f.error = 0;
|
||||||
f.cookie = fd;
|
//f.cookie = fd;
|
||||||
|
|
||||||
|
native::file_ptr ff = std::move(fd).value();
|
||||||
|
|
||||||
// adjust the binary flags...
|
// adjust the binary flags...
|
||||||
// some apps are good about this but
|
// some apps are good about this but
|
||||||
@ -231,9 +231,16 @@ namespace MPW
|
|||||||
|
|
||||||
if (f.flags & kO_RSRC) f.flags |= kO_BINARY;
|
if (f.flags & kO_RSRC) f.flags |= kO_BINARY;
|
||||||
|
|
||||||
|
|
||||||
|
ff->text = !(f.flags & kO_BINARY);
|
||||||
|
ff->resource = f.flags & kO_RSRC;
|
||||||
|
|
||||||
|
f.cookie = OS::Internal::open_file(std::move(ff));
|
||||||
|
/*
|
||||||
auto &e = OS::Internal::FDEntry::allocate(fd, std::move(xname));
|
auto &e = OS::Internal::FDEntry::allocate(fd, std::move(xname));
|
||||||
e.text = !(f.flags & kO_BINARY);
|
e.text = !(f.flags & kO_BINARY);
|
||||||
e.resource = f.flags & kO_RSRC;
|
e.resource = f.flags & kO_RSRC;
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
memoryWriteWord(f.flags, parm + 0);
|
memoryWriteWord(f.flags, parm + 0);
|
||||||
|
@ -49,9 +49,6 @@ namespace MPW
|
|||||||
|
|
||||||
void ftrap_close(uint16_t trap)
|
void ftrap_close(uint16_t trap)
|
||||||
{
|
{
|
||||||
// returns an mpw_errno
|
|
||||||
// close actually checks the error in the File Entry and converts that to unix.
|
|
||||||
// (sigh)
|
|
||||||
|
|
||||||
uint32_t d0 = 0;
|
uint32_t d0 = 0;
|
||||||
|
|
||||||
@ -67,61 +64,24 @@ namespace MPW
|
|||||||
f.count = memoryReadLong(parm + 12);
|
f.count = memoryReadLong(parm + 12);
|
||||||
f.buffer = memoryReadLong(parm + 16);
|
f.buffer = memoryReadLong(parm + 16);
|
||||||
|
|
||||||
|
f.error = 0;
|
||||||
|
|
||||||
|
|
||||||
Log("%04x Close(%08x)\n", trap, parm);
|
Log("%04x Close(%08x)\n", trap, parm);
|
||||||
|
|
||||||
if (!parm)
|
|
||||||
{
|
|
||||||
cpuSetDReg(0, kEINVAL);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int fd = f.cookie;
|
int fd = f.cookie;
|
||||||
|
|
||||||
int rv = OS::Internal::FDEntry::close(fd);
|
|
||||||
|
|
||||||
if (rv < 0)
|
|
||||||
{
|
|
||||||
f.error = MacOS::notOpenErr;
|
|
||||||
d0 = kEINVAL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
f.error = 0;
|
|
||||||
d0 = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
if (fd < 0 || fd >= OS::Internal::FDTable.size())
|
|
||||||
{
|
|
||||||
f.error = OS::notOpenErr;
|
|
||||||
d0 = kEINVAL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto &e = OS::Internal::FDTable[fd];
|
|
||||||
if (e.refcount == 0)
|
|
||||||
{
|
|
||||||
f.error = OS::notOpenErr;
|
|
||||||
d0 = kEINVAL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (--e.refcount == 0)
|
|
||||||
{
|
|
||||||
Log(" close(%02x)\n", fd);
|
Log(" close(%02x)\n", fd);
|
||||||
::close(fd);
|
|
||||||
|
int rv = OS::Internal::close_file(fd);
|
||||||
|
|
||||||
|
if (rv < 0) {
|
||||||
|
d0 = kEBADF;
|
||||||
}
|
}
|
||||||
f.error = 0;
|
|
||||||
d0 = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
memoryWriteWord(f.error, parm + 2);
|
memoryWriteWord(f.error, parm + 2);
|
||||||
cpuSetDReg(0, 0);
|
cpuSetDReg(0, d0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -53,7 +53,7 @@ namespace MPW
|
|||||||
void ftrap_read(uint16_t trap)
|
void ftrap_read(uint16_t trap)
|
||||||
{
|
{
|
||||||
|
|
||||||
uint32_t d0;
|
uint32_t d0 = 0;
|
||||||
|
|
||||||
uint32_t sp = cpuGetAReg(7);
|
uint32_t sp = cpuGetAReg(7);
|
||||||
uint32_t parm = memoryReadLong(sp + 4);
|
uint32_t parm = memoryReadLong(sp + 4);
|
||||||
@ -67,27 +67,21 @@ namespace MPW
|
|||||||
f.count = memoryReadLong(parm + 12);
|
f.count = memoryReadLong(parm + 12);
|
||||||
f.buffer = memoryReadLong(parm + 16);
|
f.buffer = memoryReadLong(parm + 16);
|
||||||
|
|
||||||
|
f.error = 0;
|
||||||
|
|
||||||
Log("%04x Read(%08x)\n", trap, parm);
|
Log("%04x Read(%08x)\n", trap, parm);
|
||||||
|
|
||||||
d0 = 0;
|
|
||||||
int fd = f.cookie;
|
int fd = f.cookie;
|
||||||
ssize_t size;
|
|
||||||
|
|
||||||
Log(" read(%04x, %08x, %08x)", fd, f.buffer, f.count);
|
Log(" read(%04x, %08x, %08x)", fd, f.buffer, f.count);
|
||||||
size = OS::Internal::FDEntry::read(fd, memoryPointer(f.buffer), f.count);
|
|
||||||
//Log(" -> %ld\n", size);
|
|
||||||
|
|
||||||
if (size < 0)
|
auto ff = OS::Internal::find_file(fd);
|
||||||
{
|
if (ff) {
|
||||||
//f.count = 0;
|
auto e = ff->read(memoryPointer(f.buffer), f.count);
|
||||||
f.error = MacOS::ioErr; // ioErr
|
f.count -= e.value_or(0);
|
||||||
d0 = mpw_errno_from_errno();
|
d0 = f.error = e.error();
|
||||||
}
|
} else {
|
||||||
else
|
d0 = kEBADF;
|
||||||
{
|
|
||||||
f.count -= size;
|
|
||||||
f.error = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// write back...
|
// write back...
|
||||||
@ -99,7 +93,7 @@ namespace MPW
|
|||||||
|
|
||||||
void ftrap_write(uint16_t trap)
|
void ftrap_write(uint16_t trap)
|
||||||
{
|
{
|
||||||
uint32_t d0;
|
uint32_t d0 = 0;
|
||||||
|
|
||||||
uint32_t sp = cpuGetAReg(7);
|
uint32_t sp = cpuGetAReg(7);
|
||||||
uint32_t parm = memoryReadLong(sp + 4);
|
uint32_t parm = memoryReadLong(sp + 4);
|
||||||
@ -113,26 +107,21 @@ namespace MPW
|
|||||||
f.count = memoryReadLong(parm + 12);
|
f.count = memoryReadLong(parm + 12);
|
||||||
f.buffer = memoryReadLong(parm + 16);
|
f.buffer = memoryReadLong(parm + 16);
|
||||||
|
|
||||||
|
f.error = 0;
|
||||||
|
|
||||||
Log("%04x Write(%08x)\n", trap, parm);
|
Log("%04x Write(%08x)\n", trap, parm);
|
||||||
|
|
||||||
|
|
||||||
d0 = 0;
|
|
||||||
int fd = f.cookie;
|
int fd = f.cookie;
|
||||||
ssize_t size;
|
|
||||||
|
|
||||||
Log(" write(%04x, %08x, %08x)\n", fd, f.buffer, f.count);
|
Log(" write(%04x, %08x, %08x)\n", fd, f.buffer, f.count);
|
||||||
size = OS::Internal::FDEntry::write(fd, memoryPointer(f.buffer), f.count);
|
|
||||||
|
|
||||||
if (size < 0)
|
auto ff = OS::Internal::find_file(fd);
|
||||||
{
|
if (ff) {
|
||||||
//f.count = 0;
|
auto e = ff->write(memoryPointer(f.buffer), f.count);
|
||||||
f.error = MacOS::ioErr; // ioErr
|
f.count -= e.value_or(0);
|
||||||
d0 = mpw_errno_from_errno();
|
d0 = f.error = e.error();
|
||||||
}
|
} else {
|
||||||
else
|
d0 = kEBADF;
|
||||||
{
|
|
||||||
f.count -= size;
|
|
||||||
f.error = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// write back...
|
// write back...
|
||||||
|
@ -59,7 +59,7 @@ namespace MPW
|
|||||||
|
|
||||||
uint32_t ftrap_dup(uint32_t parm, uint32_t arg)
|
uint32_t ftrap_dup(uint32_t parm, uint32_t arg)
|
||||||
{
|
{
|
||||||
uint32_t d0;
|
uint32_t d0 = 0;
|
||||||
MPWFile f;
|
MPWFile f;
|
||||||
|
|
||||||
f.flags = memoryReadWord(parm);
|
f.flags = memoryReadWord(parm);
|
||||||
@ -75,37 +75,13 @@ namespace MPW
|
|||||||
|
|
||||||
Log(" dup(%02x)\n", fd);
|
Log(" dup(%02x)\n", fd);
|
||||||
|
|
||||||
|
auto ff = OS::Internal::find_file(fd);
|
||||||
d0 = OS::Internal::FDEntry::action(fd,
|
if (ff) {
|
||||||
[](int fd, OS::Internal::FDEntry &e){
|
ff->refcount++;
|
||||||
e.refcount++;
|
|
||||||
return 0;
|
|
||||||
},
|
|
||||||
[](int fd){
|
|
||||||
return kEINVAL;
|
|
||||||
}
|
}
|
||||||
);
|
else {
|
||||||
|
d0 = kEBADF;
|
||||||
#if 0
|
|
||||||
try
|
|
||||||
{
|
|
||||||
auto &e = OS::Internal::FDTable.at(fd);
|
|
||||||
|
|
||||||
if (e.refcount)
|
|
||||||
{
|
|
||||||
d0 = 0;
|
|
||||||
fd.refcount++;
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
d0 = kEINVAL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(std::out_of_range &ex)
|
|
||||||
{
|
|
||||||
d0 = kEINVAL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
memoryWriteWord(f.error, parm + 2);
|
memoryWriteWord(f.error, parm + 2);
|
||||||
return d0;
|
return d0;
|
||||||
@ -116,6 +92,7 @@ namespace MPW
|
|||||||
// should return the preferred buffsize in *arg
|
// should return the preferred buffsize in *arg
|
||||||
// an error will use the default size (0x400 bytes).
|
// an error will use the default size (0x400 bytes).
|
||||||
|
|
||||||
|
uint32_t d0 = 0;
|
||||||
MPWFile f;
|
MPWFile f;
|
||||||
|
|
||||||
f.flags = memoryReadWord(parm);
|
f.flags = memoryReadWord(parm);
|
||||||
@ -131,18 +108,24 @@ namespace MPW
|
|||||||
|
|
||||||
Log(" bufsize(%02x)\n", fd);
|
Log(" bufsize(%02x)\n", fd);
|
||||||
|
|
||||||
|
auto ff = OS::Internal::find_file(fd);
|
||||||
|
if (ff) {
|
||||||
|
d0 = kEINVAL;
|
||||||
|
} else {
|
||||||
|
d0 = kEBADF;
|
||||||
|
}
|
||||||
|
|
||||||
memoryWriteWord(f.error, parm + 2);
|
memoryWriteWord(f.error, parm + 2);
|
||||||
return kEINVAL;
|
return d0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint32_t ftrap_interactive(uint32_t parm, uint32_t arg)
|
uint32_t ftrap_interactive(uint32_t parm, uint32_t arg)
|
||||||
{
|
{
|
||||||
// return 0 if interactive, an error if
|
// return 0 if interactive, an error if
|
||||||
// non-interactive.
|
// non-interactive. arg is null.
|
||||||
|
|
||||||
uint32_t d0;
|
|
||||||
|
|
||||||
|
uint32_t d0 = 0;
|
||||||
MPWFile f;
|
MPWFile f;
|
||||||
|
|
||||||
f.flags = memoryReadWord(parm);
|
f.flags = memoryReadWord(parm);
|
||||||
@ -162,37 +145,13 @@ namespace MPW
|
|||||||
|
|
||||||
Log(" interactive(%02x)\n", fd);
|
Log(" interactive(%02x)\n", fd);
|
||||||
|
|
||||||
d0 = OS::Internal::FDEntry::action(fd,
|
|
||||||
[](int fd, OS::Internal::FDEntry &e){
|
|
||||||
|
|
||||||
int tty = ::isatty(fd);
|
auto ff = OS::Internal::find_file(fd);
|
||||||
return tty ? 0 : kEINVAL;
|
if (!ff) {
|
||||||
},
|
d0 = kEBADF;
|
||||||
[](int fd){
|
} else if (!ff->interactive()) {
|
||||||
return kEINVAL;
|
f.error = d0 = MacOS::paramErr;
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
try
|
|
||||||
{
|
|
||||||
auto &e = OS::Internal::FDTable.at(fd);
|
|
||||||
|
|
||||||
if (e.refcount)
|
|
||||||
{
|
|
||||||
int tty = ::isatty(fd);
|
|
||||||
d0 = tty ? 0 : kEINVAL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
d0 = kEINVAL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(std::out_of_range &ex)
|
|
||||||
{
|
|
||||||
d0 = kEINVAL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
memoryWriteWord(f.error, parm + 2);
|
memoryWriteWord(f.error, parm + 2);
|
||||||
return d0;
|
return d0;
|
||||||
@ -200,9 +159,11 @@ namespace MPW
|
|||||||
|
|
||||||
uint32_t ftrap_fname(uint32_t parm, uint32_t arg)
|
uint32_t ftrap_fname(uint32_t parm, uint32_t arg)
|
||||||
{
|
{
|
||||||
// return file name.
|
// return file name (full path).
|
||||||
// AsmIIgs uses this...
|
// AsmIIgs uses this...
|
||||||
|
// arg is a c-string ptr.
|
||||||
|
|
||||||
|
uint32_t d0 = 0;
|
||||||
MPWFile f;
|
MPWFile f;
|
||||||
|
|
||||||
f.flags = memoryReadWord(parm);
|
f.flags = memoryReadWord(parm);
|
||||||
@ -218,15 +179,22 @@ namespace MPW
|
|||||||
|
|
||||||
Log(" fname(%02x)\n", fd);
|
Log(" fname(%02x)\n", fd);
|
||||||
|
|
||||||
|
auto ff = OS::Internal::find_file(fd);
|
||||||
|
if (ff) {
|
||||||
|
f.error = d0 = MacOS::paramErr;
|
||||||
|
} else {
|
||||||
|
d0 = kEBADF;
|
||||||
|
}
|
||||||
|
|
||||||
memoryWriteWord(f.error, parm + 2);
|
memoryWriteWord(f.error, parm + 2);
|
||||||
return kEINVAL;
|
return d0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t ftrap_refnum(uint32_t parm, uint32_t arg)
|
uint32_t ftrap_refnum(uint32_t parm, uint32_t arg)
|
||||||
{
|
{
|
||||||
// returns the refnum in *arg
|
// returns the refnum in *arg
|
||||||
uint32_t d0;
|
// on mpw, stdin/stdout/stderr return a param error.
|
||||||
|
uint32_t d0 = 0;
|
||||||
MPWFile f;
|
MPWFile f;
|
||||||
|
|
||||||
f.flags = memoryReadWord(parm);
|
f.flags = memoryReadWord(parm);
|
||||||
@ -242,27 +210,13 @@ namespace MPW
|
|||||||
|
|
||||||
Log(" refnum(%02x)\n", fd);
|
Log(" refnum(%02x)\n", fd);
|
||||||
|
|
||||||
d0 = OS::Internal::FDEntry::action(fd,
|
auto ff = OS::Internal::find_file(fd);
|
||||||
[arg](int fd, OS::Internal::FDEntry &e){
|
if (ff) {
|
||||||
memoryWriteWord(fd, arg);
|
if (ff->interactive()) f.error = d0 = MacOS::paramErr;
|
||||||
return 0;
|
else memoryWriteWord(fd, arg);
|
||||||
},
|
} else {
|
||||||
[](int fd){
|
d0 = kEBADF;
|
||||||
return kEINVAL;
|
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
if (fd < 0 || fd >= FDTable.size() || !FDTable[fd])
|
|
||||||
{
|
|
||||||
d0 = kEINVAL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
d0 = 0;
|
|
||||||
memoryWriteWord(fd, arg);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
memoryWriteWord(f.error, parm + 2);
|
memoryWriteWord(f.error, parm + 2);
|
||||||
return d0;
|
return d0;
|
||||||
@ -272,8 +226,8 @@ namespace MPW
|
|||||||
|
|
||||||
uint32_t ftrap_lseek(uint32_t parm, uint32_t arg)
|
uint32_t ftrap_lseek(uint32_t parm, uint32_t arg)
|
||||||
{
|
{
|
||||||
|
uint32_t d0 = 0;
|
||||||
MPWFile f;
|
MPWFile f;
|
||||||
uint32_t d0;
|
|
||||||
|
|
||||||
uint32_t whence = memoryReadLong(arg);
|
uint32_t whence = memoryReadLong(arg);
|
||||||
int32_t offset = memoryReadLong(arg + 4); // signed value.
|
int32_t offset = memoryReadLong(arg + 4); // signed value.
|
||||||
@ -286,8 +240,8 @@ namespace MPW
|
|||||||
f.count = memoryReadLong(parm + 12);
|
f.count = memoryReadLong(parm + 12);
|
||||||
f.buffer = memoryReadLong(parm + 16);
|
f.buffer = memoryReadLong(parm + 16);
|
||||||
|
|
||||||
|
f.error = 0;
|
||||||
|
|
||||||
int fd = f.cookie;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* LinkIIgs does a seek on stdin. If it doesn't cause an
|
* LinkIIgs does a seek on stdin. If it doesn't cause an
|
||||||
@ -316,32 +270,20 @@ namespace MPW
|
|||||||
return kEINVAL;
|
return kEINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int fd = f.cookie;
|
||||||
Log(" lseek(%02x, %08x, %02x)\n", fd, offset, nativeWhence);
|
Log(" lseek(%02x, %08x, %02x)\n", fd, offset, nativeWhence);
|
||||||
|
|
||||||
if (::isatty(fd))
|
|
||||||
{
|
|
||||||
off_t rv = -1;
|
|
||||||
|
|
||||||
d0 = kEINVAL;
|
off_t rv = - 1;
|
||||||
f.error = 0;
|
auto ff = OS::Internal::find_file(fd);
|
||||||
|
if (ff) {
|
||||||
memoryWriteLong(rv, arg + 4);
|
MacOS::tool_return<size_t> e(MacOS::noErr);
|
||||||
memoryWriteWord(f.error, parm + 2);
|
if (ff->interactive()) e = MacOS::paramErr;
|
||||||
return d0;
|
else e = ff->seek(offset, nativeWhence);
|
||||||
|
rv = e.value_or(-1);
|
||||||
}
|
f.error = d0 = e.error();
|
||||||
|
} else {
|
||||||
off_t rv = ::lseek(fd, offset, nativeWhence);
|
d0 = kEBADF;
|
||||||
if (rv < 0)
|
|
||||||
{
|
|
||||||
d0 = mpw_errno_from_errno();
|
|
||||||
f.error = macos_error_from_errno();
|
|
||||||
//perror(NULL);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
d0 = 0;
|
|
||||||
f.error = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
memoryWriteLong(rv, arg + 4);
|
memoryWriteLong(rv, arg + 4);
|
||||||
@ -353,8 +295,7 @@ namespace MPW
|
|||||||
uint32_t ftrap_seteof(uint32_t parm, uint32_t arg)
|
uint32_t ftrap_seteof(uint32_t parm, uint32_t arg)
|
||||||
{
|
{
|
||||||
|
|
||||||
uint32_t d0;
|
uint32_t d0 = 0;
|
||||||
|
|
||||||
MPWFile f;
|
MPWFile f;
|
||||||
|
|
||||||
f.flags = memoryReadWord(parm);
|
f.flags = memoryReadWord(parm);
|
||||||
@ -370,18 +311,15 @@ namespace MPW
|
|||||||
|
|
||||||
Log(" seteof(%02x, %08x)\n", fd, arg);
|
Log(" seteof(%02x, %08x)\n", fd, arg);
|
||||||
|
|
||||||
d0 = OS::Internal::FDEntry::action(fd,
|
auto ff = OS::Internal::find_file(fd);
|
||||||
[arg, &f](int fd, OS::Internal::FDEntry &e){
|
if (ff) {
|
||||||
int ok = ftruncate(fd, arg);
|
MacOS::tool_return<size_t> e(MacOS::noErr);
|
||||||
if (ok == 0) return 0;
|
if (ff->interactive()) e = MacOS::paramErr;
|
||||||
f.error = macos_error_from_errno();
|
else e = ff->set_eof(arg);
|
||||||
return (int)mpw_errno_from_errno();
|
f.error = d0 = e.error();
|
||||||
},
|
} else {
|
||||||
[](int fd){
|
d0 = kEBADF;
|
||||||
return kEINVAL;
|
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
memoryWriteWord(f.error, parm + 2);
|
memoryWriteWord(f.error, parm + 2);
|
||||||
return d0;
|
return d0;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||||
|
|
||||||
set(NATIVE_SRC native.cpp ${CMAKE_SYSTEM_NAME}.cpp)
|
set(NATIVE_SRC native.cpp file.cpp ${CMAKE_SYSTEM_NAME}.cpp)
|
||||||
|
|
||||||
add_library(NATIVE_LIB ${NATIVE_SRC})
|
add_library(NATIVE_LIB ${NATIVE_SRC})
|
||||||
|
target_link_libraries(NATIVE_LIB MACOS_LIB)
|
||||||
|
@ -359,13 +359,20 @@ namespace native {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int open_resource_fork(const std::string &path_name, int oflag) {
|
tool_return<file_ptr> open_resource_fork(const std::string &path_name, int oflag) {
|
||||||
|
|
||||||
std::string rname = path_name + _PATH_RSRCFORKSPEC;
|
std::string rname = path_name + _PATH_RSRCFORKSPEC;
|
||||||
|
|
||||||
// todo -- verify behavior on non-hfs volume.
|
// todo -- verify behavior on non-hfs volume.
|
||||||
//if ((oflag & O_ACCMODE) & O_WRONLY) oflag |= O_CREAT;
|
//if ((oflag & O_ACCMODE) & O_WRONLY) oflag |= O_CREAT;
|
||||||
return open(rname.c_str(), oflag, 0666);
|
|
||||||
|
int fd = open(rname.c_str(), oflag, 0666);
|
||||||
|
if (fd < 0) return macos_error_from_errno();
|
||||||
|
|
||||||
|
auto tmp = new fd_file(path_name, fd);
|
||||||
|
tmp->resource = true;
|
||||||
|
|
||||||
|
return file_ptr(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
193
native/Linux.cpp
193
native/Linux.cpp
@ -24,3 +24,196 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#define XATTR_FINDERINFO_NAME "user.apple.FinderInfo"
|
||||||
|
#define XATTR_RESOURCEFORK_NAME "user.apple.ResourceFork"
|
||||||
|
|
||||||
|
#define XATTR_FILETYPE_NAME "user.prodos.FileType"
|
||||||
|
#define XATTR_AUXTYPE_NAME "user.prodos.AuxType"
|
||||||
|
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/xattr.h>
|
||||||
|
|
||||||
|
#include "file.h"
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <macos/errors.h>
|
||||||
|
|
||||||
|
using MacOS::tool_return;
|
||||||
|
using MacOS::macos_error_from_errno;
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
class xattr_file final : public file {
|
||||||
|
public:
|
||||||
|
xattr_file(int fd): _fd(fd);
|
||||||
|
~xattr_file();
|
||||||
|
|
||||||
|
|
||||||
|
tool_return<size_t> read(void *out_buffer, size_t count) override;
|
||||||
|
tool_return<size_t> write(void *in_buffer, size_t count) override;
|
||||||
|
tool_return<size_t> get_mark() override;
|
||||||
|
tool_return<void> set_mark(ssize_t new_mark) override;
|
||||||
|
tool_return<size_t> get_eof() override;
|
||||||
|
tool_return<void> set_eof(ssize_t new_eof) override;
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
ssize_t read_rfork(std::vector<uint8_t> &buffer);
|
||||||
|
|
||||||
|
int _fd = -1;
|
||||||
|
off_t _displacement = 0;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
xattr_file::~xattr_file() {
|
||||||
|
close(_fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ssize_t xattr_file::read_rfork(std::vector<uint8_t> &buffer) {
|
||||||
|
ssize_t eof = -1;
|
||||||
|
buffer.clear();
|
||||||
|
do {
|
||||||
|
eof = fgetxattr(_fd, XATTR_RESOURCEFORK_NAME, NULL, 0);
|
||||||
|
if (eof < 0) break;
|
||||||
|
buffer.resize(eof);
|
||||||
|
eof = fgetxattr(_fd, XATTR_RESOURCEFORK_NAME, buffer.data(), eof);
|
||||||
|
} while (eof < 0 && errno == ERANGE);
|
||||||
|
return eof;
|
||||||
|
}
|
||||||
|
|
||||||
|
tool_return<size_t> xattr_file::read(void *out_buffer, size_t count) {
|
||||||
|
std::vector<uint8_t> buffer;
|
||||||
|
ssize_t size;
|
||||||
|
size = read_rfork(buffer);
|
||||||
|
if (size < 0) size = 0;
|
||||||
|
|
||||||
|
if (_displacement >= buffer.size()) return 0;
|
||||||
|
|
||||||
|
count = std::min(count, buffer.size() - _displacement);
|
||||||
|
std::copy_n(buffer.begin() + _displacement, count, (uint8_t *)out_buffer);
|
||||||
|
_displacement += count;
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
tool_return<size_t> xattr_file::write(const void *in_buffer, size_t count) {
|
||||||
|
std::vector<uint8_t> buffer;
|
||||||
|
ssize_t size;
|
||||||
|
size = read_rfork(buffer);
|
||||||
|
if (size < 0) size = 0;
|
||||||
|
|
||||||
|
if (_displacement >= buffer.size()) {
|
||||||
|
buffer.resize(_displacement, 0);
|
||||||
|
}
|
||||||
|
if (_displacement + count >= buffer.size()) {
|
||||||
|
buffer.resize(_displacement + count, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::copy_n((const uint8_t *)in_buffer, count, buffer.begin() + _displacement);
|
||||||
|
|
||||||
|
int ok = fsetxattr(_fd, XATTR_RESOURCEFORK_NAME, buffer.data(), buffer.size(), 0);
|
||||||
|
if (ok < 0) return macos_error_from_errno();
|
||||||
|
_displacement += count;
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
tool_return<size_t> xattr_file::get_mark() {
|
||||||
|
return _displacement;
|
||||||
|
}
|
||||||
|
|
||||||
|
tool_return<void> xattr_file::set_mark(ssize_t new_mark) {
|
||||||
|
if (new_mark < 0) return paramErr;
|
||||||
|
_displacement = new_mark;
|
||||||
|
}
|
||||||
|
|
||||||
|
tool_return<size_t> xattr_file::get_eof() {
|
||||||
|
ssize_t eof = fgetxattr(_fd, XATTR_RESOURCEFORK_NAME, NULL, 0);
|
||||||
|
if (eof < 0) eof = 0;
|
||||||
|
return eof;
|
||||||
|
}
|
||||||
|
|
||||||
|
tool_return<void> xattr_file::set_eof(ssize_t new_eof) {
|
||||||
|
|
||||||
|
if (new_eof < 0) return paramErr;
|
||||||
|
|
||||||
|
std::vector<uint8_t> buffer;
|
||||||
|
|
||||||
|
ssize_t eof = read_rfork(buffer);
|
||||||
|
if (eof < 0) eof = 0;
|
||||||
|
if (eof == new_eof) return noErr;
|
||||||
|
|
||||||
|
buffer.resize(new_eof, 0);
|
||||||
|
int ok = fsetxattr(_fd, XATTR_RESOURCEFORK_NAME, buffer->data(), buffer.size(), 0);
|
||||||
|
if (ok < 0) return macos_error_from_errno();
|
||||||
|
return noErr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace native {
|
||||||
|
|
||||||
|
tool_return<file_ptr> open_resource_fork(const std::string &path_name, int oflag) {
|
||||||
|
|
||||||
|
int fd = open(rname.c_str(), oflag);
|
||||||
|
if (fd < 0) return macos_error_from_errno();
|
||||||
|
return std::make_shared<file>(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
macos_error get_file_info(const std::string &path_name, file_info &fi)
|
||||||
|
{
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
|
if (stat(path_name.c_str(), &st) < 0)
|
||||||
|
return macos_error_from_errno();
|
||||||
|
|
||||||
|
fi.create_date = unix_to_mac(st.st_birthtime);
|
||||||
|
fi.modify_date = unix_to_mac(st.st_mtime);
|
||||||
|
fi.backup_date = 0;
|
||||||
|
|
||||||
|
fi.attributes = 0;
|
||||||
|
|
||||||
|
if (S_ISDIR(st.st_mode)) {
|
||||||
|
fi.type = file_info::directory;
|
||||||
|
fi.attributes = 1 << 4;
|
||||||
|
|
||||||
|
int links = st.st_nlink - 2;
|
||||||
|
if (links < 0) links = 0;
|
||||||
|
if (links > 65535) links = 65535;
|
||||||
|
|
||||||
|
fi.entry_count = links;
|
||||||
|
return noErr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo -- get actual block size instead of assuming 512. oh well!
|
||||||
|
|
||||||
|
fi.type = file_info::file;
|
||||||
|
fi.data_logical_size = st.st_size;
|
||||||
|
fi.data_physical_size = (st.st_size + 511) & ~511;
|
||||||
|
fi.resource_physical_size = 0;
|
||||||
|
fi.resource_logical_size = 0;
|
||||||
|
|
||||||
|
get_finder_info(path_name, fi.finder_info);
|
||||||
|
|
||||||
|
ssize_t rsize = rforksize(path_name);
|
||||||
|
if (rsize > 0) {
|
||||||
|
fi.resource_physical_size = rsize;
|
||||||
|
fi.resource_logical_size = (rsize + 511) & ~511;
|
||||||
|
}
|
||||||
|
|
||||||
|
return noErr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -202,13 +202,19 @@ namespace native {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int open_resource_fork(const std::string &path_name, int oflag) {
|
tool_return<file_ptr> open_resource_fork(const std::string &path_name, int oflag) {
|
||||||
/* under HFS, every file has a resource fork.
|
/* under HFS, every file has a resource fork.
|
||||||
* Therefore, create it if opening for O_RDWR or O_WRONLY
|
* Therefore, create it if opening for O_RDWR or O_WRONLY
|
||||||
*/
|
*/
|
||||||
int mode = oflag & O_ACCMODE;
|
int mode = oflag & O_ACCMODE;
|
||||||
if (mode == O_WRONLY || mode == O_RDWR) oflag |= O_CREAT;
|
if (mode == O_WRONLY || mode == O_RDWR) oflag |= O_CREAT;
|
||||||
return attropen(path_name.c_str(), XATTR_RESOURCEFORK_NAME, oflag, 0666);
|
int fd = attropen(path_name.c_str(), XATTR_RESOURCEFORK_NAME, oflag, 0666);
|
||||||
|
if (fd < 0) return macos_error_from_errno();
|
||||||
|
|
||||||
|
auto tmp = new fd_file(path_name, fd);
|
||||||
|
tmp->resource = true;
|
||||||
|
|
||||||
|
return file_ptr(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -328,16 +328,21 @@ namespace native {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int open_fork(const std::string &path_name, int fork, int oflag, int perm) {
|
tool_return<file_ptr> open_fork(const std::string &path_name, int fork, int oflag, int perm) {
|
||||||
|
|
||||||
if (!fork) return ::open(path_name.c_str(), oflag, perm);
|
if (!fork) {
|
||||||
|
int fd = ::open(path_name.c_str(), oflag, perm);
|
||||||
|
if (fd < 0) return macos_error_from_errno();
|
||||||
|
|
||||||
|
return file_ptr(new fd_file(path_name, fd));
|
||||||
|
}
|
||||||
|
|
||||||
// if O_CREAT or E_EXCL, may need to create the file
|
// if O_CREAT or E_EXCL, may need to create the file
|
||||||
|
|
||||||
int tmp = oflag & (O_CREAT | O_EXCL);
|
int tmp = oflag & (O_CREAT | O_EXCL);
|
||||||
if (tmp) {
|
if (tmp) {
|
||||||
int fd = ::open(path_name.c_str(), (oflag & O_ACCMODE) | tmp, perm);
|
int fd = ::open(path_name.c_str(), (oflag & O_ACCMODE) | tmp, perm);
|
||||||
if (fd < 0) return fd;
|
if (fd < 0) return macos_error_from_errno();
|
||||||
::close(fd);
|
::close(fd);
|
||||||
oflag &= ~ (O_CREAT | O_EXCL);
|
oflag &= ~ (O_CREAT | O_EXCL);
|
||||||
}
|
}
|
||||||
|
@ -6,10 +6,14 @@
|
|||||||
#include <ctime>
|
#include <ctime>
|
||||||
|
|
||||||
#include <macos/errors.h>
|
#include <macos/errors.h>
|
||||||
|
#include <macos/tool_return.h>
|
||||||
|
|
||||||
|
#include "file.h"
|
||||||
|
|
||||||
namespace native {
|
namespace native {
|
||||||
|
|
||||||
using MacOS::macos_error;
|
using MacOS::macos_error;
|
||||||
|
using MacOS::tool_return;
|
||||||
|
|
||||||
struct file_info {
|
struct file_info {
|
||||||
|
|
||||||
@ -49,8 +53,8 @@ namespace native {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
int open_fork(const std::string &path_name, int fork, int oflag, int perm = 0666);
|
tool_return<file_ptr> open_fork(const std::string &path_name, int fork, int oflag, int perm = 0666);
|
||||||
int open_resource_fork(const std::string &path_name, int oflag);
|
tool_return<file_ptr> open_resource_fork(const std::string &path_name, int oflag);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,3 +50,5 @@ set_source_files_properties(
|
|||||||
)
|
)
|
||||||
|
|
||||||
add_library(TOOLBOX_LIB ${TOOLBOX_SRC})
|
add_library(TOOLBOX_LIB ${TOOLBOX_SRC})
|
||||||
|
target_link_libraries(TOOLBOX_LIB MACOS_LIB)
|
||||||
|
target_link_libraries(TOOLBOX_LIB NATIVE_LIB)
|
||||||
|
394
toolbox/os.cpp
394
toolbox/os.cpp
@ -47,6 +47,9 @@
|
|||||||
#include <macos/errors.h>
|
#include <macos/errors.h>
|
||||||
#include <macos/traps.h>
|
#include <macos/traps.h>
|
||||||
|
|
||||||
|
#include <native/native.h>
|
||||||
|
#include <native/file.h>
|
||||||
|
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
#include "os_internal.h"
|
#include "os_internal.h"
|
||||||
#include "toolbox.h"
|
#include "toolbox.h"
|
||||||
@ -117,180 +120,6 @@ namespace OS
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
// known text file extensions
|
|
||||||
bool IsTextFile(const std::string &s)
|
|
||||||
{
|
|
||||||
|
|
||||||
// 1. check for a TEXT file type.
|
|
||||||
{
|
|
||||||
int rv;
|
|
||||||
char buffer[32];
|
|
||||||
|
|
||||||
rv = ::getxattr(s.c_str(), XATTR_FINDERINFO_NAME, buffer, 32, 0, 0);
|
|
||||||
if (rv >= 8 && memcmp(buffer, "TEXT", 4) == 0)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string ext = extension(s);
|
|
||||||
if (ext.empty()) return false;
|
|
||||||
|
|
||||||
char c = ext[0];
|
|
||||||
switch(c)
|
|
||||||
{
|
|
||||||
case 'a':
|
|
||||||
if (ext == "aii") // assembler
|
|
||||||
return true;
|
|
||||||
if (ext == "asm")
|
|
||||||
return true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'c':
|
|
||||||
if (ext == "c")
|
|
||||||
return true;
|
|
||||||
if (ext == "cpp")
|
|
||||||
return true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'e':
|
|
||||||
if (ext == "equ") // asm iigs include file.
|
|
||||||
return true;
|
|
||||||
if (ext == "equates") // asm iigs include file.
|
|
||||||
return true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'i':
|
|
||||||
if (ext == "i") // asmiigs include file
|
|
||||||
return true;
|
|
||||||
if (ext == "inc")
|
|
||||||
return true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'h':
|
|
||||||
if (ext == "h") // c header
|
|
||||||
return true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'l':
|
|
||||||
if (ext == "lst") // asm iigs listing
|
|
||||||
return true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'm':
|
|
||||||
if (ext == "macros")
|
|
||||||
return true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'p':
|
|
||||||
if (ext == "p") // pascal
|
|
||||||
return true;
|
|
||||||
if (ext == "pas") // pascal
|
|
||||||
return true;
|
|
||||||
if (ext == "pii") // pascal
|
|
||||||
return true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'r':
|
|
||||||
if (ext == "r")
|
|
||||||
return true;
|
|
||||||
if (ext == "rez")
|
|
||||||
return true;
|
|
||||||
if (ext == "rii") // rez
|
|
||||||
return true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 's':
|
|
||||||
if (ext == "src") // asm equates
|
|
||||||
return true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// check for e16.xxxx or m16.xxxx
|
|
||||||
ext = basename(s);
|
|
||||||
if (ext.length() > 4)
|
|
||||||
{
|
|
||||||
switch (ext[0])
|
|
||||||
{
|
|
||||||
case 'm':
|
|
||||||
case 'M':
|
|
||||||
case 'e':
|
|
||||||
case 'E':
|
|
||||||
if (!strncmp("16.", ext.c_str() + 1, 3))
|
|
||||||
return true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// known binary file extensions
|
|
||||||
bool IsBinaryFile(const std::string &s)
|
|
||||||
{
|
|
||||||
|
|
||||||
// first -- check for a finder info extension.
|
|
||||||
{
|
|
||||||
uint8_t buffer[32];
|
|
||||||
int rv;
|
|
||||||
|
|
||||||
rv = ::getxattr(s.c_str(), XATTR_FINDERINFO_NAME, buffer, 32, 0, 0);
|
|
||||||
|
|
||||||
if (rv >= 8 && ::memcmp(buffer + 4, "pdos",4) == 0)
|
|
||||||
{
|
|
||||||
// Bx__ ?
|
|
||||||
if (buffer[0] == 'B' && buffer[2] == ' ' && buffer[3] == ' ')
|
|
||||||
return true;
|
|
||||||
|
|
||||||
// "p" $uv $wx $yz
|
|
||||||
if (buffer[0] == 'p')
|
|
||||||
{
|
|
||||||
uint8_t fileType = buffer[1];
|
|
||||||
//uint16_t auxType = buffer[2] | (buffer[3] << 8);
|
|
||||||
|
|
||||||
if (fileType >= 0xb1 && fileType <= 0xbf)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string ext = extension(s);
|
|
||||||
if (ext.empty()) return false;
|
|
||||||
|
|
||||||
char c = ext[0];
|
|
||||||
switch(c)
|
|
||||||
{
|
|
||||||
case 'l':
|
|
||||||
if (ext == "lib")
|
|
||||||
return true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'n':
|
|
||||||
// MrC / MrCpp temp file.
|
|
||||||
if (ext == "n")
|
|
||||||
return true;
|
|
||||||
// Newton C++ Tools output
|
|
||||||
if (ext == "ntkc")
|
|
||||||
return true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'o':
|
|
||||||
if (ext == "o")
|
|
||||||
return true;
|
|
||||||
if (ext == "obj")
|
|
||||||
return true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 's':
|
|
||||||
// Newton C++ Intermediate file
|
|
||||||
if (ext == "sym")
|
|
||||||
return true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
uint16_t Close(uint16_t trap)
|
uint16_t Close(uint16_t trap)
|
||||||
{
|
{
|
||||||
@ -303,8 +132,8 @@ namespace OS
|
|||||||
uint16_t ioRefNum = memoryReadWord(parm + 24);
|
uint16_t ioRefNum = memoryReadWord(parm + 24);
|
||||||
|
|
||||||
|
|
||||||
int rv = OS::Internal::FDEntry::close(ioRefNum, true);
|
int rv = OS::Internal::close_file(ioRefNum, true);
|
||||||
if (rv < 0) d0 = macos_error_from_errno();
|
if (rv < 0) d0 = MacOS::rfNumErr;
|
||||||
else d0 = 0;
|
else d0 = 0;
|
||||||
|
|
||||||
memoryWriteWord(d0, parm + 16);
|
memoryWriteWord(d0, parm + 16);
|
||||||
@ -418,9 +247,7 @@ namespace OS
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
uint32_t d0;
|
uint32_t d0 = 0;
|
||||||
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
uint8_t ioPermission = memoryReadByte(parm + _ioPermssn);
|
uint8_t ioPermission = memoryReadByte(parm + _ioPermssn);
|
||||||
uint32_t namePtr = memoryReadLong(parm + _ioNamePtr);
|
uint32_t namePtr = memoryReadLong(parm + _ioNamePtr);
|
||||||
@ -433,12 +260,9 @@ namespace OS
|
|||||||
sname = FSSpecManager::ExpandPath(sname, ioDirID);
|
sname = FSSpecManager::ExpandPath(sname, ioDirID);
|
||||||
}
|
}
|
||||||
|
|
||||||
fd = Internal::FDEntry::open(sname, ioPermission, resource);
|
auto fd = Internal::open_file(sname, resource, ioPermission);
|
||||||
d0 = fd < 0 ? fd : 0;
|
if (fd) memoryWriteWord(fd.value(), parm + _ioRefNum);
|
||||||
if (fd >= 0)
|
d0 = fd.error();
|
||||||
{
|
|
||||||
memoryWriteWord(fd, parm + _ioRefNum);
|
|
||||||
}
|
|
||||||
|
|
||||||
memoryWriteWord(d0, parm + _ioResult);
|
memoryWriteWord(d0, parm + _ioResult);
|
||||||
return d0;
|
return d0;
|
||||||
@ -469,8 +293,7 @@ namespace OS
|
|||||||
|
|
||||||
uint16_t Read(uint16_t trap)
|
uint16_t Read(uint16_t trap)
|
||||||
{
|
{
|
||||||
uint32_t d0;
|
uint32_t d0 = 0;
|
||||||
int32_t pos;
|
|
||||||
uint32_t parm = cpuGetAReg(0);
|
uint32_t parm = cpuGetAReg(0);
|
||||||
|
|
||||||
Log("%04x Read(%08x)\n", trap, parm);
|
Log("%04x Read(%08x)\n", trap, parm);
|
||||||
@ -483,6 +306,24 @@ namespace OS
|
|||||||
uint16_t ioPosMode = memoryReadWord(parm + 44);
|
uint16_t ioPosMode = memoryReadWord(parm + 44);
|
||||||
int32_t ioPosOffset = memoryReadLong(parm + 46);
|
int32_t ioPosOffset = memoryReadLong(parm + 46);
|
||||||
|
|
||||||
|
Log(" read(%04x, %08x, %08x)\n", ioRefNum, ioBuffer, ioReqCount);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* per inside macintosh II-101:
|
||||||
|
* bit 6 (0x40) of ioPosOffset is used for read-verify operation
|
||||||
|
* (write date, call read w/ bit 6 to verify disk matches memory)
|
||||||
|
* returns ioError if it doesn't match.
|
||||||
|
*
|
||||||
|
* bit 7 (0x80) of ioPosMode indicate new-line mode is enabled --
|
||||||
|
* bits 8-15 are a newline character. reading terminates when newline
|
||||||
|
* char is encountered (or eof or ioReqCount).
|
||||||
|
*
|
||||||
|
* bit 4 is please cache bit
|
||||||
|
* bit 5 is please don't cache bit
|
||||||
|
* (if neither or both set, no preference)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
if (ioReqCount < 0)
|
if (ioReqCount < 0)
|
||||||
{
|
{
|
||||||
d0 = MacOS::paramErr;
|
d0 = MacOS::paramErr;
|
||||||
@ -490,46 +331,48 @@ namespace OS
|
|||||||
return d0;
|
return d0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pos = Internal::mac_seek(ioRefNum, ioPosMode, ioPosOffset);
|
if (ioPosMode & 0x80) {
|
||||||
if (pos < 0)
|
fprintf(stderr, "Newline Read (eof char = %02x)\n", ioPosMode >> 8);
|
||||||
{
|
exit(1);
|
||||||
d0 = pos;
|
}
|
||||||
pos = 0;
|
|
||||||
|
|
||||||
memoryWriteLong(pos, parm + 46); // new offset.
|
ssize_t offset = ioPosOffset;
|
||||||
|
int whence = ioPosMode;
|
||||||
|
uint32_t transferCount = 0;
|
||||||
|
|
||||||
|
Internal::remap_seek(offset, whence);
|
||||||
|
|
||||||
|
auto ff = Internal::find_file(ioRefNum);
|
||||||
|
if (!ff) {
|
||||||
|
d0 = MacOS::rfNumErr;
|
||||||
memoryWriteWord(d0, parm + 16);
|
memoryWriteWord(d0, parm + 16);
|
||||||
return d0;
|
return d0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log(" read(%04x, %08x, %08x)\n", ioRefNum, ioBuffer, ioReqCount);
|
auto pos = ff->seek(offset, whence);
|
||||||
ssize_t count = OS::Internal::FDEntry::read(ioRefNum, memoryPointer(ioBuffer), ioReqCount);
|
if (!pos) {
|
||||||
if (count >= 0)
|
d0 = pos.error();
|
||||||
{
|
|
||||||
d0 = 0;
|
|
||||||
pos += count;
|
|
||||||
memoryWriteLong(count, parm + 40);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count == 0)
|
|
||||||
{
|
|
||||||
d0 = MacOS::eofErr;
|
|
||||||
}
|
|
||||||
if (count < 0)
|
|
||||||
{
|
|
||||||
d0 = macos_error_from_errno();
|
|
||||||
}
|
|
||||||
|
|
||||||
memoryWriteLong(pos, parm + 46); // new offset.
|
|
||||||
memoryWriteWord(d0, parm + 16);
|
memoryWriteWord(d0, parm + 16);
|
||||||
return d0;
|
return d0;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto xfer = ff->read(memoryPointer(ioBuffer), ioReqCount);
|
||||||
|
if (xfer && *xfer == 0) xfer = MacOS::eofErr;
|
||||||
|
|
||||||
|
d0 = xfer.error();
|
||||||
|
transferCount = xfer.value_or(0);
|
||||||
|
offset = ff->get_mark().value_or(0ul);
|
||||||
|
|
||||||
|
memoryWriteLong(offset, parm + 46); // new offset.
|
||||||
|
memoryWriteLong(transferCount, parm + 40);
|
||||||
|
memoryWriteWord(d0, parm + 16);
|
||||||
|
return d0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint16_t Write(uint16_t trap)
|
uint16_t Write(uint16_t trap)
|
||||||
{
|
{
|
||||||
uint32_t d0;
|
uint32_t d0 = 0;
|
||||||
int32_t pos;
|
|
||||||
uint32_t parm = cpuGetAReg(0);
|
uint32_t parm = cpuGetAReg(0);
|
||||||
|
|
||||||
Log("%04x Write(%08x)\n", trap, parm);
|
Log("%04x Write(%08x)\n", trap, parm);
|
||||||
@ -542,6 +385,8 @@ namespace OS
|
|||||||
uint16_t ioPosMode = memoryReadWord(parm + 44);
|
uint16_t ioPosMode = memoryReadWord(parm + 44);
|
||||||
int32_t ioPosOffset = memoryReadLong(parm + 46);
|
int32_t ioPosOffset = memoryReadLong(parm + 46);
|
||||||
|
|
||||||
|
Log(" write(%04x, %08x, %08x)\n", ioRefNum, ioBuffer, ioReqCount);
|
||||||
|
|
||||||
if (ioReqCount < 0)
|
if (ioReqCount < 0)
|
||||||
{
|
{
|
||||||
d0 = MacOS::paramErr;
|
d0 = MacOS::paramErr;
|
||||||
@ -549,36 +394,37 @@ namespace OS
|
|||||||
return d0;
|
return d0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pos = Internal::mac_seek(ioRefNum, ioPosMode, ioPosOffset);
|
ssize_t offset = ioPosOffset;
|
||||||
if (pos < 0)
|
int whence = ioPosMode;
|
||||||
{
|
uint32_t transferCount = 0;
|
||||||
d0 = pos;
|
|
||||||
pos = 0;
|
|
||||||
|
|
||||||
memoryWriteLong(pos, parm + 46); // new offset.
|
Internal::remap_seek(offset, whence);
|
||||||
|
|
||||||
|
auto ff = Internal::find_file(ioRefNum);
|
||||||
|
if (!ff) {
|
||||||
|
d0 = MacOS::rfNumErr;
|
||||||
memoryWriteWord(d0, parm + 16);
|
memoryWriteWord(d0, parm + 16);
|
||||||
return d0;
|
return d0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Log(" write(%04x, %08x, %08x)\n", ioRefNum, ioBuffer, ioReqCount);
|
auto pos = ff->seek(offset, whence);
|
||||||
ssize_t count = OS::Internal::FDEntry::write(ioRefNum, memoryPointer(ioBuffer), ioReqCount);
|
if (!pos) {
|
||||||
if (count >= 0)
|
d0 = pos.error();
|
||||||
{
|
|
||||||
d0 = 0;
|
|
||||||
pos += count;
|
|
||||||
memoryWriteLong(count, parm + 40);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (count < 0)
|
|
||||||
{
|
|
||||||
d0 = macos_error_from_errno();
|
|
||||||
}
|
|
||||||
|
|
||||||
memoryWriteLong(pos, parm + 46); // new offset.
|
|
||||||
memoryWriteWord(d0, parm + 16);
|
memoryWriteWord(d0, parm + 16);
|
||||||
return d0;
|
return d0;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto xfer = ff->write(memoryPointer(ioBuffer), ioReqCount);
|
||||||
|
if (xfer && *xfer == 0) xfer = MacOS::eofErr;
|
||||||
|
|
||||||
|
d0 = xfer.error();
|
||||||
|
transferCount = xfer.value_or(0);
|
||||||
|
offset = ff->get_mark().value_or(0ul);
|
||||||
|
|
||||||
|
memoryWriteLong(offset, parm + 46); // new offset.
|
||||||
|
memoryWriteLong(transferCount, parm + 40);
|
||||||
|
memoryWriteWord(d0, parm + 16);
|
||||||
|
return d0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -670,8 +516,8 @@ namespace OS
|
|||||||
|
|
||||||
uint16_t GetEOF(uint16_t trap)
|
uint16_t GetEOF(uint16_t trap)
|
||||||
{
|
{
|
||||||
uint32_t d0;
|
uint32_t d0 = 0;
|
||||||
size_t size;
|
size_t size = 0;
|
||||||
|
|
||||||
uint32_t parm = cpuGetAReg(0);
|
uint32_t parm = cpuGetAReg(0);
|
||||||
|
|
||||||
@ -680,18 +526,15 @@ namespace OS
|
|||||||
//uint32_t ioCompletion = memoryReadLong(parm + 12);
|
//uint32_t ioCompletion = memoryReadLong(parm + 12);
|
||||||
uint16_t ioRefNum = memoryReadWord(parm + 24);
|
uint16_t ioRefNum = memoryReadWord(parm + 24);
|
||||||
|
|
||||||
struct stat st;
|
auto ff = Internal::find_file(ioRefNum);
|
||||||
|
if (ff) {
|
||||||
if (::fstat(ioRefNum, &st) < 0)
|
auto eof = ff->get_eof();
|
||||||
{
|
d0 = eof.error();
|
||||||
d0 = macos_error_from_errno();
|
size = eof.value_or(0);
|
||||||
|
} else {
|
||||||
|
d0 = MacOS::rfNumErr;
|
||||||
size = 0;
|
size = 0;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
d0 = 0;
|
|
||||||
size = st.st_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
memoryWriteWord(d0, parm + 16);
|
memoryWriteWord(d0, parm + 16);
|
||||||
memoryWriteLong(size, parm + 28);
|
memoryWriteLong(size, parm + 28);
|
||||||
@ -711,9 +554,14 @@ namespace OS
|
|||||||
uint16_t ioRefNum = memoryReadWord(parm + 24);
|
uint16_t ioRefNum = memoryReadWord(parm + 24);
|
||||||
uint32_t ioMisc = memoryReadLong(parm + 28);
|
uint32_t ioMisc = memoryReadLong(parm + 28);
|
||||||
|
|
||||||
int rv = ::ftruncate(ioRefNum, ioMisc);
|
|
||||||
|
|
||||||
d0 = rv < 0 ? macos_error_from_errno() : 0;
|
auto ff = Internal::find_file(ioRefNum);
|
||||||
|
if (ff) {
|
||||||
|
auto eof = ff->set_eof(ioMisc);
|
||||||
|
d0 = eof.error();
|
||||||
|
} else {
|
||||||
|
d0 = MacOS::rfNumErr;
|
||||||
|
}
|
||||||
|
|
||||||
memoryWriteWord(d0, parm + 16);
|
memoryWriteWord(d0, parm + 16);
|
||||||
return d0;
|
return d0;
|
||||||
@ -721,7 +569,8 @@ namespace OS
|
|||||||
|
|
||||||
uint16_t GetFPos(uint16_t trap)
|
uint16_t GetFPos(uint16_t trap)
|
||||||
{
|
{
|
||||||
uint32_t d0;
|
uint32_t d0 = 0;
|
||||||
|
size_t size = 0;
|
||||||
|
|
||||||
uint32_t parm = cpuGetAReg(0);
|
uint32_t parm = cpuGetAReg(0);
|
||||||
|
|
||||||
@ -730,19 +579,22 @@ namespace OS
|
|||||||
//uint32_t ioCompletion = memoryReadLong(parm + 12);
|
//uint32_t ioCompletion = memoryReadLong(parm + 12);
|
||||||
uint16_t ioRefNum = memoryReadWord(parm + 24);
|
uint16_t ioRefNum = memoryReadWord(parm + 24);
|
||||||
|
|
||||||
int rv = ::lseek(ioRefNum, 0, SEEK_CUR);
|
|
||||||
if (rv < 0)
|
auto ff = Internal::find_file(ioRefNum);
|
||||||
{
|
if (ff) {
|
||||||
d0 = macos_error_from_errno();
|
auto mark = ff->get_mark();
|
||||||
|
d0 = mark.error();
|
||||||
|
size = mark.value_or(0);
|
||||||
|
} else {
|
||||||
|
d0 = MacOS::rfNumErr;
|
||||||
|
size = 0;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
memoryWriteLong(0, parm + 36); // ioReqCount
|
memoryWriteLong(0, parm + 36); // ioReqCount
|
||||||
memoryWriteLong(0, parm + 40); // ioActCount
|
memoryWriteLong(0, parm + 40); // ioActCount
|
||||||
memoryWriteWord(0, parm + 44); // ioPosMode
|
memoryWriteWord(0, parm + 44); // ioPosMode
|
||||||
memoryWriteLong(rv, parm + 46); // ioPosOffset
|
memoryWriteLong(size, parm + 46); // ioPosOffset
|
||||||
d0 = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
memoryWriteWord(d0, parm + 16);
|
memoryWriteWord(d0, parm + 16);
|
||||||
return d0;
|
return d0;
|
||||||
@ -762,15 +614,23 @@ namespace OS
|
|||||||
int32_t ioPosOffset = memoryReadLong(parm + 46);
|
int32_t ioPosOffset = memoryReadLong(parm + 46);
|
||||||
|
|
||||||
|
|
||||||
ioPosOffset = Internal::mac_seek(ioRefNum, ioPosMode, ioPosOffset);
|
ssize_t offset = ioPosOffset;
|
||||||
d0 = 0;
|
int whence = ioPosMode;
|
||||||
if (ioPosOffset < 0)
|
|
||||||
{
|
Internal::remap_seek(offset, whence);
|
||||||
d0 = ioPosOffset;
|
|
||||||
ioPosOffset = 0;
|
auto ff = Internal::find_file(ioRefNum);
|
||||||
|
if (ff) {
|
||||||
|
auto pos = ff->seek(offset, whence);
|
||||||
|
d0 = pos.error();
|
||||||
|
offset = pos.value_or(0);
|
||||||
|
} else {
|
||||||
|
d0 = MacOS::rfNumErr;
|
||||||
|
offset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
memoryWriteLong(ioPosOffset, parm + 46); // new offset.
|
|
||||||
|
memoryWriteLong(offset, parm + 46); // new offset.
|
||||||
memoryWriteWord(d0, parm + 16);
|
memoryWriteWord(d0, parm + 16);
|
||||||
return d0;
|
return d0;
|
||||||
}
|
}
|
||||||
|
@ -49,6 +49,8 @@
|
|||||||
|
|
||||||
#include <macos/errors.h>
|
#include <macos/errors.h>
|
||||||
|
|
||||||
|
#include <native/native.h>
|
||||||
|
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
#include "rm.h"
|
#include "rm.h"
|
||||||
#include "os_internal.h"
|
#include "os_internal.h"
|
||||||
@ -211,12 +213,9 @@ namespace OS {
|
|||||||
return MacOS::dirNFErr;
|
return MacOS::dirNFErr;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fd = Internal::FDEntry::open(sname, permission, 0);
|
auto fd = Internal::open_file(sname, 0, permission);
|
||||||
if (fd < 0) return fd;
|
memoryWriteWord(fd.value_or(-1), refNum);
|
||||||
|
return fd.error();
|
||||||
memoryWriteWord(fd, refNum);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t FSpGetFInfo()
|
uint16_t FSpGetFInfo()
|
||||||
|
@ -35,22 +35,26 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/attr.h>
|
#include <sys/attr.h>
|
||||||
|
|
||||||
#include <native/native.h>
|
#include <native/native.h>
|
||||||
|
#include <native/file.h>
|
||||||
|
|
||||||
//#include <machine/endian.h>
|
//#include <machine/endian.h>
|
||||||
|
|
||||||
using ToolBox::Log;
|
using ToolBox::Log;
|
||||||
using MacOS::macos_error_from_errno;
|
using MacOS::macos_error_from_errno;
|
||||||
|
using MacOS::tool_return;
|
||||||
|
using MacOS::macos_error;
|
||||||
|
|
||||||
namespace OS { namespace Internal {
|
namespace OS { namespace Internal {
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
int32_t mac_seek(uint16_t refNum, uint16_t mode, int32_t offset)
|
int32_t mac_seek(uint16_t refNum, uint16_t mode, int32_t offset)
|
||||||
{
|
{
|
||||||
off_t rv;
|
off_t rv;
|
||||||
@ -75,7 +79,135 @@ namespace OS { namespace Internal {
|
|||||||
if (rv < 0) return macos_error_from_errno();
|
if (rv < 0) return macos_error_from_errno();
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
std::vector<native::file_ptr> file_table;
|
||||||
|
}
|
||||||
|
|
||||||
|
int open_file(native::file_ptr &&f) {
|
||||||
|
|
||||||
|
int fd = 0;
|
||||||
|
for (auto &ff : file_table) {
|
||||||
|
if (!ff) {
|
||||||
|
ff = std::move(f);
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
++fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
file_table.emplace_back(std::move(f));
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
tool_return<int> open_file(const std::string &name, int resource, int ioPermission) {
|
||||||
|
|
||||||
|
|
||||||
|
ioPermission &= 0x0f;
|
||||||
|
int oflag;
|
||||||
|
|
||||||
|
switch(ioPermission)
|
||||||
|
{
|
||||||
|
case fsWrPerm:
|
||||||
|
oflag = O_WRONLY;
|
||||||
|
break;
|
||||||
|
case fsRdWrPerm:
|
||||||
|
case fsRdWrShPerm:
|
||||||
|
case fsCurPerm:
|
||||||
|
oflag = O_RDWR;
|
||||||
|
break;
|
||||||
|
case fsRdPerm:
|
||||||
|
oflag = O_RDONLY;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return MacOS::paramErr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
auto ff = native::open_fork(name, resource, oflag);
|
||||||
|
if (ff.error() == MacOS::permErr && ioPermission == fsCurPerm)
|
||||||
|
ff = native::open_fork(name, resource, O_RDONLY);
|
||||||
|
|
||||||
|
|
||||||
|
if (!ff) return ff.error();
|
||||||
|
|
||||||
|
auto f = std::move(ff).value();
|
||||||
|
f->resource = resource;
|
||||||
|
f->text = resource ? false : native::is_text_file(name);
|
||||||
|
|
||||||
|
return open_file(std::move(f));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int close_file(int fd, bool force) {
|
||||||
|
if (fd < 0 || fd >= file_table.size()) return -1;
|
||||||
|
auto &f = file_table[fd];
|
||||||
|
if (!f) return -1;
|
||||||
|
if (force || --f->refcount == 0) f.reset();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
native::file *find_file(int fd) {
|
||||||
|
if (fd < 0 || fd >= file_table.size()) return nullptr;
|
||||||
|
return file_table[fd].get();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
macos_error remap_iopermission(int ioPermission) {
|
||||||
|
switch(ioPermission & 0x0f)
|
||||||
|
{
|
||||||
|
case fsWrPerm:
|
||||||
|
case fsRdWrPerm:
|
||||||
|
case fsRdWrShPerm:
|
||||||
|
case fsCurPerm:
|
||||||
|
ioPermission = O_RDWR;
|
||||||
|
return MacOS::noErr;
|
||||||
|
break;
|
||||||
|
case fsRdPerm:
|
||||||
|
ioPermission = O_RDONLY;
|
||||||
|
return MacOS::noErr;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ioPermission = O_RDWR;
|
||||||
|
return MacOS::paramErr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
macos_error remap_seek(ssize_t &offset, int &mode) {
|
||||||
|
|
||||||
|
switch (mode & 0x03)
|
||||||
|
{
|
||||||
|
case OS::fsAtMark:
|
||||||
|
mode = SEEK_CUR;
|
||||||
|
offset = 0;
|
||||||
|
break;
|
||||||
|
case OS::fsFromStart:
|
||||||
|
mode = SEEK_SET;
|
||||||
|
break;
|
||||||
|
case OS::fsFromLEOF:
|
||||||
|
mode = SEEK_END;
|
||||||
|
break;
|
||||||
|
case OS::fsFromMark:
|
||||||
|
mode = SEEK_CUR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MacOS::noErr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
//std::deque<FDEntry> FDTable;
|
//std::deque<FDEntry> FDTable;
|
||||||
|
|
||||||
std::deque<FDEntry> FDEntry::FDTable;
|
std::deque<FDEntry> FDEntry::FDTable;
|
||||||
@ -264,5 +396,5 @@ namespace OS { namespace Internal {
|
|||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
} }
|
} }
|
||||||
|
@ -5,17 +5,43 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <native/file.h>
|
||||||
|
|
||||||
namespace OS {
|
namespace OS {
|
||||||
|
|
||||||
std::string realpath(const std::string &path);
|
std::string realpath(const std::string &path);
|
||||||
|
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
|
using MacOS::tool_return;
|
||||||
|
|
||||||
int32_t mac_seek(uint16_t refNum, uint16_t mode, int32_t offset);
|
//int32_t mac_seek(uint16_t refNum, uint16_t mode, int32_t offset);
|
||||||
|
|
||||||
|
MacOS::macos_error remap_iopermission(int ioPermission);
|
||||||
|
MacOS::macos_error remap_seek(ssize_t &offset, int &mode);
|
||||||
|
|
||||||
|
|
||||||
|
int open_file(native::file_ptr &&f);
|
||||||
|
|
||||||
|
tool_return<int> open_file(const std::string &name, int fork, int permission);
|
||||||
|
|
||||||
|
int close_file(int fd, bool force = false);
|
||||||
|
native::file *find_file(int fd);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
template<class FX>
|
||||||
|
macos_error with_file(int fd, FX fx) {
|
||||||
|
if (fd < 0 || fd >= FDTable.size()) return MacOS::rfNumErr;
|
||||||
|
auto &e = FDTable[fd];
|
||||||
|
if (!e) return MacOS::rfNumErr;
|
||||||
|
return fx(e);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if 0
|
||||||
struct FDEntry
|
struct FDEntry
|
||||||
{
|
{
|
||||||
int refcount;
|
int refcount;
|
||||||
@ -65,6 +91,7 @@ namespace Internal {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
} }
|
} }
|
||||||
|
|
||||||
|
@ -24,6 +24,10 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO - https://www.fenestrated.net/mirrors/Apple%20Technotes%20(As%20of%202002)/tn/tn1120.html
|
||||||
|
* Opening Files Twice Considered Hard
|
||||||
|
*/
|
||||||
|
|
||||||
#include "rm.h"
|
#include "rm.h"
|
||||||
#include "mm.h"
|
#include "mm.h"
|
||||||
@ -50,6 +54,7 @@
|
|||||||
#include <macos/sysequ.h>
|
#include <macos/sysequ.h>
|
||||||
|
|
||||||
#include <native/native.h>
|
#include <native/native.h>
|
||||||
|
#include <native/file.h>
|
||||||
#include <include/endian.h>
|
#include <include/endian.h>
|
||||||
|
|
||||||
#include "stackframe.h"
|
#include "stackframe.h"
|
||||||
@ -174,7 +179,7 @@ struct resource {
|
|||||||
|
|
||||||
struct resource_file {
|
struct resource_file {
|
||||||
resource_file *next = nullptr;
|
resource_file *next = nullptr;
|
||||||
int fd = -1;
|
native::file_ptr file;
|
||||||
int refnum = -1;
|
int refnum = -1;
|
||||||
|
|
||||||
|
|
||||||
@ -197,9 +202,7 @@ struct resource_file {
|
|||||||
resource_file &operator=(const resource_file &) = delete;
|
resource_file &operator=(const resource_file &) = delete;
|
||||||
resource_file &operator=(resource_file &&) = delete;
|
resource_file &operator=(resource_file &&) = delete;
|
||||||
|
|
||||||
~resource_file() {
|
~resource_file() = default;
|
||||||
if (fd >= 0) close(fd);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -419,23 +422,22 @@ namespace {
|
|||||||
tool_return<int32_t> get_resource_size(resource_file &rf, resource &r) {
|
tool_return<int32_t> get_resource_size(resource_file &rf, resource &r) {
|
||||||
|
|
||||||
uint8_t buffer[4];
|
uint8_t buffer[4];
|
||||||
if (lseek(rf.fd, rf.offset_rdata + r.data_offset, SEEK_SET) < 0)
|
auto sm = rf.file->set_mark(rf.offset_rdata + r.data_offset);
|
||||||
return macos_error_from_errno();
|
if (sm.error()) return sm.error();
|
||||||
size_t ok = read(rf.fd, buffer, sizeof(buffer));
|
|
||||||
if (ok != 4) return mapReadErr;
|
auto ok = rf.file->read(buffer, sizeof(buffer));
|
||||||
|
if (ok.value_or(0) != 4) return mapReadErr;
|
||||||
|
|
||||||
return r.disk_size = read_32(buffer);
|
return r.disk_size = read_32(buffer);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
tool_return<void> read_resource_map(resource_file &rf) {
|
tool_return<void> read_resource_map(resource_file &rf) {
|
||||||
|
|
||||||
ssize_t ok;
|
|
||||||
uint8_t header[100];
|
uint8_t header[100];
|
||||||
|
|
||||||
ok = read(rf.fd, header, sizeof(header));
|
auto ok = rf.file->read(header, sizeof(header));
|
||||||
if (ok != sizeof(header)) return mapReadErr;
|
if (ok.value_or(0) != sizeof(header)) return mapReadErr;
|
||||||
|
|
||||||
rf.offset_rdata = read_32(header+0);
|
rf.offset_rdata = read_32(header+0);
|
||||||
rf.offset_rmap = read_32(header+4);
|
rf.offset_rmap = read_32(header+4);
|
||||||
@ -445,9 +447,11 @@ namespace {
|
|||||||
if (rf.length_rmap < 30) return mapReadErr;
|
if (rf.length_rmap < 30) return mapReadErr;
|
||||||
std::vector<uint8_t> rmap(rf.length_rmap);
|
std::vector<uint8_t> rmap(rf.length_rmap);
|
||||||
|
|
||||||
if (lseek(rf.fd, rf.offset_rmap, SEEK_SET) < 0) return macos_error_from_errno();
|
auto sm = rf.file->set_mark(rf.offset_rmap);
|
||||||
ok = read(rf.fd, rmap.data(), rf.length_rmap);
|
if (sm.error()) return sm.error();
|
||||||
if (ok != rf.length_rmap) return mapReadErr;
|
|
||||||
|
ok = rf.file->read(rmap.data(), rf.length_rmap);
|
||||||
|
if (ok.value_or(0) != rf.length_rmap) return mapReadErr;
|
||||||
|
|
||||||
rf.attr = read_16(rmap, 22, std::nothrow);
|
rf.attr = read_16(rmap, 22, std::nothrow);
|
||||||
uint16_t offset_type_list = read_16(rmap, 24, std::nothrow);
|
uint16_t offset_type_list = read_16(rmap, 24, std::nothrow);
|
||||||
@ -507,7 +511,6 @@ namespace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tool_return<void> load_resource(resource_file &rf, resource &r) {
|
tool_return<void> load_resource(resource_file &rf, resource &r) {
|
||||||
ssize_t ok;
|
|
||||||
uint32_t handle = r.handle;
|
uint32_t handle = r.handle;
|
||||||
|
|
||||||
//if (!handle) return resNotFound;
|
//if (!handle) return resNotFound;
|
||||||
@ -529,15 +532,14 @@ namespace {
|
|||||||
if (r.attr & resLocked) attr |= MM::attrLocked;
|
if (r.attr & resLocked) attr |= MM::attrLocked;
|
||||||
|
|
||||||
|
|
||||||
ok = read(rf.fd, memoryPointer(*ptr), *size);
|
auto ok = rf.file->read(memoryPointer(*ptr), *size);
|
||||||
if (ok < 0) {
|
if (ok.error()) {
|
||||||
auto rv = macos_error_from_errno();
|
|
||||||
// ???
|
// ???
|
||||||
MM::Native::EmptyHandle(handle);
|
MM::Native::EmptyHandle(handle);
|
||||||
return rv;
|
return ok.error();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ok != *size) {
|
if (ok.value() != *size) {
|
||||||
MM::Native::EmptyHandle(handle);
|
MM::Native::EmptyHandle(handle);
|
||||||
return mapReadErr;
|
return mapReadErr;
|
||||||
}
|
}
|
||||||
@ -549,8 +551,6 @@ namespace {
|
|||||||
|
|
||||||
tool_return<uint32_t> read_resource(resource_file &rf, resource &r) {
|
tool_return<uint32_t> read_resource(resource_file &rf, resource &r) {
|
||||||
|
|
||||||
ssize_t ok;
|
|
||||||
|
|
||||||
if (r.handle) return r.handle;
|
if (r.handle) return r.handle;
|
||||||
|
|
||||||
|
|
||||||
@ -574,14 +574,13 @@ namespace {
|
|||||||
auto hh = MM::Native::NewHandleWithAttr(*size, attr);
|
auto hh = MM::Native::NewHandleWithAttr(*size, attr);
|
||||||
if (hh.error()) return hh.error();
|
if (hh.error()) return hh.error();
|
||||||
|
|
||||||
ok = read(rf.fd, memoryPointer(hh->pointer), *size);
|
auto ok = rf.file->read(memoryPointer(hh->pointer), *size);
|
||||||
if (ok < 0) {
|
if (ok.error()) {
|
||||||
auto rv = macos_error_from_errno();
|
|
||||||
MM::Native::DisposeHandle(hh->handle);
|
MM::Native::DisposeHandle(hh->handle);
|
||||||
return rv;
|
return ok.error();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ok != *size) {
|
if (*ok != *size) {
|
||||||
MM::Native::DisposeHandle(hh->handle);
|
MM::Native::DisposeHandle(hh->handle);
|
||||||
return mapReadErr;
|
return mapReadErr;
|
||||||
}
|
}
|
||||||
@ -614,10 +613,10 @@ namespace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uint32_t xx = htobe32(hi->size);
|
uint32_t xx = htobe32(hi->size);
|
||||||
lseek(rf.fd, rf.offset_rdata + r.data_offset, SEEK_SET);
|
rf.file->set_mark(rf.offset_rdata + r.data_offset);
|
||||||
write(rf.fd, &xx, 4);
|
rf.file->write(&xx, 4);
|
||||||
// todo -- if purged, is size 0??
|
// todo -- if purged, is size 0??
|
||||||
write(rf.fd, memoryPointer(hi->address), hi->size);
|
rf.file->write(memoryPointer(hi->address), hi->size);
|
||||||
rf.attr &= ~resChanged;
|
rf.attr &= ~resChanged;
|
||||||
return noErr;
|
return noErr;
|
||||||
|
|
||||||
@ -719,12 +718,13 @@ namespace Native {
|
|||||||
|
|
||||||
tool_return<int16_t> OpenResFile(const std::string &path_name, uint16_t perm) {
|
tool_return<int16_t> OpenResFile(const std::string &path_name, uint16_t perm) {
|
||||||
|
|
||||||
int fd = native::open_resource_fork(path_name, O_RDONLY);
|
auto fd = native::open_resource_fork(path_name, O_RDONLY);
|
||||||
if (fd < 0) return SetResError(macos_error_from_errno());
|
if (fd.error()) return SetResError(fd.error());
|
||||||
|
|
||||||
auto rf = std::make_unique<resource_file>();
|
auto rf = std::make_unique<resource_file>();
|
||||||
|
|
||||||
rf->fd = fd;
|
rf->file = std::move(fd).value();
|
||||||
|
rf->file->resource = true;
|
||||||
rf->attr |= mapReadOnly;
|
rf->attr |= mapReadOnly;
|
||||||
auto rv = read_resource_map(*rf);
|
auto rv = read_resource_map(*rf);
|
||||||
if (!rv) return SetResError(rv.error());
|
if (!rv) return SetResError(rv.error());
|
||||||
@ -838,38 +838,26 @@ namespace Native {
|
|||||||
if (path.empty()) return SetResError(MacOS::bdNamErr);
|
if (path.empty()) return SetResError(MacOS::bdNamErr);
|
||||||
|
|
||||||
|
|
||||||
struct stat st;
|
|
||||||
macos_error err = noErr;
|
macos_error err = noErr;
|
||||||
|
|
||||||
int fd = native::open_fork(path, 0, O_CREAT | O_EXCL | O_WRONLY, 0666);
|
auto fd = native::open_fork(path, 0, O_CREAT | O_EXCL | O_WRONLY, 0666);
|
||||||
if (fd < 0) {
|
if ((err = fd.error())) {
|
||||||
if (errno == EEXIST) err = dupFNErr;
|
if (err != dupFNErr) return SetResError(err);
|
||||||
else return SetResError(macos_error_from_errno());
|
|
||||||
}
|
}
|
||||||
close(fd);
|
|
||||||
|
|
||||||
fd = native::open_fork(path, 1, O_WRONLY, 0666);
|
fd = native::open_fork(path, 1, O_WRONLY, 0666);
|
||||||
if (fd < 0) return SetResError(macos_error_from_errno());
|
if (fd.error()) return SetResError(macos_error_from_errno());
|
||||||
|
|
||||||
|
auto ff = std::move(fd).value();
|
||||||
|
|
||||||
// need to check if resource fork size > 0 -- don't clobber an existing fork.
|
// need to check if resource fork size > 0 -- don't clobber an existing fork.
|
||||||
if (fstat(fd, &st) < 0) {
|
if (ff->get_eof().value()) {
|
||||||
auto rv = macos_error_from_errno();
|
|
||||||
close(fd);
|
|
||||||
return SetResError(rv);
|
|
||||||
}
|
|
||||||
if (st.st_size > 0) {
|
|
||||||
close(fd);
|
|
||||||
return SetResError(err);
|
return SetResError(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t ok = write(fd, empty_resource_fork, sizeof(empty_resource_fork));
|
auto ok = ff->write(empty_resource_fork, sizeof(empty_resource_fork));
|
||||||
if (ok != sizeof(empty_resource_fork)) {
|
if (ok.error()) return SetResError(ok.error());
|
||||||
auto rv = macos_error_from_errno();
|
|
||||||
close(fd);
|
|
||||||
return SetResError(rv);
|
|
||||||
}
|
|
||||||
|
|
||||||
close(fd);
|
|
||||||
return SetResError(err);
|
return SetResError(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user