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 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) unsigned FileEntry::ValidName(const char *cp)
{ {
@ -195,7 +203,7 @@ void FileEntry::truncateCommon(unsigned newSize)
throw ProFUSE::POSIXException(__METHOD__ ": Unable to expand file.", ENOSPC); throw ProFUSE::POSIXException(__METHOD__ ": Unable to expand file.", ENOSPC);
unsigned remainder = newSize - currentSize; unsigned remainder = newSize - currentSize;
unsigned block = _lastBlock; unsigned block = _lastBlock - 1;
if (_lastByte != 512) if (_lastByte != 512)
{ {
@ -227,7 +235,7 @@ void FileEntry::truncateCommon(unsigned newSize)
} }
_lastBlock = _firstBlock + newSize / 512; _lastBlock = 1 + _firstBlock + newSize / 512;
_lastByte = newSize % 512; _lastByte = newSize % 512;
if (_lastByte = 0) _lastByte = 512; if (_lastByte = 0) _lastByte = 512;
@ -294,7 +302,7 @@ int FileEntry::write(uint8_t *buffer, unsigned size, unsigned offset)
if (newSize > currentSize) if (newSize > currentSize)
{ {
_lastBlock = _firstBlock + currentSize / 512; _lastBlock = 1 + _firstBlock + currentSize / 512;
_lastByte = currentSize % 512; _lastByte = currentSize % 512;
if (_lastByte == 0) _lastByte = 512; if (_lastByte == 0) _lastByte = 512;

View File

@ -1,5 +1,6 @@
#include <memory> #include <memory>
#include <algorithm>
#include <Pascal/Pascal.h> #include <Pascal/Pascal.h>
@ -12,14 +13,17 @@
#include <Device/BlockDevice.h> #include <Device/BlockDevice.h>
#include <Cache/BlockCache.h> #include <Cache/BlockCache.h>
#pragma mark -
#pragma mark VolumeEntry
using namespace LittleEndian; using namespace LittleEndian;
using namespace Pascal; using namespace Pascal;
using namespace Device; using namespace Device;
using ProFUSE::Exception;
using ProFUSE::ProDOSException;
using ProFUSE::POSIXException;
unsigned VolumeEntry::ValidName(const char *cp) unsigned VolumeEntry::ValidName(const char *cp)
{ {
// 7 chars max. Legal values: ascii, printable, // 7 chars max. Legal values: ascii, printable,
@ -50,10 +54,18 @@ VolumeEntry::VolumeEntry(const char *name, Device::BlockDevice *device)
#define __METHOD__ "VolumeEntry::VolumeEntry" #define __METHOD__ "VolumeEntry::VolumeEntry"
unsigned length; unsigned length;
unsigned deviceBlocks = device->blocks();
deviceBlocks = std::min(0xffffu, deviceBlocks);
if (deviceBlocks < 6)
throw Exception(__METHOD__ ": device too small.");
length = ValidName(name); length = ValidName(name);
if (!length) if (!length)
throw ProFUSE::Exception(__METHOD__ ": Invalid volume name."); throw ProDOSException(__METHOD__ ": Invalid volume name.", ProFUSE::badPathSyntax);
_firstBlock = 0; _firstBlock = 0;
_lastBlock = 6; _lastBlock = 6;
@ -69,7 +81,7 @@ VolumeEntry::VolumeEntry(const char *name, Device::BlockDevice *device)
_fileName[i] = std::toupper(name[i]); _fileName[i] = std::toupper(name[i]);
} }
_lastVolumeBlock = device->blocks(); _lastVolumeBlock = deviceBlocks;
_fileCount = 0; _fileCount = 0;
_accessTime = 0; _accessTime = 0;
_lastBoot = Date::Today(); _lastBoot = Date::Today();
@ -99,6 +111,7 @@ VolumeEntry::VolumeEntry(const char *name, Device::BlockDevice *device)
VolumeEntry::VolumeEntry(Device::BlockDevice *device) VolumeEntry::VolumeEntry(Device::BlockDevice *device)
{ {
unsigned blockCount; unsigned blockCount;
unsigned deviceBlocks = device->blocks();
ProFUSE::auto_array<uint8_t> buffer(new uint8_t[512]); ProFUSE::auto_array<uint8_t> buffer(new uint8_t[512]);
@ -132,7 +145,10 @@ VolumeEntry::VolumeEntry(Device::BlockDevice *device)
try 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) for (unsigned i = 1; i <= _fileCount; ++i)
{ {
@ -150,13 +166,40 @@ VolumeEntry::VolumeEntry(Device::BlockDevice *device)
// sanity check _firstBlock, _lastBlock? // sanity check _firstBlock, _lastBlock?
// set up _maxBlocks; block = _lastBlock;
unsigned lastBlock = _lastVolumeBlock;
for (iter = _files.rbegin(); iter != _files.rend(); ++iter) for (iter = _files.begin(); iter != _files.end(); ++iter)
{ {
FileEntry *e = *iter; FileEntry *e = *iter;
e->_maxFileSize = (lastBlock - e->_firstBlock) * 512; bool error = false;
lastBlock = e->_firstBlock - 1; 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 // verify filenamelength <= 7
if (_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 fileKind == 0
// verify _fileCount reasonable // verify _fileCount reasonable
@ -240,29 +283,41 @@ unsigned VolumeEntry::unlink(const char *name)
{ {
unsigned index; unsigned index;
std::vector<FileEntry *>::iterator iter;
// TODO -- update _maxFileSize. // TODO -- update _maxFileSize.
if (_device->readOnly()) return ProFUSE::drvrWrtProt; // WRITE-PROTECTED DISK 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 (::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; delete e;
_files[index] = NULL; *iter = NULL;
break; 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--; _fileCount--;
// reset addresses. // reset addresses.
for (unsigned i = index; i < _fileCount; ++i) for ( ; iter != _files.end(); ++iter)
{ {
FileEntry *e = _files[i]; FileEntry *e = *iter;
e->_address -= 0x1a; 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) int action_rm(int argc, char **argv, Pascal::VolumeEntry *volume)
{ {
// mv rm file [file ....] // rm file [file ....]
// needs ':' as f
// TODO -- catch errors.
for (unsigned i = 1; i < argc; ++i)
{
volume->unlink(argv[i]);
}
return 0; return 0;
} }
int action_krunch(int argc, char **argv, Pascal::VolumeEntry *volume) int action_krunch(int argc, char **argv, Pascal::VolumeEntry *volume)
@ -492,8 +499,9 @@ int main(int argc, char **argv)
try { 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) );