mirror of
https://github.com/ksherlock/profuse.git
synced 2024-12-23 11:31:43 +00:00
unlink
git-svn-id: https://profuse.googlecode.com/svn/branches/v2@285 aa027e90-d47c-11dd-86d7-074df07e0730
This commit is contained in:
parent
0fda850b94
commit
10190d13a2
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
14
apfm.cpp
14
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) );
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user