view common/filesystem.cpp @ 28:9a907e58f978

Plugin ask: fix errors in documentation
author David Demelier <markand@malikania.fr>
date Mon, 22 Feb 2016 13:00:56 +0100
parents 03068f5ed79d
children
line wrap: on
line source

/*
 * 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)
	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(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 (std::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