use smart pointer for everything (not yet tested)
git-svn-id: https://profuse.googlecode.com/svn/branches/v2@350 aa027e90-d47c-11dd-86d7-074df07e0730
This commit is contained in:
parent
e71ab41481
commit
89e80dcc10
|
@ -64,7 +64,6 @@ Entry::Entry()
|
||||||
_lastBlock = 0;
|
_lastBlock = 0;
|
||||||
_fileKind = 0;
|
_fileKind = 0;
|
||||||
_inode = 0;
|
_inode = 0;
|
||||||
_parent = NULL;
|
|
||||||
_address = NULL;
|
_address = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#ifndef __PASCAL_ENTRY_H__
|
#ifndef __PASCAL_ENTRY_H__
|
||||||
#define __PASCAL_ENTRY_H__
|
#define __PASCAL_ENTRY_H__
|
||||||
|
|
||||||
|
#include <tr1/memory>
|
||||||
|
|
||||||
#include <Pascal/Date.h>
|
#include <Pascal/Date.h>
|
||||||
|
|
||||||
|
|
||||||
|
@ -31,7 +33,14 @@ namespace Pascal {
|
||||||
class FileEntry;
|
class FileEntry;
|
||||||
class VolumeEntry;
|
class VolumeEntry;
|
||||||
|
|
||||||
class Entry {
|
|
||||||
|
typedef std::tr1::shared_ptr<FileEntry> FileEntryPointer;
|
||||||
|
typedef std::tr1::shared_ptr<VolumeEntry> VolumeEntryPointer;
|
||||||
|
|
||||||
|
typedef std::tr1::weak_ptr<FileEntry> FileEntryWeakPointer;
|
||||||
|
typedef std::tr1::weak_ptr<VolumeEntry> VolumeEntryWeakPointer;
|
||||||
|
|
||||||
|
class Entry : public std::tr1::enable_shared_from_this<Entry> {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -47,7 +56,7 @@ namespace Pascal {
|
||||||
unsigned inode() const { return _inode; }
|
unsigned inode() const { return _inode; }
|
||||||
void setInode(unsigned inode) { _inode = inode; }
|
void setInode(unsigned inode) { _inode = inode; }
|
||||||
|
|
||||||
VolumeEntry *parent() { return _parent; }
|
VolumeEntryWeakPointer parent() { return _parent; }
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -70,7 +79,7 @@ namespace Pascal {
|
||||||
|
|
||||||
friend class VolumeEntry;
|
friend class VolumeEntry;
|
||||||
|
|
||||||
VolumeEntry *_parent;
|
VolumeEntryWeakPointer _parent;
|
||||||
unsigned _address;
|
unsigned _address;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -42,6 +42,16 @@ unsigned FileEntry::ValidName(const char *cp)
|
||||||
return Entry::ValidName(cp, 15);
|
return Entry::ValidName(cp, 15);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FileEntryPointer FileEntry::Open(void *vp)
|
||||||
|
{
|
||||||
|
return FileEntryPointer(new FileEntry(vp));
|
||||||
|
}
|
||||||
|
|
||||||
|
FileEntryPointer FileEntry::Create(const char *name, unsigned fileKind)
|
||||||
|
{
|
||||||
|
return FileEntryPointer(new FileEntry(name, fileKind));
|
||||||
|
}
|
||||||
|
|
||||||
FileEntry::FileEntry(void *vp) :
|
FileEntry::FileEntry(void *vp) :
|
||||||
Entry(vp)
|
Entry(vp)
|
||||||
{
|
{
|
||||||
|
@ -99,7 +109,10 @@ void FileEntry::setFileKind(unsigned kind)
|
||||||
_pageSize = NULL;
|
_pageSize = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
parent()->writeEntry(this);
|
VolumeEntryPointer v = parent().lock();
|
||||||
|
|
||||||
|
// throw if expired?
|
||||||
|
if (v) v->writeEntry(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -194,7 +207,9 @@ int FileEntry::truncate(unsigned newSize)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
_modification = Date::Today();
|
_modification = Date::Today();
|
||||||
parent()->writeEntry(this);
|
|
||||||
|
VolumeEntryPointer v = parent().lock();
|
||||||
|
if (v) v->writeEntry(this);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -211,6 +226,8 @@ int FileEntry::truncateCommon(unsigned newSize)
|
||||||
|
|
||||||
unsigned currentSize = fileSize();
|
unsigned currentSize = fileSize();
|
||||||
|
|
||||||
|
VolumeEntryPointer v = parent().lock();
|
||||||
|
|
||||||
if (newSize == currentSize) return 0;
|
if (newSize == currentSize) return 0;
|
||||||
if (newSize > currentSize)
|
if (newSize > currentSize)
|
||||||
{
|
{
|
||||||
|
@ -228,12 +245,13 @@ int FileEntry::truncateCommon(unsigned newSize)
|
||||||
{
|
{
|
||||||
// last page not full
|
// last page not full
|
||||||
unsigned count = std::min(512 - _lastByte, remainder);
|
unsigned count = std::min(512 - _lastByte, remainder);
|
||||||
uint8_t *address = (uint8_t *)parent()->loadBlock(block);
|
|
||||||
|
|
||||||
std::memset(address + _lastByte, 0, count);
|
|
||||||
|
|
||||||
parent()->unloadBlock(block, true);
|
|
||||||
|
|
||||||
|
if (v)
|
||||||
|
{
|
||||||
|
uint8_t *address = (uint8_t *)v->loadBlock(block);
|
||||||
|
std::memset(address + _lastByte, 0, count);
|
||||||
|
v->unloadBlock(block, true);
|
||||||
|
}
|
||||||
remainder -= count;
|
remainder -= count;
|
||||||
}
|
}
|
||||||
block++;
|
block++;
|
||||||
|
@ -241,12 +259,12 @@ int FileEntry::truncateCommon(unsigned newSize)
|
||||||
while (remainder)
|
while (remainder)
|
||||||
{
|
{
|
||||||
unsigned count = std::min(512u, remainder);
|
unsigned count = std::min(512u, remainder);
|
||||||
uint8_t *address = (uint8_t *)parent()->loadBlock(block);
|
if (v)
|
||||||
|
{
|
||||||
std::memset(address, 0, count);
|
uint8_t *address = (uint8_t *)v->loadBlock(block);
|
||||||
|
std::memset(address, 0, count);
|
||||||
parent()->unloadBlock(block, true);
|
v->unloadBlock(block, true);
|
||||||
|
}
|
||||||
remainder -= count;
|
remainder -= count;
|
||||||
block++;
|
block++;
|
||||||
}
|
}
|
||||||
|
@ -264,7 +282,15 @@ int FileEntry::write(TextWriter &text)
|
||||||
{
|
{
|
||||||
unsigned blocks = text.blocks();
|
unsigned blocks = text.blocks();
|
||||||
|
|
||||||
if (parent()->readOnly())
|
VolumeEntryPointer v = parent().lock();
|
||||||
|
if (!v)
|
||||||
|
{
|
||||||
|
errno = EROFS;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (v->readOnly())
|
||||||
{
|
{
|
||||||
errno = EROFS;
|
errno = EROFS;
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -286,7 +312,7 @@ int FileEntry::write(TextWriter &text)
|
||||||
for (unsigned i = 0; i < blocks; ++i)
|
for (unsigned i = 0; i < blocks; ++i)
|
||||||
{
|
{
|
||||||
void *buffer = text.data(i);
|
void *buffer = text.data(i);
|
||||||
parent()->writeBlock(_firstBlock + i, buffer);
|
v->writeBlock(_firstBlock + i, buffer);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -294,8 +320,8 @@ int FileEntry::write(TextWriter &text)
|
||||||
|
|
||||||
setFileSize(blocks * 512);
|
setFileSize(blocks * 512);
|
||||||
|
|
||||||
parent()->writeEntry(this);
|
v->writeEntry(this);
|
||||||
parent()->sync();
|
v->sync();
|
||||||
|
|
||||||
return blocks * 512;
|
return blocks * 512;
|
||||||
}
|
}
|
||||||
|
@ -304,8 +330,15 @@ int FileEntry::write(const uint8_t *buffer, unsigned size, unsigned offset)
|
||||||
{
|
{
|
||||||
#undef __METHOD__
|
#undef __METHOD__
|
||||||
#define __METHOD__ "FileEntry::write"
|
#define __METHOD__ "FileEntry::write"
|
||||||
|
|
||||||
if (parent()->readOnly())
|
VolumeEntryPointer v = parent().lock();
|
||||||
|
if (!v)
|
||||||
|
{
|
||||||
|
errno = EROFS;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v->readOnly())
|
||||||
{
|
{
|
||||||
errno = EROFS;
|
errno = EROFS;
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -342,10 +375,10 @@ int FileEntry::write(const uint8_t *buffer, unsigned size, unsigned offset)
|
||||||
if (start)
|
if (start)
|
||||||
{
|
{
|
||||||
unsigned count = std::min(512 - start, remainder);
|
unsigned count = std::min(512 - start, remainder);
|
||||||
uint8_t *address = (uint8_t *)parent()->loadBlock(block);
|
uint8_t *address = (uint8_t *)v->loadBlock(block);
|
||||||
|
|
||||||
std::memcpy(address + start, buffer, count);
|
std::memcpy(address + start, buffer, count);
|
||||||
parent()->unloadBlock(block, true);
|
v->unloadBlock(block, true);
|
||||||
|
|
||||||
remainder -= count;
|
remainder -= count;
|
||||||
buffer += count;
|
buffer += count;
|
||||||
|
@ -354,12 +387,12 @@ int FileEntry::write(const uint8_t *buffer, unsigned size, unsigned offset)
|
||||||
|
|
||||||
while (remainder)
|
while (remainder)
|
||||||
{
|
{
|
||||||
uint8_t *address = (uint8_t *)parent()->loadBlock(block);
|
uint8_t *address = (uint8_t *)v->loadBlock(block);
|
||||||
|
|
||||||
unsigned count = std::min(512u, size);
|
unsigned count = std::min(512u, size);
|
||||||
|
|
||||||
std::memcpy(address, buffer, count);
|
std::memcpy(address, buffer, count);
|
||||||
parent()->unloadBlock(block, true);
|
v->unloadBlock(block, true);
|
||||||
|
|
||||||
remainder -= count;
|
remainder -= count;
|
||||||
buffer += count;
|
buffer += count;
|
||||||
|
@ -371,7 +404,7 @@ int FileEntry::write(const uint8_t *buffer, unsigned size, unsigned offset)
|
||||||
|
|
||||||
|
|
||||||
_modification = Date::Today();
|
_modification = Date::Today();
|
||||||
parent()->writeEntry(this);
|
v->writeEntry(this);
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
@ -419,6 +452,13 @@ int FileEntry::dataRead(uint8_t *buffer, unsigned size, unsigned offset)
|
||||||
|
|
||||||
unsigned count = 0;
|
unsigned count = 0;
|
||||||
unsigned block = 0;
|
unsigned block = 0;
|
||||||
|
|
||||||
|
VolumeEntryPointer v = parent().lock();
|
||||||
|
if (!v)
|
||||||
|
{
|
||||||
|
errno = EROFS;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
block = _firstBlock + (offset / 512);
|
block = _firstBlock + (offset / 512);
|
||||||
|
|
||||||
|
@ -433,7 +473,7 @@ int FileEntry::dataRead(uint8_t *buffer, unsigned size, unsigned offset)
|
||||||
{
|
{
|
||||||
unsigned bytes = std::min(offset % 512, size);
|
unsigned bytes = std::min(offset % 512, size);
|
||||||
|
|
||||||
parent()->readBlock(block++, tmp);
|
v->readBlock(block++, tmp);
|
||||||
|
|
||||||
std::memcpy(buffer, tmp + 512 - bytes, bytes);
|
std::memcpy(buffer, tmp + 512 - bytes, bytes);
|
||||||
|
|
||||||
|
@ -448,7 +488,7 @@ int FileEntry::dataRead(uint8_t *buffer, unsigned size, unsigned offset)
|
||||||
|
|
||||||
while (size >= 512)
|
while (size >= 512)
|
||||||
{
|
{
|
||||||
parent()->readBlock(block++, buffer);
|
v->readBlock(block++, buffer);
|
||||||
|
|
||||||
buffer += 512;
|
buffer += 512;
|
||||||
count += 512;
|
count += 512;
|
||||||
|
@ -460,7 +500,7 @@ int FileEntry::dataRead(uint8_t *buffer, unsigned size, unsigned offset)
|
||||||
*/
|
*/
|
||||||
if (size)
|
if (size)
|
||||||
{
|
{
|
||||||
parent()->readBlock(block, tmp);
|
v->readBlock(block, tmp);
|
||||||
std::memcpy(buffer, tmp, size);
|
std::memcpy(buffer, tmp, size);
|
||||||
|
|
||||||
count += size;
|
count += size;
|
||||||
|
@ -589,13 +629,20 @@ unsigned FileEntry::textReadPage(unsigned block, uint8_t *in)
|
||||||
// reads up to 2 blocks.
|
// reads up to 2 blocks.
|
||||||
// assumes block within _startBlock ... _lastBlock - 1
|
// assumes block within _startBlock ... _lastBlock - 1
|
||||||
|
|
||||||
parent()->readBlock(block, in);
|
VolumeEntryPointer v = parent().lock();
|
||||||
|
if (!v)
|
||||||
|
{
|
||||||
|
errno = EROFS;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
v->readBlock(block, in);
|
||||||
if (block + 1 == _lastBlock)
|
if (block + 1 == _lastBlock)
|
||||||
{
|
{
|
||||||
return _lastByte;
|
return _lastByte;
|
||||||
}
|
}
|
||||||
|
|
||||||
parent()->readBlock(block + 1, in + 512);
|
v->readBlock(block + 1, in + 512);
|
||||||
if (block +2 == _lastBlock)
|
if (block +2 == _lastBlock)
|
||||||
{
|
{
|
||||||
return 512 + _lastByte;
|
return 512 + _lastByte;
|
||||||
|
|
|
@ -22,8 +22,10 @@ namespace Pascal {
|
||||||
static bool Uncompress(std::string& text);
|
static bool Uncompress(std::string& text);
|
||||||
|
|
||||||
|
|
||||||
FileEntry(const char *name, unsigned fileKind);
|
static FileEntryPointer Create(const char *name, unsigned fileKind);
|
||||||
FileEntry(void *vp);
|
static FileEntryPointer Open(void *vp);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
virtual ~FileEntry();
|
virtual ~FileEntry();
|
||||||
|
|
||||||
|
@ -54,6 +56,15 @@ namespace Pascal {
|
||||||
|
|
||||||
friend class VolumeEntry;
|
friend class VolumeEntry;
|
||||||
|
|
||||||
|
FileEntry(const char *name, unsigned fileKind);
|
||||||
|
FileEntry(void *vp);
|
||||||
|
|
||||||
|
FileEntryPointer thisPointer()
|
||||||
|
{
|
||||||
|
return std::tr1::static_pointer_cast<FileEntry>(shared_from_this());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void setName(const char *name);
|
void setName(const char *name);
|
||||||
|
|
||||||
int truncateCommon(unsigned newSize);
|
int truncateCommon(unsigned newSize);
|
||||||
|
|
|
@ -61,6 +61,26 @@ unsigned VolumeEntry::ValidName(const char *cp)
|
||||||
return Entry::ValidName(cp, 7);
|
return Entry::ValidName(cp, 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VolumeEntryPointer VolumeEntry::Open(Device::BlockDevicePointer device)
|
||||||
|
{
|
||||||
|
VolumeEntryPointer ptr(new VolumeEntry(device));
|
||||||
|
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
VolumeEntryPointer VolumeEntry::Create(Device::BlockDevicePointer device, const char *name)
|
||||||
|
{
|
||||||
|
VolumeEntryPointer ptr(new VolumeEntry(device, name));
|
||||||
|
|
||||||
|
|
||||||
|
// set up the weak references from the file entry to this.
|
||||||
|
if (ptr) ptr->setParents();
|
||||||
|
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
VolumeEntry::VolumeEntry()
|
VolumeEntry::VolumeEntry()
|
||||||
{
|
{
|
||||||
_fileNameLength = 0;
|
_fileNameLength = 0;
|
||||||
|
@ -74,7 +94,7 @@ VolumeEntry::VolumeEntry()
|
||||||
_inodeGenerator = 1;
|
_inodeGenerator = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
VolumeEntry::VolumeEntry(const char *name, Device::BlockDevicePointer device) :
|
VolumeEntry::VolumeEntry(Device::BlockDevicePointer device, const char *name) :
|
||||||
_device(device)
|
_device(device)
|
||||||
{
|
{
|
||||||
#undef __METHOD__
|
#undef __METHOD__
|
||||||
|
@ -166,88 +186,79 @@ VolumeEntry::VolumeEntry(Device::BlockDevicePointer device)
|
||||||
}
|
}
|
||||||
|
|
||||||
// now load up all the children.
|
// now load up all the children.
|
||||||
// if this throws, memory could be lost...
|
// the parent cannot be set (yet), since we need a shared_ptr to create a weak_ptr.
|
||||||
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
|
|
||||||
std::vector<FileEntry *>::iterator iter;
|
|
||||||
|
|
||||||
unsigned block;
|
std::vector<FileEntryPointer>::iterator iter;
|
||||||
|
|
||||||
for (unsigned i = 1; i <= _fileCount; ++i)
|
|
||||||
{
|
|
||||||
std::auto_ptr<FileEntry> child;
|
|
||||||
|
|
||||||
//
|
|
||||||
child.reset(new FileEntry(buffer.get() + i * 0x1a));
|
|
||||||
|
|
||||||
child->setInode(++_inodeGenerator);
|
|
||||||
child->_parent = this;
|
|
||||||
child->_address = 512 * 2 + i * 0x1a;
|
|
||||||
|
|
||||||
_files.push_back(child.release());
|
|
||||||
}
|
|
||||||
|
|
||||||
// sanity check _firstBlock, _lastBlock?
|
|
||||||
|
|
||||||
block = _lastBlock;
|
|
||||||
|
|
||||||
for (iter = _files.begin(); iter != _files.end(); ++iter)
|
|
||||||
{
|
|
||||||
FileEntry *e = *iter;
|
|
||||||
bool error = false;
|
|
||||||
if (e->_firstBlock > e->_lastBlock)
|
|
||||||
error = true;
|
|
||||||
|
|
||||||
if (e->_firstBlock >= _lastVolumeBlock)
|
unsigned block;
|
||||||
error = true;
|
|
||||||
|
for (unsigned i = 1; i <= _fileCount; ++i)
|
||||||
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;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
calcMaxFileSize();
|
|
||||||
|
|
||||||
}
|
|
||||||
catch (...)
|
|
||||||
{
|
{
|
||||||
std::vector<FileEntry *>::iterator iter;
|
FileEntryPointer child;
|
||||||
|
|
||||||
for(iter = _files.begin(); iter != _files.end(); ++iter)
|
//
|
||||||
{
|
child = FileEntry::Open(buffer.get() + i * 0x1a);
|
||||||
if (*iter) delete *iter;
|
|
||||||
}
|
child->setInode(++_inodeGenerator);
|
||||||
|
// need to set later....
|
||||||
throw;
|
//child->_parent = this;
|
||||||
|
child->_address = 512 * 2 + i * 0x1a;
|
||||||
|
|
||||||
|
_files.push_back(child);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// sanity check _firstBlock, _lastBlock?
|
||||||
|
|
||||||
|
block = _lastBlock;
|
||||||
|
|
||||||
|
for (iter = _files.begin(); iter != _files.end(); ++iter)
|
||||||
|
{
|
||||||
|
FileEntryPointer e = *iter;
|
||||||
|
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;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
calcMaxFileSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
VolumeEntry::~VolumeEntry()
|
VolumeEntry::~VolumeEntry()
|
||||||
{
|
{
|
||||||
|
|
||||||
std::vector<FileEntry *>::iterator iter;
|
|
||||||
for(iter = _files.begin(); iter != _files.end(); ++iter)
|
|
||||||
{
|
|
||||||
if (*iter) delete *iter;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void VolumeEntry::setParents()
|
||||||
|
{
|
||||||
|
// parent is this....
|
||||||
|
|
||||||
|
VolumeEntryWeakPointer parent(thisPointer());
|
||||||
|
std::vector<FileEntryPointer>::iterator iter;
|
||||||
|
|
||||||
|
for (iter = _files.begin(); iter != _files.end(); ++iter)
|
||||||
|
{
|
||||||
|
FileEntryPointer e = *iter;
|
||||||
|
|
||||||
|
e->_parent = parent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void VolumeEntry::init(void *vp)
|
void VolumeEntry::init(void *vp)
|
||||||
{
|
{
|
||||||
#undef __METHOD__
|
#undef __METHOD__
|
||||||
|
@ -278,20 +289,20 @@ void VolumeEntry::init(void *vp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
FileEntry *VolumeEntry::fileAtIndex(unsigned i) const
|
FileEntryPointer VolumeEntry::fileAtIndex(unsigned i) const
|
||||||
{
|
{
|
||||||
return i < _files.size() ? _files[i] : NULL;
|
return i < _files.size() ? _files[i] : FileEntryPointer();
|
||||||
}
|
}
|
||||||
|
|
||||||
FileEntry *VolumeEntry::fileByName(const char *name) const
|
FileEntryPointer VolumeEntry::fileByName(const char *name) const
|
||||||
{
|
{
|
||||||
std::vector<FileEntry *>::const_iterator iter;
|
std::vector<FileEntryPointer>::const_iterator iter;
|
||||||
for(iter = _files.begin(); iter != _files.end(); ++iter)
|
for(iter = _files.begin(); iter != _files.end(); ++iter)
|
||||||
{
|
{
|
||||||
FileEntry *e = *iter;
|
FileEntryPointer e = *iter;
|
||||||
if (::strcasecmp(name, e->name()) == 0) return e;
|
if (::strcasecmp(name, e->name()) == 0) return e;
|
||||||
}
|
}
|
||||||
return NULL;
|
return FileEntryPointer();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -303,7 +314,7 @@ int VolumeEntry::unlink(const char *name)
|
||||||
{
|
{
|
||||||
unsigned index;
|
unsigned index;
|
||||||
|
|
||||||
std::vector<FileEntry *>::iterator iter;
|
std::vector<FileEntryPointer>::iterator iter;
|
||||||
|
|
||||||
if (_device->readOnly())
|
if (_device->readOnly())
|
||||||
{
|
{
|
||||||
|
@ -315,7 +326,7 @@ int VolumeEntry::unlink(const char *name)
|
||||||
|
|
||||||
for (iter = _files.begin(); iter != _files.end(); ++iter)
|
for (iter = _files.begin(); iter != _files.end(); ++iter)
|
||||||
{
|
{
|
||||||
FileEntry *e = *iter;
|
FileEntryPointer e = *iter;
|
||||||
if (::strcasecmp(name, e->name()) == 0)
|
if (::strcasecmp(name, e->name()) == 0)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -323,12 +334,11 @@ int VolumeEntry::unlink(const char *name)
|
||||||
// _maxFileSize.
|
// _maxFileSize.
|
||||||
if (iter != _files.begin())
|
if (iter != _files.begin())
|
||||||
{
|
{
|
||||||
FileEntry *prev = iter[-1];
|
FileEntryPointer prev = iter[-1];
|
||||||
prev->_maxFileSize += e->_maxFileSize;
|
prev->_maxFileSize += e->_maxFileSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete e;
|
iter->reset();
|
||||||
*iter = NULL;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -347,7 +357,7 @@ int VolumeEntry::unlink(const char *name)
|
||||||
// reset addresses.
|
// reset addresses.
|
||||||
for ( ; iter != _files.end(); ++iter)
|
for ( ; iter != _files.end(); ++iter)
|
||||||
{
|
{
|
||||||
FileEntry *e = *iter;
|
FileEntryPointer e = *iter;
|
||||||
e->_address -= 0x1a;
|
e->_address -= 0x1a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -380,7 +390,7 @@ int VolumeEntry::unlink(const char *name)
|
||||||
*/
|
*/
|
||||||
int VolumeEntry::rename(const char *oldName, const char *newName)
|
int VolumeEntry::rename(const char *oldName, const char *newName)
|
||||||
{
|
{
|
||||||
FileEntry *e;
|
FileEntryPointer e;
|
||||||
|
|
||||||
|
|
||||||
// check if read only.
|
// check if read only.
|
||||||
|
@ -417,7 +427,7 @@ int VolumeEntry::rename(const char *oldName, const char *newName)
|
||||||
|
|
||||||
// and commit to disk.
|
// and commit to disk.
|
||||||
|
|
||||||
writeEntry(e);
|
writeEntry(e.get());
|
||||||
_cache->sync();
|
_cache->sync();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -431,8 +441,8 @@ int VolumeEntry::rename(const char *oldName, const char *newName)
|
||||||
*/
|
*/
|
||||||
int VolumeEntry::copy(const char *oldName, const char *newName)
|
int VolumeEntry::copy(const char *oldName, const char *newName)
|
||||||
{
|
{
|
||||||
FileEntry *oldEntry;
|
FileEntryPointer oldEntry;
|
||||||
FileEntry *newEntry;
|
FileEntryPointer newEntry;
|
||||||
// check if read only.
|
// check if read only.
|
||||||
if (_device->readOnly())
|
if (_device->readOnly())
|
||||||
{
|
{
|
||||||
|
@ -482,14 +492,14 @@ int VolumeEntry::copy(const char *oldName, const char *newName)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
newEntry = NULL;
|
newEntry.reset();
|
||||||
|
|
||||||
if (unlink(newName) != 0) return -1;
|
if (unlink(newName) != 0) return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (newEntry == NULL)
|
if (!newEntry)
|
||||||
{
|
{
|
||||||
// newName does not exist (or was just deleted), so create a new file (if possible) and write to it.
|
// newName does not exist (or was just deleted), so create a new file (if possible) and write to it.
|
||||||
if (maxContiguousBlocks() < blocks)
|
if (maxContiguousBlocks() < blocks)
|
||||||
|
@ -534,7 +544,7 @@ int VolumeEntry::copy(const char *oldName, const char *newName)
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
FileEntry *VolumeEntry::create(const char *name, unsigned blocks)
|
FileEntryPointer VolumeEntry::create(const char *name, unsigned blocks)
|
||||||
{
|
{
|
||||||
// 0. check read only access.
|
// 0. check read only access.
|
||||||
// 1. verify < 77 file names.
|
// 1. verify < 77 file names.
|
||||||
|
@ -547,46 +557,45 @@ FileEntry *VolumeEntry::create(const char *name, unsigned blocks)
|
||||||
unsigned lastBlock = _lastBlock;
|
unsigned lastBlock = _lastBlock;
|
||||||
|
|
||||||
|
|
||||||
std::auto_ptr<FileEntry>entry;
|
FileEntryPointer entry;
|
||||||
FileEntry *prev = NULL;
|
FileEntryPointer prev;
|
||||||
FileEntry *curr = NULL;
|
FileEntryPointer curr;
|
||||||
std::vector<FileEntry *>::iterator iter;
|
std::vector<FileEntryPointer>::iterator iter;
|
||||||
|
|
||||||
|
|
||||||
if (readOnly())
|
if (readOnly())
|
||||||
{
|
{
|
||||||
errno = EROFS;
|
errno = EROFS;
|
||||||
return NULL;
|
return FileEntryPointer();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_fileCount == kMaxFiles)
|
if (_fileCount == kMaxFiles)
|
||||||
{
|
{
|
||||||
errno = ENOSPC;
|
errno = ENOSPC;
|
||||||
return NULL;
|
return FileEntryPointer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!FileEntry::ValidName(name))
|
if (!FileEntry::ValidName(name))
|
||||||
{
|
{
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return NULL;
|
return FileEntryPointer();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fileByName(name))
|
if (fileByName(name))
|
||||||
{
|
{
|
||||||
errno = EEXIST;
|
errno = EEXIST;
|
||||||
return NULL;
|
return FileEntryPointer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
entry.reset(new FileEntry(name, kUntypedFile));
|
entry = FileEntry::Create(name, kUntypedFile);
|
||||||
|
|
||||||
|
ProFUSE::auto_array<uint8_t> buffer(readDirectoryHeader());
|
||||||
std::auto_ptr<uint8_t> buffer(readDirectoryHeader());
|
|
||||||
|
|
||||||
for (iter = _files.begin(); iter != _files.end(); ++iter)
|
for (iter = _files.begin(); iter != _files.end(); ++iter)
|
||||||
{
|
{
|
||||||
FileEntry *e = *iter;
|
FileEntryPointer e = *iter;
|
||||||
|
|
||||||
unsigned freeSpace = e->_firstBlock - _lastBlock;
|
unsigned freeSpace = e->_firstBlock - _lastBlock;
|
||||||
// this could do something stupid like selecting a slot with only 1 free block but too bad.
|
// this could do something stupid like selecting a slot with only 1 free block but too bad.
|
||||||
|
@ -611,12 +620,13 @@ FileEntry *VolumeEntry::create(const char *name, unsigned blocks)
|
||||||
// keep track of the index *before* the insert.
|
// keep track of the index *before* the insert.
|
||||||
unsigned index = distance(_files.begin(), iter); // current index.
|
unsigned index = distance(_files.begin(), iter); // current index.
|
||||||
|
|
||||||
iter = _files.insert(iter, entry.get());
|
iter = _files.insert(iter, entry);
|
||||||
++_fileCount;
|
++_fileCount;
|
||||||
|
|
||||||
curr = entry.release();
|
curr = entry;
|
||||||
|
|
||||||
curr->_parent = this;
|
//curr->_parent = this;
|
||||||
|
curr->_parent = VolumeEntryWeakPointer(thisPointer());
|
||||||
curr->_firstBlock = lastBlock;
|
curr->_firstBlock = lastBlock;
|
||||||
curr->_lastBlock = lastBlock + 1;
|
curr->_lastBlock = lastBlock + 1;
|
||||||
curr->_lastByte = 0;
|
curr->_lastByte = 0;
|
||||||
|
@ -638,15 +648,16 @@ FileEntry *VolumeEntry::create(const char *name, unsigned blocks)
|
||||||
if (freeSpace < blocks)
|
if (freeSpace < blocks)
|
||||||
{
|
{
|
||||||
errno = ENOSPC;
|
errno = ENOSPC;
|
||||||
return NULL;
|
return FileEntryPointer();
|
||||||
}
|
}
|
||||||
|
|
||||||
_files.push_back(entry.get());
|
_files.push_back(entry);
|
||||||
_fileCount++;
|
_fileCount++;
|
||||||
|
|
||||||
curr = entry.release();
|
curr = entry;
|
||||||
|
|
||||||
curr->_parent = this;
|
//curr->_parent = this;
|
||||||
|
curr->_parent = VolumeEntryWeakPointer(thisPointer());
|
||||||
curr->_firstBlock = lastBlock;
|
curr->_firstBlock = lastBlock;
|
||||||
curr->_lastBlock = lastBlock + 1;
|
curr->_lastBlock = lastBlock + 1;
|
||||||
curr->_lastByte = 0;
|
curr->_lastByte = 0;
|
||||||
|
@ -658,7 +669,7 @@ FileEntry *VolumeEntry::create(const char *name, unsigned blocks)
|
||||||
prev->_maxFileSize = prev->blocks() * 512;
|
prev->_maxFileSize = prev->blocks() * 512;
|
||||||
}
|
}
|
||||||
|
|
||||||
writeEntry(curr);
|
writeEntry(curr.get());
|
||||||
writeEntry(); // header.
|
writeEntry(); // header.
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -670,7 +681,7 @@ FileEntry *VolumeEntry::create(const char *name, unsigned blocks)
|
||||||
unsigned address = 2 * 512 + 0x1a;
|
unsigned address = 2 * 512 + 0x1a;
|
||||||
for (iter = _files.begin(); iter != _files.end(); ++iter, address += 0x1a)
|
for (iter = _files.begin(); iter != _files.end(); ++iter, address += 0x1a)
|
||||||
{
|
{
|
||||||
FileEntry *e = *iter;
|
FileEntryPointer e = *iter;
|
||||||
e->_address = address;
|
e->_address = address;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -706,7 +717,7 @@ int VolumeEntry::krunch()
|
||||||
{
|
{
|
||||||
unsigned prevBlock;
|
unsigned prevBlock;
|
||||||
|
|
||||||
std::vector<FileEntry *>::const_iterator iter;
|
std::vector<FileEntryPointer>::const_iterator iter;
|
||||||
|
|
||||||
bool gap = false;
|
bool gap = false;
|
||||||
|
|
||||||
|
@ -716,7 +727,7 @@ int VolumeEntry::krunch()
|
||||||
|
|
||||||
for (iter = _files.begin(); iter != _files.end(); ++iter)
|
for (iter = _files.begin(); iter != _files.end(); ++iter)
|
||||||
{
|
{
|
||||||
FileEntry *e = *iter;
|
FileEntryPointer e = *iter;
|
||||||
|
|
||||||
unsigned first = e->firstBlock();
|
unsigned first = e->firstBlock();
|
||||||
unsigned last = e->lastBlock();
|
unsigned last = e->lastBlock();
|
||||||
|
@ -751,7 +762,7 @@ int VolumeEntry::krunch()
|
||||||
unsigned offset = 0;
|
unsigned offset = 0;
|
||||||
for (iter = _files.begin(); iter != _files.end(); ++iter, ++offset)
|
for (iter = _files.begin(); iter != _files.end(); ++iter, ++offset)
|
||||||
{
|
{
|
||||||
FileEntry *e = *iter;
|
FileEntryPointer e = *iter;
|
||||||
|
|
||||||
b.setOffset(0x1a + 0x1a * offset);
|
b.setOffset(0x1a + 0x1a * offset);
|
||||||
|
|
||||||
|
@ -812,13 +823,13 @@ unsigned VolumeEntry::freeBlocks(bool krunched) const
|
||||||
|
|
||||||
if (krunched)
|
if (krunched)
|
||||||
{
|
{
|
||||||
std::vector<FileEntry *>::const_iterator iter;
|
std::vector<FileEntryPointer>::const_iterator iter;
|
||||||
|
|
||||||
lastBlock = _lastBlock;
|
lastBlock = _lastBlock;
|
||||||
|
|
||||||
for (iter = _files.begin(); iter != _files.end(); ++iter)
|
for (iter = _files.begin(); iter != _files.end(); ++iter)
|
||||||
{
|
{
|
||||||
const FileEntry *e = *iter;
|
const FileEntryPointer e = *iter;
|
||||||
freeBlocks += e->_firstBlock - lastBlock;
|
freeBlocks += e->_firstBlock - lastBlock;
|
||||||
lastBlock = e->_lastBlock;
|
lastBlock = e->_lastBlock;
|
||||||
}
|
}
|
||||||
|
@ -842,13 +853,13 @@ unsigned VolumeEntry::freeBlocks(bool krunched) const
|
||||||
bool VolumeEntry::canKrunch() const
|
bool VolumeEntry::canKrunch() const
|
||||||
{
|
{
|
||||||
|
|
||||||
std::vector<FileEntry *>::const_iterator iter;
|
std::vector<FileEntryPointer>::const_iterator iter;
|
||||||
|
|
||||||
unsigned lastBlock = _lastBlock;
|
unsigned lastBlock = _lastBlock;
|
||||||
|
|
||||||
for (iter = _files.begin(); iter != _files.end(); ++iter)
|
for (iter = _files.begin(); iter != _files.end(); ++iter)
|
||||||
{
|
{
|
||||||
const FileEntry *e = *iter;
|
const FileEntryPointer e = *iter;
|
||||||
if (e->_lastBlock != lastBlock) return true;
|
if (e->_lastBlock != lastBlock) return true;
|
||||||
lastBlock = e->_lastBlock;
|
lastBlock = e->_lastBlock;
|
||||||
}
|
}
|
||||||
|
@ -864,13 +875,13 @@ unsigned VolumeEntry::maxContiguousBlocks() const
|
||||||
{
|
{
|
||||||
unsigned max = 0;
|
unsigned max = 0;
|
||||||
|
|
||||||
std::vector<FileEntry *>::const_iterator iter;
|
std::vector<FileEntryPointer>::const_iterator iter;
|
||||||
|
|
||||||
unsigned lastBlock = _lastBlock;
|
unsigned lastBlock = _lastBlock;
|
||||||
|
|
||||||
for (iter = _files.begin(); iter != _files.end(); ++iter)
|
for (iter = _files.begin(); iter != _files.end(); ++iter)
|
||||||
{
|
{
|
||||||
const FileEntry *e = *iter;
|
const FileEntryPointer e = *iter;
|
||||||
unsigned free = e->_firstBlock - lastBlock;
|
unsigned free = e->_firstBlock - lastBlock;
|
||||||
max = std::max(max, free);
|
max = std::max(max, free);
|
||||||
|
|
||||||
|
@ -999,11 +1010,11 @@ void VolumeEntry::writeEntry(FileEntry *e)
|
||||||
// set _maxFileSize for all entries.
|
// set _maxFileSize for all entries.
|
||||||
void VolumeEntry::calcMaxFileSize()
|
void VolumeEntry::calcMaxFileSize()
|
||||||
{
|
{
|
||||||
std::vector<FileEntry *>::reverse_iterator riter;
|
std::vector<FileEntryPointer>::reverse_iterator riter;
|
||||||
unsigned block = _lastVolumeBlock;
|
unsigned block = _lastVolumeBlock;
|
||||||
for (riter = _files.rbegin(); riter != _files.rend(); ++riter)
|
for (riter = _files.rbegin(); riter != _files.rend(); ++riter)
|
||||||
{
|
{
|
||||||
FileEntry *e = *riter;
|
FileEntryPointer e = *riter;
|
||||||
e->_maxFileSize = (block - e->_firstBlock) * 512;
|
e->_maxFileSize = (block - e->_firstBlock) * 512;
|
||||||
block = e->_firstBlock;
|
block = e->_firstBlock;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,20 +9,18 @@
|
||||||
|
|
||||||
namespace Pascal {
|
namespace Pascal {
|
||||||
|
|
||||||
class FileEntry;
|
|
||||||
|
|
||||||
class VolumeEntry : public Entry {
|
class VolumeEntry : public Entry {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
static unsigned ValidName(const char *);
|
static unsigned ValidName(const char *);
|
||||||
|
|
||||||
|
static VolumeEntryPointer Open(Device::BlockDevicePointer);
|
||||||
|
static VolumeEntryPointer Create(Device::BlockDevicePointer, const char *name);
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
// create new
|
|
||||||
VolumeEntry(const char *name, Device::BlockDevicePointer);
|
|
||||||
|
|
||||||
// open existing
|
|
||||||
VolumeEntry(Device::BlockDevicePointer);
|
|
||||||
virtual ~VolumeEntry();
|
virtual ~VolumeEntry();
|
||||||
|
|
||||||
const char *name() const { return _fileName; }
|
const char *name() const { return _fileName; }
|
||||||
|
@ -36,8 +34,8 @@ namespace Pascal {
|
||||||
bool canKrunch() const;
|
bool canKrunch() const;
|
||||||
|
|
||||||
|
|
||||||
FileEntry *fileAtIndex(unsigned i) const;
|
FileEntryPointer fileAtIndex(unsigned i) const;
|
||||||
FileEntry *fileByName(const char *name) const;
|
FileEntryPointer fileByName(const char *name) const;
|
||||||
|
|
||||||
|
|
||||||
void *loadBlock(unsigned block);
|
void *loadBlock(unsigned block);
|
||||||
|
@ -53,7 +51,7 @@ namespace Pascal {
|
||||||
int unlink(const char *name);
|
int unlink(const char *name);
|
||||||
int rename(const char *oldName, const char *newName);
|
int rename(const char *oldName, const char *newName);
|
||||||
int copy(const char *oldName, const char *newName);
|
int copy(const char *oldName, const char *newName);
|
||||||
FileEntry *create(const char *name, unsigned blocks);
|
FileEntryPointer create(const char *name, unsigned blocks);
|
||||||
|
|
||||||
|
|
||||||
int krunch();
|
int krunch();
|
||||||
|
@ -65,10 +63,21 @@ namespace Pascal {
|
||||||
private:
|
private:
|
||||||
|
|
||||||
friend class FileEntry;
|
friend class FileEntry;
|
||||||
|
|
||||||
|
|
||||||
VolumeEntry();
|
VolumeEntry();
|
||||||
|
VolumeEntry(Device::BlockDevicePointer, const char *name);
|
||||||
|
VolumeEntry(Device::BlockDevicePointer);
|
||||||
|
|
||||||
|
VolumeEntryPointer thisPointer()
|
||||||
|
{
|
||||||
|
return std::tr1::static_pointer_cast<VolumeEntry>(shared_from_this());
|
||||||
|
}
|
||||||
|
|
||||||
void init(void *);
|
void init(void *);
|
||||||
|
void setParents();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
uint8_t *readDirectoryHeader();
|
uint8_t *readDirectoryHeader();
|
||||||
|
@ -90,7 +99,7 @@ namespace Pascal {
|
||||||
unsigned _accessTime;
|
unsigned _accessTime;
|
||||||
Pascal::Date _lastBoot;
|
Pascal::Date _lastBoot;
|
||||||
|
|
||||||
std::vector<FileEntry *> _files;
|
std::vector<FileEntryPointer> _files;
|
||||||
unsigned _inodeGenerator;
|
unsigned _inodeGenerator;
|
||||||
|
|
||||||
Device::BlockDevicePointer _device;
|
Device::BlockDevicePointer _device;
|
||||||
|
|
18
bin/apfm.cpp
18
bin/apfm.cpp
|
@ -263,7 +263,7 @@ void printUnusedEntry(unsigned block, unsigned size)
|
||||||
std::printf("< UNUSED > %4u %4u\n", size, block);
|
std::printf("< UNUSED > %4u %4u\n", size, block);
|
||||||
}
|
}
|
||||||
|
|
||||||
void printFileEntry(Pascal::FileEntry *e, bool extended)
|
void printFileEntry(Pascal::FileEntryPointer e, bool extended)
|
||||||
{
|
{
|
||||||
Pascal::Date dt = e->modification();
|
Pascal::Date dt = e->modification();
|
||||||
|
|
||||||
|
@ -329,7 +329,7 @@ int action_ls(int argc, char **argv, Pascal::VolumeEntry *volume)
|
||||||
|
|
||||||
for (unsigned i = 0; i < fileCount; ++i)
|
for (unsigned i = 0; i < fileCount; ++i)
|
||||||
{
|
{
|
||||||
Pascal::FileEntry *e = volume->fileAtIndex(i);
|
Pascal::FileEntryPointer e = volume->fileAtIndex(i);
|
||||||
if (!e) continue;
|
if (!e) continue;
|
||||||
|
|
||||||
|
|
||||||
|
@ -409,7 +409,7 @@ int action_cat(unsigned argc, char **argv, Pascal::VolumeEntry *volume)
|
||||||
unsigned fileSize;
|
unsigned fileSize;
|
||||||
unsigned offset;
|
unsigned offset;
|
||||||
uint8_t buffer[512];
|
uint8_t buffer[512];
|
||||||
Pascal::FileEntry *e = NULL;
|
Pascal::FileEntryPointer e;
|
||||||
// find it...
|
// find it...
|
||||||
|
|
||||||
e = volume->fileByName(argv[i]);
|
e = volume->fileByName(argv[i]);
|
||||||
|
@ -588,7 +588,7 @@ int action_rm(int argc, char **argv, Pascal::VolumeEntry *volume)
|
||||||
// TODO -- catch errors ?
|
// TODO -- catch errors ?
|
||||||
for (int i = 0; i < argc; ++i)
|
for (int i = 0; i < argc; ++i)
|
||||||
{
|
{
|
||||||
Pascal::FileEntry *e = volume->fileByName(argv[i]);
|
Pascal::FileEntryPointer e = volume->fileByName(argv[i]);
|
||||||
|
|
||||||
if (!e)
|
if (!e)
|
||||||
{
|
{
|
||||||
|
@ -691,7 +691,7 @@ int action_get(int argc, char **argv, Pascal::VolumeEntry *volume)
|
||||||
argc -= optind;
|
argc -= optind;
|
||||||
argv += optind;
|
argv += optind;
|
||||||
|
|
||||||
Pascal::FileEntry *entry;
|
Pascal::FileEntryPointer entry;
|
||||||
|
|
||||||
switch(argc)
|
switch(argc)
|
||||||
{
|
{
|
||||||
|
@ -910,7 +910,7 @@ int action_put(int argc, char **argv, Pascal::VolumeEntry *volume)
|
||||||
|
|
||||||
blocks = text.blocks();
|
blocks = text.blocks();
|
||||||
|
|
||||||
Pascal::FileEntry *entry = volume->create(outfile, blocks);
|
Pascal::FileEntryPointer entry = volume->create(outfile, blocks);
|
||||||
if (!entry)
|
if (!entry)
|
||||||
{
|
{
|
||||||
perror(NULL);
|
perror(NULL);
|
||||||
|
@ -923,7 +923,7 @@ int action_put(int argc, char **argv, Pascal::VolumeEntry *volume)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Pascal::FileEntry *entry = volume->create(outfile, blocks);
|
Pascal::FileEntryPointer entry = volume->create(outfile, blocks);
|
||||||
if (!entry)
|
if (!entry)
|
||||||
{
|
{
|
||||||
perror(NULL);
|
perror(NULL);
|
||||||
|
@ -962,7 +962,7 @@ int action_put(int argc, char **argv, Pascal::VolumeEntry *volume)
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
std::auto_ptr<Pascal::VolumeEntry> volume;
|
Pascal::VolumeEntryPointer volume;
|
||||||
Device::BlockDevicePointer device;
|
Device::BlockDevicePointer device;
|
||||||
|
|
||||||
unsigned fmt = 0;
|
unsigned fmt = 0;
|
||||||
|
@ -1027,7 +1027,7 @@ int main(int argc, char **argv)
|
||||||
|
|
||||||
device = Device::BlockDevice::Open(file, commandFlags(actionCode), fmt);
|
device = Device::BlockDevice::Open(file, commandFlags(actionCode), fmt);
|
||||||
|
|
||||||
volume.reset( new Pascal::VolumeEntry(device));
|
volume = Pascal::VolumeEntry::Open(device);
|
||||||
device.reset();
|
device.reset();
|
||||||
|
|
||||||
switch (actionCode)
|
switch (actionCode)
|
||||||
|
|
|
@ -169,7 +169,7 @@ int main(int argc, char **argv)
|
||||||
int multithread = false;
|
int multithread = false;
|
||||||
|
|
||||||
|
|
||||||
std::auto_ptr<Pascal::VolumeEntry> volume;
|
Pascal::VolumeEntryPointer volume;
|
||||||
|
|
||||||
|
|
||||||
init_ops(&pascal_ops);
|
init_ops(&pascal_ops);
|
||||||
|
@ -210,8 +210,7 @@ int main(int argc, char **argv)
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
volume.reset( new Pascal::VolumeEntry(device) );
|
volume = Pascal::VolumeEntry::Open(device);
|
||||||
device.reset();
|
|
||||||
}
|
}
|
||||||
catch (ProFUSE::POSIXException &e)
|
catch (ProFUSE::POSIXException &e)
|
||||||
{
|
{
|
||||||
|
|
|
@ -56,18 +56,23 @@
|
||||||
using namespace Pascal;
|
using namespace Pascal;
|
||||||
|
|
||||||
|
|
||||||
static FileEntry *findChild(VolumeEntry *volume, unsigned inode)
|
// fd_table is files which have been open.
|
||||||
|
// fd_table_available is a list of indexes in fd_table which are not currently used.
|
||||||
|
static std::vector<FileEntryPointer> fd_table;
|
||||||
|
static std::vector<unsigned> fd_table_available;
|
||||||
|
|
||||||
|
static FileEntryPointer findChild(VolumeEntry *volume, unsigned inode)
|
||||||
{
|
{
|
||||||
|
|
||||||
for (unsigned i = 0, l = volume->fileCount(); i < l; ++i)
|
for (unsigned i = 0, l = volume->fileCount(); i < l; ++i)
|
||||||
{
|
{
|
||||||
FileEntry *child = volume->fileAtIndex(i);
|
FileEntryPointer child = volume->fileAtIndex(i);
|
||||||
if (!child) continue;
|
if (!child) continue;
|
||||||
|
|
||||||
if (inode == child->inode()) return child;
|
if (inode == child->inode()) return child;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return FileEntryPointer();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void pascal_init(void *userdata, struct fuse_conn_info *conn)
|
static void pascal_init(void *userdata, struct fuse_conn_info *conn)
|
||||||
|
@ -82,7 +87,7 @@ static void pascal_init(void *userdata, struct fuse_conn_info *conn)
|
||||||
|
|
||||||
for (unsigned i = 0, l = volume->fileCount(); i < l; ++i)
|
for (unsigned i = 0, l = volume->fileCount(); i < l; ++i)
|
||||||
{
|
{
|
||||||
FileEntry *child = volume->fileAtIndex(i);
|
FileEntryPointer child = volume->fileAtIndex(i);
|
||||||
child->fileSize();
|
child->fileSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,7 +110,7 @@ static void pascal_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size)
|
||||||
DEBUGNAME()
|
DEBUGNAME()
|
||||||
|
|
||||||
VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req);
|
VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req);
|
||||||
FileEntry *file;
|
FileEntryPointer file;
|
||||||
std::string attr;
|
std::string attr;
|
||||||
unsigned attrSize;
|
unsigned attrSize;
|
||||||
|
|
||||||
|
@ -149,7 +154,7 @@ static void pascal_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name, si
|
||||||
|
|
||||||
|
|
||||||
VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req);
|
VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req);
|
||||||
FileEntry *file;
|
FileEntryPointer file;
|
||||||
std::string attr(name);
|
std::string attr(name);
|
||||||
|
|
||||||
ERROR(ino == 1, ENOATTR)
|
ERROR(ino == 1, ENOATTR)
|
||||||
|
@ -269,7 +274,7 @@ static void pascal_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, off_t of
|
||||||
{
|
{
|
||||||
unsigned tmp;
|
unsigned tmp;
|
||||||
|
|
||||||
FileEntry *file = volume->fileAtIndex(i);
|
FileEntryPointer file = volume->fileAtIndex(i);
|
||||||
if (file == NULL) break; //?
|
if (file == NULL) break; //?
|
||||||
|
|
||||||
// only these fields are used.
|
// only these fields are used.
|
||||||
|
@ -352,7 +357,7 @@ static void pascal_lookup(fuse_req_t req, fuse_ino_t parent, const char *name)
|
||||||
|
|
||||||
for (unsigned i = 0, l = volume->fileCount(); i < l; ++i)
|
for (unsigned i = 0, l = volume->fileCount(); i < l; ++i)
|
||||||
{
|
{
|
||||||
FileEntry *file = volume->fileAtIndex(i);
|
FileEntryPointer file = volume->fileAtIndex(i);
|
||||||
if (file == NULL) break;
|
if (file == NULL) break;
|
||||||
|
|
||||||
if (::strcasecmp(file->name(), name)) continue;
|
if (::strcasecmp(file->name(), name)) continue;
|
||||||
|
@ -363,7 +368,7 @@ static void pascal_lookup(fuse_req_t req, fuse_ino_t parent, const char *name)
|
||||||
entry.entry_timeout = 0.0;
|
entry.entry_timeout = 0.0;
|
||||||
entry.ino = file->inode();
|
entry.ino = file->inode();
|
||||||
|
|
||||||
stat(file, &entry.attr);
|
stat(file.get(), &entry.attr);
|
||||||
fuse_reply_entry(req, &entry);
|
fuse_reply_entry(req, &entry);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -378,7 +383,7 @@ static void pascal_getattr(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info
|
||||||
|
|
||||||
struct stat st;
|
struct stat st;
|
||||||
VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req);
|
VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req);
|
||||||
FileEntry *file;
|
FileEntryPointer file;
|
||||||
|
|
||||||
if (ino == 1)
|
if (ino == 1)
|
||||||
{
|
{
|
||||||
|
@ -392,7 +397,7 @@ static void pascal_getattr(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info
|
||||||
ERROR(file == NULL, ENOENT)
|
ERROR(file == NULL, ENOENT)
|
||||||
//printf("\t%s\n", file->name());
|
//printf("\t%s\n", file->name());
|
||||||
|
|
||||||
stat(file, &st);
|
stat(file.get(), &st);
|
||||||
fuse_reply_attr(req, &st, 0.0);
|
fuse_reply_attr(req, &st, 0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -402,10 +407,11 @@ static void pascal_getattr(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info
|
||||||
|
|
||||||
static void pascal_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
|
static void pascal_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
|
||||||
{
|
{
|
||||||
|
unsigned index;
|
||||||
DEBUGNAME()
|
DEBUGNAME()
|
||||||
|
|
||||||
VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req);
|
VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req);
|
||||||
FileEntry *file;
|
FileEntryPointer file;
|
||||||
|
|
||||||
ERROR(ino == 1, EISDIR)
|
ERROR(ino == 1, EISDIR)
|
||||||
|
|
||||||
|
@ -415,7 +421,20 @@ static void pascal_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *f
|
||||||
|
|
||||||
ERROR((fi->flags & O_ACCMODE) != O_RDONLY, EACCES)
|
ERROR((fi->flags & O_ACCMODE) != O_RDONLY, EACCES)
|
||||||
|
|
||||||
fi->fh = (uint64_t)file;
|
// insert the FileEntryPointer into fd_table.
|
||||||
|
if (fd_table_available.size())
|
||||||
|
{
|
||||||
|
index = fd_table_available.back();
|
||||||
|
fd_table_available.pop_back();
|
||||||
|
fd_table[index] = file;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
index = fd_table.size();
|
||||||
|
fd_table.push_back(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
fi->fh = index;
|
||||||
|
|
||||||
fuse_reply_open(req, fi);
|
fuse_reply_open(req, fi);
|
||||||
}
|
}
|
||||||
|
@ -423,19 +442,25 @@ static void pascal_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *f
|
||||||
|
|
||||||
static void pascal_release(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
|
static void pascal_release(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
|
||||||
{
|
{
|
||||||
|
unsigned index = fi->fh;
|
||||||
DEBUGNAME()
|
DEBUGNAME()
|
||||||
|
|
||||||
|
fd_table[index].reset();
|
||||||
|
fd_table_available.push_back(index);
|
||||||
|
|
||||||
fuse_reply_err(req, 0);
|
fuse_reply_err(req, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void pascal_read(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info *fi)
|
static void pascal_read(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info *fi)
|
||||||
{
|
{
|
||||||
|
unsigned index = fi->fh;
|
||||||
|
|
||||||
DEBUGNAME()
|
DEBUGNAME()
|
||||||
|
|
||||||
|
|
||||||
//VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req);
|
//VolumeEntry *volume = (VolumeEntry *)fuse_req_userdata(req);
|
||||||
FileEntry *file = (FileEntry *)fi->fh;
|
FileEntryPointer file = fd_table[index];
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -215,7 +215,7 @@ int main(int argc, char **argv)
|
||||||
bool rawDevice;
|
bool rawDevice;
|
||||||
|
|
||||||
BlockDevicePointer device;
|
BlockDevicePointer device;
|
||||||
std::auto_ptr<VolumeEntry> volume;
|
VolumeEntryPointer volume;
|
||||||
|
|
||||||
// Check for block device. if so, verify.
|
// Check for block device. if so, verify.
|
||||||
// if file exists, verify before overwrite.
|
// if file exists, verify before overwrite.
|
||||||
|
@ -298,9 +298,7 @@ int main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
volume.reset(
|
volume = VolumeEntry::Create(device, volumeName.c_str());
|
||||||
new VolumeEntry(volumeName.c_str(), device)
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue