--- a/src/AttributeFinder.h Wed Jan 16 18:19:50 2019 +0100
+++ b/src/AttributeFinder.h Wed Jan 16 19:31:37 2019 +0100
@@ -37,41 +37,14 @@
protected:
fs::path currentFile;
string currentFileRaw;
-public:
-
- /**
- * Single requested fields might generate multiple attributes in the relation.
- * But usually it is 1:1.
- * @param field requested field from the user (usually from CLI arguments)
- * @return attribute metadata to be used in the RelationalWriter.startRelation()
- */
- virtual vector<AttributeMetadata> toMetadata(const RequestedField& field) = 0;
-
- /**
- * Writing of the record for current file is starting.
- * Following writeField() calls are related to this file.
- * @param file path to the file
- * @param fileRaw raw file name as it was on the input
- */
- virtual void startFile(const fs::path& file, const string& fileRaw) {
- currentFile = file;
- currentFileRaw = fileRaw;
- }
-
- /**
- * Writing of the record for current file is finished. All resources linked to this file should be released.
- */
- virtual void endFile() {
- currentFile.clear();
- currentFileRaw.clear();
- }
+ bool currentFileExists;
/**
* Writes field attribute(s). The attribute count must match with count of AttributeMetadata returned in toMetadata().
* @param writer
* @param field
*/
- virtual void writeField(RelationalWriter* writer, const RequestedField& field) = 0;
+ virtual void writeFieldOfExistingFile(RelationalWriter* writer, const RequestedField& field) = 0;
/**
* Writes empty attribute(s) in case of non-existent file or an error.
@@ -98,6 +71,41 @@
}
}
+public:
+
+ /**
+ * Single requested fields might generate multiple attributes in the relation.
+ * But usually it is 1:1.
+ * @param field requested field from the user (usually from CLI arguments)
+ * @return attribute metadata to be used in the RelationalWriter.startRelation()
+ */
+ virtual vector<AttributeMetadata> toMetadata(const RequestedField& field) = 0;
+
+ /**
+ * Writing of the record for current file is starting.
+ * Following writeField() calls are related to this file.
+ * @param file path to the file
+ * @param fileRaw raw file name as it was on the input
+ */
+ virtual void startFile(const fs::path& file, const string& fileRaw, bool exists) {
+ currentFile = file;
+ currentFileRaw = fileRaw;
+ currentFileExists = exists;
+ }
+
+ virtual void writeField(RelationalWriter* writer, const RequestedField& field) {
+ if (currentFileExists) writeFieldOfExistingFile(writer, field);
+ else writeEmptyField(writer, field);
+ }
+
+ /**
+ * Writing of the record for current file is finished. All resources linked to this file should be released.
+ */
+ virtual void endFile() {
+ currentFile.clear();
+ currentFileRaw.clear();
+ }
+
virtual ~AttributeFinder() {
}
};
--- a/src/FileAttributeFinder.h Wed Jan 16 18:19:50 2019 +0100
+++ b/src/FileAttributeFinder.h Wed Jan 16 19:31:37 2019 +0100
@@ -41,9 +41,9 @@
string_t currentOwner;
string_t currentGroup;
- string_t getType(const fs::path& file, bool x) {
+ string_t getType(const fs::path& file, bool workWithSymlinkItself) {
// TODO: Use whole words? (letters are compatible with find -type)
- if (fs::is_symlink(file) && x) return L"l"; // symlinks are both symlinks and files/directories/etc.
+ if (fs::is_symlink(file) && workWithSymlinkItself) return L"l"; // symlinks are both symlinks and files/directories/etc.
else if (fs::is_regular_file(file)) return L"f";
else if (fs::is_directory(file)) return L"d";
else if (fs::is_fifo(file)) return L"p";
@@ -69,6 +69,50 @@
owner = convertor.from_bytes(pw->pw_name);
group = convertor.from_bytes(gr->gr_name);
}
+
+protected:
+
+ virtual void writeFieldOfExistingFile(RelationalWriter* writer, const RequestedField& field) override {
+ if (field.group == RequestedField::GROUP_FILE) {
+ for (string_t alias : field.getAliases()) {
+ if (field.name == FIELD_NAME) {
+ writer->writeAttribute(currentFile.filename().wstring());
+ } else if (field.name == FIELD_PATH_ORIGINAL) {
+ writer->writeAttribute(convertor.from_bytes(currentFileRaw));
+ } else if (field.name == FIELD_PATH_ABSOLUTE) {
+ writer->writeAttribute(fs::absolute(currentFile).wstring());
+ } else if (field.name == FIELD_PATH_CANONICAL) {
+ writer->writeAttribute(fs::canonical(currentFile).wstring());
+ } else if (field.name == FIELD_TYPE) {
+ writer->writeAttribute(getType(currentFile, true));
+ } else if (field.name == FIELD_SYMLINK_TARGET_TYPE) {
+ writer->writeAttribute(getType(currentFile, false));
+ } else if (field.name == FIELD_SYMLINK_TARGET) {
+ string_t symlinkTarget; // TODO: null value (when supported)
+ if (fs::is_symlink(currentFile)) {
+ try {
+ symlinkTarget = fs::read_symlink(currentFile).wstring();
+ } catch (...) {
+ // missing permissions, not readable → leave empty
+ }
+ }
+ writer->writeAttribute(symlinkTarget);
+ } else if (field.name == FIELD_SIZE) {
+ integer_t size = fs::is_regular_file(currentFile) ? fs::file_size(currentFile) : 0;
+ writer->writeAttribute(&size, typeid (size));
+ } else if (field.name == FIELD_OWNER) {
+ if (currentOwner.empty()) fetchOwner(currentFile, currentOwner, currentGroup);
+ writer->writeAttribute(currentOwner);
+ } else if (field.name == FIELD_GROUP) {
+ if (currentOwner.empty()) fetchOwner(currentFile, currentOwner, currentGroup);
+ writer->writeAttribute(currentGroup);
+ } else {
+ throw RelpipeWriterException(L"Unsupported field name in FileAttributeFinder: " + field.name);
+ }
+ }
+ }
+ }
+
public:
static const string_t FIELD_PATH_ORIGINAL;
@@ -95,46 +139,21 @@
}
}
+ void writeField(RelationalWriter* writer, const RequestedField& field) override {
+ if (currentFileExists
+ || field.name == FIELD_PATH_ORIGINAL
+ || (fs::is_symlink(currentFile) && (field.name == FIELD_SYMLINK_TARGET || field.name == FIELD_TYPE)))
+ writeFieldOfExistingFile(writer, field);
+ else
+ writeEmptyField(writer, field);
+ }
+
void endFile() override {
AttributeFinder::endFile();
currentOwner.clear();
currentGroup.clear();
};
- virtual void writeField(RelationalWriter* writer, const RequestedField& field) override {
- if (field.group == RequestedField::GROUP_FILE) {
- for (string_t alias : field.getAliases()) {
- if (field.name == FIELD_NAME) {
- writer->writeAttribute(currentFile.filename().wstring());
- } else if (field.name == FIELD_PATH_ORIGINAL) {
- writer->writeAttribute(convertor.from_bytes(currentFileRaw));
- } else if (field.name == FIELD_PATH_ABSOLUTE) {
- writer->writeAttribute(fs::absolute(currentFile).wstring());
- } else if (field.name == FIELD_PATH_CANONICAL) {
- writer->writeAttribute(fs::canonical(currentFile).wstring());
- } else if (field.name == FIELD_TYPE) {
- writer->writeAttribute(getType(currentFile, true));
- } else if (field.name == FIELD_SYMLINK_TARGET_TYPE) {
- writer->writeAttribute(getType(currentFile, false));
- } else if (field.name == FIELD_SYMLINK_TARGET) {
- writer->writeAttribute(fs::is_symlink(currentFile) ? fs::read_symlink(currentFile).wstring() : L""); // TODO: null value (when supported)
- } else if (field.name == FIELD_SIZE) {
- integer_t size = fs::is_regular_file(currentFile) ? fs::file_size(currentFile) : 0;
- writer->writeAttribute(&size, typeid (size));
- } else if (field.name == FIELD_OWNER) {
- if (currentOwner.empty()) fetchOwner(currentFile, currentOwner, currentGroup);
- writer->writeAttribute(currentOwner);
- } else if (field.name == FIELD_GROUP) {
- if (currentOwner.empty()) fetchOwner(currentFile, currentOwner, currentGroup);
- writer->writeAttribute(currentGroup);
- } else {
- // TODO: should not happend; check supported attributes in toMetadata()?
- writer->writeAttribute(L"");
- }
- }
- }
- }
-
virtual ~FileAttributeFinder() override {
}
};
--- a/src/FilesystemCommand.h Wed Jan 16 18:19:50 2019 +0100
+++ b/src/FilesystemCommand.h Wed Jan 16 19:31:37 2019 +0100
@@ -95,17 +95,11 @@
// we probably do not have permissions to given directory → pretend that the file does not exist
}
- for (auto& finder : attributeFinders) finder.second->startFile(file, originalName.str());
+ for (auto& finder : attributeFinders) finder.second->startFile(file, originalName.str(), exists);
for (RequestedField field : configuration.fields) {
AttributeFinder* finder = attributeFinders[field.group]; // should not be nullptr, because already checked while writing the relation metadata
-
- // TODO: links to non-existent files are currently treated as non-existent files → we still can return the type and symlink_target values
- if (exists || (field.group == RequestedField::GROUP_FILE && field.name == FileAttributeFinder::FIELD_PATH_ORIGINAL)) {
- finder->writeField(writer.get(), field);
- } else {
- finder->writeEmptyField(writer.get(), field);
- }
+ finder->writeField(writer.get(), field);
}
for (auto& finder : attributeFinders) finder.second->endFile();
--- a/src/XattrAttributeFinder.h Wed Jan 16 18:19:50 2019 +0100
+++ b/src/XattrAttributeFinder.h Wed Jan 16 19:31:37 2019 +0100
@@ -51,6 +51,14 @@
return L"";
}
}
+protected:
+
+ virtual void writeFieldOfExistingFile(RelationalWriter* writer, const RequestedField& field) override {
+ for (string_t alias : field.getAliases()) {
+ if (field.group == RequestedField::GROUP_XATTR) writer->writeAttribute(getXattr(currentFile, field.name));
+ }
+ }
+
public:
virtual vector<AttributeMetadata> toMetadata(const RequestedField& field) override {
@@ -63,12 +71,6 @@
}
}
- virtual void writeField(RelationalWriter* writer, const RequestedField& field) override {
- for (string_t alias : field.getAliases()) {
- if (field.group == RequestedField::GROUP_XATTR) writer->writeAttribute(getXattr(currentFile, field.name));
- }
- }
-
virtual ~XattrAttributeFinder() override {
}
};