From 1aebf4665396b89d9240e8550d64d9bfc18a9c01 Mon Sep 17 00:00:00 2001 From: Kelvin Sherlock Date: Sun, 23 Jun 2013 20:42:16 -0400 Subject: [PATCH] RM::CreateResFile --- toolbox/rm.cpp | 62 +++++++++++++++++++++++++++++++++++++++++++-- toolbox/rm.h | 2 ++ toolbox/toolbox.cpp | 5 ++++ 3 files changed, 67 insertions(+), 2 deletions(-) diff --git a/toolbox/rm.cpp b/toolbox/rm.cpp index 6d79c40..d8b196c 100644 --- a/toolbox/rm.cpp +++ b/toolbox/rm.cpp @@ -10,18 +10,21 @@ #include "rm.h" #include "toolbox.h" #include "mm.h" +#include "os_internal.h" #include #include #include #include - +#include #include "stackframe.h" using ToolBox::Log; +using namespace OS::Internal; + namespace { @@ -290,7 +293,7 @@ namespace RM sp = StackFrame<4>(fileName); - std::string sname = ToolBox::ReadPString(fileName); + std::string sname = ToolBox::ReadPString(fileName, true); Log("%04x OpenResFile(%s)\n", trap, sname.c_str()); @@ -322,6 +325,61 @@ namespace RM return SetResError(::ResError()); } + uint16_t CreateResFile(uint16_t trap) + { + // PROCEDURE CreateResFile (fileName: Str255); + + /* + * CreateResFile creates a resource file containing no resource + * data. If there's no file at all with the given name, it also + * creates an empty data fork for the file. If there's already a + * resource file with the given name (that is, a resource fork + * that isn't empty), CreateResFile will do nothing and the + * ResError function will return an appropriate Operating System + * result code. + */ + + // FSCreateResourceFile uses the parent FSRef + a file name. + + + uint32_t fileName; + FSRef ref; + OSErr error; + int fd; + + StackFrame<4>(fileName); + + std::string sname = ToolBox::ReadPString(fileName, true); + Log("%04x CreateResFile(%s)\n", trap, sname.c_str()); + + if (!sname.length()) return SetResError(MacOS::paramErr); + + // 1. if the file exists, call FSCreateResourceFork on the file. + // 2. if the file does not exist, create the file then call + // FSCreateResourceFork + + error = FSPathMakeRef((const UInt8 *)sname.c_str(), &ref, NULL); + if (error != noErr) + { + return SetResError(error); + } + + 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 (fd >= 0) close(fd); + + HFSUniStr255 fork = {0,{0}}; + FSGetResourceForkName(&fork); + + error = FSCreateResourceFork(&ref, fork.length, fork.unicode, 0); + + return SetResError(error); + } + + // todo -- move since it's not RM related. uint16_t UnloadSeg(uint16_t trap) diff --git a/toolbox/rm.h b/toolbox/rm.h index 07077ba..68e340d 100644 --- a/toolbox/rm.h +++ b/toolbox/rm.h @@ -29,6 +29,8 @@ namespace RM uint16_t CurResFile(uint16_t trap); uint16_t UseResFile(uint16_t trap); + + uint16_t CreateResFile(uint16_t trap); } diff --git a/toolbox/toolbox.cpp b/toolbox/toolbox.cpp index 6645d7d..207075a 100644 --- a/toolbox/toolbox.cpp +++ b/toolbox/toolbox.cpp @@ -305,6 +305,11 @@ namespace ToolBox { d0 = RM::ResError(trap); break; + // CreateResFile(fileName: Str255); + case 0xa9b1: + d0 = RM::CreateResFile(trap); + break; + // UnloadSeg (routineAddr: Ptr); case 0xa9f1: d0 = RM::UnloadSeg(trap);