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:
ksherlock 2011-03-07 00:09:37 +00:00
parent 0e083d53e7
commit 87d6070dcf
4 changed files with 295 additions and 9 deletions

View File

@ -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?

254
Device/SDKImage.cpp Normal file
View 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
View 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 &);
};
}

View File

@ -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;
}