From b002ea9a20ea2a9b36c4f577bfeb506ff2cf0696 Mon Sep 17 00:00:00 2001
From: Max Kellermann <max@duempel.org>
Date: Sun, 28 Sep 2014 13:50:15 +0200
Subject: [PATCH] storage/nfs: convert file name to UTF-8

Assume the configured filesystem character set is also used by the NFS
server.
---
 src/storage/plugins/NfsStorage.cxx | 40 +++++++++++++++++++++++-------
 1 file changed, 31 insertions(+), 9 deletions(-)

diff --git a/src/storage/plugins/NfsStorage.cxx b/src/storage/plugins/NfsStorage.cxx
index 2c331dde6..ecf1fb0b6 100644
--- a/src/storage/plugins/NfsStorage.cxx
+++ b/src/storage/plugins/NfsStorage.cxx
@@ -23,6 +23,7 @@
 #include "storage/StorageInterface.hxx"
 #include "storage/FileInfo.hxx"
 #include "lib/nfs/Domain.hxx"
+#include "fs/AllocatedPath.hxx"
 #include "util/Error.hxx"
 #include "thread/Mutex.hxx"
 
@@ -42,6 +43,12 @@ class NfsDirectoryReader final : public StorageDirectoryReader {
 
 	nfsdirent *ent;
 
+	/**
+	 * Buffer for Read() which holds the current file name
+	 * converted to UTF-8.
+	 */
+	std::string name_utf8;
+
 public:
 	NfsDirectoryReader(const char *_base, nfs_context *_ctx, nfsdir *_dir)
 		:base(_base), ctx(_ctx), dir(_dir) {}
@@ -80,13 +87,15 @@ public:
 };
 
 static std::string
-UriToNfsPath(const char *uri_utf8)
+UriToNfsPath(const char *_uri_utf8, Error &error)
 {
-	/* libnfs paths must begin with a slash */
-	std::string path("/");
-	path.append(uri_utf8);
+	assert(_uri_utf8 != nullptr);
 
-	return path;
+	/* libnfs paths must begin with a slash */
+	std::string uri_utf8("/");
+	uri_utf8.append(_uri_utf8);
+
+	return AllocatedPath::FromUTF8(uri_utf8.c_str(), error).Steal();
 }
 
 std::string
@@ -134,7 +143,9 @@ bool
 NfsStorage::GetInfo(const char *uri_utf8, gcc_unused bool follow,
 		    FileInfo &info, Error &error)
 {
-	const std::string path = UriToNfsPath(uri_utf8);
+	const std::string path = UriToNfsPath(uri_utf8, error);
+	if (path.empty())
+		return false;
 
 	return ::GetInfo(ctx, path.c_str(), info, error);
 }
@@ -142,7 +153,9 @@ NfsStorage::GetInfo(const char *uri_utf8, gcc_unused bool follow,
 StorageDirectoryReader *
 NfsStorage::OpenDirectory(const char *uri_utf8, Error &error)
 {
-	const std::string path = UriToNfsPath(uri_utf8);
+	const std::string path = UriToNfsPath(uri_utf8, error);
+	if (path.empty())
+		return nullptr;
 
 	nfsdir *dir;
 	int result = nfs_opendir(ctx, path.c_str(), &dir);
@@ -172,8 +185,17 @@ const char *
 NfsDirectoryReader::Read()
 {
 	while ((ent = nfs_readdir(ctx, dir)) != nullptr) {
-		if (!SkipNameFS(ent->name))
-			return ent->name;
+		const Path name_fs = Path::FromFS(ent->name);
+		if (SkipNameFS(name_fs.c_str()))
+			continue;
+
+		name_utf8 = name_fs.ToUTF8();
+		if (name_utf8.empty())
+			/* ignore files whose name cannot be converted
+			   to UTF-8 */
+			continue;
+
+		return name_utf8.c_str();
 	}
 
 	return nullptr;