annotate common/filesystem.cpp @ 25:afff3f16d86e

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