From 10190d13a2137b5f2bd1501e546f66f6bdb05d39 Mon Sep 17 00:00:00 2001 From: ksherlock Date: Thu, 27 May 2010 04:16:04 +0000 Subject: [PATCH] unlink git-svn-id: https://profuse.googlecode.com/svn/branches/v2@285 aa027e90-d47c-11dd-86d7-074df07e0730 --- Pascal/FileEntry.cpp | 18 ++++++--- Pascal/VolumeEntry.cpp | 91 +++++++++++++++++++++++++++++++++--------- apfm.cpp | 14 +++++-- 3 files changed, 97 insertions(+), 26 deletions(-) diff --git a/Pascal/FileEntry.cpp b/Pascal/FileEntry.cpp index 72bdb4a..ffbf206 100644 --- a/Pascal/FileEntry.cpp +++ b/Pascal/FileEntry.cpp @@ -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; diff --git a/Pascal/VolumeEntry.cpp b/Pascal/VolumeEntry.cpp index c7d0ed4..66afc9e 100644 --- a/Pascal/VolumeEntry.cpp +++ b/Pascal/VolumeEntry.cpp @@ -1,5 +1,6 @@ #include +#include #include @@ -12,14 +13,17 @@ #include #include -#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 buffer(new uint8_t[512]); @@ -132,8 +145,11 @@ VolumeEntry::VolumeEntry(Device::BlockDevice *device) try { - std::vector::reverse_iterator iter; + std::vector::reverse_iterator riter; + std::vector::iterator iter; + unsigned block; + for (unsigned i = 1; i <= _fileCount; ++i) { std::auto_ptr 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::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; } diff --git a/apfm.cpp b/apfm.cpp index e186ba2..8fcca3f 100644 --- a/apfm.cpp +++ b/apfm.cpp @@ -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) );