git-svn-id: https://profuse.googlecode.com/svn/branches/v2@188 aa027e90-d47c-11dd-86d7-074df07e0730

This commit is contained in:
ksherlock 2009-12-19 23:17:39 +00:00
parent b18551dea9
commit 3a0871a158
5 changed files with 178 additions and 53 deletions

View File

@ -5,7 +5,7 @@
#include <vector> #include <vector>
namespace ProFUSE { namespace Device {
class BlockDevice; class BlockDevice;
class AbstractBlockCache; class AbstractBlockCache;
} }

9
ProFUSE/Makefile Normal file
View File

@ -0,0 +1,9 @@
CC = g++
CPPFLAGS += -g -Wall -I../
all : Exception.o Lock.o
Exception.o : Exception.cpp Exception.h
Lock.o : Lock.cpp Lock.h

149
apfm.cpp
View File

@ -23,7 +23,6 @@
const char *MonthName(unsigned m) const char *MonthName(unsigned m)
{ {
static const char *months[] = { static const char *months[] = {
@ -102,16 +101,35 @@ void printFileEntry(Pascal::FileEntry *e, bool extended)
} }
int list(Pascal::VolumeEntry *volume, bool extended) int action_ls(int argc, char **argv, Pascal::VolumeEntry *volume)
{ {
//TODO -- check for -l flag.
bool extended = false;
unsigned fileCount = volume->fileCount(); unsigned fileCount = volume->fileCount();
unsigned used = volume->blocks(); unsigned used = volume->blocks();
unsigned max = 0; unsigned max = 0;
unsigned volumeSize = volume->volumeBlocks(); unsigned volumeSize = volume->volumeBlocks();
unsigned lastBlock = volume->lastBlock(); unsigned lastBlock = volume->lastBlock();
int ch;
std::fprintf(stdout, "%s:\n", volume->name()); std::fprintf(stdout, "%s:\n", volume->name());
argv[0] = "afpm ls";
while ((ch = ::getopt(argc, argv, "l")) != -1)
{
switch(ch)
{
case 'l':
extended = true;
break;
}
}
argc -= optind;
argv += optind;
for (unsigned i = 0; i < fileCount; ++i) for (unsigned i = 0; i < fileCount; ++i)
{ {
Pascal::FileEntry *e = volume->fileAtIndex(i); Pascal::FileEntry *e = volume->fileAtIndex(i);
@ -158,20 +176,95 @@ int list(Pascal::VolumeEntry *volume, bool extended)
} }
int action_cat(unsigned argc, char **argv, Pascal::VolumeEntry *volume)
{
// cat file1, file2...
argv[0] = "afpm cat";
if (argc < 2)
{
std::fprintf(stderr, "apfm cat: Please specify one or more files.");
return 1;
}
for (unsigned i = 0; i < argc; ++i)
{
const char *fname = argv[i];
unsigned fileSize;
unsigned offset;
uint8_t buffer[512];
Pascal::FileEntry *e = NULL;
// find it...
for (unsigned i = 0, l = volume->fileCount(); i < l; ++i)
{
e = volume->fileAtIndex(i);
if (::strcasecmp(e->name(), fname) == 0) break;
e = NULL;
}
if (!e)
{
std::fprintf(stderr, "apfm cat: %s: no such file.\n", fname);
continue;
}
fileSize = e->fileSize();
offset = 0;
while (offset < fileSize)
{
unsigned count = std::min(512u, fileSize - offset);
e->read(buffer, count, offset);
std::fwrite(buffer, count, 1, stdout);
offset += count;
}
}
return 0;
}
int action_cp(int argc, char **argv, Pascal::VolumeEntry *volume)
{
return 0;
}
int action_mv(int argc, char **argv, Pascal::VolumeEntry *volume)
{
return 0;
}
int action_rm(int argc, char **argv, Pascal::VolumeEntry *volume)
{
return 0;
}
int action_krunch(int argc, char **argv, Pascal::VolumeEntry *volume)
{
return 0;
}
void usage() void usage()
{ {
std::printf( std::printf(
"Pascal File Manager v 0.0\n\n" "Pascal File Manager v 0.0\n\n"
"Usage: fileman [-h] [-f format] action diskimage\n" "Usage: fileman [-h] [-f format] diskimage action ...\n"
"Options:\n" "Options:\n"
" -h Show usage information.\n" " -h Show usage information.\n"
" -f format Specify disk format. Valid values are:\n" " -f format Specify disk format. Valid values are:\n"
" po: ProDOS order disk image\n" " po: ProDOS order disk image\n"
" do: DOS Order disk image\n" " do: DOS Order disk image\n"
"\n" "\n"
"Actions:\n" "Actions:\n"
" L List files\n" " cat\n"
" E List files (extended)\n" " cp\n"
" krunch\n"
" ls\n"
" mv\n"
" rm\n"
); );
} }
@ -179,14 +272,14 @@ void usage()
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
std::auto_ptr<Pascal::VolumeEntry> volume; std::auto_ptr<Pascal::VolumeEntry> volume;
std::auto_ptr<ProFUSE::BlockDevice> device; std::auto_ptr<Device::BlockDevice> device;
unsigned fmt = 0; unsigned fmt = 0;
int c; int c;
// getop stops at first non '-' arg so it will not affect action flags.
while ((c = ::getopt(argc, argv, "f:h")) != -1) while ((c = ::getopt(argc, argv, "f:h")) != -1)
{ {
std::printf("%c\n", c); std::printf("%c\n", c);
@ -203,24 +296,27 @@ int main(int argc, char **argv)
case 'h': case 'h':
case '?': case '?':
case ':':
usage(); usage();
std::exit(0); return c == 'h' ? 0 : 1;
} }
} }
argc -= optind; argc -= optind;
argv += optind; argv += optind;
optreset = 1;
optind = 1;
if (argc != 2) if (argc != 2)
{ {
usage(); usage();
std::exit(1); return 0;
} }
const char *file = argv[1]; const char *file = argv[0];
const char *action = argv[0]; const char *action = argv[1];
if (!fmt) fmt = Device::DiskImage::ImageType(optarg, 'PO__'); if (!fmt) fmt = Device::DiskImage::ImageType(optarg, 'PO__');
@ -230,28 +326,35 @@ int main(int argc, char **argv)
switch(fmt) switch(fmt)
{ {
case 'DO__': case 'DO__':
device.reset( new ProFUSE::DOSOrderDiskImage(file, true) ); device.reset( new Device::DOSOrderDiskImage(file, true) );
break; break;
case 'PO__': case 'PO__':
device.reset( new ProFUSE::ProDOSOrderDiskImage(file, true) ); device.reset( new Device::ProDOSOrderDiskImage(file, true) );
break; break;
case 'DC42': case 'DC42':
device.reset( new ProFUSE::DiskCopy42Image(file, true) ); device.reset( new Device::DiskCopy42Image(file, true) );
break; break;
default: default:
std::fprintf(stderr, "Unable to determine format. Please use -f flag.\n"); std::fprintf(stderr, "Unable to determine format. Please use -f flag.\n");
exit(2); return 2;
} }
volume.reset( new Pascal::VolumeEntry(device.get())); volume.reset( new Pascal::VolumeEntry(device.get()));
device.release(); device.release();
if (!::strcasecmp("E", action)) return list(volume.get(), true);
if (!::strcasecmp("L", action)) return list(volume.get(), false); if (!::strcasecmp("cat", action)) return action_cat(argc - 1, argv + 1, volume.get());
if (!::strcasecmp("cp", action)) return action_cp(argc - 1, argv + 1, volume.get());
if (!::strcasecmp("krunch", action)) return action_krunch(argc - 1, argv + 1, volume.get());
if (!::strcasecmp("ls", action)) return action_ls(argc - 1, argv + 1, volume.get());
if (!::strcasecmp("mv", action)) return action_mv(argc - 1, argv + 1, volume.get());
if (!::strcasecmp("rm", action)) return action_rm(argc - 1, argv + 1, volume.get());
usage();
return 3;
} }
catch (ProFUSE::Exception& e) catch (ProFUSE::Exception& e)
{ {
@ -259,5 +362,5 @@ int main(int argc, char **argv)
std::fprintf(stderr, "%s\n", strerror(e.error())); std::fprintf(stderr, "%s\n", strerror(e.error()));
} }
return 0;
} }

View File

@ -18,11 +18,12 @@
#include <fuse/fuse_lowlevel.h> #include <fuse/fuse_lowlevel.h>
#include "File.h" #include <Pascal/File.h>
#include "../BlockDevice.h" #include <ProFUSE/Exception.h>
#include "../Exception.h"
#include "../MappedFile.h" #include <Device/BlockDevice.h>
#include "../DiskCopy42Image.h" #include <Device/MappedFile.h>
#include <Device/DiskCopy42Image.h>
Pascal::VolumeEntry *fVolume = NULL; Pascal::VolumeEntry *fVolume = NULL;
std::string fDiskImage; std::string fDiskImage;
@ -102,6 +103,7 @@ static int pascal_option_proc(void *data, const char *arg, int key, struct fuse_
case FUSE_OPT_KEY_NONOPT: case FUSE_OPT_KEY_NONOPT:
// first arg is the disk image.
if (fDiskImage.empty()) if (fDiskImage.empty())
{ {
fDiskImage = arg; fDiskImage = arg;
@ -120,9 +122,12 @@ bool make_mount_dir(std::string name, std::string &path)
{ {
path = ""; path = "";
if (name.find('/') != std::string::npos) return false; if (name.find('/') != std::string::npos
if (name.find('\\') != std::string::npos) return false; || name.find('\\') != std::string::npos
if (name.find(':') != std::string::npos) return false; || name.find(':') != std::string::npos )
{
name = "Pascal Volume";
}
path = ""; path = "";
path = "/Volumes/" + name; path = "/Volumes/" + name;
@ -134,10 +139,7 @@ bool make_mount_dir(std::string name, std::string &path)
path = "/Volumes/" + name + " " + (char)('a' + i); path = "/Volumes/" + name + " " + (char)('a' + i);
rmdir(path.c_str()); rmdir(path.c_str());
if (mkdir(path.c_str(), 0777) == 0) return true; if (mkdir(path.c_str(), 0777) == 0) return true;
} }
path = ""; path = "";
@ -178,31 +180,31 @@ int main(int argc, char **argv)
// default prodos-order disk image. // default prodos-order disk image.
if (options.format) if (options.format)
{ {
format = ProFUSE::DiskImage::ImageType(options.format); format = Device::DiskImage::ImageType(options.format);
if (!format) if (!format)
std::fprintf(stderr, "Warning: Unknown image type ``%s''\n", options.format); std::fprintf(stderr, "Warning: Unknown image type ``%s''\n", options.format);
} }
if (!format) if (!format)
format = ProFUSE::DiskImage::ImageType(fDiskImage.c_str(), 'PO__'); format = Device::DiskImage::ImageType(fDiskImage.c_str(), 'PO__');
bool readOnly = true; bool readOnly = true;
try { try {
std::auto_ptr<ProFUSE::BlockDevice> device; std::auto_ptr<Device::BlockDevice> device;
switch(format) switch(format)
{ {
case 'DC42': case 'DC42':
device.reset(new ProFUSE::DiskCopy42Image(fDiskImage.c_str(), readOnly)); device.reset(new Device::DiskCopy42Image(fDiskImage.c_str(), readOnly));
break; break;
case 'PO__': case 'PO__':
device.reset(new ProFUSE::ProDOSOrderDiskImage(fDiskImage.c_str(), readOnly)); device.reset(new Device::ProDOSOrderDiskImage(fDiskImage.c_str(), readOnly));
break; break;
case 'DO__': case 'DO__':
device.reset(new ProFUSE::DOSOrderDiskImage(fDiskImage.c_str(), readOnly)); device.reset(new Device::DOSOrderDiskImage(fDiskImage.c_str(), readOnly));
break; break;
@ -278,8 +280,8 @@ int main(int argc, char **argv)
se = fuse_lowlevel_new(&args, &pascal_ops, sizeof(pascal_ops), fVolume); se = fuse_lowlevel_new(&args, &pascal_ops, sizeof(pascal_ops), fVolume);
if (se) do { if (se) do {
foreground = 1; //foreground = 1;
multithread = 0; //multithread = 0;
err = fuse_daemonize(foreground); // todo err = fuse_daemonize(foreground); // todo
if (err < 0 ) break; if (err < 0 ) break;

View File

@ -8,11 +8,11 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
/*
#define __FreeBSD__ 10 #define __FreeBSD__ 10
#define __DARWIN_64_BIT_INO_T 1 #define __DARWIN_64_BIT_INO_T 1
#define _FILE_OFFSET_BITS 64 #define _FILE_OFFSET_BITS 64
*/
#define FUSE_USE_VERSION 27 #define FUSE_USE_VERSION 27
#include <fuse/fuse_opt.h> #include <fuse/fuse_opt.h>
@ -20,10 +20,9 @@
#include <Pascal/File.h>
#include "File.h" #include <ProFUSE/auto.h>
#include "../auto.h" #include <ProFUSE/Exception.h>
#include "../Exception.h"
#define NO_ATTR() \ #define NO_ATTR() \
{ \ { \
@ -64,11 +63,21 @@ static void pascal_init(void *userdata, struct fuse_conn_info *conn)
{ {
std::printf("pascal_init\n"); std::printf("pascal_init\n");
// nop // nop
// text files have a non-thread safe index.
// which is initialized via read() or fileSize()
VolumeEntry *volume = (VolumeEntry *)userdata;
for (unsigned i = 0, l = volume->fileCount(); i < l; ++i)
{
volume->fileAtIndex(i)->fileSize();
}
} }
static void pascal_destroy(void *userdata) static void pascal_destroy(void *userdata)
{ {
std::printf("pascal_destroy\n"); std::printf("pascal_destroy\n");
// nop // nop
} }
@ -199,7 +208,7 @@ static void pascal_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, off_t of
std::printf("pascal_readdir %u, %u, %u\n", (unsigned)ino, (unsigned)size, (unsigned)off); std::printf("pascal_readdir %u, %u, %u\n", (unsigned)ino, (unsigned)size, (unsigned)off);
VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req); VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req);
auto_array<uint8_t> buffer(new uint8_t[size]); ProFUSE::auto_array<uint8_t> buffer(new uint8_t[size]);
unsigned count = volume->fileCount(); unsigned count = volume->fileCount();
@ -208,7 +217,7 @@ static void pascal_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, off_t of
std::memset(&st, 0, sizeof(st)); std::memset(&st, 0, sizeof(st));
// . && .. entries. // . and .. need to be added in here but are handled by the fs elsewhere.
do { do {
if (off == 0) if (off == 0)
@ -408,9 +417,11 @@ static void pascal_read(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off,
//VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req); //VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req);
FileEntry *file = (FileEntry *)fi->fh; FileEntry *file = (FileEntry *)fi->fh;
try try
{ {
auto_array<uint8_t> buffer(new uint8_t[size]); ProFUSE::auto_array<uint8_t> buffer(new uint8_t[size]);
unsigned rsize = file->read(buffer.get(), size, off); unsigned rsize = file->read(buffer.get(), size, off);
fuse_reply_buf(req, (char *)(buffer.get()), rsize); fuse_reply_buf(req, (char *)(buffer.get()), rsize);