diff common/filesystem.cpp @ 0:1158cffe5a5e

Initial import
author David Demelier <markand@malikania.fr>
date Mon, 08 Feb 2016 16:43:14 +0100
parents
children 03068f5ed79d
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/common/filesystem.cpp	Mon Feb 08 16:43:14 2016 +0100
@@ -0,0 +1,187 @@
+/*
+ * filesystem.cpp -- some file system operation
+ *
+ * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <cerrno>
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <stdexcept>
+#include <sstream>
+
+#include <irccd-config.h>
+
+#if defined(IRCCD_SYSTEM_WINDOWS)
+#  include <direct.h>
+#  include <shlwapi.h>
+#else
+#  include <sys/stat.h>
+#  include <climits>
+#  include <unistd.h>
+#  include <libgen.h>
+#endif
+
+#include "filesystem.h"
+
+namespace irccd {
+
+namespace fs {
+
+#if defined(IRCCD_SYSTEM_WINDOWS)
+const char Separator{'\\'};
+#else
+const char Separator{'/'};
+#endif
+
+std::string baseName(std::string path)
+{
+#if defined(IRCCD_SYSTEM_WINDOWS)
+	size_t pos;
+
+	pos = path.find_last_of('\\');
+	if (pos == std::string::npos)
+		pos = path.find_last_of('/');
+	if (pos == std::string::npos)
+		return path;
+
+	return path.substr(pos + 1);
+#else
+	return basename(&path[0]);
+#endif
+}
+
+std::string dirName(std::string path)
+{
+#if defined(IRCCD_SYSTEM_WINDOWS)
+	std::size_t pos;
+
+	pos = path.find_last_of('\\');
+	if (pos == std::string::npos)
+		pos = path.find_last_of('/');
+	if (pos == std::string::npos)
+		return path;
+
+	return path.substr(0, pos);
+#else
+	return dirname(&path[0]);
+#endif
+}
+
+bool isAbsolute(const std::string &path) noexcept
+{
+#if defined(IRCCD_SYSTEM_WINDOWS)
+	return !isRelative(path);
+#else
+	return path.size() > 0 && path[0] == '/';
+#endif
+}
+
+bool isRelative(const std::string &path) noexcept
+{
+#if defined(IRCCD_SYSTEM_WINDOWS)
+	return PathIsRelativeA(path.c_str());
+#else
+	return !isAbsolute(path);
+#endif
+}
+
+bool exists(const std::string &path)
+{
+#if defined(HAVE_ACCESS)
+	return access(path.c_str(), F_OK) == 0;
+#elif defined(HAVE_STAT)
+	struct stat st;
+
+	return (stat(path.c_str(), &st) == 0);
+#else
+	// worse fallback
+	std::FILE *file = std::fopen(path.c_str(), "r");
+	bool result;
+
+	if (file != nullptr) {
+		result = true;
+		std::fclose(file);
+	} else {
+		result = false;
+	}
+
+	return result;
+#endif
+}
+
+void mkdir(const std::string &dir, int mode)
+{
+	std::ostringstream oss;
+
+	oss << "mkdir: ";
+
+	for (size_t i = 0; i < dir.length(); ++i) {
+		if (dir[i] != '/' && dir[i] != '\\')
+			continue;
+
+		std::string part = dir.substr(0, i);
+		if (part.length() <= 0 || exists(part))
+			continue;
+
+#if defined(IRCCD_SYSTEM_WINDOWS)
+		if (::_mkdir(part.c_str()) < 0) {
+#else
+		if (::mkdir(part.c_str(), mode) < 0) {
+#endif
+			oss << part << ": " << std::strerror(errno);
+			throw std::runtime_error(oss.str());
+		}
+	}
+
+	// Last part
+#if defined(IRCCD_SYSTEM_WINDOWS)
+	if (::_mkdir(dir.c_str()) < 0) {
+#else
+	if (::mkdir(dir.c_str(), mode) < 0) {
+#endif
+		oss << dir << ": " << std::strerror(errno);
+		throw std::runtime_error(oss.str());
+	}
+
+#if defined(IRCCD_SYSTEM_WINDOWS)
+	// Windows's mkdir does not use mode.
+	(void)mode;
+#endif
+}
+
+std::string cwd()
+{
+#if defined(IRCCD_SYSTEM_WINDOWS)
+	char path[MAX_PATH];
+
+	if (!GetCurrentDirectoryA(sizeof (path), path))
+		throw std::runtime_error("failed to get current working directory");
+
+	return path;
+#else
+	char path[PATH_MAX];
+
+	if (getcwd(path, sizeof (path)) == nullptr)
+		throw std::runtime_error(std::strerror(errno));
+
+	return path;
+#endif
+}
+
+} // !fs
+
+} // !irccd