diff --git a/Device/BlockDevice.cpp b/Device/BlockDevice.cpp index c114a00..79f6e86 100644 --- a/Device/BlockDevice.cpp +++ b/Device/BlockDevice.cpp @@ -19,6 +19,7 @@ #include #include #include +#include using namespace Device; @@ -51,7 +52,9 @@ unsigned BlockDevice::ImageType(const char *type, unsigned defv) return '2IMG'; if (::strcasecmp(type, "2img") == 0) return '2IMG'; - + + if (::strcasecmp(type, "dc") == 0) + return 'DC42'; if (::strcasecmp(type, "dc42") == 0) return 'DC42'; @@ -74,6 +77,8 @@ unsigned BlockDevice::ImageType(const char *type, unsigned defv) // not supported yet. if (::strcasecmp(type, "sdk") == 0) return 'SDK_'; + if (::strcasecmp(type, "shk") == 0) + return 'SDK_'; return defv; } @@ -102,7 +107,11 @@ BlockDevicePointer BlockDevice::Open(const char *name, File::FileFlags flags, un imageType = ImageType(name, 'PO__'); } - + if (imageType == 'SDK_') + { + // opened by path name. + return SDKImage::Open(name); + } // TODO -- if no image type, guess based on file size? MappedFile file(name, flags); @@ -124,7 +133,7 @@ BlockDevicePointer BlockDevice::Open(const char *name, File::FileFlags flags, un case 'DVX_': return DavexDiskImage::Open(&file); - + } // throw an error? diff --git a/Device/SDKImage.cpp b/Device/SDKImage.cpp new file mode 100644 index 0000000..7b550b1 --- /dev/null +++ b/Device/SDKImage.cpp @@ -0,0 +1,254 @@ +// +// SDKImage.cpp +// profuse +// +// Created by Kelvin Sherlock on 3/6/2011. +// Copyright 2011 __MyCompanyName__. All rights reserved. +// + +#include "SDKImage.h" + +#include +#include +#include +#include + +#include + + +#include +#include + +#include + + +using ProFUSE::Exception; +using ProFUSE::POSIXException; + + +class NuFXException : public Exception +{ +public: + + NuFXException(const char *cp, NuError error); + NuFXException(const std::string& string, NuError error); + + virtual const char *errorString(); + +}; + + +inline NuFXException::NuFXException(const char *cp, NuError error) : +Exception(cp, error) +{ +} + +inline NuFXException::NuFXException(const std::string& string, NuError error) : +Exception(string, error) +{ +} + +const char *NuFXException::errorString() +{ + return ::NuStrError((NuError)error()); +} + + +using namespace Device; + +struct record_thread +{ + NuRecordIdx record_index; + NuThreadIdx thread_index; +}; + +/* + * callback function to + * + * + */ +static NuResult ContentFunction(NuArchive *archive, void *vp) +{ + const NuRecord *record = (const NuRecord *)vp; + + /* + * The application must not attempt to retain a copy of "pRecord" + * after the callback returns, as the structure may be freed. + * Anything of interest should be copied out. + */ + + + for (unsigned i = 0; i < NuRecordGetNumThreads(record); ++i) + { + const NuThread *thread = NuGetThread(record, i); + + + printf("%ld, %ld\n", (long)record->recordIdx, (long)thread->threadIdx); + + if (NuGetThreadID(thread) == kNuThreadIDDiskImage) + { + record_thread *rt; + + NuGetExtraData(archive, (void **)&rt); + if (rt) + { + rt->record_index = record->recordIdx; + rt->thread_index = thread->threadIdx; + } + + return kNuAbort; + } + + } + + + return kNuOK; +} + +static NuThreadIdx FindDiskThread(const NuRecord *record) +{ +#undef __METHOD__ +#define __METHOD__ "SDKImage::FindDiskThread" + + for (unsigned i = 0; i < NuRecordGetNumThreads(record); ++i) + { + const NuThread *thread = NuGetThread(record, i); + + if (NuGetThreadID(thread) == kNuThreadIDDiskImage) + return thread->threadIdx; + } + + throw Exception(__METHOD__ ": not a disk image"); +} + +/* + * helper function to extract SDK image to /tmp and return a + * ProDOSDiskImage of the /tmp file. + * + */ +BlockDevicePointer SDKImage::Open(const char *name) +{ +#undef __METHOD__ +#define __METHOD__ "SDKImage::Open" + + + char tmp[] = "/tmp/pfuse.XXXXXXXX"; + + int fd = -1; + FILE *fp = NULL; + NuArchive *archive = NULL; + //const NuThread *thread = NULL; + const NuRecord *record = NULL; + NuDataSink *sink = NULL; + NuRecordIdx rIndex; + NuThreadIdx tIndex; + + NuError e; + + + record_thread rt = {0, 0}; + + try { + + + e = NuOpenRO(name, &archive); + if (e) + { + throw NuFXException(__METHOD__ ": NuOpenRO", e); + } + NuSetExtraData(archive, (void *)&rt); + + // NuContents screws everything up??? + /* + e = NuContents(archive, ContentFunction); + if (e == kNuErrAborted) + { + // ok! + } + else if (e == kNuErrNone) + { + throw Exception(__METHOD__ ": NuContents: not a disk image"); + } + else + { + throw NuFXException(__METHOD__ ": NuContents", e); + } + + + printf("%ld, %ld\n", (long)rt.record_index, (long)rt.thread_index); + */ + + e = NuGetRecordIdxByPosition(archive, 0, &rIndex); + if (e) + { + throw NuFXException(__METHOD__ ": NuGetRecordIdxByPosition", e); + } + printf("%ld\n", rIndex); + + /* load up the record. + * I assume this is necessary since thread ids are only unique + * within a record, not across the entire archive + */ + + e = NuGetRecord(archive, rIndex, &record); + if (e) + { + + throw NuFXException(__METHOD__ ": NuGetRecord", e); + } + + tIndex = FindDiskThread(record); // throws on error. + printf("%ld\n", tIndex); + + + fd = mkstemp(tmp); + if (fd < 0) + { + throw POSIXException(__METHOD__ ": mkstemp", errno); + } + + fp = fdopen(fd, "w"); + if (!fp) + { + ::close(fd); + throw POSIXException(__METHOD__ ": fdopen", errno); + } + + e = NuCreateDataSinkForFP(true, kNuConvertOff, fp, &sink); + if (e) + { + throw NuFXException(__METHOD__ ": NuCreateDataSinkForFP", e); + } + + + e = NuExtractThread(archive, tIndex, sink); + if (e) + { + throw NuFXException(__METHOD__ ": NuExtractThread", e); + } + + + fclose(fp); + NuClose(archive); + NuFreeDataSink(sink); + fp = NULL; + archive = NULL; + sink = NULL; + } + catch(...) + { + if (fp) fclose(fp); + if (archive) NuClose(archive); + if (sink) NuFreeDataSink(sink); + + throw; + } + + // todo -- maybe SDKImage should extend ProDOSOrderDiskImage, have destructor + // that unklinks the temp file. + + MappedFile file(tmp, File::ReadOnly); + + return ProDOSOrderDiskImage::Open(&file); + +} diff --git a/Device/SDKImage.h b/Device/SDKImage.h new file mode 100644 index 0000000..4d54444 --- /dev/null +++ b/Device/SDKImage.h @@ -0,0 +1,27 @@ +// +// SDKImage.h +// profuse +// +// Created by Kelvin Sherlock on 3/6/2011. +// Copyright 2011 __MyCompanyName__. All rights reserved. +// + +#include +#include + +namespace Device { + + class SDKImage : public DiskImage + { + public: + + static BlockDevicePointer Open(const char *name); + + + private: + SDKImage(); + SDKImage(const SDKImage &); + ~SDKImage(); + SDKImage & operator=(const SDKImage &); + }; +} \ No newline at end of file diff --git a/main.cpp b/main.cpp index b14005d..137d0d3 100644 --- a/main.cpp +++ b/main.cpp @@ -278,15 +278,11 @@ int main(int argc, char *argv[]) exit(1); } } - catch (ProFUSE::POSIXException &e) - { - std::fprintf(stderr, "%s\n", e.what()); - std::fprintf(stderr, "%s\n", e.errorString()); - return -1; - } + catch (ProFUSE::Exception &e) { std::fprintf(stderr, "%s\n", e.what()); + std::fprintf(stderr, "%s\n", e.errorString()); return -1; }