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
|
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;
|
||||||
|
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
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) );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user