VFS tar: always set dirent type

Assume tar nodes with missing records are directories.

Fixes #1843
This commit is contained in:
Emery Hemingway 2016-01-05 15:45:08 +01:00 committed by Christian Helmuth
parent b4c5fb2d29
commit 56c637c1f6
1 changed files with 21 additions and 10 deletions

View File

@ -176,9 +176,9 @@ class Vfs::Tar_file_system : public File_system
} }
Node *lookup_child(int index) Node const *lookup_child(int index) const
{ {
for (Node *child_node = first(); child_node; child_node = child_node->next(), index--) { for (Node const *child_node = first(); child_node; child_node = child_node->next(), index--) {
if (index == 0) if (index == 0)
return child_node; return child_node;
} }
@ -464,7 +464,7 @@ class Vfs::Tar_file_system : public File_system
Dirent_result dirent(char const *path, file_offset index, Dirent &out) override Dirent_result dirent(char const *path, file_offset index, Dirent &out) override
{ {
Node *node = _root_node.lookup(path); Node const *node = dereference(path);
if (!node) if (!node)
return DIRENT_ERR_INVALID_PATH; return DIRENT_ERR_INVALID_PATH;
@ -472,6 +472,7 @@ class Vfs::Tar_file_system : public File_system
node = node->lookup_child(index); node = node->lookup_child(index);
if (!node) { if (!node) {
out.name[0] = '\0';
out.type = DIRENT_TYPE_END; out.type = DIRENT_TYPE_END;
return DIRENT_OK; return DIRENT_OK;
} }
@ -480,16 +481,26 @@ class Vfs::Tar_file_system : public File_system
Record const *record = node->record; Record const *record = node->record;
while (record && (record->type() == Record::TYPE_HARDLINK)) {
Node const *target = dereference(record->linked_name());
record = target ? target->record : 0;
}
if (record) { if (record) {
switch (record->type()) { switch (record->type()) {
case 0: out.type = DIRENT_TYPE_FILE; break; case Record::TYPE_FILE:
case 2: out.type = DIRENT_TYPE_SYMLINK; break; out.type = DIRENT_TYPE_FILE; break;
case 5: out.type = DIRENT_TYPE_DIRECTORY; break; case Record::TYPE_SYMLINK:
out.type = DIRENT_TYPE_SYMLINK; break;
case Record::TYPE_DIR:
out.type = DIRENT_TYPE_DIRECTORY; break;
default: default:
if (verbose) PERR("unhandled record type %d for %s", record->type(), node->name);
PDBG("unhandled record type %d", record->type());
} }
} else {
/* If no record exists, assume it is a directory */
out.type = DIRENT_TYPE_DIRECTORY;
} }
strncpy(out.name, node->name, sizeof(out.name)); strncpy(out.name, node->name, sizeof(out.name));
@ -502,7 +513,7 @@ class Vfs::Tar_file_system : public File_system
Readlink_result readlink(char const *path, char *buf, file_size buf_size, Readlink_result readlink(char const *path, char *buf, file_size buf_size,
file_size &out_len) override file_size &out_len) override
{ {
Node *node = _root_node.lookup(path); Node const *node = dereference(path);
Record const *record = node ? node->record : 0; Record const *record = node ? node->record : 0;
if (!record || (record->type() != Record::TYPE_SYMLINK)) if (!record || (record->type() != Record::TYPE_SYMLINK))
@ -539,7 +550,7 @@ class Vfs::Tar_file_system : public File_system
bool is_directory(char const *path) override bool is_directory(char const *path) override
{ {
Node *node = _root_node.lookup(path); Node const *node = dereference(path);
if (!node) if (!node)
return false; return false;