diff --git a/Disk.cpp b/Disk.cpp index 89dc05b..497d760 100644 --- a/Disk.cpp +++ b/Disk.cpp @@ -24,6 +24,7 @@ #include #include + struct ucmp { bool operator()(unsigned a, unsigned b) const @@ -39,20 +40,28 @@ typedef set uset; Disk::Disk() { - _data = (uint8_t *)-1; _blocks = 0; - _offset = 0; - _size = 0; - _flags = 0; + } 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) { int fd; @@ -155,7 +164,7 @@ Disk *Disk::OpenFile(const char *file, unsigned flags) return d; } - +#endif // load the mini entry into the regular entry. 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) { - 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; } diff --git a/Disk.h b/Disk.h index 5f2f622..683defc 100644 --- a/Disk.h +++ b/Disk.h @@ -13,7 +13,10 @@ #include -#include "File.h" +#include +#include + +#include enum { @@ -40,6 +43,8 @@ enum { }; +class Disk; +typedef std::tr1::shared_ptr DiskPointer; class Disk { @@ -47,7 +52,7 @@ public: ~Disk(); //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); @@ -65,13 +70,14 @@ public: private: Disk(); - uint8_t *_data; - unsigned _offset; - unsigned _blocks; - size_t _size; + Disk(Device::BlockDevicePointer device); - unsigned _flags; + unsigned _blocks; + + Device::BlockDevicePointer _device; }; + + #endif diff --git a/main.cpp b/main.cpp index a55211e..265d499 100644 --- a/main.cpp +++ b/main.cpp @@ -14,29 +14,39 @@ #define _POSIX_C_SOURCE 200112L */ -#include -#include -#include -#include - +#include +#include +#include +#include #include #include +#include + +#include + #include "profuse.h" + + using std::vector; using std::string; +using std::tr1::shared_ptr; -Disk *disk = NULL; -char *dfile = NULL; + +/* + * globals variables. + * + */ + +std::string fDiskImage; + + +DiskPointer disk; VolumeEntry volume; -bool dos_order = false; - - - bool validProdosName(const char *name) { // 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 { PRODOS_OPT_HELP, 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[] = { FUSE_OPT_KEY("-h", PRODOS_OPT_HELP), FUSE_OPT_KEY("--help", PRODOS_OPT_HELP), + FUSE_OPT_KEY("-V", 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} }; 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) { switch(key) { - /* case PRODOS_OPT_HELP: usage(); exit(0); break; - */ + case PRODOS_OPT_VERSION: // TODO exit(1); break; - case PRODOS_OPT_DOS_ORDER: - dos_order = true; - return 0; - break; - + 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 1; @@ -159,15 +204,25 @@ int main(int argc, char *argv[]) struct fuse_chan *ch; char *mountpoint = NULL; int err = -1; + struct options options; + + unsigned format = 0; + + int foreground = false; + int multithread = false; + #if __APPLE__ string mountpath; #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.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. - 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); - if (dfile == NULL || *dfile == 0) + if (fDiskImage.empty()) { usage(); - exit(0); + exit(1); } - disk = Disk::OpenFile(dfile, dos_order); - - if (!disk) + // default prodos-order disk image. + if (options.format) { - fprintf(stderr, "Unable to mount disk %s\n", dfile); - exit(1); + format = Device::BlockDevice::ImageType(options.format); + 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); @@ -235,6 +321,7 @@ int main(int argc, char *argv[]) #endif + foreground = options.debug; if (mountpoint == NULL || *mountpoint == 0) @@ -244,26 +331,32 @@ int main(int argc, char *argv[]) } - - if ( (ch = fuse_mount(mountpoint, &args)) != NULL) { struct fuse_session *se; se = fuse_lowlevel_new(&args, &prodos_oper, sizeof(prodos_oper), NULL); - if (se != NULL) - { - if (fuse_set_signal_handlers(se) != -1) - { - fuse_session_add_chan(se, ch); - err = fuse_session_loop(se); - fuse_remove_signal_handlers(se); - fuse_session_remove_chan(ch); - } + if (se != NULL) do { + + err = fuse_daemonize(foreground); + if (err < 0 ) break; - 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); } @@ -271,9 +364,8 @@ int main(int argc, char *argv[]) fuse_opt_free_args(&args); - if (disk) delete disk; + disk.reset(); - if (dfile) free(dfile); #ifdef __APPLE__ if (mountpath.size()) rmdir(mountpath.c_str()); diff --git a/profuse.h b/profuse.h index 23513e3..4cf8c54 100644 --- a/profuse.h +++ b/profuse.h @@ -9,7 +9,7 @@ #ifndef __PROFUSE_H__ #define __PROFUSE_H__ -#include "File.h" +#include #include "Disk.h" #include "common.h" @@ -22,7 +22,7 @@ #define ERROR(cond,errno) if ( (cond) ){ fuse_reply_err(req, errno); return; } -extern Disk *disk; +extern DiskPointer disk; bool validProdosName(const char *name);