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>
namespace ProFUSE {
namespace Device {
class BlockDevice;
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)
{
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 used = volume->blocks();
unsigned max = 0;
unsigned volumeSize = volume->volumeBlocks();
unsigned lastBlock = volume->lastBlock();
int ch;
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)
{
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()
{
std::printf(
"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"
" -h Show usage information.\n"
" -f format Specify disk format. Valid values are:\n"
" po: ProDOS order disk image\n"
" do: DOS Order disk image\n"
" po: ProDOS order disk image\n"
" do: DOS Order disk image\n"
"\n"
"Actions:\n"
" L List files\n"
" E List files (extended)\n"
" cat\n"
" cp\n"
" krunch\n"
" ls\n"
" mv\n"
" rm\n"
);
}
@ -179,14 +272,14 @@ void usage()
int main(int argc, char **argv)
{
std::auto_ptr<Pascal::VolumeEntry> volume;
std::auto_ptr<ProFUSE::BlockDevice> device;
std::auto_ptr<Device::BlockDevice> device;
unsigned fmt = 0;
int c;
// getop stops at first non '-' arg so it will not affect action flags.
while ((c = ::getopt(argc, argv, "f:h")) != -1)
{
std::printf("%c\n", c);
@ -203,24 +296,27 @@ int main(int argc, char **argv)
case 'h':
case '?':
case ':':
usage();
std::exit(0);
return c == 'h' ? 0 : 1;
}
}
argc -= optind;
argv += optind;
optreset = 1;
optind = 1;
if (argc != 2)
{
usage();
std::exit(1);
return 0;
}
const char *file = argv[1];
const char *action = argv[0];
const char *file = argv[0];
const char *action = argv[1];
if (!fmt) fmt = Device::DiskImage::ImageType(optarg, 'PO__');
@ -230,28 +326,35 @@ int main(int argc, char **argv)
switch(fmt)
{
case 'DO__':
device.reset( new ProFUSE::DOSOrderDiskImage(file, true) );
device.reset( new Device::DOSOrderDiskImage(file, true) );
break;
case 'PO__':
device.reset( new ProFUSE::ProDOSOrderDiskImage(file, true) );
device.reset( new Device::ProDOSOrderDiskImage(file, true) );
break;
case 'DC42':
device.reset( new ProFUSE::DiskCopy42Image(file, true) );
device.reset( new Device::DiskCopy42Image(file, true) );
break;
default:
std::fprintf(stderr, "Unable to determine format. Please use -f flag.\n");
exit(2);
return 2;
}
volume.reset( new Pascal::VolumeEntry(device.get()));
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)
{
@ -259,5 +362,5 @@ int main(int argc, char **argv)
std::fprintf(stderr, "%s\n", strerror(e.error()));
}
return 0;
}

View File

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

View File

@ -8,11 +8,11 @@
#include <sys/stat.h>
#include <unistd.h>
/*
#define __FreeBSD__ 10
#define __DARWIN_64_BIT_INO_T 1
#define _FILE_OFFSET_BITS 64
*/
#define FUSE_USE_VERSION 27
#include <fuse/fuse_opt.h>
@ -20,10 +20,9 @@
#include "File.h"
#include "../auto.h"
#include "../Exception.h"
#include <Pascal/File.h>
#include <ProFUSE/auto.h>
#include <ProFUSE/Exception.h>
#define NO_ATTR() \
{ \
@ -64,11 +63,21 @@ static void pascal_init(void *userdata, struct fuse_conn_info *conn)
{
std::printf("pascal_init\n");
// 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)
{
std::printf("pascal_destroy\n");
// 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);
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();
@ -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));
// . && .. entries.
// . and .. need to be added in here but are handled by the fs elsewhere.
do {
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);
FileEntry *file = (FileEntry *)fi->fh;
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);
fuse_reply_buf(req, (char *)(buffer.get()), rsize);