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/DavexDiskImage.h>
|
||||
#include <Device/RawDevice.h>
|
||||
#include <Device/SDKImage.h>
|
||||
|
||||
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?
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue