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:
ksherlock 2011-02-26 02:11:46 +00:00
parent e71ab41481
commit 89e80dcc10
10 changed files with 305 additions and 197 deletions

View File

@ -64,7 +64,6 @@ Entry::Entry()
_lastBlock = 0; _lastBlock = 0;
_fileKind = 0; _fileKind = 0;
_inode = 0; _inode = 0;
_parent = NULL;
_address = NULL; _address = NULL;
} }

View File

@ -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;
}; };

View File

@ -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;

View File

@ -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);

View File

@ -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;
} }

View File

@ -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;

View File

@ -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)

View File

@ -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)
{ {

View File

@ -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];

View File

@ -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)
);
} }