From 6636c69a11e8b4d8aa079d86ef89fb8dbf96964e Mon Sep 17 00:00:00 2001
From: Max Kellermann <max@musicpd.org>
Date: Sat, 11 Feb 2017 22:47:05 +0100
Subject: [PATCH] storage/FileInfo: convert mtime to
 std::chrono::system_clock::time_point

---
 src/SongUpdate.cxx                       |  2 +-
 src/command/StorageCommands.cxx          |  3 ++-
 src/db/update/Archive.cxx                |  4 ++--
 src/db/update/Container.cxx              |  6 +++---
 src/db/update/UpdateSong.cxx             |  5 +++--
 src/db/update/Walk.cxx                   |  4 ++--
 src/storage/FileInfo.hxx                 | 10 ++++++----
 src/storage/plugins/CurlStorage.cxx      |  8 ++------
 src/storage/plugins/LocalStorage.cxx     |  2 +-
 src/storage/plugins/NfsStorage.cxx       |  4 ++--
 src/storage/plugins/SmbclientStorage.cxx |  2 +-
 test/run_storage.cxx                     |  6 ++++--
 12 files changed, 29 insertions(+), 27 deletions(-)

diff --git a/src/SongUpdate.cxx b/src/SongUpdate.cxx
index 8913fea14..0c976b883 100644
--- a/src/SongUpdate.cxx
+++ b/src/SongUpdate.cxx
@@ -88,7 +88,7 @@ Song::UpdateFile(Storage &storage)
 			return false;
 	}
 
-	mtime = info.mtime;
+	mtime = std::chrono::system_clock::to_time_t(info.mtime);
 	tag_builder.Commit(tag);
 	return true;
 }
diff --git a/src/command/StorageCommands.cxx b/src/command/StorageCommands.cxx
index c77011cc0..87bb44199 100644
--- a/src/command/StorageCommands.cxx
+++ b/src/command/StorageCommands.cxx
@@ -24,6 +24,7 @@
 #include "Request.hxx"
 #include "CommandError.hxx"
 #include "util/UriUtil.hxx"
+#include "util/ChronoUtil.hxx"
 #include "util/ConstBuffer.hxx"
 #include "fs/Traits.hxx"
 #include "client/Client.hxx"
@@ -88,7 +89,7 @@ handle_listfiles_storage(Response &r, StorageDirectoryReader &reader)
 			break;
 		}
 
-		if (info.mtime != 0)
+		if (!IsNegative(info.mtime))
 			time_print(r, "Last-Modified", info.mtime);
 	}
 }
diff --git a/src/db/update/Archive.cxx b/src/db/update/Archive.cxx
index 6004ed835..d6fb77d21 100644
--- a/src/db/update/Archive.cxx
+++ b/src/db/update/Archive.cxx
@@ -137,7 +137,7 @@ UpdateWalk::UpdateArchiveFile(Directory &parent, const char *name,
 {
 	Directory *directory = LockFindChild(parent, name);
 
-	if (directory != nullptr && directory->mtime == info.mtime &&
+	if (directory != nullptr && directory->mtime == std::chrono::system_clock::to_time_t(info.mtime) &&
 	    !walk_discard)
 		/* MPD has already scanned the archive, and it hasn't
 		   changed since - don't consider updating it */
@@ -173,7 +173,7 @@ UpdateWalk::UpdateArchiveFile(Directory &parent, const char *name,
 		directory->device = DEVICE_INARCHIVE;
 	}
 
-	directory->mtime = info.mtime;
+	directory->mtime = std::chrono::system_clock::to_time_t(info.mtime);
 
 	UpdateArchiveVisitor visitor(*this, *file, directory);
 	file->Visit(visitor);
diff --git a/src/db/update/Container.cxx b/src/db/update/Container.cxx
index fc4ec416c..6069b172b 100644
--- a/src/db/update/Container.cxx
+++ b/src/db/update/Container.cxx
@@ -43,7 +43,7 @@ UpdateWalk::MakeDirectoryIfModified(Directory &parent, const char *name,
 		if (directory->IsMount())
 			return nullptr;
 
-		if (directory->mtime == info.mtime && !walk_discard) {
+		if (directory->mtime == std::chrono::system_clock::to_time_t(info.mtime) && !walk_discard) {
 			/* not modified */
 			return nullptr;
 		}
@@ -53,7 +53,7 @@ UpdateWalk::MakeDirectoryIfModified(Directory &parent, const char *name,
 	}
 
 	directory = parent.MakeChild(name);
-	directory->mtime = info.mtime;
+	directory->mtime = std::chrono::system_clock::to_time_t(info.mtime);
 	return directory;
 }
 
@@ -107,7 +107,7 @@ UpdateWalk::UpdateContainerFile(Directory &directory,
 						   *contdir);
 
 			// shouldn't be necessary but it's there..
-			song->mtime = info.mtime;
+			song->mtime = std::chrono::system_clock::to_time_t(info.mtime);
 
 			FormatDefault(update_domain, "added %s/%s",
 				      contdir->GetPath(), song->uri);
diff --git a/src/db/update/UpdateSong.cxx b/src/db/update/UpdateSong.cxx
index 2249f3d8b..6d3802069 100644
--- a/src/db/update/UpdateSong.cxx
+++ b/src/db/update/UpdateSong.cxx
@@ -51,7 +51,8 @@ UpdateWalk::UpdateSongFile2(Directory &directory,
 		return;
 	}
 
-	if (!(song != nullptr && info.mtime == song->mtime &&
+	if (!(song != nullptr &&
+	      std::chrono::system_clock::to_time_t(info.mtime) == song->mtime &&
 	      !walk_discard) &&
 	    UpdateContainerFile(directory, name, suffix, info)) {
 		if (song != nullptr)
@@ -79,7 +80,7 @@ UpdateWalk::UpdateSongFile2(Directory &directory,
 		modified = true;
 		FormatDefault(update_domain, "added %s/%s",
 			      directory.GetPath(), name);
-	} else if (info.mtime != song->mtime || walk_discard) {
+	} else if (std::chrono::system_clock::to_time_t(info.mtime) != song->mtime || walk_discard) {
 		FormatDefault(update_domain, "updating %s/%s",
 			      directory.GetPath(), name);
 		if (!song->UpdateFile(storage)) {
diff --git a/src/db/update/Walk.cxx b/src/db/update/Walk.cxx
index 2e917037d..fc3497b3a 100644
--- a/src/db/update/Walk.cxx
+++ b/src/db/update/Walk.cxx
@@ -192,7 +192,7 @@ UpdateWalk::UpdatePlaylistFile(Directory &directory,
 	if (!playlist_suffix_supported(suffix))
 		return false;
 
-	PlaylistInfo pi(name, info.mtime);
+	PlaylistInfo pi(name, std::chrono::system_clock::to_time_t(info.mtime));
 
 	const ScopeDatabaseLock protect;
 	if (directory.playlists.UpdateOrInsert(std::move(pi)))
@@ -382,7 +382,7 @@ UpdateWalk::UpdateDirectory(Directory &directory,
 		UpdateDirectoryChild(directory, child_exclude_list, name_utf8, info2);
 	}
 
-	directory.mtime = info.mtime;
+	directory.mtime = std::chrono::system_clock::to_time_t(info.mtime);
 
 	return true;
 }
diff --git a/src/storage/FileInfo.hxx b/src/storage/FileInfo.hxx
index 5d09bda5c..6a8bc2dd6 100644
--- a/src/storage/FileInfo.hxx
+++ b/src/storage/FileInfo.hxx
@@ -22,7 +22,8 @@
 
 #include "check.h"
 
-#include <time.h>
+#include <chrono>
+
 #include <stdint.h>
 
 struct StorageFileInfo {
@@ -40,9 +41,10 @@ struct StorageFileInfo {
 	uint64_t size;
 
 	/**
-	 * The modification time.  0 means unknown / not applicable.
+	 * The modification time.  A negative value means unknown /
+	 * not applicable.
 	 */
-	time_t mtime;
+	std::chrono::system_clock::time_point mtime;
 
 	/**
 	 * Device id and inode number.  0 means unknown / not
@@ -55,7 +57,7 @@ struct StorageFileInfo {
 	explicit constexpr StorageFileInfo(Type _type)
 		:type(_type),
 		 size(0),
-		 mtime(0),
+		 mtime(std::chrono::system_clock::time_point::min()),
 		 device(0), inode(0) {}
 
 	constexpr bool IsRegular() const {
diff --git a/src/storage/plugins/CurlStorage.cxx b/src/storage/plugins/CurlStorage.cxx
index 072787bc3..24b5709a1 100644
--- a/src/storage/plugins/CurlStorage.cxx
+++ b/src/storage/plugins/CurlStorage.cxx
@@ -418,9 +418,7 @@ protected:
 			? StorageFileInfo::Type::DIRECTORY
 			: StorageFileInfo::Type::REGULAR;
 		info.size = r.length;
-		info.mtime = !IsNegative(r.mtime)
-			? std::chrono::system_clock::to_time_t(r.mtime)
-			: 0;
+		info.mtime = r.mtime;
 	}
 };
 
@@ -514,9 +512,7 @@ protected:
 				       ? StorageFileInfo::Type::DIRECTORY
 				       : StorageFileInfo::Type::REGULAR);
 		info.size = r.length;
-		info.mtime = !IsNegative(r.mtime)
-			? std::chrono::system_clock::to_time_t(r.mtime)
-			: 0;
+		info.mtime = r.mtime;
 	}
 };
 
diff --git a/src/storage/plugins/LocalStorage.cxx b/src/storage/plugins/LocalStorage.cxx
index 057b34ab7..59e0c34f3 100644
--- a/src/storage/plugins/LocalStorage.cxx
+++ b/src/storage/plugins/LocalStorage.cxx
@@ -86,7 +86,7 @@ Stat(Path path, bool follow)
 		info.type = StorageFileInfo::Type::OTHER;
 
 	info.size = src.GetSize();
-	info.mtime = std::chrono::system_clock::to_time_t(src.GetModificationTime());
+	info.mtime = src.GetModificationTime();
 #ifdef WIN32
 	info.device = info.inode = 0;
 #else
diff --git a/src/storage/plugins/NfsStorage.cxx b/src/storage/plugins/NfsStorage.cxx
index 0e5780b61..fcf083b02 100644
--- a/src/storage/plugins/NfsStorage.cxx
+++ b/src/storage/plugins/NfsStorage.cxx
@@ -250,7 +250,7 @@ Copy(StorageFileInfo &info, const struct stat &st)
 		info.type = StorageFileInfo::Type::OTHER;
 
 	info.size = st.st_size;
-	info.mtime = st.st_mtime;
+	info.mtime = std::chrono::system_clock::from_time_t(st.st_mtime);
 	info.device = st.st_dev;
 	info.inode = st.st_ino;
 }
@@ -316,7 +316,7 @@ Copy(StorageFileInfo &info, const struct nfsdirent &ent)
 	}
 
 	info.size = ent.size;
-	info.mtime = ent.mtime.tv_sec;
+	info.mtime = std::chrono::system_clock::from_time_t(ent.mtime.tv_sec);
 	info.device = 0;
 	info.inode = ent.inode;
 }
diff --git a/src/storage/plugins/SmbclientStorage.cxx b/src/storage/plugins/SmbclientStorage.cxx
index 54bd4df8c..4254d6e9f 100644
--- a/src/storage/plugins/SmbclientStorage.cxx
+++ b/src/storage/plugins/SmbclientStorage.cxx
@@ -111,7 +111,7 @@ GetInfo(const char *path)
 		info.type = StorageFileInfo::Type::OTHER;
 
 	info.size = st.st_size;
-	info.mtime = st.st_mtime;
+	info.mtime = std::chrono::system_clock::from_time_t(st.st_mtime);
 	info.device = st.st_dev;
 	info.inode = st.st_ino;
 	return info;
diff --git a/test/run_storage.cxx b/test/run_storage.cxx
index 3d33772ea..32ba8ed47 100644
--- a/test/run_storage.cxx
+++ b/test/run_storage.cxx
@@ -23,6 +23,7 @@
 #include "storage/Registry.hxx"
 #include "storage/StorageInterface.hxx"
 #include "storage/FileInfo.hxx"
+#include "util/ChronoUtil.hxx"
 
 #include <memory>
 #include <stdexcept>
@@ -69,9 +70,10 @@ Ls(Storage &storage, const char *path)
 
 		char mtime_buffer[32];
 		const char *mtime = "          ";
-		if (info.mtime > 0) {
+		if (!IsNegative(info.mtime)) {
+			time_t t = std::chrono::system_clock::to_time_t(info.mtime);
 			strftime(mtime_buffer, sizeof(mtime_buffer), "%F",
-				 gmtime(&info.mtime));
+				 gmtime(&t));
 			mtime = mtime_buffer;
 		}