mirror of
https://github.com/ksherlock/mpw.git
synced 2024-12-22 00:29:18 +00:00
Merge branch 'PPCLink'
Fixes and support for the PPCLink utility.
This commit is contained in:
commit
3dd91f18b6
@ -577,6 +577,20 @@ namespace MacOS {
|
||||
{
|
||||
return std::error_condition(static_cast<int>(e), macos_system_category());
|
||||
}
|
||||
|
||||
inline void throw_macos_error(int e)
|
||||
{
|
||||
throw std::system_error(e, macos_system_category());
|
||||
}
|
||||
inline void throw_macos_error(int e, const char *what)
|
||||
{
|
||||
throw std::system_error(e, macos_system_category(), what);
|
||||
}
|
||||
inline void throw_macos_error(int e, const std::string &what)
|
||||
{
|
||||
throw std::system_error(e, macos_system_category(), what);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace std {
|
||||
|
137
macos/tool_return.h
Normal file
137
macos/tool_return.h
Normal file
@ -0,0 +1,137 @@
|
||||
#ifndef __tool_return__
|
||||
#define __tool_return__
|
||||
|
||||
#include "errors.h"
|
||||
#include <utility>
|
||||
|
||||
namespace MacOS {
|
||||
|
||||
namespace internal {
|
||||
|
||||
class tool_return_base
|
||||
{
|
||||
protected:
|
||||
macos_error _error;
|
||||
|
||||
tool_return_base() : _error(static_cast<macos_error>(0))
|
||||
{}
|
||||
|
||||
tool_return_base(macos_error error) : _error(error)
|
||||
{}
|
||||
|
||||
public:
|
||||
|
||||
macos_error error() const
|
||||
{
|
||||
return _error;
|
||||
}
|
||||
|
||||
|
||||
template<class... Args>
|
||||
void throw_macos_error(Args&&... args) const
|
||||
{
|
||||
if (_error) MacOS::throw_macos_error(_error, std::forward<Args>(args)...);
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
} // namespace
|
||||
|
||||
template<class T>
|
||||
class tool_return : public internal::tool_return_base
|
||||
{
|
||||
private:
|
||||
T _value;
|
||||
|
||||
tool_return() = delete;
|
||||
|
||||
operator T() const
|
||||
{
|
||||
return _value;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
tool_return(T value) : _value(value)
|
||||
{}
|
||||
|
||||
tool_return(macos_error error) : tool_return_base(error)
|
||||
{}
|
||||
|
||||
|
||||
tool_return &operator=(T value)
|
||||
{
|
||||
_value = value;
|
||||
_error = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
tool_return &operator=(macos_error error)
|
||||
{
|
||||
_value = T();
|
||||
_error = error;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
constexpr const T* operator->() const
|
||||
{
|
||||
return &_value;
|
||||
}
|
||||
|
||||
|
||||
constexpr const T& operator *() const
|
||||
{
|
||||
return _value;
|
||||
}
|
||||
|
||||
|
||||
T value() const
|
||||
{
|
||||
return _value;
|
||||
}
|
||||
|
||||
template<class U>
|
||||
T value_or(U&& u) const
|
||||
{
|
||||
if (_error) return u;
|
||||
return _value;
|
||||
}
|
||||
|
||||
template<class... Args>
|
||||
T value_or_throw(Args&&... args) const
|
||||
{
|
||||
if (_error) throw_macos_error(std::forward<Args>(args)...);
|
||||
|
||||
return _value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
template<>
|
||||
class tool_return<void> : public internal::tool_return_base
|
||||
{
|
||||
public:
|
||||
|
||||
tool_return()
|
||||
{}
|
||||
|
||||
tool_return(macos_error error) : tool_return_base(error)
|
||||
{}
|
||||
|
||||
tool_return &operator=(macos_error error)
|
||||
{
|
||||
_error = error;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
} // namespace IIgs
|
||||
#endif
|
45
mpw/mpw.cpp
45
mpw/mpw.cpp
@ -73,52 +73,7 @@ namespace MPW
|
||||
|
||||
bool Trace = false;
|
||||
|
||||
int errno_to_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;
|
||||
|
||||
}
|
||||
|
||||
static bool isdir(const std::string &path)
|
||||
{
|
||||
|
@ -119,8 +119,6 @@ namespace MPW {
|
||||
void ftrap_write(uint16_t trap);
|
||||
void ftrap_ioctl(uint16_t trap);
|
||||
|
||||
// native errno to an MPW errno.
|
||||
int errno_to_errno(int xerrno);
|
||||
}
|
||||
|
||||
#endif
|
@ -133,7 +133,7 @@ namespace MPW
|
||||
Log(" delete(%s)\n", sname.c_str());
|
||||
|
||||
rv = ::unlink(sname.c_str());
|
||||
if (rv < 0) return 0x40000000 | errno_to_errno(errno);
|
||||
if (rv < 0) return 0x40000000 | mpw_errno_from_errno();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -192,7 +192,7 @@ namespace MPW
|
||||
if (fd < 0)
|
||||
{
|
||||
// return an errno.
|
||||
d0 = 0x40000000 | errno_to_errno(errno);
|
||||
d0 = 0x40000000 | mpw_errno_from_errno();
|
||||
f.error = MacOS::ioErr;
|
||||
f.cookie = 0;
|
||||
}
|
||||
|
@ -26,6 +26,7 @@
|
||||
|
||||
#include "mpw.h"
|
||||
#include "mpw_internal.h"
|
||||
#include "mpw_errno.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
@ -81,7 +82,7 @@ namespace MPW
|
||||
{
|
||||
//f.count = 0;
|
||||
f.error = MacOS::ioErr; // ioErr
|
||||
d0 = errno_to_errno(errno);
|
||||
d0 = mpw_errno_from_errno();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -126,7 +127,7 @@ namespace MPW
|
||||
{
|
||||
//f.count = 0;
|
||||
f.error = MacOS::ioErr; // ioErr
|
||||
d0 = errno_to_errno(errno);
|
||||
d0 = mpw_errno_from_errno();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -52,7 +52,7 @@
|
||||
#include <toolbox/os.h>
|
||||
#include <toolbox/os_internal.h>
|
||||
|
||||
|
||||
using MacOS::macos_error_from_errno;
|
||||
|
||||
|
||||
namespace MPW
|
||||
@ -335,8 +335,8 @@ namespace MPW
|
||||
off_t rv = ::lseek(fd, offset, nativeWhence);
|
||||
if (rv < 0)
|
||||
{
|
||||
d0 = errno_to_errno(errno);
|
||||
f.error = OS::Internal::errno_to_oserr(errno);
|
||||
d0 = mpw_errno_from_errno();
|
||||
f.error = macos_error_from_errno();
|
||||
//perror(NULL);
|
||||
}
|
||||
else
|
||||
@ -375,8 +375,8 @@ namespace MPW
|
||||
[arg, &f](int fd, OS::Internal::FDEntry &e){
|
||||
int ok = ftruncate(fd, arg);
|
||||
if (ok == 0) return 0;
|
||||
f.error = OS::Internal::errno_to_oserr(errno);
|
||||
return errno_to_errno(errno);
|
||||
f.error = macos_error_from_errno();
|
||||
return (int)mpw_errno_from_errno();
|
||||
},
|
||||
[](int fd){
|
||||
return kEINVAL;
|
||||
|
@ -22,6 +22,7 @@ set(TOOLBOX_SRC
|
||||
pathnames.cpp
|
||||
utility.cpp
|
||||
fs_spec.cpp
|
||||
realpath.c
|
||||
)
|
||||
|
||||
|
||||
|
198
toolbox/mm.cpp
198
toolbox/mm.cpp
@ -73,7 +73,7 @@ namespace
|
||||
// map of handle -> size [? just use Ptr map?]
|
||||
std::map<uint32_t, HandleInfo> HandleMap;
|
||||
|
||||
inline uint16_t SetMemError(uint16_t error)
|
||||
inline int16_t SetMemError(int16_t error)
|
||||
{
|
||||
memoryWriteWord(error, MacOS::MemErr);
|
||||
return error;
|
||||
@ -284,9 +284,12 @@ namespace MM
|
||||
|
||||
// todo -- size 0 should have a ptr to differentiate
|
||||
// from purged.
|
||||
if (size)
|
||||
{
|
||||
ptr = (uint8_t *)mplite_malloc(&pool, size);
|
||||
|
||||
// PPCLink calls NewHandle(0) but expects a valid pointer
|
||||
// Assertion failed: *fHandle != NULL
|
||||
//if (size)
|
||||
//{
|
||||
ptr = (uint8_t *)mplite_malloc(&pool, size ? size : 1);
|
||||
if (!ptr)
|
||||
{
|
||||
HandleQueue.push_back(hh);
|
||||
@ -296,7 +299,7 @@ namespace MM
|
||||
|
||||
if (clear)
|
||||
std::memset(ptr, 0, size);
|
||||
}
|
||||
//}
|
||||
|
||||
// need a handle -> ptr map?
|
||||
HandleMap.emplace(std::make_pair(hh, HandleInfo(mcptr, size)));
|
||||
@ -394,6 +397,8 @@ namespace MM
|
||||
|
||||
uint16_t SetHandleSize(uint32_t handle, uint32_t newSize)
|
||||
{
|
||||
if (handle == 0) return SetMemError(MacOS::nilHandleErr);
|
||||
|
||||
const auto iter = HandleMap.find(handle);
|
||||
|
||||
if (iter == HandleMap.end()) return SetMemError(MacOS::memWZErr);
|
||||
@ -409,7 +414,14 @@ namespace MM
|
||||
// 1. - resizing to 0.
|
||||
if (!newSize)
|
||||
{
|
||||
if (info.locked) return SetMemError(MacOS::memLockedErr);
|
||||
if (info.locked)
|
||||
{
|
||||
//return SetMemError(MacOS::memLockedErr);
|
||||
|
||||
// ppclink resizes locked handles.
|
||||
info.size = 0;
|
||||
return SetMemError(0);
|
||||
}
|
||||
|
||||
// todo -- size 0 should have a ptr to differentiate
|
||||
// from purged.
|
||||
@ -562,6 +574,9 @@ namespace MM
|
||||
|
||||
uint16_t BlockMove(uint16_t trap)
|
||||
{
|
||||
// also implements BlockMoveData.
|
||||
// BlockMove will flush caches, BlockMoveData will not.
|
||||
|
||||
/*
|
||||
* on entry:
|
||||
* A0 Pointer to source
|
||||
@ -744,17 +759,9 @@ namespace MM
|
||||
|
||||
SetMemError(0);
|
||||
|
||||
// find the pointer base...
|
||||
// todo -- call lower bound, then iter-- ?
|
||||
for (const auto & iter : PtrMap)
|
||||
{
|
||||
if (sp >= iter.first && sp < iter.first + iter.second)
|
||||
{
|
||||
return sp - iter.first;
|
||||
}
|
||||
}
|
||||
// MemorySize is the top of the heap. stack is after it.
|
||||
|
||||
return 0;
|
||||
return sp - MemorySize;
|
||||
}
|
||||
|
||||
|
||||
@ -1037,9 +1044,21 @@ namespace MM
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* The trap dispatcher sets the condition codes before returning
|
||||
* from a trap by testing the low-order word of register D0 with
|
||||
* a TST.W instruction. Because the block size returned in D0 by
|
||||
* _GetHandleSize is a full 32-bit long word, the word-length
|
||||
* test sets the condition codes incorrectly in this case. To
|
||||
* branch on the contents of D0, use your own TST.L instruction
|
||||
* on return from the trap to test the full 32 bits of the register.
|
||||
*/
|
||||
|
||||
uint32_t hh = cpuGetAReg(0);
|
||||
|
||||
Log("%08x GetHandleSize(%08x)\n", trap, hh);
|
||||
Log("%04x GetHandleSize(%08x)\n", trap, hh);
|
||||
|
||||
if (hh == 0) return SetMemError(MacOS::nilHandleErr); // ????
|
||||
|
||||
auto iter = HandleMap.find(hh);
|
||||
|
||||
@ -1068,112 +1087,51 @@ namespace MM
|
||||
Log("%04x SetHandleSize(%08x, %08x)\n", trap, hh, newSize);
|
||||
|
||||
return Native::SetHandleSize(hh, newSize);
|
||||
}
|
||||
|
||||
#if 0
|
||||
auto iter = HandleMap.find(hh);
|
||||
uint32_t RecoverHandle(uint16_t trap)
|
||||
{
|
||||
// FUNCTION RecoverHandle (p: Ptr): Handle;
|
||||
|
||||
if (iter == HandleMap.end()) return SetMemError(MacOS::memWZErr);
|
||||
// todo -- if handle ptr is null, other logic?
|
||||
// todo -- if locked, can't move.
|
||||
|
||||
auto &info = iter->second;
|
||||
|
||||
// 0 - no change in size.
|
||||
if (info.size == newSize) return SetMemError(0);
|
||||
|
||||
uint32_t mcptr = info.address;
|
||||
uint8_t *ptr = mcptr + Memory;
|
||||
/*
|
||||
* on entry:
|
||||
* A0 Master pointer
|
||||
*
|
||||
* on exit:
|
||||
* A0 Handle to master pointer’s relocatable block
|
||||
* D0 Unchanged
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
// 1. - resizing to 0.
|
||||
if (!newSize)
|
||||
uint32_t p = cpuGetAReg(0);
|
||||
uint32_t hh = 0;
|
||||
|
||||
Log("%04x RecoverHandle(%08x)\n", trap, p);
|
||||
|
||||
uint16_t error = MacOS::memBCErr;
|
||||
for (const auto kv : HandleMap)
|
||||
{
|
||||
if (info.locked) return SetMemError(MacOS::memLockedErr);
|
||||
const HandleInfo &info = kv.second;
|
||||
|
||||
mplite_free(&pool, ptr);
|
||||
info.address = 0;
|
||||
info.size = 0;
|
||||
if (!info.address) continue;
|
||||
|
||||
memoryWriteLong(info.address, hh);
|
||||
return SetMemError(0);
|
||||
uint32_t begin = info.address;
|
||||
uint32_t end = info.address + info.size;
|
||||
if (!info.size) end++;
|
||||
if (p >= begin && p < end)
|
||||
{
|
||||
hh = kv.first;
|
||||
error = MacOS::noErr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. - resizing from 0.
|
||||
SetMemError(error);
|
||||
cpuSetAReg(0, hh);
|
||||
|
||||
if (!mcptr)
|
||||
{
|
||||
if (info.locked) return SetMemError(MacOS::memLockedErr);
|
||||
|
||||
ptr = (uint8_t *)mplite_malloc(&pool, newSize);
|
||||
if (!ptr) return SetMemError(MacOS::memFullErr);
|
||||
|
||||
mcptr = ptr - Memory;
|
||||
info.address = mcptr;
|
||||
info.size = newSize;
|
||||
|
||||
memoryWriteLong(info.address, hh);
|
||||
return SetMemError(0);
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < 2; ++i)
|
||||
{
|
||||
|
||||
// 3. - locked
|
||||
if (info.locked)
|
||||
{
|
||||
if (mplite_resize(&pool, ptr, mplite_roundup(&pool, newSize)) == MPLITE_OK)
|
||||
{
|
||||
info.size = newSize;
|
||||
return SetMemError(0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// 4. - resize.
|
||||
|
||||
ptr = (uint8_t *)mplite_realloc(&pool, ptr, mplite_roundup(&pool, newSize));
|
||||
|
||||
if (ptr)
|
||||
{
|
||||
mcptr = ptr - Memory;
|
||||
info.address = mcptr;
|
||||
info.size = newSize;
|
||||
|
||||
memoryWriteLong(info.address, hh);
|
||||
return SetMemError(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fprintf(stderr, "mplite_realloc failed.\n");
|
||||
Native::PrintMemoryStats();
|
||||
|
||||
|
||||
if (i > 0) return SetMemError(MacOS::memFullErr);
|
||||
|
||||
// purge...
|
||||
for (auto & kv : HandleMap)
|
||||
{
|
||||
uint32_t handle = kv.first;
|
||||
auto &info = kv.second;
|
||||
|
||||
if (handle == hh) continue;
|
||||
if (info.size && info.purgeable && !info.locked)
|
||||
{
|
||||
mplite_free(&pool, Memory + info.address);
|
||||
info.size = 0;
|
||||
info.address = 0;
|
||||
|
||||
// also need to update memory
|
||||
memoryWriteLong(0, handle);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return SetMemError(MacOS::memFullErr);
|
||||
#endif
|
||||
// return d0 register unchanged.
|
||||
return cpuGetDReg(0);
|
||||
}
|
||||
|
||||
|
||||
@ -1501,9 +1459,19 @@ namespace MM
|
||||
if (address) memoryWriteLong(0, address);
|
||||
|
||||
ToolReturn<4>(sp, mplite_maxmem(&pool));
|
||||
SetMemError(0); // not sure if this is correct. oh well.
|
||||
|
||||
return 0;
|
||||
return SetMemError(0);
|
||||
}
|
||||
|
||||
uint16_t TempFreeMem(void)
|
||||
{
|
||||
|
||||
// FUNCTION TempFreeMem: LongInt;
|
||||
|
||||
Log(" TempFreeMem()\n");
|
||||
|
||||
ToolReturn<4>(-1, mplite_freemem(&pool));
|
||||
|
||||
return SetMemError(0);
|
||||
}
|
||||
}
|
||||
|
@ -59,6 +59,8 @@ namespace MM
|
||||
uint16_t SetHandleSize(uint16_t);
|
||||
uint16_t SetPtrSize(uint16_t);
|
||||
|
||||
uint32_t RecoverHandle(uint16_t);
|
||||
|
||||
uint16_t HGetState(uint16_t trap);
|
||||
|
||||
uint16_t HLock(uint16_t trap);
|
||||
@ -88,6 +90,7 @@ namespace MM
|
||||
// OS Dispatch
|
||||
|
||||
uint16_t TempMaxMem(void);
|
||||
uint16_t TempFreeMem(void);
|
||||
}
|
||||
|
||||
|
||||
|
274
toolbox/os.cpp
274
toolbox/os.cpp
@ -52,11 +52,11 @@
|
||||
#include "os_internal.h"
|
||||
#include "toolbox.h"
|
||||
#include "stackframe.h"
|
||||
|
||||
#include "fs_spec.h"
|
||||
|
||||
using ToolBox::Log;
|
||||
|
||||
using OS::Internal::errno_to_oserr;
|
||||
using MacOS::macos_error_from_errno;
|
||||
|
||||
namespace {
|
||||
|
||||
@ -288,7 +288,7 @@ namespace OS
|
||||
|
||||
|
||||
int rv = OS::Internal::FDEntry::close(ioRefNum, true);
|
||||
if (rv < 0) d0 = errno_to_oserr(errno);
|
||||
if (rv < 0) d0 = macos_error_from_errno();
|
||||
else d0 = 0;
|
||||
|
||||
memoryWriteWord(d0, parm + 16);
|
||||
@ -324,7 +324,7 @@ namespace OS
|
||||
|
||||
if (fd < 0)
|
||||
{
|
||||
d0 = errno_to_oserr(errno);
|
||||
d0 = macos_error_from_errno();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -339,6 +339,31 @@ namespace OS
|
||||
|
||||
uint16_t Open(uint16_t trap)
|
||||
{
|
||||
|
||||
enum {
|
||||
/* IOParam */
|
||||
_qLink = 0,
|
||||
_qType = 4,
|
||||
_ioTrap = 6,
|
||||
_ioCmdAddr = 8,
|
||||
_ioCompletion = 12,
|
||||
_ioResult = 16,
|
||||
_ioNamePtr = 18,
|
||||
_ioVRefNum = 22,
|
||||
_ioRefNum = 24,
|
||||
_ioVersNum = 26,
|
||||
_ioPermssn = 27,
|
||||
_ioMisc = 28,
|
||||
_ioBuffer = 32,
|
||||
_ioReqCount = 36,
|
||||
_ioActCount = 40,
|
||||
_ioPosMode = 44,
|
||||
_ioPosOffset = 46,
|
||||
|
||||
_ioDirID = 48,
|
||||
|
||||
};
|
||||
|
||||
uint32_t d0;
|
||||
|
||||
int fd;
|
||||
@ -348,25 +373,54 @@ namespace OS
|
||||
|
||||
Log("%04x Open(%08x)\n", trap, parm);
|
||||
|
||||
uint32_t namePtr = memoryReadLong(parm + 18);
|
||||
uint32_t namePtr = memoryReadLong(parm + _ioNamePtr);
|
||||
uint32_t ioDirID = memoryReadLong(parm + _ioDirID);
|
||||
|
||||
uint8_t ioPermission = memoryReadByte(parm + 27);
|
||||
uint8_t ioPermission = memoryReadByte(parm + _ioPermssn);
|
||||
|
||||
std::string sname = ToolBox::ReadPString(namePtr, true);
|
||||
sname = FSSpecManager::ExpandPath(sname, ioDirID);
|
||||
|
||||
|
||||
|
||||
fd = Internal::FDEntry::open(sname, ioPermission, false);
|
||||
d0 = fd < 0 ? fd : 0;
|
||||
if (fd >= 0)
|
||||
{
|
||||
memoryWriteWord(fd, parm + 24);
|
||||
memoryWriteWord(fd, parm + _ioRefNum);
|
||||
}
|
||||
|
||||
memoryWriteWord(d0, parm + 16);
|
||||
memoryWriteWord(d0, parm + _ioResult);
|
||||
return d0;
|
||||
}
|
||||
|
||||
uint16_t OpenRF(uint16_t trap)
|
||||
{
|
||||
|
||||
enum {
|
||||
/* IOParam */
|
||||
_qLink = 0,
|
||||
_qType = 4,
|
||||
_ioTrap = 6,
|
||||
_ioCmdAddr = 8,
|
||||
_ioCompletion = 12,
|
||||
_ioResult = 16,
|
||||
_ioNamePtr = 18,
|
||||
_ioVRefNum = 22,
|
||||
_ioRefNum = 24,
|
||||
_ioVersNum = 26,
|
||||
_ioPermssn = 27,
|
||||
_ioMisc = 28,
|
||||
_ioBuffer = 32,
|
||||
_ioReqCount = 36,
|
||||
_ioActCount = 40,
|
||||
_ioPosMode = 44,
|
||||
_ioPosOffset = 46,
|
||||
|
||||
_ioDirID = 48,
|
||||
|
||||
};
|
||||
|
||||
uint32_t d0;
|
||||
|
||||
int fd;
|
||||
@ -376,20 +430,22 @@ namespace OS
|
||||
|
||||
Log("%04x OpenRF(%08x)\n", trap, parm);
|
||||
|
||||
uint32_t namePtr = memoryReadLong(parm + 18);
|
||||
uint32_t namePtr = memoryReadLong(parm + _ioNamePtr);
|
||||
uint32_t ioDirID = memoryReadLong(parm + _ioDirID);
|
||||
|
||||
uint8_t ioPermission = memoryReadByte(parm + 27);
|
||||
uint8_t ioPermission = memoryReadByte(parm + _ioPermssn);
|
||||
|
||||
std::string sname = ToolBox::ReadPString(namePtr, true);
|
||||
sname = FSSpecManager::ExpandPath(sname, ioDirID);
|
||||
|
||||
fd = Internal::FDEntry::open(sname, ioPermission, true);
|
||||
d0 = fd < 0 ? fd : 0;
|
||||
if (fd >= 0)
|
||||
{
|
||||
memoryWriteWord(fd, parm + 24);
|
||||
memoryWriteWord(fd, parm + _ioRefNum);
|
||||
}
|
||||
|
||||
memoryWriteWord(d0, parm + 16);
|
||||
memoryWriteWord(d0, parm + _ioResult);
|
||||
return d0;
|
||||
}
|
||||
|
||||
@ -443,7 +499,7 @@ namespace OS
|
||||
}
|
||||
if (count < 0)
|
||||
{
|
||||
d0 = errno_to_oserr(errno);
|
||||
d0 = macos_error_from_errno();
|
||||
}
|
||||
|
||||
memoryWriteLong(pos, parm + 46); // new offset.
|
||||
@ -499,7 +555,7 @@ namespace OS
|
||||
|
||||
if (count < 0)
|
||||
{
|
||||
d0 = errno_to_oserr(errno);
|
||||
d0 = macos_error_from_errno();
|
||||
}
|
||||
|
||||
memoryWriteLong(pos, parm + 46); // new offset.
|
||||
@ -536,7 +592,7 @@ namespace OS
|
||||
|
||||
int ok = ::unlink(sname.c_str());
|
||||
if (ok < 0)
|
||||
d0 = errno_to_oserr(errno);
|
||||
d0 = macos_error_from_errno();
|
||||
else
|
||||
d0 = 0;
|
||||
|
||||
@ -560,7 +616,7 @@ namespace OS
|
||||
|
||||
if (::fstat(ioRefNum, &st) < 0)
|
||||
{
|
||||
d0 = errno_to_oserr(errno);
|
||||
d0 = macos_error_from_errno();
|
||||
size = 0;
|
||||
}
|
||||
else
|
||||
@ -589,7 +645,7 @@ namespace OS
|
||||
|
||||
int rv = ::ftruncate(ioRefNum, ioMisc);
|
||||
|
||||
d0 = rv < 0 ? errno_to_oserr(errno) : 0;
|
||||
d0 = rv < 0 ? macos_error_from_errno() : 0;
|
||||
|
||||
memoryWriteWord(d0, parm + 16);
|
||||
return d0;
|
||||
@ -609,7 +665,7 @@ namespace OS
|
||||
int rv = ::lseek(ioRefNum, 0, SEEK_CUR);
|
||||
if (rv < 0)
|
||||
{
|
||||
d0 = errno_to_oserr(errno);
|
||||
d0 = macos_error_from_errno();
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -768,7 +824,7 @@ namespace OS
|
||||
|
||||
if (::stat(sname.c_str(), &st) < 0)
|
||||
{
|
||||
d0 = errno_to_oserr(errno);
|
||||
d0 = macos_error_from_errno();
|
||||
|
||||
memoryWriteWord(d0, parm + 16);
|
||||
return d0;
|
||||
@ -871,7 +927,7 @@ namespace OS
|
||||
ok = ::stat(sname.c_str(), &st);
|
||||
if (ok < 0)
|
||||
{
|
||||
d0 = errno_to_oserr(errno);
|
||||
d0 = macos_error_from_errno();
|
||||
memoryWriteWord(d0, parm + 16);
|
||||
return d0;
|
||||
}
|
||||
@ -1197,4 +1253,182 @@ namespace OS
|
||||
return MacOS::prWrErr;
|
||||
}
|
||||
|
||||
#pragma mark - Timer
|
||||
|
||||
struct TimerEntry {
|
||||
uint32_t tmTaskPtr = 0; // address of the queue. passed back in A1.
|
||||
uint32_t tmAddr = 0;
|
||||
bool extended = false;
|
||||
bool active = false;
|
||||
|
||||
std::chrono::time_point<std::chrono::steady_clock> when;
|
||||
|
||||
TimerEntry(uint32_t a, uint32_t b) : tmTaskPtr(a), tmAddr(b)
|
||||
{}
|
||||
};
|
||||
|
||||
// heap sorted by next task to run?
|
||||
static std::deque<TimerEntry> TimerQueue;
|
||||
|
||||
namespace TMTask {
|
||||
enum {
|
||||
_qLink = 0,
|
||||
_qType = 4,
|
||||
_tmAddr = 6,
|
||||
_tmCount = 10,
|
||||
_tmWakeUp = 14,
|
||||
_tmReserved = 18
|
||||
};
|
||||
}
|
||||
|
||||
uint16_t InsTime(uint16_t trap)
|
||||
{
|
||||
// PROCEDURE InsTime (tmTaskPtr: QElemPtr);
|
||||
|
||||
// this adds an entry to the queue but does not schedule it.
|
||||
|
||||
/*
|
||||
* on entry
|
||||
* A0 Address of the task record
|
||||
*
|
||||
* on exit
|
||||
* D0 Result code
|
||||
*/
|
||||
|
||||
using namespace TMTask;
|
||||
|
||||
uint32_t tmTaskPtr = cpuGetAReg(0);
|
||||
|
||||
Log("%04x InsTime(%08x)\n", trap, tmTaskPtr);
|
||||
|
||||
if (tmTaskPtr)
|
||||
{
|
||||
memoryWriteLong(0, tmTaskPtr + _qLink);
|
||||
memoryWriteWord(0, tmTaskPtr + _qType);
|
||||
memoryWriteLong(0, tmTaskPtr + _tmCount);
|
||||
memoryWriteLong(0, tmTaskPtr + _tmWakeUp);
|
||||
memoryWriteLong(0, tmTaskPtr + _tmReserved);
|
||||
|
||||
TimerQueue.emplace_back(tmTaskPtr, memoryReadLong(tmTaskPtr + _tmAddr));
|
||||
}
|
||||
|
||||
return MacOS::noErr;
|
||||
}
|
||||
|
||||
uint16_t PrimeTime(uint16_t trap)
|
||||
{
|
||||
// PROCEDURE PrimeTime (tmTaskPtr: QElemPtr; count: LongInt);
|
||||
// this activates an entry.
|
||||
|
||||
/*
|
||||
* on entry
|
||||
* A0 Address of the task record
|
||||
* D0 Specified delay time (long)
|
||||
*
|
||||
* on exit
|
||||
* D0 Result code
|
||||
*/
|
||||
|
||||
using namespace TMTask;
|
||||
|
||||
uint32_t tmTaskPtr = cpuGetAReg(0);
|
||||
uint32_t count = cpuGetDReg(0);
|
||||
|
||||
Log("%04x PrimeTime(%08x, %08x)\n", trap, tmTaskPtr, count);
|
||||
|
||||
if (tmTaskPtr)
|
||||
{
|
||||
auto iter = std::find_if(TimerQueue.begin(), TimerQueue.end(), [tmTaskPtr](const TimerEntry &e){
|
||||
return e.tmTaskPtr == tmTaskPtr;
|
||||
});
|
||||
|
||||
if (iter != TimerQueue.end() && !iter->active)
|
||||
{
|
||||
auto now = std::chrono::steady_clock::now();
|
||||
|
||||
iter->active = true;
|
||||
|
||||
if (count == 0) {
|
||||
// retain the original time or set it to now.
|
||||
iter->when = std::max(now, iter->when);
|
||||
}
|
||||
else
|
||||
{
|
||||
int64_t micro;
|
||||
if (count < 0x80000000)
|
||||
micro = count * 1000;
|
||||
else
|
||||
micro = -(int32_t)count;
|
||||
|
||||
|
||||
iter->when = now + std::chrono::microseconds(micro);
|
||||
|
||||
}
|
||||
memoryWriteWord(tmTaskPtr + _qType, 0x8000);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return MacOS::noErr;
|
||||
|
||||
}
|
||||
|
||||
uint16_t RmvTime(uint16_t trap)
|
||||
{
|
||||
// PROCEDURE RmvTime (tmTaskPtr: QElemPtr);
|
||||
|
||||
// unschedule (but not actually remove)
|
||||
|
||||
/*
|
||||
* on entry
|
||||
* A0 Address of the task record
|
||||
*
|
||||
* on exit
|
||||
* D0 Result code
|
||||
*/
|
||||
|
||||
using namespace TMTask;
|
||||
|
||||
uint32_t tmTaskPtr = cpuGetAReg(0);
|
||||
|
||||
Log("%04x RmvTime(%08x)\n", trap, tmTaskPtr);
|
||||
|
||||
if (tmTaskPtr)
|
||||
{
|
||||
auto iter = std::find_if(TimerQueue.begin(), TimerQueue.end(), [tmTaskPtr](const TimerEntry &e){
|
||||
return e.tmTaskPtr == tmTaskPtr;
|
||||
});
|
||||
|
||||
if (iter != TimerQueue.end())
|
||||
{
|
||||
uint32_t count = 0;
|
||||
if (iter->active)
|
||||
{
|
||||
iter->active = false;
|
||||
|
||||
|
||||
// update tmCount to the amount of time remaining.
|
||||
// uses negative microseconds
|
||||
// or positive milliseconds.
|
||||
|
||||
auto now = std::chrono::steady_clock::now();
|
||||
|
||||
int64_t micro = std::chrono::duration_cast< std::chrono::microseconds >(iter->when - now).count();
|
||||
|
||||
if (micro < 0)
|
||||
count = 0;
|
||||
else if (micro < 0x80000000)
|
||||
count = -micro;
|
||||
else
|
||||
count = micro / 10000;
|
||||
}
|
||||
|
||||
memoryWriteWord(tmTaskPtr + _qType, 0);
|
||||
memoryWriteLong(tmTaskPtr + _tmCount, count);
|
||||
}
|
||||
}
|
||||
|
||||
return MacOS::noErr;
|
||||
}
|
||||
|
||||
}
|
17
toolbox/os.h
17
toolbox/os.h
@ -9,11 +9,13 @@ namespace OS
|
||||
{
|
||||
|
||||
enum {
|
||||
fsCurPerm = 0,
|
||||
fsRdPerm = 1,
|
||||
fsWrPerm = 2,
|
||||
fsRdWrPerm = 3,
|
||||
fsRdWrShPerm = 4,
|
||||
fsCurPerm = 0x00,
|
||||
fsRdPerm = 0x01,
|
||||
fsWrPerm = 0x02,
|
||||
fsRdWrPerm = 0x03,
|
||||
fsRdWrShPerm = 0x04,
|
||||
fsRdDenyPerm = 0x10,
|
||||
fsWrDenyPerm = 0x20
|
||||
};
|
||||
|
||||
enum {
|
||||
@ -98,6 +100,11 @@ namespace OS
|
||||
uint16_t ReadXPRam(uint16_t trap);
|
||||
uint16_t WriteXPRam(uint16_t trap);
|
||||
|
||||
uint16_t InsTime(uint16_t trap);
|
||||
uint16_t InsXTime(uint16_t trap);
|
||||
uint16_t PrimeTime(uint16_t trap);
|
||||
uint16_t RmvTime(uint16_t trap);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -56,7 +56,7 @@
|
||||
|
||||
using ToolBox::Log;
|
||||
|
||||
using OS::Internal::errno_to_oserr;
|
||||
using MacOS::macos_error_from_errno;
|
||||
|
||||
|
||||
|
||||
@ -155,7 +155,7 @@ namespace OS {
|
||||
|
||||
if (::stat(sname.c_str(), &st) < 0)
|
||||
{
|
||||
d0 = errno_to_oserr(errno);
|
||||
d0 = macos_error_from_errno();
|
||||
|
||||
memoryWriteWord(d0, parm + _ioResult);
|
||||
return d0;
|
||||
@ -279,7 +279,7 @@ namespace OS {
|
||||
ok = ::stat(sname.c_str(), &st);
|
||||
if (ok < 0)
|
||||
{
|
||||
d0 = errno_to_oserr(errno);
|
||||
d0 = macos_error_from_errno();
|
||||
memoryWriteWord(d0, parm + _ioResult);
|
||||
return d0;
|
||||
}
|
||||
|
@ -65,6 +65,7 @@ namespace OS {
|
||||
|
||||
std::map<uint32_t, uint32_t> GestaltMap = {
|
||||
{'alis', 1}, // Alias Manager
|
||||
{'tmgr', 2}, // Time Manager (2 = revised, 3 = extended.)
|
||||
};
|
||||
|
||||
uint16_t Gestalt(uint16_t trap)
|
||||
|
@ -55,7 +55,7 @@
|
||||
|
||||
using ToolBox::Log;
|
||||
|
||||
using OS::Internal::errno_to_oserr;
|
||||
using MacOS::macos_error_from_errno;
|
||||
|
||||
namespace OS {
|
||||
|
||||
@ -194,7 +194,7 @@ namespace OS {
|
||||
|
||||
if (::stat(sname.c_str(), &st) < 0)
|
||||
{
|
||||
d0 = errno_to_oserr(errno);
|
||||
d0 = macos_error_from_errno();
|
||||
|
||||
memoryWriteWord(d0, parm + _ioResult);
|
||||
return d0;
|
||||
@ -353,7 +353,7 @@ namespace OS {
|
||||
ok = ::stat(sname.c_str(), &st);
|
||||
if (ok < 0)
|
||||
{
|
||||
d0 = errno_to_oserr(errno);
|
||||
d0 = macos_error_from_errno();
|
||||
memoryWriteWord(d0, parm + _ioResult);
|
||||
return d0;
|
||||
}
|
||||
@ -396,6 +396,21 @@ namespace OS {
|
||||
}
|
||||
|
||||
|
||||
uint16_t PBHOpenDeny(uint32_t paramBlock)
|
||||
{
|
||||
// AccessParam.ioDenyModes short word matches
|
||||
// up with the permission byte considering it's big-endian.
|
||||
|
||||
Log(" PBHOpenDeny\n");
|
||||
return OS::Open(0xa000);
|
||||
}
|
||||
|
||||
uint16_t PBHOpenRFDeny(uint32_t paramBlock)
|
||||
{
|
||||
Log(" PBHOpenRFDeny\n");
|
||||
return OS::OpenRF(0xa000);
|
||||
}
|
||||
|
||||
uint16_t FSDispatch(uint16_t trap)
|
||||
{
|
||||
|
||||
@ -449,6 +464,12 @@ namespace OS {
|
||||
case 0x001a:
|
||||
return PBHOpenDF(paramBlock);
|
||||
|
||||
case 0x0038:
|
||||
return PBHOpenDeny(paramBlock);
|
||||
|
||||
case 0x0039:
|
||||
return PBHOpenRFDeny(paramBlock);
|
||||
|
||||
default:
|
||||
fprintf(stderr, "HFSDispatch: selector %08x not implemented\n",
|
||||
selector);
|
||||
|
@ -35,6 +35,8 @@
|
||||
#include <sys/xattr.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/paths.h>
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
@ -48,14 +50,18 @@
|
||||
#include <macos/errors.h>
|
||||
|
||||
#include "os.h"
|
||||
#include "rm.h"
|
||||
#include "os_internal.h"
|
||||
#include "toolbox.h"
|
||||
#include "stackframe.h"
|
||||
#include "fs_spec.h"
|
||||
|
||||
using ToolBox::Log;
|
||||
using OS::Internal::errno_to_oserr;
|
||||
using MacOS::macos_error_from_errno;
|
||||
|
||||
extern "C" {
|
||||
char * fs_spec_realpath(const char * __restrict path, char * __restrict resolved);
|
||||
}
|
||||
|
||||
namespace OS {
|
||||
|
||||
@ -71,6 +77,25 @@ namespace OS {
|
||||
// MacOS: -> { -1, 1, "MacOS" }
|
||||
// MacOS:dumper -> {-1, 2 "dumper"}
|
||||
|
||||
std::string realpath(const std::string &path)
|
||||
{
|
||||
char buffer[PATH_MAX + 1];
|
||||
|
||||
// FSSpecs are valid for non-existant files
|
||||
// but not non-existant directories.
|
||||
// realpath does not behave in such a manner.
|
||||
|
||||
// expand the path. Also handles relative paths.
|
||||
char *cp = ::fs_spec_realpath(path.c_str(), buffer);
|
||||
if (!cp)
|
||||
{
|
||||
fprintf(stderr, "realpath failed %s\n", path.c_str());
|
||||
return "";
|
||||
}
|
||||
|
||||
return std::string(cp);
|
||||
}
|
||||
|
||||
uint16_t FSMakeFSSpec(void)
|
||||
{
|
||||
// FSMakeFSSpec(vRefNum: Integer; dirID: LongInt; fileName: Str255; VAR spec: FSSpec): OSErr;
|
||||
@ -87,8 +112,6 @@ namespace OS {
|
||||
uint32_t spec;
|
||||
|
||||
|
||||
|
||||
|
||||
StackFrame<14>(vRefNum, dirID, fileName, spec);
|
||||
|
||||
std::string sname = ToolBox::ReadPString(fileName, true);
|
||||
@ -113,49 +136,38 @@ namespace OS {
|
||||
bool absolute = sname.length() ? sname[0] == '/' : false;
|
||||
if (absolute || (vRefNum == 0 && dirID == 0))
|
||||
{
|
||||
char buffer[PATH_MAX + 1];
|
||||
|
||||
// TODO -- FSSpecs are valid for non-existant files
|
||||
// but not non-existant directories.
|
||||
// realpath does not behave in such a manner.
|
||||
|
||||
// expand the path. Also handles relative paths.
|
||||
char *cp = realpath(sname.c_str(), buffer);
|
||||
if (!cp)
|
||||
{
|
||||
std::memset(memoryPointer(spec), 0, 8);
|
||||
return MacOS::mFulErr;
|
||||
}
|
||||
|
||||
std::string leaf;
|
||||
std::string path;
|
||||
int parentID;
|
||||
|
||||
|
||||
path.assign(cp);
|
||||
|
||||
// if sname is null then the target is the default directory...
|
||||
// so this should be ok.
|
||||
path = realpath(sname);
|
||||
if (path.empty())
|
||||
{
|
||||
std::memset(memoryPointer(spec), 0, 8);
|
||||
return MacOS::mFulErr;
|
||||
}
|
||||
|
||||
int pos = path.find_last_of('/');
|
||||
if (pos == path.npos)
|
||||
{
|
||||
// ? should never happen...
|
||||
std::swap(leaf, path);
|
||||
// file is relative to cwd.
|
||||
leaf = std::move(path);
|
||||
parentID = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
leaf = path.substr(pos + 1);
|
||||
path = path.substr(0, pos + 1); // include the /
|
||||
parentID = FSSpecManager::IDForPath(path, true);
|
||||
}
|
||||
|
||||
int parentID = FSSpecManager::IDForPath(path, true);
|
||||
|
||||
memoryWriteWord(vRefNum, spec + 0);
|
||||
memoryWriteLong(parentID, spec + 2);
|
||||
// write the filename...
|
||||
ToolBox::WritePString(spec + 6, leaf);
|
||||
|
||||
// TODO -- return fnf if file does not exist.
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -177,6 +189,7 @@ namespace OS {
|
||||
|
||||
uint32_t spec;
|
||||
uint32_t finderInfo;
|
||||
uint16_t d0;
|
||||
|
||||
StackFrame<8>(spec, finderInfo);
|
||||
|
||||
@ -190,9 +203,8 @@ namespace OS {
|
||||
Log(" FSpGetFInfo(%s, %08x)\n", path.c_str(), finderInfo);
|
||||
|
||||
|
||||
|
||||
Internal::GetFinderInfo(path, memoryPointer(finderInfo), false);
|
||||
return 0;
|
||||
d0 = Internal::GetFinderInfo(path, memoryPointer(finderInfo), false);
|
||||
return d0;
|
||||
}
|
||||
|
||||
uint16_t FSpSetFInfo()
|
||||
@ -201,7 +213,7 @@ namespace OS {
|
||||
|
||||
uint32_t spec;
|
||||
uint32_t finderInfo;
|
||||
uint16_t d0;
|
||||
uint16_t d0 = 0;
|
||||
|
||||
StackFrame<8>(spec, finderInfo);
|
||||
|
||||
@ -222,12 +234,19 @@ namespace OS {
|
||||
|
||||
|
||||
|
||||
|
||||
uint16_t ResolveAliasFile()
|
||||
{
|
||||
// FUNCTION ResolveAliasFile (VAR theSpec: FSSpec;
|
||||
// resolveAliasChains: Boolean;
|
||||
// VAR targetIsFolder: Boolean;
|
||||
// VAR wasAliased: Boolean): OSErr;
|
||||
|
||||
uint32_t spec;
|
||||
uint16_t resolveAliasChains;
|
||||
uint32_t targetIsFolder;
|
||||
uint32_t wasAliased;
|
||||
uint16_t d0 = 0;
|
||||
|
||||
StackFrame<14>(spec, resolveAliasChains, targetIsFolder, wasAliased);
|
||||
|
||||
@ -238,23 +257,22 @@ namespace OS {
|
||||
|
||||
path += leaf;
|
||||
|
||||
Log(" ResolveAliasFile(%s)\n", path.c_str());
|
||||
Log(" ResolveAliasFile(%s)\n", path.c_str());
|
||||
|
||||
struct stat st;
|
||||
int rv;
|
||||
|
||||
rv = ::stat(path.c_str(), &st);
|
||||
if (rv < 0) return errno_to_oserr(errno);
|
||||
if (rv < 0)
|
||||
return macos_error_from_errno();
|
||||
|
||||
if (targetIsFolder)
|
||||
{
|
||||
memoryWriteWord(S_ISDIR(st.st_mode) ? 1 : 0, targetIsFolder);
|
||||
}
|
||||
memoryWriteWord(S_ISDIR(st.st_mode) ? 1 : 0, targetIsFolder);
|
||||
|
||||
// don't bother pretending a soft link is an alias.
|
||||
if (wasAliased) memoryWriteWord(0, wasAliased);
|
||||
|
||||
return 0;
|
||||
return d0;
|
||||
}
|
||||
|
||||
|
||||
@ -262,7 +280,26 @@ namespace OS {
|
||||
uint16_t HighLevelHFSDispatch(uint16_t trap)
|
||||
{
|
||||
|
||||
/*
|
||||
* $0001 FSMakeFSSpec
|
||||
* $0002 FSpOpenDF
|
||||
* $0003 FSpOpenRF
|
||||
* $0004 FSpCreate
|
||||
* $0005 FSpDirCreate
|
||||
* $0006 FSpDelete
|
||||
* $0007 FSpGetFInfo
|
||||
* $0008 FSpSetFInfo
|
||||
* $0009 FSpSetFLock
|
||||
* $000A FSpRstFLock
|
||||
* $000B FSpRename
|
||||
* $000C FSpCatMove
|
||||
* $000D FSpOpenResFile
|
||||
* $000E FSpCreateResFile
|
||||
* $000F FSpExchangeFiles
|
||||
*/
|
||||
|
||||
uint16_t selector;
|
||||
uint16_t d0;
|
||||
|
||||
selector = cpuGetDReg(0) & 0xffff;
|
||||
Log("%04x HighLevelHFSDispatch(%04x)\n", trap, selector);
|
||||
@ -270,23 +307,34 @@ namespace OS {
|
||||
switch (selector)
|
||||
{
|
||||
case 0x0001:
|
||||
return FSMakeFSSpec();
|
||||
d0 = FSMakeFSSpec();
|
||||
break;
|
||||
|
||||
case 0x0007:
|
||||
return FSpGetFInfo();
|
||||
d0 = FSpGetFInfo();
|
||||
break;
|
||||
|
||||
case 0x0008:
|
||||
return FSpSetFInfo();
|
||||
d0 = FSpSetFInfo();
|
||||
break;
|
||||
|
||||
case 0x000d:
|
||||
d0 = RM::FSpOpenResFile();
|
||||
break;
|
||||
|
||||
case 0x000e:
|
||||
d0 = RM::FSpCreateResFile();
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "selector %04x not yet supported\n", selector);
|
||||
fprintf(stderr, "HighLevelHFSDispatch selector %04x not yet supported\n", selector);
|
||||
exit(1);
|
||||
|
||||
}
|
||||
|
||||
ToolReturn<2>(-1, d0);
|
||||
return d0;
|
||||
|
||||
}
|
||||
|
||||
uint16_t HGetVol(uint16_t trap)
|
||||
|
@ -41,38 +41,11 @@
|
||||
#include <machine/endian.h>
|
||||
|
||||
using ToolBox::Log;
|
||||
using MacOS::macos_error_from_errno;
|
||||
|
||||
namespace OS { namespace Internal {
|
||||
|
||||
|
||||
uint16_t errno_to_oserr(int xerrno)
|
||||
{
|
||||
|
||||
switch (xerrno)
|
||||
{
|
||||
case 0: return 0;
|
||||
case EBADF: return MacOS::rfNumErr;
|
||||
case EIO: return MacOS::ioErr;
|
||||
case EACCES: return MacOS::permErr;
|
||||
case ENOENT: return MacOS::fnfErr;
|
||||
case ENOTDIR: return MacOS::dirNFErr;
|
||||
case EISDIR: return MacOS::notAFileErr;
|
||||
case ENOTSUP: return MacOS::extFSErr;
|
||||
case EROFS: return MacOS::wPrErr;
|
||||
|
||||
case EEXIST: return MacOS::dupFNErr;
|
||||
|
||||
case EBUSY: return MacOS::fBsyErr;
|
||||
|
||||
case EDQUOT: return MacOS::dskFulErr;
|
||||
case ENOSPC: return MacOS::dskFulErr;
|
||||
|
||||
|
||||
default:
|
||||
return MacOS::ioErr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@ -126,7 +99,7 @@ namespace OS { namespace Internal {
|
||||
{
|
||||
case ENOENT:
|
||||
case EACCES:
|
||||
return errno_to_oserr(errno);
|
||||
return macos_error_from_errno();
|
||||
}
|
||||
|
||||
// check for prodos ftype/auxtype
|
||||
@ -268,7 +241,7 @@ namespace OS { namespace Internal {
|
||||
{
|
||||
case ENOENT:
|
||||
case EACCES:
|
||||
return errno_to_oserr(errno);
|
||||
return macos_error_from_errno();
|
||||
}
|
||||
}
|
||||
std::memmove(buffer, info, 16);
|
||||
@ -291,7 +264,7 @@ namespace OS { namespace Internal {
|
||||
}
|
||||
|
||||
rv = ::setxattr(pathName.c_str(), XATTR_FINDERINFO_NAME, buffer, 32, 0, 0);
|
||||
if (rv < 0) return errno_to_oserr(errno);
|
||||
if (rv < 0) return macos_error_from_errno();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -318,7 +291,7 @@ namespace OS { namespace Internal {
|
||||
}
|
||||
|
||||
rv = ::lseek(refNum, offset, mode);
|
||||
if (rv < 0) return errno_to_oserr(errno);
|
||||
if (rv < 0) return macos_error_from_errno();
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -470,8 +443,14 @@ namespace OS { namespace Internal {
|
||||
if (filename.empty()) return MacOS::bdNamErr;
|
||||
|
||||
int access = 0;
|
||||
if (ioPermission != 0x33) ioPermission &= ~0x30; // drop deny read/write
|
||||
switch(ioPermission)
|
||||
{
|
||||
case 0x33:
|
||||
// PBHOpenDeny exclusive access.
|
||||
access = O_RDWR | O_CREAT; // | O_EXCL;
|
||||
break;
|
||||
|
||||
case fsWrPerm:
|
||||
case fsRdWrPerm:
|
||||
case fsRdWrShPerm:
|
||||
@ -492,7 +471,7 @@ namespace OS { namespace Internal {
|
||||
|
||||
Log(" open(%s, %04x)\n", xname.c_str(), access);
|
||||
|
||||
fd = ::open(xname.c_str(), access);
|
||||
fd = ::open(xname.c_str(), access, 0666);
|
||||
if (fd < 0 && ioPermission == fsCurPerm && errno == EACCES)
|
||||
{
|
||||
fd = ::open(xname.c_str(), O_RDONLY);
|
||||
@ -500,7 +479,7 @@ namespace OS { namespace Internal {
|
||||
|
||||
if (fd < 0)
|
||||
{
|
||||
return errno_to_oserr(errno);
|
||||
return macos_error_from_errno();
|
||||
}
|
||||
|
||||
// allocate the fd entry
|
||||
|
@ -6,8 +6,6 @@
|
||||
|
||||
namespace OS { namespace Internal {
|
||||
|
||||
uint16_t errno_to_oserr(int xerrno);
|
||||
|
||||
uint16_t GetFinderInfo(const std::string &pathname, void *info, bool extended);
|
||||
uint16_t SetFinderInfo(const std::string &pathname, void *info, bool extended);
|
||||
|
||||
|
253
toolbox/realpath.c
Normal file
253
toolbox/realpath.c
Normal file
@ -0,0 +1,253 @@
|
||||
/*
|
||||
* Copyright (c) 2003 Constantin S. Svintsoff <kostik@iclub.nsu.ru>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The names of the authors may not be used to endorse or promote
|
||||
* products derived from this software without specific prior written
|
||||
* permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
static char sccsid[] = "@(#)realpath.c 8.1 (Berkeley) 2/16/94";
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
//#include "namespace.h"
|
||||
#include <sys/param.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
//#include "un-namespace.h"
|
||||
|
||||
#define FS_SPEC
|
||||
|
||||
/*
|
||||
* Find the real name of path, by removing all ".", ".." and symlink
|
||||
* components. Returns (resolved) on success, or (NULL) on failure,
|
||||
* in which case the path which caused trouble is left in (resolved).
|
||||
*/
|
||||
|
||||
#ifdef FS_SPEC
|
||||
char *
|
||||
fs_spec_realpath(const char * __restrict path, char * __restrict resolved)
|
||||
#else
|
||||
char *
|
||||
realpath(const char * __restrict path, char * __restrict resolved)
|
||||
#endif
|
||||
{
|
||||
struct stat sb;
|
||||
char *p, *q, *s;
|
||||
size_t left_len, resolved_len;
|
||||
unsigned symlinks;
|
||||
int m, slen;
|
||||
char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX];
|
||||
|
||||
#ifdef FS_SPEC
|
||||
int serrno = errno;
|
||||
#endif
|
||||
|
||||
if (path == NULL) {
|
||||
errno = EINVAL;
|
||||
return (NULL);
|
||||
}
|
||||
if (path[0] == '\0') {
|
||||
errno = ENOENT;
|
||||
return (NULL);
|
||||
}
|
||||
if (resolved == NULL) {
|
||||
resolved = malloc(PATH_MAX);
|
||||
if (resolved == NULL)
|
||||
return (NULL);
|
||||
m = 1;
|
||||
} else
|
||||
m = 0;
|
||||
symlinks = 0;
|
||||
if (path[0] == '/') {
|
||||
resolved[0] = '/';
|
||||
resolved[1] = '\0';
|
||||
if (path[1] == '\0')
|
||||
return (resolved);
|
||||
resolved_len = 1;
|
||||
left_len = strlcpy(left, path + 1, sizeof(left));
|
||||
} else {
|
||||
if (getcwd(resolved, PATH_MAX) == NULL) {
|
||||
if (m)
|
||||
free(resolved);
|
||||
else {
|
||||
resolved[0] = '.';
|
||||
resolved[1] = '\0';
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
resolved_len = strlen(resolved);
|
||||
left_len = strlcpy(left, path, sizeof(left));
|
||||
}
|
||||
if (left_len >= sizeof(left) || resolved_len >= PATH_MAX) {
|
||||
if (m)
|
||||
free(resolved);
|
||||
errno = ENAMETOOLONG;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Iterate over path components in `left'.
|
||||
*/
|
||||
while (left_len != 0) {
|
||||
/*
|
||||
* Extract the next path component and adjust `left'
|
||||
* and its length.
|
||||
*/
|
||||
p = strchr(left, '/');
|
||||
s = p ? p : left + left_len;
|
||||
if (s - left >= sizeof(next_token)) {
|
||||
if (m)
|
||||
free(resolved);
|
||||
errno = ENAMETOOLONG;
|
||||
return (NULL);
|
||||
}
|
||||
memcpy(next_token, left, s - left);
|
||||
next_token[s - left] = '\0';
|
||||
left_len -= s - left;
|
||||
if (p != NULL)
|
||||
memmove(left, s + 1, left_len + 1);
|
||||
if (resolved[resolved_len - 1] != '/') {
|
||||
if (resolved_len + 1 >= PATH_MAX) {
|
||||
if (m)
|
||||
free(resolved);
|
||||
errno = ENAMETOOLONG;
|
||||
return (NULL);
|
||||
}
|
||||
resolved[resolved_len++] = '/';
|
||||
resolved[resolved_len] = '\0';
|
||||
}
|
||||
if (next_token[0] == '\0') {
|
||||
/* Handle consequential slashes. */
|
||||
continue;
|
||||
}
|
||||
else if (strcmp(next_token, ".") == 0)
|
||||
continue;
|
||||
else if (strcmp(next_token, "..") == 0) {
|
||||
/*
|
||||
* Strip the last path component except when we have
|
||||
* single "/"
|
||||
*/
|
||||
if (resolved_len > 1) {
|
||||
resolved[resolved_len - 1] = '\0';
|
||||
q = strrchr(resolved, '/') + 1;
|
||||
*q = '\0';
|
||||
resolved_len = q - resolved;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Append the next path component and lstat() it.
|
||||
*/
|
||||
resolved_len = strlcat(resolved, next_token, PATH_MAX);
|
||||
if (resolved_len >= PATH_MAX) {
|
||||
if (m)
|
||||
free(resolved);
|
||||
errno = ENAMETOOLONG;
|
||||
return (NULL);
|
||||
}
|
||||
if (lstat(resolved, &sb) != 0) {
|
||||
#ifdef FS_SPEC
|
||||
if (errno == ENOENT && p == NULL) {
|
||||
errno = serrno;
|
||||
return (resolved);
|
||||
}
|
||||
#endif
|
||||
if (m)
|
||||
free(resolved);
|
||||
return (NULL);
|
||||
}
|
||||
if (S_ISLNK(sb.st_mode)) {
|
||||
if (symlinks++ > MAXSYMLINKS) {
|
||||
if (m)
|
||||
free(resolved);
|
||||
errno = ELOOP;
|
||||
return (NULL);
|
||||
}
|
||||
slen = readlink(resolved, symlink, sizeof(symlink) - 1);
|
||||
if (slen < 0) {
|
||||
if (m)
|
||||
free(resolved);
|
||||
return (NULL);
|
||||
}
|
||||
symlink[slen] = '\0';
|
||||
if (symlink[0] == '/') {
|
||||
resolved[1] = 0;
|
||||
resolved_len = 1;
|
||||
} else if (resolved_len > 1) {
|
||||
/* Strip the last path component. */
|
||||
resolved[resolved_len - 1] = '\0';
|
||||
q = strrchr(resolved, '/') + 1;
|
||||
*q = '\0';
|
||||
resolved_len = q - resolved;
|
||||
}
|
||||
|
||||
/*
|
||||
* If there are any path components left, then
|
||||
* append them to symlink. The result is placed
|
||||
* in `left'.
|
||||
*/
|
||||
if (p != NULL) {
|
||||
if (symlink[slen - 1] != '/') {
|
||||
if (slen + 1 >= sizeof(symlink)) {
|
||||
if (m)
|
||||
free(resolved);
|
||||
errno = ENAMETOOLONG;
|
||||
return (NULL);
|
||||
}
|
||||
symlink[slen] = '/';
|
||||
symlink[slen + 1] = 0;
|
||||
}
|
||||
left_len = strlcat(symlink, left,
|
||||
sizeof(symlink));
|
||||
if (left_len >= sizeof(left)) {
|
||||
if (m)
|
||||
free(resolved);
|
||||
errno = ENAMETOOLONG;
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
left_len = strlcpy(left, symlink, sizeof(left));
|
||||
} else if (!S_ISDIR(sb.st_mode) && p != NULL) {
|
||||
if (m)
|
||||
free(resolved);
|
||||
errno = ENOTDIR;
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove trailing slash except when the resolved pathname
|
||||
* is a single "/".
|
||||
*/
|
||||
if (resolved_len > 1 && resolved[resolved_len - 1] == '/')
|
||||
resolved[resolved_len - 1] = '\0';
|
||||
return (resolved);
|
||||
}
|
211
toolbox/rm.cpp
211
toolbox/rm.cpp
@ -43,6 +43,7 @@
|
||||
|
||||
#include <macos/sysequ.h>
|
||||
#include <macos/errors.h>
|
||||
#include <macos/tool_return.h>
|
||||
|
||||
#include "stackframe.h"
|
||||
#include "fs_spec.h"
|
||||
@ -51,6 +52,10 @@ using ToolBox::Log;
|
||||
using namespace OS::Internal;
|
||||
using namespace ToolBox;
|
||||
|
||||
using MacOS::tool_return;
|
||||
using MacOS::macos_error_from_errno;
|
||||
using MacOS::macos_error;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
@ -101,6 +106,8 @@ namespace
|
||||
case 0x434f4445: // 'CODE' (Link)
|
||||
case 0x5041434b: // 'PACK' (PascalIIgs)
|
||||
case 0x4b4f4445: // 'KODE' (Link 32-bit Startup)
|
||||
case 0x45525253: // 'ERRS' (PPCLink)
|
||||
case 0x63667267: // 'cfrg' (PPCLink)
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
@ -398,6 +405,39 @@ namespace RM
|
||||
return SetResError(::ResError());
|
||||
}
|
||||
|
||||
|
||||
tool_return<void> CreateResFile(const std::string &path)
|
||||
{
|
||||
|
||||
if (path.empty()) return MacOS::paramErr;
|
||||
|
||||
FSRef ref;
|
||||
OSErr error;
|
||||
int fd;
|
||||
|
||||
error = ::FSPathMakeRef((const UInt8 *)path.c_str(), &ref, NULL);
|
||||
if (error != noErr)
|
||||
return macos_error(error);
|
||||
|
||||
// FSCreateResourceFork only works with existing files.
|
||||
|
||||
fd = ::open(path.c_str(), O_CREAT | O_EXCL | O_RDWR, 0666);
|
||||
if (fd < 0)
|
||||
{
|
||||
if (errno != EEXIST) return macos_error_from_errno();
|
||||
}
|
||||
if (fd >= 0) close(fd);
|
||||
|
||||
|
||||
HFSUniStr255 fork = {0,{0}};
|
||||
::FSGetResourceForkName(&fork);
|
||||
|
||||
|
||||
error = ::FSCreateResourceFork(&ref, fork.length, fork.unicode, 0);
|
||||
|
||||
return macos_error(error);
|
||||
}
|
||||
|
||||
uint16_t CreateResFile(uint16_t trap)
|
||||
{
|
||||
// PROCEDURE CreateResFile (fileName: Str255);
|
||||
@ -440,12 +480,12 @@ namespace RM
|
||||
fd = ::open(sname.c_str(), O_CREAT | O_EXCL | O_RDWR, 0666);
|
||||
if (fd < 0)
|
||||
{
|
||||
if (errno != EEXIST) return SetResError(errno_to_oserr(errno));
|
||||
if (errno != EEXIST) return SetResError(macos_error_from_errno());
|
||||
}
|
||||
if (fd >= 0) close(fd);
|
||||
|
||||
HFSUniStr255 fork = {0,{0}};
|
||||
::FSGetResourceForkName(&fork);
|
||||
HFSUniStr255 fork = {0,{0}};
|
||||
::FSGetResourceForkName(&fork);
|
||||
|
||||
error = ::FSCreateResourceFork(&ref, fork.length, fork.unicode, 0);
|
||||
|
||||
@ -453,17 +493,97 @@ namespace RM
|
||||
}
|
||||
|
||||
|
||||
uint16_t FSpCreateResFile(void)
|
||||
{
|
||||
|
||||
// PROCEDURE FSpCreateResFile (spec: FSSpec; creator, fileType: OSType; scriptTag: ScriptCode);
|
||||
|
||||
// creates the file, if necessary.
|
||||
|
||||
uint32_t sp;
|
||||
uint32_t spec;
|
||||
uint32_t creator;
|
||||
uint32_t fileType;
|
||||
uint16_t scriptTag;
|
||||
|
||||
sp = StackFrame<14>(spec, creator, fileType, scriptTag);
|
||||
|
||||
|
||||
int parentID = memoryReadLong(spec + 2);
|
||||
std::string sname = ToolBox::ReadPString(spec + 6, false);
|
||||
|
||||
Log(" FSpCreateResFile(%s, %08x ('%s'), %08x ('%s'), %02x)\n",
|
||||
sname.c_str(),
|
||||
creator, ToolBox::TypeToString(creator).c_str(),
|
||||
fileType, ToolBox::TypeToString(fileType).c_str(),
|
||||
scriptTag);
|
||||
|
||||
|
||||
sname = OS::FSSpecManager::ExpandPath(sname, parentID);
|
||||
if (sname.empty())
|
||||
{
|
||||
return SetResError(MacOS::dirNFErr);
|
||||
}
|
||||
|
||||
auto rv = CreateResFile(sname);
|
||||
// returns errFSForkExists if fork already exists.
|
||||
// therefore, if no error, set the ftype/ctype.
|
||||
if (rv.error() == 0)
|
||||
{
|
||||
char buffer[32];
|
||||
std::memset(buffer, 0, sizeof(buffer));
|
||||
buffer[0] = fileType >> 24;
|
||||
buffer[1] = fileType >> 16;
|
||||
buffer[2] = fileType >> 8;
|
||||
buffer[3] = fileType >> 0;
|
||||
|
||||
buffer[4] = creator >> 24;
|
||||
buffer[5] = creator >> 16;
|
||||
buffer[6] = creator >> 8;
|
||||
buffer[7] = creator >> 0;
|
||||
|
||||
std::memcpy(buffer+4, &creator, 4);
|
||||
OS::Internal::SetFinderInfo(sname, buffer, false);
|
||||
}
|
||||
|
||||
return SetResError(rv.error() == errFSForkExists ? 0 : rv.error());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
tool_return<int16_t> OpenResCommon(const std::string &path, uint16_t permission = 0)
|
||||
{
|
||||
OSErr error;
|
||||
FSRef ref;
|
||||
ResFileRefNum refNum;
|
||||
|
||||
error = ::FSPathMakeRef( (const UInt8 *)path.c_str(), &ref, NULL);
|
||||
if (error != noErr)
|
||||
return (MacOS::macos_error)error;
|
||||
|
||||
HFSUniStr255 fork = {0,{0}};
|
||||
::FSGetResourceForkName(&fork);
|
||||
|
||||
refNum = -1;
|
||||
error = ::FSOpenResourceFile(&ref,
|
||||
fork.length,
|
||||
fork.unicode,
|
||||
permission,
|
||||
&refNum);
|
||||
|
||||
if (error != noErr)
|
||||
return (MacOS::macos_error)error;
|
||||
|
||||
return refNum;
|
||||
}
|
||||
|
||||
uint16_t OpenResFile(uint16_t trap)
|
||||
{
|
||||
// OpenResFile (fileName: Str255) : INTEGER;
|
||||
|
||||
ResFileRefNum refNum;
|
||||
FSRef ref;
|
||||
|
||||
uint32_t sp;
|
||||
uint32_t fileName;
|
||||
uint16_t permission;
|
||||
OSErr error;
|
||||
|
||||
sp = StackFrame<4>(fileName);
|
||||
|
||||
@ -471,27 +591,11 @@ namespace RM
|
||||
|
||||
Log("%04x OpenResFile(%s)\n", trap, sname.c_str());
|
||||
|
||||
error = ::FSPathMakeRef( (const UInt8 *)sname.c_str(), &ref, NULL);
|
||||
if (error != noErr)
|
||||
{
|
||||
ToolReturn<2>(sp, (uint16_t)-1);
|
||||
return SetResError(error);
|
||||
}
|
||||
auto rv = OpenResCommon(sname);
|
||||
|
||||
HFSUniStr255 fork = {0,{0}};
|
||||
::FSGetResourceForkName(&fork);
|
||||
ToolReturn<2>(sp, rv.value_or(-1));
|
||||
|
||||
refNum = -1;
|
||||
permission = 0; // whatever is allowed.
|
||||
error = ::FSOpenResourceFile(&ref,
|
||||
fork.length,
|
||||
fork.unicode,
|
||||
permission,
|
||||
&refNum);
|
||||
|
||||
ToolReturn<2>(sp, (uint16_t)refNum);
|
||||
|
||||
return SetResError(error);
|
||||
return SetResError(rv.error());
|
||||
}
|
||||
|
||||
uint16_t HOpenResFile(uint16_t trap)
|
||||
@ -499,10 +603,6 @@ namespace RM
|
||||
// FUNCTION HOpenResFile (vRefNum: Integer; dirID: LongInt;
|
||||
// fileName: Str255; permission: SignedByte): Integer;
|
||||
|
||||
ResFileRefNum refNum;
|
||||
FSRef ref;
|
||||
OSErr error;
|
||||
|
||||
uint32_t sp;
|
||||
|
||||
uint16_t vRefNum;
|
||||
@ -525,34 +625,51 @@ namespace RM
|
||||
sname = OS::FSSpecManager::ExpandPath(sname, dirID);
|
||||
if (sname.empty())
|
||||
{
|
||||
error = MacOS::dirNFErr;
|
||||
ToolReturn<2>(sp, (uint16_t)-1);
|
||||
return SetResError(error);
|
||||
return SetResError(MacOS::dirNFErr);
|
||||
}
|
||||
|
||||
error = ::FSPathMakeRef( (const UInt8 *)sname.c_str(), &ref, NULL);
|
||||
if (error != noErr)
|
||||
auto rv = OpenResCommon(sname, permission);
|
||||
|
||||
ToolReturn<2>(sp, rv.value_or(-1));
|
||||
|
||||
return SetResError(rv.error());
|
||||
}
|
||||
|
||||
uint16_t FSpOpenResFile(void)
|
||||
{
|
||||
// FUNCTION FSpOpenResFile (spec: FSSpec; permission: SignedByte): Integer;
|
||||
|
||||
uint32_t sp;
|
||||
uint32_t spec;
|
||||
uint16_t permission;
|
||||
|
||||
sp = StackFrame<6>(spec, permission);
|
||||
|
||||
|
||||
int parentID = memoryReadLong(spec + 2);
|
||||
|
||||
std::string sname = ToolBox::ReadPString(spec + 6, false);
|
||||
|
||||
Log(" FSpOpenResFile(%s, %04x)\n", sname.c_str(), permission);
|
||||
|
||||
|
||||
sname = OS::FSSpecManager::ExpandPath(sname, parentID);
|
||||
if (sname.empty())
|
||||
{
|
||||
ToolReturn<2>(sp, (uint16_t)-1);
|
||||
return SetResError(error);
|
||||
return SetResError(MacOS::dirNFErr);
|
||||
}
|
||||
|
||||
HFSUniStr255 fork = {0,{0}};
|
||||
::FSGetResourceForkName(&fork);
|
||||
auto rv = OpenResCommon(sname, permission);
|
||||
|
||||
refNum = -1;
|
||||
error = ::FSOpenResourceFile(&ref,
|
||||
fork.length,
|
||||
fork.unicode,
|
||||
permission,
|
||||
&refNum);
|
||||
ToolReturn<2>(sp, rv.value_or(-1));
|
||||
|
||||
ToolReturn<2>(sp, (uint16_t)refNum);
|
||||
|
||||
return SetResError(0);
|
||||
return SetResError(rv.error());
|
||||
}
|
||||
|
||||
|
||||
|
||||
uint16_t OpenRFPerm(uint16_t trap)
|
||||
{
|
||||
// FUNCTION OpenRFPerm (fileName: Str255; vRefNum: Integer;
|
||||
|
@ -57,6 +57,9 @@ namespace RM
|
||||
uint16_t Get1IndType(uint16_t trap);
|
||||
|
||||
|
||||
uint16_t FSpOpenResFile(void);
|
||||
uint16_t FSpCreateResFile(void);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -65,6 +65,9 @@ namespace ToolBox {
|
||||
case 0x0015:
|
||||
return MM::TempMaxMem();
|
||||
|
||||
case 0x0018:
|
||||
return MM::TempFreeMem();
|
||||
|
||||
default:
|
||||
fprintf(stderr, "OSDispatch: selector %04x not implemented\n",
|
||||
selector);
|
||||
@ -223,7 +226,8 @@ namespace ToolBox {
|
||||
break;
|
||||
|
||||
// BlockMove (sourcePtr,destPtr: Ptr; byteCount: Size);
|
||||
case 0xa02e:
|
||||
case 0xa02e: // BlockMove
|
||||
case 0xa22e: // BlockMoveData
|
||||
d0 = MM::BlockMove(trap);
|
||||
break;
|
||||
|
||||
@ -285,6 +289,10 @@ namespace ToolBox {
|
||||
d0 = MM::HandleZone(trap);
|
||||
break;
|
||||
|
||||
case 0xa128:
|
||||
d0 = MM::RecoverHandle(trap);
|
||||
break;
|
||||
|
||||
// MaxApplZone
|
||||
case 0xa063:
|
||||
d0 = MM::MaxApplZone(trap);
|
||||
@ -358,6 +366,19 @@ namespace ToolBox {
|
||||
d0 = MM::EmptyHandle(trap);
|
||||
break;
|
||||
|
||||
|
||||
case 0xa058:
|
||||
d0 = OS::InsTime(trap);
|
||||
break;
|
||||
|
||||
case 0xa059:
|
||||
d0 = OS::RmvTime(trap);
|
||||
break;
|
||||
|
||||
case 0xa05a:
|
||||
d0 = OS::PrimeTime(trap);
|
||||
break;
|
||||
|
||||
// resource manager stuff.
|
||||
|
||||
// Count1Resources (theType: ResType): Integer;
|
||||
|
Loading…
Reference in New Issue
Block a user