mirror of
https://github.com/ksherlock/mpw.git
synced 2025-08-15 10:27:40 +00:00
Merge branch 'PPCLink'
Fixes and support for the PPCLink utility.
This commit is contained in:
@@ -577,6 +577,20 @@ namespace MacOS {
|
|||||||
{
|
{
|
||||||
return std::error_condition(static_cast<int>(e), macos_system_category());
|
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 {
|
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;
|
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)
|
static bool isdir(const std::string &path)
|
||||||
{
|
{
|
||||||
|
@@ -119,8 +119,6 @@ namespace MPW {
|
|||||||
void ftrap_write(uint16_t trap);
|
void ftrap_write(uint16_t trap);
|
||||||
void ftrap_ioctl(uint16_t trap);
|
void ftrap_ioctl(uint16_t trap);
|
||||||
|
|
||||||
// native errno to an MPW errno.
|
|
||||||
int errno_to_errno(int xerrno);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
@@ -133,7 +133,7 @@ namespace MPW
|
|||||||
Log(" delete(%s)\n", sname.c_str());
|
Log(" delete(%s)\n", sname.c_str());
|
||||||
|
|
||||||
rv = ::unlink(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;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -192,7 +192,7 @@ namespace MPW
|
|||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
{
|
{
|
||||||
// return an errno.
|
// return an errno.
|
||||||
d0 = 0x40000000 | errno_to_errno(errno);
|
d0 = 0x40000000 | mpw_errno_from_errno();
|
||||||
f.error = MacOS::ioErr;
|
f.error = MacOS::ioErr;
|
||||||
f.cookie = 0;
|
f.cookie = 0;
|
||||||
}
|
}
|
||||||
|
@@ -26,6 +26,7 @@
|
|||||||
|
|
||||||
#include "mpw.h"
|
#include "mpw.h"
|
||||||
#include "mpw_internal.h"
|
#include "mpw_internal.h"
|
||||||
|
#include "mpw_errno.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@@ -81,7 +82,7 @@ namespace MPW
|
|||||||
{
|
{
|
||||||
//f.count = 0;
|
//f.count = 0;
|
||||||
f.error = MacOS::ioErr; // ioErr
|
f.error = MacOS::ioErr; // ioErr
|
||||||
d0 = errno_to_errno(errno);
|
d0 = mpw_errno_from_errno();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -126,7 +127,7 @@ namespace MPW
|
|||||||
{
|
{
|
||||||
//f.count = 0;
|
//f.count = 0;
|
||||||
f.error = MacOS::ioErr; // ioErr
|
f.error = MacOS::ioErr; // ioErr
|
||||||
d0 = errno_to_errno(errno);
|
d0 = mpw_errno_from_errno();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@@ -52,7 +52,7 @@
|
|||||||
#include <toolbox/os.h>
|
#include <toolbox/os.h>
|
||||||
#include <toolbox/os_internal.h>
|
#include <toolbox/os_internal.h>
|
||||||
|
|
||||||
|
using MacOS::macos_error_from_errno;
|
||||||
|
|
||||||
|
|
||||||
namespace MPW
|
namespace MPW
|
||||||
@@ -335,8 +335,8 @@ namespace MPW
|
|||||||
off_t rv = ::lseek(fd, offset, nativeWhence);
|
off_t rv = ::lseek(fd, offset, nativeWhence);
|
||||||
if (rv < 0)
|
if (rv < 0)
|
||||||
{
|
{
|
||||||
d0 = errno_to_errno(errno);
|
d0 = mpw_errno_from_errno();
|
||||||
f.error = OS::Internal::errno_to_oserr(errno);
|
f.error = macos_error_from_errno();
|
||||||
//perror(NULL);
|
//perror(NULL);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -375,8 +375,8 @@ namespace MPW
|
|||||||
[arg, &f](int fd, OS::Internal::FDEntry &e){
|
[arg, &f](int fd, OS::Internal::FDEntry &e){
|
||||||
int ok = ftruncate(fd, arg);
|
int ok = ftruncate(fd, arg);
|
||||||
if (ok == 0) return 0;
|
if (ok == 0) return 0;
|
||||||
f.error = OS::Internal::errno_to_oserr(errno);
|
f.error = macos_error_from_errno();
|
||||||
return errno_to_errno(errno);
|
return (int)mpw_errno_from_errno();
|
||||||
},
|
},
|
||||||
[](int fd){
|
[](int fd){
|
||||||
return kEINVAL;
|
return kEINVAL;
|
||||||
|
@@ -22,6 +22,7 @@ set(TOOLBOX_SRC
|
|||||||
pathnames.cpp
|
pathnames.cpp
|
||||||
utility.cpp
|
utility.cpp
|
||||||
fs_spec.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?]
|
// map of handle -> size [? just use Ptr map?]
|
||||||
std::map<uint32_t, HandleInfo> HandleMap;
|
std::map<uint32_t, HandleInfo> HandleMap;
|
||||||
|
|
||||||
inline uint16_t SetMemError(uint16_t error)
|
inline int16_t SetMemError(int16_t error)
|
||||||
{
|
{
|
||||||
memoryWriteWord(error, MacOS::MemErr);
|
memoryWriteWord(error, MacOS::MemErr);
|
||||||
return error;
|
return error;
|
||||||
@@ -284,9 +284,12 @@ namespace MM
|
|||||||
|
|
||||||
// todo -- size 0 should have a ptr to differentiate
|
// todo -- size 0 should have a ptr to differentiate
|
||||||
// from purged.
|
// from purged.
|
||||||
if (size)
|
|
||||||
{
|
// PPCLink calls NewHandle(0) but expects a valid pointer
|
||||||
ptr = (uint8_t *)mplite_malloc(&pool, size);
|
// Assertion failed: *fHandle != NULL
|
||||||
|
//if (size)
|
||||||
|
//{
|
||||||
|
ptr = (uint8_t *)mplite_malloc(&pool, size ? size : 1);
|
||||||
if (!ptr)
|
if (!ptr)
|
||||||
{
|
{
|
||||||
HandleQueue.push_back(hh);
|
HandleQueue.push_back(hh);
|
||||||
@@ -296,7 +299,7 @@ namespace MM
|
|||||||
|
|
||||||
if (clear)
|
if (clear)
|
||||||
std::memset(ptr, 0, size);
|
std::memset(ptr, 0, size);
|
||||||
}
|
//}
|
||||||
|
|
||||||
// need a handle -> ptr map?
|
// need a handle -> ptr map?
|
||||||
HandleMap.emplace(std::make_pair(hh, HandleInfo(mcptr, size)));
|
HandleMap.emplace(std::make_pair(hh, HandleInfo(mcptr, size)));
|
||||||
@@ -394,6 +397,8 @@ namespace MM
|
|||||||
|
|
||||||
uint16_t SetHandleSize(uint32_t handle, uint32_t newSize)
|
uint16_t SetHandleSize(uint32_t handle, uint32_t newSize)
|
||||||
{
|
{
|
||||||
|
if (handle == 0) return SetMemError(MacOS::nilHandleErr);
|
||||||
|
|
||||||
const auto iter = HandleMap.find(handle);
|
const auto iter = HandleMap.find(handle);
|
||||||
|
|
||||||
if (iter == HandleMap.end()) return SetMemError(MacOS::memWZErr);
|
if (iter == HandleMap.end()) return SetMemError(MacOS::memWZErr);
|
||||||
@@ -409,7 +414,14 @@ namespace MM
|
|||||||
// 1. - resizing to 0.
|
// 1. - resizing to 0.
|
||||||
if (!newSize)
|
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
|
// todo -- size 0 should have a ptr to differentiate
|
||||||
// from purged.
|
// from purged.
|
||||||
@@ -562,6 +574,9 @@ namespace MM
|
|||||||
|
|
||||||
uint16_t BlockMove(uint16_t trap)
|
uint16_t BlockMove(uint16_t trap)
|
||||||
{
|
{
|
||||||
|
// also implements BlockMoveData.
|
||||||
|
// BlockMove will flush caches, BlockMoveData will not.
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* on entry:
|
* on entry:
|
||||||
* A0 Pointer to source
|
* A0 Pointer to source
|
||||||
@@ -744,17 +759,9 @@ namespace MM
|
|||||||
|
|
||||||
SetMemError(0);
|
SetMemError(0);
|
||||||
|
|
||||||
// find the pointer base...
|
// MemorySize is the top of the heap. stack is after it.
|
||||||
// todo -- call lower bound, then iter-- ?
|
|
||||||
for (const auto & iter : PtrMap)
|
|
||||||
{
|
|
||||||
if (sp >= iter.first && sp < iter.first + iter.second)
|
|
||||||
{
|
|
||||||
return sp - iter.first;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
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);
|
auto iter = HandleMap.find(hh);
|
||||||
|
|
||||||
@@ -1068,112 +1087,51 @@ namespace MM
|
|||||||
Log("%04x SetHandleSize(%08x, %08x)\n", trap, hh, newSize);
|
Log("%04x SetHandleSize(%08x, %08x)\n", trap, hh, newSize);
|
||||||
|
|
||||||
return Native::SetHandleSize(hh, newSize);
|
return Native::SetHandleSize(hh, newSize);
|
||||||
|
}
|
||||||
|
|
||||||
#if 0
|
uint32_t RecoverHandle(uint16_t trap)
|
||||||
auto iter = HandleMap.find(hh);
|
{
|
||||||
|
// FUNCTION RecoverHandle (p: Ptr): Handle;
|
||||||
|
|
||||||
if (iter == HandleMap.end()) return SetMemError(MacOS::memWZErr);
|
/*
|
||||||
// todo -- if handle ptr is null, other logic?
|
* on entry:
|
||||||
// todo -- if locked, can't move.
|
* A0 Master pointer
|
||||||
|
*
|
||||||
auto &info = iter->second;
|
* on exit:
|
||||||
|
* A0 Handle to master pointer’s relocatable block
|
||||||
// 0 - no change in size.
|
* D0 Unchanged
|
||||||
if (info.size == newSize) return SetMemError(0);
|
*
|
||||||
|
*/
|
||||||
uint32_t mcptr = info.address;
|
|
||||||
uint8_t *ptr = mcptr + Memory;
|
|
||||||
|
|
||||||
|
|
||||||
// 1. - resizing to 0.
|
uint32_t p = cpuGetAReg(0);
|
||||||
if (!newSize)
|
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);
|
if (!info.address) continue;
|
||||||
info.address = 0;
|
|
||||||
info.size = 0;
|
|
||||||
|
|
||||||
memoryWriteLong(info.address, hh);
|
uint32_t begin = info.address;
|
||||||
return SetMemError(0);
|
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)
|
// return d0 register unchanged.
|
||||||
{
|
return cpuGetDReg(0);
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1501,9 +1459,19 @@ namespace MM
|
|||||||
if (address) memoryWriteLong(0, address);
|
if (address) memoryWriteLong(0, address);
|
||||||
|
|
||||||
ToolReturn<4>(sp, mplite_maxmem(&pool));
|
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 SetHandleSize(uint16_t);
|
||||||
uint16_t SetPtrSize(uint16_t);
|
uint16_t SetPtrSize(uint16_t);
|
||||||
|
|
||||||
|
uint32_t RecoverHandle(uint16_t);
|
||||||
|
|
||||||
uint16_t HGetState(uint16_t trap);
|
uint16_t HGetState(uint16_t trap);
|
||||||
|
|
||||||
uint16_t HLock(uint16_t trap);
|
uint16_t HLock(uint16_t trap);
|
||||||
@@ -88,6 +90,7 @@ namespace MM
|
|||||||
// OS Dispatch
|
// OS Dispatch
|
||||||
|
|
||||||
uint16_t TempMaxMem(void);
|
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 "os_internal.h"
|
||||||
#include "toolbox.h"
|
#include "toolbox.h"
|
||||||
#include "stackframe.h"
|
#include "stackframe.h"
|
||||||
|
#include "fs_spec.h"
|
||||||
|
|
||||||
using ToolBox::Log;
|
using ToolBox::Log;
|
||||||
|
|
||||||
using OS::Internal::errno_to_oserr;
|
using MacOS::macos_error_from_errno;
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
@@ -288,7 +288,7 @@ namespace OS
|
|||||||
|
|
||||||
|
|
||||||
int rv = OS::Internal::FDEntry::close(ioRefNum, true);
|
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;
|
else d0 = 0;
|
||||||
|
|
||||||
memoryWriteWord(d0, parm + 16);
|
memoryWriteWord(d0, parm + 16);
|
||||||
@@ -324,7 +324,7 @@ namespace OS
|
|||||||
|
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
{
|
{
|
||||||
d0 = errno_to_oserr(errno);
|
d0 = macos_error_from_errno();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -339,6 +339,31 @@ namespace OS
|
|||||||
|
|
||||||
uint16_t Open(uint16_t trap)
|
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;
|
uint32_t d0;
|
||||||
|
|
||||||
int fd;
|
int fd;
|
||||||
@@ -348,25 +373,54 @@ namespace OS
|
|||||||
|
|
||||||
Log("%04x Open(%08x)\n", trap, parm);
|
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);
|
std::string sname = ToolBox::ReadPString(namePtr, true);
|
||||||
|
sname = FSSpecManager::ExpandPath(sname, ioDirID);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
fd = Internal::FDEntry::open(sname, ioPermission, false);
|
fd = Internal::FDEntry::open(sname, ioPermission, false);
|
||||||
d0 = fd < 0 ? fd : 0;
|
d0 = fd < 0 ? fd : 0;
|
||||||
if (fd >= 0)
|
if (fd >= 0)
|
||||||
{
|
{
|
||||||
memoryWriteWord(fd, parm + 24);
|
memoryWriteWord(fd, parm + _ioRefNum);
|
||||||
}
|
}
|
||||||
|
|
||||||
memoryWriteWord(d0, parm + 16);
|
memoryWriteWord(d0, parm + _ioResult);
|
||||||
return d0;
|
return d0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t OpenRF(uint16_t trap)
|
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;
|
uint32_t d0;
|
||||||
|
|
||||||
int fd;
|
int fd;
|
||||||
@@ -376,20 +430,22 @@ namespace OS
|
|||||||
|
|
||||||
Log("%04x OpenRF(%08x)\n", trap, parm);
|
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);
|
std::string sname = ToolBox::ReadPString(namePtr, true);
|
||||||
|
sname = FSSpecManager::ExpandPath(sname, ioDirID);
|
||||||
|
|
||||||
fd = Internal::FDEntry::open(sname, ioPermission, true);
|
fd = Internal::FDEntry::open(sname, ioPermission, true);
|
||||||
d0 = fd < 0 ? fd : 0;
|
d0 = fd < 0 ? fd : 0;
|
||||||
if (fd >= 0)
|
if (fd >= 0)
|
||||||
{
|
{
|
||||||
memoryWriteWord(fd, parm + 24);
|
memoryWriteWord(fd, parm + _ioRefNum);
|
||||||
}
|
}
|
||||||
|
|
||||||
memoryWriteWord(d0, parm + 16);
|
memoryWriteWord(d0, parm + _ioResult);
|
||||||
return d0;
|
return d0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -443,7 +499,7 @@ namespace OS
|
|||||||
}
|
}
|
||||||
if (count < 0)
|
if (count < 0)
|
||||||
{
|
{
|
||||||
d0 = errno_to_oserr(errno);
|
d0 = macos_error_from_errno();
|
||||||
}
|
}
|
||||||
|
|
||||||
memoryWriteLong(pos, parm + 46); // new offset.
|
memoryWriteLong(pos, parm + 46); // new offset.
|
||||||
@@ -499,7 +555,7 @@ namespace OS
|
|||||||
|
|
||||||
if (count < 0)
|
if (count < 0)
|
||||||
{
|
{
|
||||||
d0 = errno_to_oserr(errno);
|
d0 = macos_error_from_errno();
|
||||||
}
|
}
|
||||||
|
|
||||||
memoryWriteLong(pos, parm + 46); // new offset.
|
memoryWriteLong(pos, parm + 46); // new offset.
|
||||||
@@ -536,7 +592,7 @@ namespace OS
|
|||||||
|
|
||||||
int ok = ::unlink(sname.c_str());
|
int ok = ::unlink(sname.c_str());
|
||||||
if (ok < 0)
|
if (ok < 0)
|
||||||
d0 = errno_to_oserr(errno);
|
d0 = macos_error_from_errno();
|
||||||
else
|
else
|
||||||
d0 = 0;
|
d0 = 0;
|
||||||
|
|
||||||
@@ -560,7 +616,7 @@ namespace OS
|
|||||||
|
|
||||||
if (::fstat(ioRefNum, &st) < 0)
|
if (::fstat(ioRefNum, &st) < 0)
|
||||||
{
|
{
|
||||||
d0 = errno_to_oserr(errno);
|
d0 = macos_error_from_errno();
|
||||||
size = 0;
|
size = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -589,7 +645,7 @@ namespace OS
|
|||||||
|
|
||||||
int rv = ::ftruncate(ioRefNum, ioMisc);
|
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);
|
memoryWriteWord(d0, parm + 16);
|
||||||
return d0;
|
return d0;
|
||||||
@@ -609,7 +665,7 @@ namespace OS
|
|||||||
int rv = ::lseek(ioRefNum, 0, SEEK_CUR);
|
int rv = ::lseek(ioRefNum, 0, SEEK_CUR);
|
||||||
if (rv < 0)
|
if (rv < 0)
|
||||||
{
|
{
|
||||||
d0 = errno_to_oserr(errno);
|
d0 = macos_error_from_errno();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -768,7 +824,7 @@ namespace OS
|
|||||||
|
|
||||||
if (::stat(sname.c_str(), &st) < 0)
|
if (::stat(sname.c_str(), &st) < 0)
|
||||||
{
|
{
|
||||||
d0 = errno_to_oserr(errno);
|
d0 = macos_error_from_errno();
|
||||||
|
|
||||||
memoryWriteWord(d0, parm + 16);
|
memoryWriteWord(d0, parm + 16);
|
||||||
return d0;
|
return d0;
|
||||||
@@ -871,7 +927,7 @@ namespace OS
|
|||||||
ok = ::stat(sname.c_str(), &st);
|
ok = ::stat(sname.c_str(), &st);
|
||||||
if (ok < 0)
|
if (ok < 0)
|
||||||
{
|
{
|
||||||
d0 = errno_to_oserr(errno);
|
d0 = macos_error_from_errno();
|
||||||
memoryWriteWord(d0, parm + 16);
|
memoryWriteWord(d0, parm + 16);
|
||||||
return d0;
|
return d0;
|
||||||
}
|
}
|
||||||
@@ -1197,4 +1253,182 @@ namespace OS
|
|||||||
return MacOS::prWrErr;
|
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 {
|
enum {
|
||||||
fsCurPerm = 0,
|
fsCurPerm = 0x00,
|
||||||
fsRdPerm = 1,
|
fsRdPerm = 0x01,
|
||||||
fsWrPerm = 2,
|
fsWrPerm = 0x02,
|
||||||
fsRdWrPerm = 3,
|
fsRdWrPerm = 0x03,
|
||||||
fsRdWrShPerm = 4,
|
fsRdWrShPerm = 0x04,
|
||||||
|
fsRdDenyPerm = 0x10,
|
||||||
|
fsWrDenyPerm = 0x20
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@@ -98,6 +100,11 @@ namespace OS
|
|||||||
uint16_t ReadXPRam(uint16_t trap);
|
uint16_t ReadXPRam(uint16_t trap);
|
||||||
uint16_t WriteXPRam(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
|
#endif
|
||||||
|
@@ -56,7 +56,7 @@
|
|||||||
|
|
||||||
using ToolBox::Log;
|
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)
|
if (::stat(sname.c_str(), &st) < 0)
|
||||||
{
|
{
|
||||||
d0 = errno_to_oserr(errno);
|
d0 = macos_error_from_errno();
|
||||||
|
|
||||||
memoryWriteWord(d0, parm + _ioResult);
|
memoryWriteWord(d0, parm + _ioResult);
|
||||||
return d0;
|
return d0;
|
||||||
@@ -279,7 +279,7 @@ namespace OS {
|
|||||||
ok = ::stat(sname.c_str(), &st);
|
ok = ::stat(sname.c_str(), &st);
|
||||||
if (ok < 0)
|
if (ok < 0)
|
||||||
{
|
{
|
||||||
d0 = errno_to_oserr(errno);
|
d0 = macos_error_from_errno();
|
||||||
memoryWriteWord(d0, parm + _ioResult);
|
memoryWriteWord(d0, parm + _ioResult);
|
||||||
return d0;
|
return d0;
|
||||||
}
|
}
|
||||||
|
@@ -65,6 +65,7 @@ namespace OS {
|
|||||||
|
|
||||||
std::map<uint32_t, uint32_t> GestaltMap = {
|
std::map<uint32_t, uint32_t> GestaltMap = {
|
||||||
{'alis', 1}, // Alias Manager
|
{'alis', 1}, // Alias Manager
|
||||||
|
{'tmgr', 2}, // Time Manager (2 = revised, 3 = extended.)
|
||||||
};
|
};
|
||||||
|
|
||||||
uint16_t Gestalt(uint16_t trap)
|
uint16_t Gestalt(uint16_t trap)
|
||||||
|
@@ -55,7 +55,7 @@
|
|||||||
|
|
||||||
using ToolBox::Log;
|
using ToolBox::Log;
|
||||||
|
|
||||||
using OS::Internal::errno_to_oserr;
|
using MacOS::macos_error_from_errno;
|
||||||
|
|
||||||
namespace OS {
|
namespace OS {
|
||||||
|
|
||||||
@@ -194,7 +194,7 @@ namespace OS {
|
|||||||
|
|
||||||
if (::stat(sname.c_str(), &st) < 0)
|
if (::stat(sname.c_str(), &st) < 0)
|
||||||
{
|
{
|
||||||
d0 = errno_to_oserr(errno);
|
d0 = macos_error_from_errno();
|
||||||
|
|
||||||
memoryWriteWord(d0, parm + _ioResult);
|
memoryWriteWord(d0, parm + _ioResult);
|
||||||
return d0;
|
return d0;
|
||||||
@@ -353,7 +353,7 @@ namespace OS {
|
|||||||
ok = ::stat(sname.c_str(), &st);
|
ok = ::stat(sname.c_str(), &st);
|
||||||
if (ok < 0)
|
if (ok < 0)
|
||||||
{
|
{
|
||||||
d0 = errno_to_oserr(errno);
|
d0 = macos_error_from_errno();
|
||||||
memoryWriteWord(d0, parm + _ioResult);
|
memoryWriteWord(d0, parm + _ioResult);
|
||||||
return d0;
|
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)
|
uint16_t FSDispatch(uint16_t trap)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -449,6 +464,12 @@ namespace OS {
|
|||||||
case 0x001a:
|
case 0x001a:
|
||||||
return PBHOpenDF(paramBlock);
|
return PBHOpenDF(paramBlock);
|
||||||
|
|
||||||
|
case 0x0038:
|
||||||
|
return PBHOpenDeny(paramBlock);
|
||||||
|
|
||||||
|
case 0x0039:
|
||||||
|
return PBHOpenRFDeny(paramBlock);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "HFSDispatch: selector %08x not implemented\n",
|
fprintf(stderr, "HFSDispatch: selector %08x not implemented\n",
|
||||||
selector);
|
selector);
|
||||||
|
@@ -35,6 +35,8 @@
|
|||||||
#include <sys/xattr.h>
|
#include <sys/xattr.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/paths.h>
|
#include <sys/paths.h>
|
||||||
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
@@ -48,14 +50,18 @@
|
|||||||
#include <macos/errors.h>
|
#include <macos/errors.h>
|
||||||
|
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
|
#include "rm.h"
|
||||||
#include "os_internal.h"
|
#include "os_internal.h"
|
||||||
#include "toolbox.h"
|
#include "toolbox.h"
|
||||||
#include "stackframe.h"
|
#include "stackframe.h"
|
||||||
#include "fs_spec.h"
|
#include "fs_spec.h"
|
||||||
|
|
||||||
using ToolBox::Log;
|
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 {
|
namespace OS {
|
||||||
|
|
||||||
@@ -71,6 +77,25 @@ namespace OS {
|
|||||||
// MacOS: -> { -1, 1, "MacOS" }
|
// MacOS: -> { -1, 1, "MacOS" }
|
||||||
// MacOS:dumper -> {-1, 2 "dumper"}
|
// 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)
|
uint16_t FSMakeFSSpec(void)
|
||||||
{
|
{
|
||||||
// FSMakeFSSpec(vRefNum: Integer; dirID: LongInt; fileName: Str255; VAR spec: FSSpec): OSErr;
|
// FSMakeFSSpec(vRefNum: Integer; dirID: LongInt; fileName: Str255; VAR spec: FSSpec): OSErr;
|
||||||
@@ -87,8 +112,6 @@ namespace OS {
|
|||||||
uint32_t spec;
|
uint32_t spec;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
StackFrame<14>(vRefNum, dirID, fileName, spec);
|
StackFrame<14>(vRefNum, dirID, fileName, spec);
|
||||||
|
|
||||||
std::string sname = ToolBox::ReadPString(fileName, true);
|
std::string sname = ToolBox::ReadPString(fileName, true);
|
||||||
@@ -113,49 +136,38 @@ namespace OS {
|
|||||||
bool absolute = sname.length() ? sname[0] == '/' : false;
|
bool absolute = sname.length() ? sname[0] == '/' : false;
|
||||||
if (absolute || (vRefNum == 0 && dirID == 0))
|
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 leaf;
|
||||||
std::string path;
|
std::string path;
|
||||||
|
int parentID;
|
||||||
|
|
||||||
|
path = realpath(sname);
|
||||||
path.assign(cp);
|
if (path.empty())
|
||||||
|
{
|
||||||
// if sname is null then the target is the default directory...
|
std::memset(memoryPointer(spec), 0, 8);
|
||||||
// so this should be ok.
|
return MacOS::mFulErr;
|
||||||
|
}
|
||||||
|
|
||||||
int pos = path.find_last_of('/');
|
int pos = path.find_last_of('/');
|
||||||
if (pos == path.npos)
|
if (pos == path.npos)
|
||||||
{
|
{
|
||||||
// ? should never happen...
|
// file is relative to cwd.
|
||||||
std::swap(leaf, path);
|
leaf = std::move(path);
|
||||||
|
parentID = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
leaf = path.substr(pos + 1);
|
leaf = path.substr(pos + 1);
|
||||||
path = path.substr(0, pos + 1); // include the /
|
path = path.substr(0, pos + 1); // include the /
|
||||||
|
parentID = FSSpecManager::IDForPath(path, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
int parentID = FSSpecManager::IDForPath(path, true);
|
|
||||||
|
|
||||||
memoryWriteWord(vRefNum, spec + 0);
|
memoryWriteWord(vRefNum, spec + 0);
|
||||||
memoryWriteLong(parentID, spec + 2);
|
memoryWriteLong(parentID, spec + 2);
|
||||||
// write the filename...
|
// write the filename...
|
||||||
ToolBox::WritePString(spec + 6, leaf);
|
ToolBox::WritePString(spec + 6, leaf);
|
||||||
|
|
||||||
// TODO -- return fnf if file does not exist.
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,6 +189,7 @@ namespace OS {
|
|||||||
|
|
||||||
uint32_t spec;
|
uint32_t spec;
|
||||||
uint32_t finderInfo;
|
uint32_t finderInfo;
|
||||||
|
uint16_t d0;
|
||||||
|
|
||||||
StackFrame<8>(spec, finderInfo);
|
StackFrame<8>(spec, finderInfo);
|
||||||
|
|
||||||
@@ -190,9 +203,8 @@ namespace OS {
|
|||||||
Log(" FSpGetFInfo(%s, %08x)\n", path.c_str(), finderInfo);
|
Log(" FSpGetFInfo(%s, %08x)\n", path.c_str(), finderInfo);
|
||||||
|
|
||||||
|
|
||||||
|
d0 = Internal::GetFinderInfo(path, memoryPointer(finderInfo), false);
|
||||||
Internal::GetFinderInfo(path, memoryPointer(finderInfo), false);
|
return d0;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t FSpSetFInfo()
|
uint16_t FSpSetFInfo()
|
||||||
@@ -201,7 +213,7 @@ namespace OS {
|
|||||||
|
|
||||||
uint32_t spec;
|
uint32_t spec;
|
||||||
uint32_t finderInfo;
|
uint32_t finderInfo;
|
||||||
uint16_t d0;
|
uint16_t d0 = 0;
|
||||||
|
|
||||||
StackFrame<8>(spec, finderInfo);
|
StackFrame<8>(spec, finderInfo);
|
||||||
|
|
||||||
@@ -222,12 +234,19 @@ namespace OS {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
uint16_t ResolveAliasFile()
|
uint16_t ResolveAliasFile()
|
||||||
{
|
{
|
||||||
|
// FUNCTION ResolveAliasFile (VAR theSpec: FSSpec;
|
||||||
|
// resolveAliasChains: Boolean;
|
||||||
|
// VAR targetIsFolder: Boolean;
|
||||||
|
// VAR wasAliased: Boolean): OSErr;
|
||||||
|
|
||||||
uint32_t spec;
|
uint32_t spec;
|
||||||
uint16_t resolveAliasChains;
|
uint16_t resolveAliasChains;
|
||||||
uint32_t targetIsFolder;
|
uint32_t targetIsFolder;
|
||||||
uint32_t wasAliased;
|
uint32_t wasAliased;
|
||||||
|
uint16_t d0 = 0;
|
||||||
|
|
||||||
StackFrame<14>(spec, resolveAliasChains, targetIsFolder, wasAliased);
|
StackFrame<14>(spec, resolveAliasChains, targetIsFolder, wasAliased);
|
||||||
|
|
||||||
@@ -238,23 +257,22 @@ namespace OS {
|
|||||||
|
|
||||||
path += leaf;
|
path += leaf;
|
||||||
|
|
||||||
Log(" ResolveAliasFile(%s)\n", path.c_str());
|
Log(" ResolveAliasFile(%s)\n", path.c_str());
|
||||||
|
|
||||||
struct stat st;
|
struct stat st;
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
rv = ::stat(path.c_str(), &st);
|
rv = ::stat(path.c_str(), &st);
|
||||||
if (rv < 0) return errno_to_oserr(errno);
|
if (rv < 0)
|
||||||
|
return macos_error_from_errno();
|
||||||
|
|
||||||
if (targetIsFolder)
|
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.
|
// don't bother pretending a soft link is an alias.
|
||||||
if (wasAliased) memoryWriteWord(0, wasAliased);
|
if (wasAliased) memoryWriteWord(0, wasAliased);
|
||||||
|
|
||||||
return 0;
|
return d0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -262,7 +280,26 @@ namespace OS {
|
|||||||
uint16_t HighLevelHFSDispatch(uint16_t trap)
|
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 selector;
|
||||||
|
uint16_t d0;
|
||||||
|
|
||||||
selector = cpuGetDReg(0) & 0xffff;
|
selector = cpuGetDReg(0) & 0xffff;
|
||||||
Log("%04x HighLevelHFSDispatch(%04x)\n", trap, selector);
|
Log("%04x HighLevelHFSDispatch(%04x)\n", trap, selector);
|
||||||
@@ -270,23 +307,34 @@ namespace OS {
|
|||||||
switch (selector)
|
switch (selector)
|
||||||
{
|
{
|
||||||
case 0x0001:
|
case 0x0001:
|
||||||
return FSMakeFSSpec();
|
d0 = FSMakeFSSpec();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x0007:
|
case 0x0007:
|
||||||
return FSpGetFInfo();
|
d0 = FSpGetFInfo();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x0008:
|
case 0x0008:
|
||||||
return FSpSetFInfo();
|
d0 = FSpSetFInfo();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x000d:
|
||||||
|
d0 = RM::FSpOpenResFile();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x000e:
|
||||||
|
d0 = RM::FSpCreateResFile();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "selector %04x not yet supported\n", selector);
|
fprintf(stderr, "HighLevelHFSDispatch selector %04x not yet supported\n", selector);
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ToolReturn<2>(-1, d0);
|
||||||
|
return d0;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t HGetVol(uint16_t trap)
|
uint16_t HGetVol(uint16_t trap)
|
||||||
|
@@ -41,38 +41,11 @@
|
|||||||
#include <machine/endian.h>
|
#include <machine/endian.h>
|
||||||
|
|
||||||
using ToolBox::Log;
|
using ToolBox::Log;
|
||||||
|
using MacOS::macos_error_from_errno;
|
||||||
|
|
||||||
namespace OS { namespace Internal {
|
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 ENOENT:
|
||||||
case EACCES:
|
case EACCES:
|
||||||
return errno_to_oserr(errno);
|
return macos_error_from_errno();
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for prodos ftype/auxtype
|
// check for prodos ftype/auxtype
|
||||||
@@ -268,7 +241,7 @@ namespace OS { namespace Internal {
|
|||||||
{
|
{
|
||||||
case ENOENT:
|
case ENOENT:
|
||||||
case EACCES:
|
case EACCES:
|
||||||
return errno_to_oserr(errno);
|
return macos_error_from_errno();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::memmove(buffer, info, 16);
|
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);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -318,7 +291,7 @@ namespace OS { namespace Internal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
rv = ::lseek(refNum, offset, mode);
|
rv = ::lseek(refNum, offset, mode);
|
||||||
if (rv < 0) return errno_to_oserr(errno);
|
if (rv < 0) return macos_error_from_errno();
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -470,8 +443,14 @@ namespace OS { namespace Internal {
|
|||||||
if (filename.empty()) return MacOS::bdNamErr;
|
if (filename.empty()) return MacOS::bdNamErr;
|
||||||
|
|
||||||
int access = 0;
|
int access = 0;
|
||||||
|
if (ioPermission != 0x33) ioPermission &= ~0x30; // drop deny read/write
|
||||||
switch(ioPermission)
|
switch(ioPermission)
|
||||||
{
|
{
|
||||||
|
case 0x33:
|
||||||
|
// PBHOpenDeny exclusive access.
|
||||||
|
access = O_RDWR | O_CREAT; // | O_EXCL;
|
||||||
|
break;
|
||||||
|
|
||||||
case fsWrPerm:
|
case fsWrPerm:
|
||||||
case fsRdWrPerm:
|
case fsRdWrPerm:
|
||||||
case fsRdWrShPerm:
|
case fsRdWrShPerm:
|
||||||
@@ -492,7 +471,7 @@ namespace OS { namespace Internal {
|
|||||||
|
|
||||||
Log(" open(%s, %04x)\n", xname.c_str(), access);
|
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)
|
if (fd < 0 && ioPermission == fsCurPerm && errno == EACCES)
|
||||||
{
|
{
|
||||||
fd = ::open(xname.c_str(), O_RDONLY);
|
fd = ::open(xname.c_str(), O_RDONLY);
|
||||||
@@ -500,7 +479,7 @@ namespace OS { namespace Internal {
|
|||||||
|
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
{
|
{
|
||||||
return errno_to_oserr(errno);
|
return macos_error_from_errno();
|
||||||
}
|
}
|
||||||
|
|
||||||
// allocate the fd entry
|
// allocate the fd entry
|
||||||
|
@@ -6,8 +6,6 @@
|
|||||||
|
|
||||||
namespace OS { namespace Internal {
|
namespace OS { namespace Internal {
|
||||||
|
|
||||||
uint16_t errno_to_oserr(int xerrno);
|
|
||||||
|
|
||||||
uint16_t GetFinderInfo(const std::string &pathname, void *info, bool extended);
|
uint16_t GetFinderInfo(const std::string &pathname, void *info, bool extended);
|
||||||
uint16_t SetFinderInfo(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/sysequ.h>
|
||||||
#include <macos/errors.h>
|
#include <macos/errors.h>
|
||||||
|
#include <macos/tool_return.h>
|
||||||
|
|
||||||
#include "stackframe.h"
|
#include "stackframe.h"
|
||||||
#include "fs_spec.h"
|
#include "fs_spec.h"
|
||||||
@@ -51,6 +52,10 @@ using ToolBox::Log;
|
|||||||
using namespace OS::Internal;
|
using namespace OS::Internal;
|
||||||
using namespace ToolBox;
|
using namespace ToolBox;
|
||||||
|
|
||||||
|
using MacOS::tool_return;
|
||||||
|
using MacOS::macos_error_from_errno;
|
||||||
|
using MacOS::macos_error;
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -101,6 +106,8 @@ namespace
|
|||||||
case 0x434f4445: // 'CODE' (Link)
|
case 0x434f4445: // 'CODE' (Link)
|
||||||
case 0x5041434b: // 'PACK' (PascalIIgs)
|
case 0x5041434b: // 'PACK' (PascalIIgs)
|
||||||
case 0x4b4f4445: // 'KODE' (Link 32-bit Startup)
|
case 0x4b4f4445: // 'KODE' (Link 32-bit Startup)
|
||||||
|
case 0x45525253: // 'ERRS' (PPCLink)
|
||||||
|
case 0x63667267: // 'cfrg' (PPCLink)
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
@@ -398,6 +405,39 @@ namespace RM
|
|||||||
return SetResError(::ResError());
|
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)
|
uint16_t CreateResFile(uint16_t trap)
|
||||||
{
|
{
|
||||||
// PROCEDURE CreateResFile (fileName: Str255);
|
// PROCEDURE CreateResFile (fileName: Str255);
|
||||||
@@ -440,12 +480,12 @@ namespace RM
|
|||||||
fd = ::open(sname.c_str(), O_CREAT | O_EXCL | O_RDWR, 0666);
|
fd = ::open(sname.c_str(), O_CREAT | O_EXCL | O_RDWR, 0666);
|
||||||
if (fd < 0)
|
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);
|
if (fd >= 0) close(fd);
|
||||||
|
|
||||||
HFSUniStr255 fork = {0,{0}};
|
HFSUniStr255 fork = {0,{0}};
|
||||||
::FSGetResourceForkName(&fork);
|
::FSGetResourceForkName(&fork);
|
||||||
|
|
||||||
error = ::FSCreateResourceFork(&ref, fork.length, fork.unicode, 0);
|
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)
|
uint16_t OpenResFile(uint16_t trap)
|
||||||
{
|
{
|
||||||
// OpenResFile (fileName: Str255) : INTEGER;
|
// OpenResFile (fileName: Str255) : INTEGER;
|
||||||
|
|
||||||
ResFileRefNum refNum;
|
|
||||||
FSRef ref;
|
|
||||||
|
|
||||||
uint32_t sp;
|
uint32_t sp;
|
||||||
uint32_t fileName;
|
uint32_t fileName;
|
||||||
uint16_t permission;
|
|
||||||
OSErr error;
|
|
||||||
|
|
||||||
sp = StackFrame<4>(fileName);
|
sp = StackFrame<4>(fileName);
|
||||||
|
|
||||||
@@ -471,27 +591,11 @@ namespace RM
|
|||||||
|
|
||||||
Log("%04x OpenResFile(%s)\n", trap, sname.c_str());
|
Log("%04x OpenResFile(%s)\n", trap, sname.c_str());
|
||||||
|
|
||||||
error = ::FSPathMakeRef( (const UInt8 *)sname.c_str(), &ref, NULL);
|
auto rv = OpenResCommon(sname);
|
||||||
if (error != noErr)
|
|
||||||
{
|
|
||||||
ToolReturn<2>(sp, (uint16_t)-1);
|
|
||||||
return SetResError(error);
|
|
||||||
}
|
|
||||||
|
|
||||||
HFSUniStr255 fork = {0,{0}};
|
ToolReturn<2>(sp, rv.value_or(-1));
|
||||||
::FSGetResourceForkName(&fork);
|
|
||||||
|
|
||||||
refNum = -1;
|
return SetResError(rv.error());
|
||||||
permission = 0; // whatever is allowed.
|
|
||||||
error = ::FSOpenResourceFile(&ref,
|
|
||||||
fork.length,
|
|
||||||
fork.unicode,
|
|
||||||
permission,
|
|
||||||
&refNum);
|
|
||||||
|
|
||||||
ToolReturn<2>(sp, (uint16_t)refNum);
|
|
||||||
|
|
||||||
return SetResError(error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t HOpenResFile(uint16_t trap)
|
uint16_t HOpenResFile(uint16_t trap)
|
||||||
@@ -499,10 +603,6 @@ namespace RM
|
|||||||
// FUNCTION HOpenResFile (vRefNum: Integer; dirID: LongInt;
|
// FUNCTION HOpenResFile (vRefNum: Integer; dirID: LongInt;
|
||||||
// fileName: Str255; permission: SignedByte): Integer;
|
// fileName: Str255; permission: SignedByte): Integer;
|
||||||
|
|
||||||
ResFileRefNum refNum;
|
|
||||||
FSRef ref;
|
|
||||||
OSErr error;
|
|
||||||
|
|
||||||
uint32_t sp;
|
uint32_t sp;
|
||||||
|
|
||||||
uint16_t vRefNum;
|
uint16_t vRefNum;
|
||||||
@@ -525,34 +625,51 @@ namespace RM
|
|||||||
sname = OS::FSSpecManager::ExpandPath(sname, dirID);
|
sname = OS::FSSpecManager::ExpandPath(sname, dirID);
|
||||||
if (sname.empty())
|
if (sname.empty())
|
||||||
{
|
{
|
||||||
error = MacOS::dirNFErr;
|
|
||||||
ToolReturn<2>(sp, (uint16_t)-1);
|
ToolReturn<2>(sp, (uint16_t)-1);
|
||||||
return SetResError(error);
|
return SetResError(MacOS::dirNFErr);
|
||||||
}
|
}
|
||||||
|
|
||||||
error = ::FSPathMakeRef( (const UInt8 *)sname.c_str(), &ref, NULL);
|
auto rv = OpenResCommon(sname, permission);
|
||||||
if (error != noErr)
|
|
||||||
|
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);
|
ToolReturn<2>(sp, (uint16_t)-1);
|
||||||
return SetResError(error);
|
return SetResError(MacOS::dirNFErr);
|
||||||
}
|
}
|
||||||
|
|
||||||
HFSUniStr255 fork = {0,{0}};
|
auto rv = OpenResCommon(sname, permission);
|
||||||
::FSGetResourceForkName(&fork);
|
|
||||||
|
|
||||||
refNum = -1;
|
ToolReturn<2>(sp, rv.value_or(-1));
|
||||||
error = ::FSOpenResourceFile(&ref,
|
|
||||||
fork.length,
|
|
||||||
fork.unicode,
|
|
||||||
permission,
|
|
||||||
&refNum);
|
|
||||||
|
|
||||||
ToolReturn<2>(sp, (uint16_t)refNum);
|
return SetResError(rv.error());
|
||||||
|
|
||||||
return SetResError(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
uint16_t OpenRFPerm(uint16_t trap)
|
uint16_t OpenRFPerm(uint16_t trap)
|
||||||
{
|
{
|
||||||
// FUNCTION OpenRFPerm (fileName: Str255; vRefNum: Integer;
|
// FUNCTION OpenRFPerm (fileName: Str255; vRefNum: Integer;
|
||||||
|
@@ -57,6 +57,9 @@ namespace RM
|
|||||||
uint16_t Get1IndType(uint16_t trap);
|
uint16_t Get1IndType(uint16_t trap);
|
||||||
|
|
||||||
|
|
||||||
|
uint16_t FSpOpenResFile(void);
|
||||||
|
uint16_t FSpCreateResFile(void);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -65,6 +65,9 @@ namespace ToolBox {
|
|||||||
case 0x0015:
|
case 0x0015:
|
||||||
return MM::TempMaxMem();
|
return MM::TempMaxMem();
|
||||||
|
|
||||||
|
case 0x0018:
|
||||||
|
return MM::TempFreeMem();
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "OSDispatch: selector %04x not implemented\n",
|
fprintf(stderr, "OSDispatch: selector %04x not implemented\n",
|
||||||
selector);
|
selector);
|
||||||
@@ -223,7 +226,8 @@ namespace ToolBox {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
// BlockMove (sourcePtr,destPtr: Ptr; byteCount: Size);
|
// BlockMove (sourcePtr,destPtr: Ptr; byteCount: Size);
|
||||||
case 0xa02e:
|
case 0xa02e: // BlockMove
|
||||||
|
case 0xa22e: // BlockMoveData
|
||||||
d0 = MM::BlockMove(trap);
|
d0 = MM::BlockMove(trap);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -285,6 +289,10 @@ namespace ToolBox {
|
|||||||
d0 = MM::HandleZone(trap);
|
d0 = MM::HandleZone(trap);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 0xa128:
|
||||||
|
d0 = MM::RecoverHandle(trap);
|
||||||
|
break;
|
||||||
|
|
||||||
// MaxApplZone
|
// MaxApplZone
|
||||||
case 0xa063:
|
case 0xa063:
|
||||||
d0 = MM::MaxApplZone(trap);
|
d0 = MM::MaxApplZone(trap);
|
||||||
@@ -358,6 +366,19 @@ namespace ToolBox {
|
|||||||
d0 = MM::EmptyHandle(trap);
|
d0 = MM::EmptyHandle(trap);
|
||||||
break;
|
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.
|
// resource manager stuff.
|
||||||
|
|
||||||
// Count1Resources (theType: ResType): Integer;
|
// Count1Resources (theType: ResType): Integer;
|
||||||
|
Reference in New Issue
Block a user