mirror of
https://github.com/ksherlock/profuse.git
synced 2024-05-28 22:41:39 +00:00
add (read only) support for SDK images. Requires nufxlib.
git-svn-id: https://profuse.googlecode.com/svn/branches/profuse_interim@374 aa027e90-d47c-11dd-86d7-074df07e0730
This commit is contained in:
parent
0e083d53e7
commit
87d6070dcf
|
@ -19,6 +19,7 @@
|
||||||
#include <Device/DiskCopy42Image.h>
|
#include <Device/DiskCopy42Image.h>
|
||||||
#include <Device/DavexDiskImage.h>
|
#include <Device/DavexDiskImage.h>
|
||||||
#include <Device/RawDevice.h>
|
#include <Device/RawDevice.h>
|
||||||
|
#include <Device/SDKImage.h>
|
||||||
|
|
||||||
using namespace Device;
|
using namespace Device;
|
||||||
|
|
||||||
|
@ -51,7 +52,9 @@ unsigned BlockDevice::ImageType(const char *type, unsigned defv)
|
||||||
return '2IMG';
|
return '2IMG';
|
||||||
if (::strcasecmp(type, "2img") == 0)
|
if (::strcasecmp(type, "2img") == 0)
|
||||||
return '2IMG';
|
return '2IMG';
|
||||||
|
|
||||||
|
if (::strcasecmp(type, "dc") == 0)
|
||||||
|
return 'DC42';
|
||||||
if (::strcasecmp(type, "dc42") == 0)
|
if (::strcasecmp(type, "dc42") == 0)
|
||||||
return 'DC42';
|
return 'DC42';
|
||||||
|
|
||||||
|
@ -74,6 +77,8 @@ unsigned BlockDevice::ImageType(const char *type, unsigned defv)
|
||||||
// not supported yet.
|
// not supported yet.
|
||||||
if (::strcasecmp(type, "sdk") == 0)
|
if (::strcasecmp(type, "sdk") == 0)
|
||||||
return 'SDK_';
|
return 'SDK_';
|
||||||
|
if (::strcasecmp(type, "shk") == 0)
|
||||||
|
return 'SDK_';
|
||||||
|
|
||||||
return defv;
|
return defv;
|
||||||
}
|
}
|
||||||
|
@ -102,7 +107,11 @@ BlockDevicePointer BlockDevice::Open(const char *name, File::FileFlags flags, un
|
||||||
imageType = ImageType(name, 'PO__');
|
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?
|
// TODO -- if no image type, guess based on file size?
|
||||||
|
|
||||||
MappedFile file(name, flags);
|
MappedFile file(name, flags);
|
||||||
|
@ -124,7 +133,7 @@ BlockDevicePointer BlockDevice::Open(const char *name, File::FileFlags flags, un
|
||||||
|
|
||||||
case 'DVX_':
|
case 'DVX_':
|
||||||
return DavexDiskImage::Open(&file);
|
return DavexDiskImage::Open(&file);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// throw an error?
|
// throw an error?
|
||||||
|
|
254
Device/SDKImage.cpp
Normal file
254
Device/SDKImage.cpp
Normal file
|
@ -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 <unistd.h>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cerrno>
|
||||||
|
|
||||||
|
#include <NufxLib.h>
|
||||||
|
|
||||||
|
|
||||||
|
#include <File/File.h>
|
||||||
|
#include <File/MappedFile.h>
|
||||||
|
|
||||||
|
#include <ProFUSE/Exception.h>
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
}
|
27
Device/SDKImage.h
Normal file
27
Device/SDKImage.h
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
//
|
||||||
|
// SDKImage.h
|
||||||
|
// profuse
|
||||||
|
//
|
||||||
|
// Created by Kelvin Sherlock on 3/6/2011.
|
||||||
|
// Copyright 2011 __MyCompanyName__. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <Device/BlockDevice.h>
|
||||||
|
#include <Device/DiskImage.h>
|
||||||
|
|
||||||
|
namespace Device {
|
||||||
|
|
||||||
|
class SDKImage : public DiskImage
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
static BlockDevicePointer Open(const char *name);
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
SDKImage();
|
||||||
|
SDKImage(const SDKImage &);
|
||||||
|
~SDKImage();
|
||||||
|
SDKImage & operator=(const SDKImage &);
|
||||||
|
};
|
||||||
|
}
|
8
main.cpp
8
main.cpp
|
@ -278,15 +278,11 @@ int main(int argc, char *argv[])
|
||||||
exit(1);
|
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)
|
catch (ProFUSE::Exception &e)
|
||||||
{
|
{
|
||||||
std::fprintf(stderr, "%s\n", e.what());
|
std::fprintf(stderr, "%s\n", e.what());
|
||||||
|
std::fprintf(stderr, "%s\n", e.errorString());
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user