src/XattrAttributeFinder.h
branchv_0
changeset 4 d44ed75822e7
parent 3 62eac7ab4cf4
child 5 ec661baf433a
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/XattrAttributeFinder.h	Wed Jan 16 17:23:05 2019 +0100
@@ -0,0 +1,80 @@
+/**
+ * Relational pipes
+ * Copyright © 2019 František Kučera (Frantovo.cz, GlobalCode.info)
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+#pragma once
+
+#include <vector>
+#include <filesystem>
+
+#include <relpipe/writer/typedefs.h>
+#include <relpipe/writer/AttributeMetadata.h>
+#include <relpipe/writer/RelationalWriter.h>
+
+#include "RequestedField.h"
+
+namespace relpipe {
+namespace in {
+namespace filesystem {
+
+namespace fs = std::filesystem;
+using namespace relpipe::writer;
+
+class XattrAttributeFinder : public AttributeFinder {
+private:
+	std::wstring_convert<codecvt_utf8<wchar_t>> convertor; // TODO: support also other encodings.
+
+	fs::path currentFile;
+
+	string_t getXattr(const fs::path& file, const string_t& attributeName) {
+		// TODO: review, test on multiple platforms
+		// TODO: improve documentation in xattr.h in glibc
+		// TODO: check XATTR_NAME_MAX in limits.h and if it is reasonably small on our system, allocate buffer for it instead of reading twice
+		// TODO: avoid race condition (another process might change the attribute between reading its length and its value)
+		ssize_t length = getxattr(file.c_str(), convertor.to_bytes(attributeName).c_str(), nullptr, 0);
+		if (length > 0) {
+			std::vector<char> buffer(length + 1);
+			getxattr(file.c_str(), convertor.to_bytes(attributeName).c_str(), buffer.data(), buffer.size());
+			return convertor.from_bytes(buffer.data());
+		} else {
+			return L"";
+		}
+	}
+public:
+
+	virtual vector<AttributeMetadata> toMetadata(const RequestedField& field) override {
+		if (field.group == RequestedField::GROUP_XATTR) return { AttributeMetadata{field.name, TypeId::STRING}};
+		else return {};
+	}
+
+	void startFile(const fs::path& file) override {
+		currentFile = file;
+	};
+
+	void endFile() override {
+	};
+
+	virtual void writeField(RelationalWriter* writer, const RequestedField& field) override {
+		if (field.group == RequestedField::GROUP_XATTR) writer->writeAttribute(getXattr(currentFile, field.name));
+	}
+
+	virtual ~XattrAttributeFinder() override {
+	}
+};
+
+}
+}
+}
\ No newline at end of file