git-svn-id: https://profuse.googlecode.com/svn/branches/v2@285 aa027e90-d47c-11dd-86d7-074df07e0730
This commit is contained in:
ksherlock 2010-05-27 04:16:04 +00:00
parent 0fda850b94
commit 10190d13a2
3 changed files with 97 additions and 26 deletions

View File

@ -25,8 +25,16 @@ enum {
kDLE = 16
};
#pragma mark -
#pragma mark FileEntry
/*
* _lastByte is in the range 1..512 and indicates how many bytes in the last
* block are in use.
* _lastBlock is the block *after* the actual last block.
* _maxFileSize is the maximum file size the file can grow to.
*
*/
unsigned FileEntry::ValidName(const char *cp)
{
@ -195,7 +203,7 @@ void FileEntry::truncateCommon(unsigned newSize)
throw ProFUSE::POSIXException(__METHOD__ ": Unable to expand file.", ENOSPC);
unsigned remainder = newSize - currentSize;
unsigned block = _lastBlock;
unsigned block = _lastBlock - 1;
if (_lastByte != 512)
{
@ -227,7 +235,7 @@ void FileEntry::truncateCommon(unsigned newSize)
}
_lastBlock = _firstBlock + newSize / 512;
_lastBlock = 1 + _firstBlock + newSize / 512;
_lastByte = newSize % 512;
if (_lastByte = 0) _lastByte = 512;
@ -294,7 +302,7 @@ int FileEntry::write(uint8_t *buffer, unsigned size, unsigned offset)
if (newSize > currentSize)
{
_lastBlock = _firstBlock + currentSize / 512;
_lastBlock = 1 + _firstBlock + currentSize / 512;
_lastByte = currentSize % 512;
if (_lastByte == 0) _lastByte = 512;

View File

@ -1,5 +1,6 @@
#include <memory>
#include <algorithm>
#include <Pascal/Pascal.h>
@ -12,14 +13,17 @@
#include <Device/BlockDevice.h>
#include <Cache/BlockCache.h>
#pragma mark -
#pragma mark VolumeEntry
using namespace LittleEndian;
using namespace Pascal;
using namespace Device;
using ProFUSE::Exception;
using ProFUSE::ProDOSException;
using ProFUSE::POSIXException;
unsigned VolumeEntry::ValidName(const char *cp)
{
// 7 chars max. Legal values: ascii, printable,
@ -50,10 +54,18 @@ VolumeEntry::VolumeEntry(const char *name, Device::BlockDevice *device)
#define __METHOD__ "VolumeEntry::VolumeEntry"
unsigned length;
unsigned deviceBlocks = device->blocks();
deviceBlocks = std::min(0xffffu, deviceBlocks);
if (deviceBlocks < 6)
throw Exception(__METHOD__ ": device too small.");
length = ValidName(name);
if (!length)
throw ProFUSE::Exception(__METHOD__ ": Invalid volume name.");
throw ProDOSException(__METHOD__ ": Invalid volume name.", ProFUSE::badPathSyntax);
_firstBlock = 0;
_lastBlock = 6;
@ -69,7 +81,7 @@ VolumeEntry::VolumeEntry(const char *name, Device::BlockDevice *device)
_fileName[i] = std::toupper(name[i]);
}
_lastVolumeBlock = device->blocks();
_lastVolumeBlock = deviceBlocks;
_fileCount = 0;
_accessTime = 0;
_lastBoot = Date::Today();
@ -99,6 +111,7 @@ VolumeEntry::VolumeEntry(const char *name, Device::BlockDevice *device)
VolumeEntry::VolumeEntry(Device::BlockDevice *device)
{
unsigned blockCount;
unsigned deviceBlocks = device->blocks();
ProFUSE::auto_array<uint8_t> buffer(new uint8_t[512]);
@ -132,8 +145,11 @@ VolumeEntry::VolumeEntry(Device::BlockDevice *device)
try
{
std::vector<FileEntry *>::reverse_iterator iter;
std::vector<FileEntry *>::reverse_iterator riter;
std::vector<FileEntry *>::iterator iter;
unsigned block;
for (unsigned i = 1; i <= _fileCount; ++i)
{
std::auto_ptr<FileEntry> child;
@ -150,13 +166,40 @@ VolumeEntry::VolumeEntry(Device::BlockDevice *device)
// sanity check _firstBlock, _lastBlock?
// set up _maxBlocks;
unsigned lastBlock = _lastVolumeBlock;
for (iter = _files.rbegin(); iter != _files.rend(); ++iter)
block = _lastBlock;
for (iter = _files.begin(); iter != _files.end(); ++iter)
{
FileEntry *e = *iter;
e->_maxFileSize = (lastBlock - e->_firstBlock) * 512;
lastBlock = e->_firstBlock - 1;
bool error = false;
if (e->_firstBlock > e->_lastBlock)
error = true;
if (e->_firstBlock >= _lastVolumeBlock)
error = true;
if (e->_lastBlock > _lastVolumeBlock)
error = true;
if (e->_firstBlock < block)
error = true;
if (error)
throw ProDOSException(__METHOD__ ": Invalid file entry.", ProFUSE::dirError);
block = e->_lastBlock;
}
// set up _maxFileSize;
block= _lastVolumeBlock;
for (riter = _files.rbegin(); riter != _files.rend(); ++riter)
{
FileEntry *e = *riter;
e->_maxFileSize = (block - e->_firstBlock) * 512;
block = e->_firstBlock;
}
}
@ -200,7 +243,7 @@ void VolumeEntry::init(void *vp)
// verify filenamelength <= 7
if (_fileNameLength > 7)
throw new ProFUSE::Exception(__METHOD__ ": invalid name length");
throw new ProDOSException(__METHOD__ ": invalid name length", ProFUSE::badPathSyntax);
// verify fileKind == 0
// verify _fileCount reasonable
@ -240,29 +283,41 @@ unsigned VolumeEntry::unlink(const char *name)
{
unsigned index;
std::vector<FileEntry *>::iterator iter;
// TODO -- update _maxFileSize.
if (_device->readOnly()) return ProFUSE::drvrWrtProt; // WRITE-PROTECTED DISK
for(index = 0; index < _fileCount; ++index)
for (index = 0, iter = _files.begin(); iter != _files.end(); ++iter, ++index)
{
FileEntry *e = _files[index];
FileEntry *e = *iter;
if (::strcasecmp(name, e->name()) == 0)
{
// if not the first entry, update the previous entry's
// _maxFileSize.
if (iter != _files.begin())
{
FileEntry *prev = iter[-1];
prev->_maxFileSize += e->_maxFileSize;
}
delete e;
_files[index] = NULL;
*iter = NULL;
break;
}
}
if (index == _fileCount) return ProFUSE::fileNotFound; // FILE NOT FOUND
if (iter == _files.end()) return ProFUSE::fileNotFound; // FILE NOT FOUND
_files.erase(_files.begin() + index);
_files.erase(iter);
_fileCount--;
// reset addresses.
for (unsigned i = index; i < _fileCount; ++i)
for ( ; iter != _files.end(); ++iter)
{
FileEntry *e = _files[i];
FileEntry *e = *iter;
e->_address -= 0x1a;
}

View File

@ -239,9 +239,16 @@ int action_mv(int argc, char **argv, Pascal::VolumeEntry *volume)
int action_rm(int argc, char **argv, Pascal::VolumeEntry *volume)
{
// mv rm file [file ....]
// needs ':' as f
// rm file [file ....]
// TODO -- catch errors.
for (unsigned i = 1; i < argc; ++i)
{
volume->unlink(argv[i]);
}
return 0;
}
int action_krunch(int argc, char **argv, Pascal::VolumeEntry *volume)
@ -492,8 +499,9 @@ int main(int argc, char **argv)
try {
// should we peek at the action to determine if read only?
device.reset( Device::BlockDevice::Open(file, true, fmt) );
device.reset( Device::BlockDevice::Open(file, false, fmt) );