Noux: add tar hardlink support in 'stat()'

Fixes #481.
This commit is contained in:
Christian Prochaska 2012-11-22 21:24:11 +01:00 committed by Norman Feske
parent d233186900
commit ec0b6f82a5
1 changed files with 44 additions and 30 deletions

View File

@ -439,40 +439,54 @@ namespace Noux {
if (verbose)
PDBG("path = %s", path);
Node *node = _root_node.lookup(path);
Node const *node = 0;
Record const *record = 0;
if (!node) {
sysio->error.stat = Sysio::STAT_ERR_NO_ENTRY;
return false;
/*
* Walk hardlinks until we reach a file
*/
for (;;) {
node = _root_node.lookup(path);
if (!node) {
sysio->error.stat = Sysio::STAT_ERR_NO_ENTRY;
return false;
}
record = node->record;
if (record) {
if (record->type() == Record::TYPE_HARDLINK) {
path = record->linked_name();
continue;
} else
break;
} else {
if (verbose)
PDBG("found a virtual directoty node");
memset(&sysio->stat_out.st, 0, sizeof(sysio->stat_out.st));
sysio->stat_out.st.mode = Sysio::STAT_MODE_DIRECTORY;
return true;
}
}
/* convert TAR record modes to stat modes */
unsigned mode = record->mode();
switch (record->type()) {
case Record::TYPE_FILE: mode |= Sysio::STAT_MODE_FILE; break;
case Record::TYPE_SYMLINK: mode |= Sysio::STAT_MODE_SYMLINK; break;
case Record::TYPE_DIR: mode |= Sysio::STAT_MODE_DIRECTORY; break;
default:
if (verbose)
PDBG("unhandled record type %d", record->type());
}
memset(&sysio->stat_out.st, 0, sizeof(sysio->stat_out.st));
Record const *record = node->record;
if (record) {
/* convert TAR record modes to stat modes */
unsigned mode = record->mode();
switch (record->type()) {
case Record::TYPE_FILE: mode |= Sysio::STAT_MODE_FILE; break;
case Record::TYPE_SYMLINK: mode |= Sysio::STAT_MODE_SYMLINK; break;
case Record::TYPE_DIR: mode |= Sysio::STAT_MODE_DIRECTORY; break;
default:
if (verbose)
PDBG("unhandled record type %d", record->type());
}
sysio->stat_out.st.mode = mode;
sysio->stat_out.st.size = record->size();
sysio->stat_out.st.uid = record->uid();
sysio->stat_out.st.gid = record->gid();
} else {
if (verbose)
PDBG("found a virtual directoty node");
sysio->stat_out.st.mode = Sysio::STAT_MODE_DIRECTORY;
}
sysio->stat_out.st.mode = mode;
sysio->stat_out.st.size = record->size();
sysio->stat_out.st.uid = record->uid();
sysio->stat_out.st.gid = record->gid();
sysio->stat_out.st.inode = (unsigned long)node;
return true;