switch to BlockDevice, smart_ptr.

git-svn-id: https://profuse.googlecode.com/svn/branches/profuse_interim@342 aa027e90-d47c-11dd-86d7-074df07e0730
This commit is contained in:
ksherlock 2011-02-20 23:05:40 +00:00
parent 4cdfc52c04
commit 3f8e7ad7ae
4 changed files with 175 additions and 88 deletions

View File

@ -24,6 +24,7 @@
#include <set> #include <set>
#include <vector> #include <vector>
struct ucmp struct ucmp
{ {
bool operator()(unsigned a, unsigned b) const bool operator()(unsigned a, unsigned b) const
@ -39,20 +40,28 @@ typedef set<unsigned, ucmp> uset;
Disk::Disk() Disk::Disk()
{ {
_data = (uint8_t *)-1;
_blocks = 0; _blocks = 0;
_offset = 0;
_size = 0;
_flags = 0;
} }
Disk::~Disk() Disk::~Disk()
{ {
if (_data != (uint8_t *)-1)
munmap(_data, _size);
} }
Disk::Disk(Device::BlockDevicePointer device) :
_device(device)
{
_blocks = _device->blocks();
}
DiskPointer Disk::OpenFile(Device::BlockDevicePointer device)
{
DiskPointer disk(new Disk(device));
return disk;
}
#if 0
Disk *Disk::OpenFile(const char *file, unsigned flags) Disk *Disk::OpenFile(const char *file, unsigned flags)
{ {
int fd; int fd;
@ -155,7 +164,7 @@ Disk *Disk::OpenFile(const char *file, unsigned flags)
return d; return d;
} }
#endif
// load the mini entry into the regular entry. // load the mini entry into the regular entry.
int Disk::Normalize(FileEntry &f, unsigned fork, ExtendedEntry *ee) int Disk::Normalize(FileEntry &f, unsigned fork, ExtendedEntry *ee)
@ -200,31 +209,11 @@ int Disk::Normalize(FileEntry &f, unsigned fork, ExtendedEntry *ee)
int Disk::Read(unsigned block, void *buffer) int Disk::Read(unsigned block, void *buffer)
{ {
if (block > _blocks) return -P8_INVALID_BLOCK;
if (_flags & P8_DOS_ORDER)
{
static unsigned do_map[] = {0x00, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x0f };
unsigned track = (block & ~0x07) << 9;
unsigned sector = (block & 0x07) << 1;
for (unsigned i = 0; i < 2; i++)
{
unsigned offset = track | (do_map[sector+i] << 8);
memcpy(buffer, _data + _offset + offset, 256);
buffer = (char *)buffer + 256;
}
return 1;
}
if (block > _blocks) return -P8_INVALID_BLOCK;
_device->read(block, buffer);
memcpy(buffer, _data + _offset + (block << 9), BLOCK_SIZE);
return 1; return 1;
} }

20
Disk.h
View File

@ -13,7 +13,10 @@
#include <vector> #include <vector>
#include "File.h" #include <ProDOS/File.h>
#include <Device/BlockDevice.h>
#include <tr1/memory>
enum { enum {
@ -40,6 +43,8 @@ enum {
}; };
class Disk;
typedef std::tr1::shared_ptr<Disk> DiskPointer;
class Disk { class Disk {
@ -47,7 +52,7 @@ public:
~Disk(); ~Disk();
//static Disk *Open2MG(const char *file); //static Disk *Open2MG(const char *file);
static Disk *OpenFile(const char *file, unsigned flags); static DiskPointer OpenFile(Device::BlockDevicePointer device);
int Normalize(FileEntry &f, unsigned fork, ExtendedEntry *ee = NULL); int Normalize(FileEntry &f, unsigned fork, ExtendedEntry *ee = NULL);
@ -65,13 +70,14 @@ public:
private: private:
Disk(); Disk();
uint8_t *_data; Disk(Device::BlockDevicePointer device);
unsigned _offset;
unsigned _blocks;
size_t _size;
unsigned _flags; unsigned _blocks;
Device::BlockDevicePointer _device;
}; };
#endif #endif

190
main.cpp
View File

@ -14,29 +14,39 @@
#define _POSIX_C_SOURCE 200112L #define _POSIX_C_SOURCE 200112L
*/ */
#include <stdio.h> #include <cstdio>
#include <stdlib.h> #include <cstdlib>
#include <string.h> #include <cstring>
#include <ctype.h> #include <cctype>
#include <vector> #include <vector>
#include <string> #include <string>
#include <tr1/memory>
#include <Device/BlockDevice.h>
#include "profuse.h" #include "profuse.h"
using std::vector; using std::vector;
using std::string; using std::string;
using std::tr1::shared_ptr;
Disk *disk = NULL;
char *dfile = NULL; /*
* globals variables.
*
*/
std::string fDiskImage;
DiskPointer disk;
VolumeEntry volume; VolumeEntry volume;
bool dos_order = false;
bool validProdosName(const char *name) bool validProdosName(const char *name)
{ {
// OS X looks for hidden files that don't exist (and aren't legal prodos names) // OS X looks for hidden files that don't exist (and aren't legal prodos names)
@ -70,46 +80,81 @@ static struct fuse_lowlevel_ops prodos_oper;
enum { enum {
PRODOS_OPT_HELP, PRODOS_OPT_HELP,
PRODOS_OPT_VERSION, PRODOS_OPT_VERSION,
PRODOS_OPT_DOS_ORDER PRODOS_OPT_WRITE,
PRODOS_OPT_FORMAT,
PRODOS_OPT_VERBOSE
}; };
struct options {
char *format;
int readOnly;
int readWrite;
int verbose;
int debug;
} options;
#define PRODOS_OPT_KEY(T, P, V) {T, offsetof(struct options, P), V}
static struct fuse_opt prodos_opts[] = { static struct fuse_opt prodos_opts[] = {
FUSE_OPT_KEY("-h", PRODOS_OPT_HELP), FUSE_OPT_KEY("-h", PRODOS_OPT_HELP),
FUSE_OPT_KEY("--help", PRODOS_OPT_HELP), FUSE_OPT_KEY("--help", PRODOS_OPT_HELP),
FUSE_OPT_KEY("-V", PRODOS_OPT_VERSION), FUSE_OPT_KEY("-V", PRODOS_OPT_VERSION),
FUSE_OPT_KEY("--version", PRODOS_OPT_VERSION), FUSE_OPT_KEY("--version", PRODOS_OPT_VERSION),
FUSE_OPT_KEY("--dos-order", PRODOS_OPT_DOS_ORDER),
PRODOS_OPT_KEY("-v", verbose, 1),
PRODOS_OPT_KEY("-w", readWrite, 1),
PRODOS_OPT_KEY("rw", readWrite, 1),
PRODOS_OPT_KEY("-d", debug, 1),
PRODOS_OPT_KEY("--format=%s", format, 0),
PRODOS_OPT_KEY("format=%s", format, 0),
{0, 0, 0} {0, 0, 0}
}; };
static void usage() static void usage()
{ {
fprintf(stderr, "profuse [options] disk_image mountpoint\n"); fprintf(stderr, "profuse [options] disk_image [mountpoint]\n"
"Options:\n"
" -d debug\n"
" -r readonly\n"
" -w mount writable [not yet]\n"
" -v verbose\n"
" --format=format specify the disk image format. Valid values are:\n"
" dc42 DiskCopy 4.2 Image\n"
" davex Davex Disk Image\n"
" 2img Universal Disk Image\n"
" do DOS Order Disk Image\n"
" po ProDOS Order Disk Image (default)\n"
" -o opt1,opt2... other mount parameters.\n"
);
} }
static int prodos_opt_proc(void *data, const char *arg, int key, struct fuse_args *outargs) static int prodos_opt_proc(void *data, const char *arg, int key, struct fuse_args *outargs)
{ {
switch(key) switch(key)
{ {
/*
case PRODOS_OPT_HELP: case PRODOS_OPT_HELP:
usage(); usage();
exit(0); exit(0);
break; break;
*/
case PRODOS_OPT_VERSION: case PRODOS_OPT_VERSION:
// TODO // TODO
exit(1); exit(1);
break; break;
case PRODOS_OPT_DOS_ORDER:
dos_order = true;
return 0;
break;
case FUSE_OPT_KEY_NONOPT: case FUSE_OPT_KEY_NONOPT:
if (dfile == NULL) // first arg is the disk image.
if (fDiskImage.empty())
{ {
dfile = strdup(arg); fDiskImage = arg;
return 0; return 0;
} }
return 1; return 1;
@ -159,15 +204,25 @@ int main(int argc, char *argv[])
struct fuse_chan *ch; struct fuse_chan *ch;
char *mountpoint = NULL; char *mountpoint = NULL;
int err = -1; int err = -1;
struct options options;
unsigned format = 0;
int foreground = false;
int multithread = false;
#if __APPLE__ #if __APPLE__
string mountpath; string mountpath;
#endif #endif
disk = NULL;
bzero(&prodos_oper, sizeof(prodos_oper));
std::memset(&prodos_oper, 0, sizeof(prodos_oper));
std::memset(&options, 0, sizeof(options));
prodos_oper.listxattr = prodos_listxattr; prodos_oper.listxattr = prodos_listxattr;
prodos_oper.getxattr = prodos_getxattr; prodos_oper.getxattr = prodos_getxattr;
@ -185,23 +240,54 @@ int main(int argc, char *argv[])
// scan the argument list, looking for the name of the disk image. // scan the argument list, looking for the name of the disk image.
if (fuse_opt_parse(&args, NULL , prodos_opts, prodos_opt_proc) == -1) if (fuse_opt_parse(&args, &options , prodos_opts, prodos_opt_proc) == -1)
exit(1); exit(1);
if (dfile == NULL || *dfile == 0) if (fDiskImage.empty())
{ {
usage(); usage();
exit(0); exit(1);
} }
disk = Disk::OpenFile(dfile, dos_order); // default prodos-order disk image.
if (options.format)
if (!disk)
{ {
fprintf(stderr, "Unable to mount disk %s\n", dfile); format = Device::BlockDevice::ImageType(options.format);
exit(1); if (!format)
std::fprintf(stderr, "Warning: Unknown image type ``%s''\n", options.format);
}
try {
Device::BlockDevicePointer device;
device.reset ( Device::BlockDevice::Open(fDiskImage.c_str(), File::ReadOnly, format) );
if (!device.get())
{
std::fprintf(stderr, "Error: Unknown or unsupported device type.\n");
exit(1);
}
disk = Disk::OpenFile(device);
if (!disk.get())
{
fprintf(stderr, "Unable to mount disk %s\n", fDiskImage.c_str());
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());
return -1;
}
disk->ReadVolume(&volume, NULL); disk->ReadVolume(&volume, NULL);
@ -235,6 +321,7 @@ int main(int argc, char *argv[])
#endif #endif
foreground = options.debug;
if (mountpoint == NULL || *mountpoint == 0) if (mountpoint == NULL || *mountpoint == 0)
@ -244,26 +331,32 @@ int main(int argc, char *argv[])
} }
if ( (ch = fuse_mount(mountpoint, &args)) != NULL) if ( (ch = fuse_mount(mountpoint, &args)) != NULL)
{ {
struct fuse_session *se; struct fuse_session *se;
se = fuse_lowlevel_new(&args, &prodos_oper, sizeof(prodos_oper), NULL); se = fuse_lowlevel_new(&args, &prodos_oper, sizeof(prodos_oper), NULL);
if (se != NULL) if (se != NULL) do {
{
if (fuse_set_signal_handlers(se) != -1) err = fuse_daemonize(foreground);
{ if (err < 0 ) break;
fuse_session_add_chan(se, ch);
err = fuse_session_loop(se);
fuse_remove_signal_handlers(se);
fuse_session_remove_chan(ch);
}
fuse_session_destroy(se); err = fuse_set_signal_handlers(se);
} if (err < 0) break;
fuse_session_add_chan(se, ch);
if (multithread) err = fuse_session_loop_mt(se);
else err = fuse_session_loop(se);
fuse_remove_signal_handlers(se);
fuse_session_remove_chan(ch);
} while (false);
if (se) fuse_session_destroy(se);
fuse_unmount(mountpoint, ch); fuse_unmount(mountpoint, ch);
} }
@ -271,9 +364,8 @@ int main(int argc, char *argv[])
fuse_opt_free_args(&args); fuse_opt_free_args(&args);
if (disk) delete disk; disk.reset();
if (dfile) free(dfile);
#ifdef __APPLE__ #ifdef __APPLE__
if (mountpath.size()) rmdir(mountpath.c_str()); if (mountpath.size()) rmdir(mountpath.c_str());

View File

@ -9,7 +9,7 @@
#ifndef __PROFUSE_H__ #ifndef __PROFUSE_H__
#define __PROFUSE_H__ #define __PROFUSE_H__
#include "File.h" #include <ProDOS/File.h>
#include "Disk.h" #include "Disk.h"
#include "common.h" #include "common.h"
@ -22,7 +22,7 @@
#define ERROR(cond,errno) if ( (cond) ){ fuse_reply_err(req, errno); return; } #define ERROR(cond,errno) if ( (cond) ){ fuse_reply_err(req, errno); return; }
extern Disk *disk; extern DiskPointer disk;
bool validProdosName(const char *name); bool validProdosName(const char *name);