From 172da3e2501487e5970e9fafef109bf00eb90793 Mon Sep 17 00:00:00 2001 From: Kelvin Sherlock Date: Sat, 17 Jan 2015 18:33:34 -0500 Subject: [PATCH] fix CreateRes, add HCreateRes --- test/makefile | 2 +- test/test_createresfile.c | 132 ++++++++++++++++++++++++++++++++++++++ toolbox/rm.cpp | 65 ++++++++++++++----- toolbox/rm.h | 1 + toolbox/toolbox.cpp | 4 ++ 5 files changed, 188 insertions(+), 16 deletions(-) create mode 100644 test/test_createresfile.c diff --git a/test/makefile b/test/makefile index 419297e..7a0e473 100644 --- a/test/makefile +++ b/test/makefile @@ -22,7 +22,7 @@ LDFLAGS = -w -c 'MPS ' -t MPST \ SCFLAGS = -p -TARGETS = test_new_handle test_new_handle_2 test_new_pointer test_volumes +TARGETS = test_new_handle test_new_handle_2 test_new_pointer test_volumes test_createresfile all : $(TARGETS) diff --git a/test/test_createresfile.c b/test/test_createresfile.c new file mode 100644 index 0000000..1d7bc42 --- /dev/null +++ b/test/test_createresfile.c @@ -0,0 +1,132 @@ +#include +#include +#include +#include + + +/* + * Test the three (thanks, Apple) ways to create a resource file. + * + */ + +ConstStr255Param fname = (ConstStr255Param)"\pxxx-test-resource-xxx"; + + +void test_fspcreateresfile(void) +{ + OSErr err; + FSSpec spec; + + err = FSMakeFSSpec(0, 0, fname, &spec); + if (err) { + + fprintf(stderr, "FSMakeFSSpec failed: %d\n", err); + exit(3); + } + + FSpDelete(&spec); + FSpCreateResFile(&spec, 'TEST', 'BINA', 0); + if ( (err = ResError()) != 0) { + fprintf(stderr, "FSpCreateResFile failed (File does not exist): %d\n", err); + exit(1); + } + + // Verify it doesn't fail if the file/fork already exist. + FSpCreateResFile(&spec, 'TEST', 'BINA', 0); + if ( (err = ResError()) != 0) { + fprintf(stderr, "FSpCreateResFile (File/Fork exist) failed: %d\n", err); + exit(2); + } + + // Verify it doesn't fail if the file exists w/o a resource fork. + FSpDelete(&spec); + FSpCreate(&spec, 'TEST', 'BINA', 0); + FSpCreateResFile(&spec, 'TEST', 'BINA', 0); + if ( (err = ResError()) != 0) { + fprintf(stderr, "FSpCreateResFile (File exists) failed: %d\n", err); + exit(2); + } + + FSpDelete(&spec); + + +} + +void test_hcreateresfile(void) +{ + OSErr err; + + // will 0, 0 work on real macos? + + HDelete(0, 0, fname); + HCreateResFile(0, 0, fname); + if ( (err = ResError()) != 0) { + fprintf(stderr, "HCreateResFile failed (File does not exist): %d\n", err); + exit(1); + } + + // Verify it doesn't fail if the file/fork already exist. + HCreateResFile(0, 0, fname); + if ( (err = ResError()) != 0) { + fprintf(stderr, "HCreateResFile (File/Fork exist) failed: %d\n", err); + exit(2); + } + + // Verify it doesn't fail if the file exists w/o a resource fork. + HDelete(0, 0, fname); + HCreate(0, 0, fname, 'TEST', 'BINA'); + HCreateResFile(0, 0, fname); + if ( (err = ResError()) != 0) { + fprintf(stderr, "HCreateResFile (File exists) failed: %d\n", err); + exit(2); + } + + HDelete(0, 0, fname); +} + +void test_createresfile(void) +{ + OSErr err; + + FSDelete(fname, 0); + CreateResFile(fname); + if ( (err = ResError()) != 0) { + fprintf(stderr, "CreateResFile failed (File does not exist): %d\n", err); + exit(1); + } + + // Verify it does fail if the file/fork already exist. + CreateResFile(fname); + if ( (err = ResError()) != dupFNErr) { + fprintf(stderr, "CreateResFile (File/Fork exist) failed: %d\n", err); + exit(2); + } + + // Verify it doesn't fail if the file exists w/o a resource fork. + FSDelete(fname, 0); + Create(fname, 0, 'TEST', 'BINA'); + CreateResFile(fname); + if ( (err = ResError()) != 0) { + fprintf(stderr, "CreateResFile (File exists) failed: %d\n", err); + exit(2); + } + + FSDelete(fname, 0); + + +} + +int main(int argc, char **argv) +{ + + (void)argc; + (void)argv; + + + test_createresfile(); + test_hcreateresfile(); + test_fspcreateresfile(); + + + return 0; +} \ No newline at end of file diff --git a/toolbox/rm.cpp b/toolbox/rm.cpp index 0c196b6..60d736e 100644 --- a/toolbox/rm.cpp +++ b/toolbox/rm.cpp @@ -418,7 +418,7 @@ namespace RM } - tool_return CreateResFile(const std::string &path) + tool_return CreateResFile(const std::string &path, uint32_t creator = 0, uint32_t fileType = 0) { if (path.empty()) return MacOS::paramErr; @@ -427,10 +427,7 @@ namespace RM OSErr error; int fd; - error = ::FSPathMakeRef((const UInt8 *)path.c_str(), &ref, NULL); - if (error != noErr) - return macos_error(error); - + // FSPathMakeRef only works with existing files. // FSCreateResourceFork only works with existing files. fd = ::open(path.c_str(), O_CREAT | O_EXCL | O_RDWR, 0666); @@ -438,7 +435,18 @@ namespace RM { if (errno != EEXIST) return macos_error_from_errno(); } - if (fd >= 0) close(fd); + else + { + if (creator || fileType) + OS::Internal::SetFinderInfo(path, fileType, creator); + + close(fd); + } + + + error = ::FSPathMakeRef((const UInt8 *)path.c_str(), &ref, NULL); + if (error != noErr) + return macos_error(error); HFSUniStr255 fork = {0,{0}}; @@ -447,6 +455,11 @@ namespace RM error = ::FSCreateResourceFork(&ref, fork.length, fork.unicode, 0); + // CreateResFile returns an error if the fork exists, HCreateResFile + // and FSpCreateResFile do not. + + + if (error == errFSForkExists) error = MacOS::dupFNErr; return macos_error(error); } @@ -476,7 +489,35 @@ namespace RM auto rv = CreateResFile(sname); - return SetResError(rv.error() == errFSForkExists ? 0 : rv.error()); + return SetResError(rv.error()); + } + + uint16_t HCreateResFile(uint16_t trap) + { + // PROCEDURE HCreateResFile (vRefNum: Integer; dirID: LongInt; + // fileName: Str255); + + uint16_t vRefNum; + uint32_t dirID; + uint32_t fileName; + + StackFrame<10>(vRefNum, dirID, fileName); + + std::string sname = ToolBox::ReadPString(fileName, true); + + Log("%04x HCreateResFile(%04x, %08x, %s)\n", + trap, vRefNum, dirID, sname.c_str()); + + + sname = OS::FSSpecManager::ExpandPath(sname, dirID); + if (sname.empty()) + { + return SetResError(MacOS::dirNFErr); + } + + auto rv = CreateResFile(sname); + + return SetResError(rv.error() == MacOS::dupFNErr ? 0 : rv.error()); } @@ -512,15 +553,9 @@ namespace RM 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) - { - OS::Internal::SetFinderInfo(sname, fileType, creator); - } + auto rv = CreateResFile(sname, creator, fileType); - return SetResError(rv.error() == errFSForkExists ? 0 : rv.error()); + return SetResError(rv.error() == MacOS::dupFNErr ? 0 : rv.error()); } diff --git a/toolbox/rm.h b/toolbox/rm.h index a67d7f4..6148545 100644 --- a/toolbox/rm.h +++ b/toolbox/rm.h @@ -33,6 +33,7 @@ namespace RM uint16_t UseResFile(uint16_t trap); uint16_t CreateResFile(uint16_t trap); + uint16_t HCreateResFile(uint16_t trap); uint16_t Count1Resources(uint16_t trap); uint16_t UpdateResFile(uint16_t trap); diff --git a/toolbox/toolbox.cpp b/toolbox/toolbox.cpp index ccb6979..5aa74df 100644 --- a/toolbox/toolbox.cpp +++ b/toolbox/toolbox.cpp @@ -434,6 +434,10 @@ namespace ToolBox { d0 = RM::HOpenResFile(trap); break; + case 0xa81b: + d0 = RM::HCreateResFile(trap); + break; + case 0xa81c: d0 = RM::Count1Types(trap); break;