comparison 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
comparison
equal deleted inserted replaced
-1:000000000000 0:1158cffe5a5e
1 /*
2 * filesystem.cpp -- some file system operation
3 *
4 * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
5 *
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 #include <cerrno>
20 #include <cstdio>
21 #include <cstdlib>
22 #include <cstring>
23 #include <stdexcept>
24 #include <sstream>
25
26 #include <irccd-config.h>
27
28 #if defined(IRCCD_SYSTEM_WINDOWS)
29 # include <direct.h>
30 # include <shlwapi.h>
31 #else
32 # include <sys/stat.h>
33 # include <climits>
34 # include <unistd.h>
35 # include <libgen.h>
36 #endif
37
38 #include "filesystem.h"
39
40 namespace irccd {
41
42 namespace fs {
43
44 #if defined(IRCCD_SYSTEM_WINDOWS)
45 const char Separator{'\\'};
46 #else
47 const char Separator{'/'};
48 #endif
49
50 std::string baseName(std::string path)
51 {
52 #if defined(IRCCD_SYSTEM_WINDOWS)
53 size_t pos;
54
55 pos = path.find_last_of('\\');
56 if (pos == std::string::npos)
57 pos = path.find_last_of('/');
58 if (pos == std::string::npos)
59 return path;
60
61 return path.substr(pos + 1);
62 #else
63 return basename(&path[0]);
64 #endif
65 }
66
67 std::string dirName(std::string path)
68 {
69 #if defined(IRCCD_SYSTEM_WINDOWS)
70 std::size_t pos;
71
72 pos = path.find_last_of('\\');
73 if (pos == std::string::npos)
74 pos = path.find_last_of('/');
75 if (pos == std::string::npos)
76 return path;
77
78 return path.substr(0, pos);
79 #else
80 return dirname(&path[0]);
81 #endif
82 }
83
84 bool isAbsolute(const std::string &path) noexcept
85 {
86 #if defined(IRCCD_SYSTEM_WINDOWS)
87 return !isRelative(path);
88 #else
89 return path.size() > 0 && path[0] == '/';
90 #endif
91 }
92
93 bool isRelative(const std::string &path) noexcept
94 {
95 #if defined(IRCCD_SYSTEM_WINDOWS)
96 return PathIsRelativeA(path.c_str());
97 #else
98 return !isAbsolute(path);
99 #endif
100 }
101
102 bool exists(const std::string &path)
103 {
104 #if defined(HAVE_ACCESS)
105 return access(path.c_str(), F_OK) == 0;
106 #elif defined(HAVE_STAT)
107 struct stat st;
108
109 return (stat(path.c_str(), &st) == 0);
110 #else
111 // worse fallback
112 std::FILE *file = std::fopen(path.c_str(), "r");
113 bool result;
114
115 if (file != nullptr) {
116 result = true;
117 std::fclose(file);
118 } else {
119 result = false;
120 }
121
122 return result;
123 #endif
124 }
125
126 void mkdir(const std::string &dir, int mode)
127 {
128 std::ostringstream oss;
129
130 oss << "mkdir: ";
131
132 for (size_t i = 0; i < dir.length(); ++i) {
133 if (dir[i] != '/' && dir[i] != '\\')
134 continue;
135
136 std::string part = dir.substr(0, i);
137 if (part.length() <= 0 || exists(part))
138 continue;
139
140 #if defined(IRCCD_SYSTEM_WINDOWS)
141 if (::_mkdir(part.c_str()) < 0) {
142 #else
143 if (::mkdir(part.c_str(), mode) < 0) {
144 #endif
145 oss << part << ": " << std::strerror(errno);
146 throw std::runtime_error(oss.str());
147 }
148 }
149
150 // Last part
151 #if defined(IRCCD_SYSTEM_WINDOWS)
152 if (::_mkdir(dir.c_str()) < 0) {
153 #else
154 if (::mkdir(dir.c_str(), mode) < 0) {
155 #endif
156 oss << dir << ": " << std::strerror(errno);
157 throw std::runtime_error(oss.str());
158 }
159
160 #if defined(IRCCD_SYSTEM_WINDOWS)
161 // Windows's mkdir does not use mode.
162 (void)mode;
163 #endif
164 }
165
166 std::string cwd()
167 {
168 #if defined(IRCCD_SYSTEM_WINDOWS)
169 char path[MAX_PATH];
170
171 if (!GetCurrentDirectoryA(sizeof (path), path))
172 throw std::runtime_error("failed to get current working directory");
173
174 return path;
175 #else
176 char path[PATH_MAX];
177
178 if (getcwd(path, sizeof (path)) == nullptr)
179 throw std::runtime_error(std::strerror(errno));
180
181 return path;
182 #endif
183 }
184
185 } // !fs
186
187 } // !irccd