src/FileAttributeFinder.h
branchv_0
changeset 9 b4f29fb16159
parent 8 eb1ecb37c6b7
child 21 1252acdc5a5a
--- 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 {
 	}
 };