annotate modules/fs/fs.cpp @ 519:d6dad57e9e6b

Fs: import
author David Demelier <markand@malikania.fr>
date Wed, 01 Jun 2016 16:35:01 +0200
parents
children ecf5fb9319da
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
519
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
1 /*
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
2 * fs.cpp -- filesystem operations
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
3 *
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
4 * Copyright (c) 2013-2016 David Demelier <markand@malikania.fr>
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
5 *
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
6 * Permission to use, copy, modify, and/or distribute this software for any
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
7 * purpose with or without fee is hereby granted, provided that the above
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
8 * copyright notice and this permission notice appear in all copies.
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
9 *
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
17 */
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
18
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
19 #if defined(_WIN32)
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
20 # define _CRT_SECURE_NO_WARNINGS
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
21 #endif
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
22
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
23 #include <algorithm>
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
24 #include <cassert>
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
25 #include <cerrno>
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
26 #include <cstdio>
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
27 #include <cstring>
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
28 #include <sstream>
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
29 #include <stdexcept>
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
30
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
31 #if defined(_WIN32)
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
32 # include <direct.h>
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
33 # include <Windows.h>
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
34 # include <Shlwapi.h>
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
35 #else
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
36 # include <sys/types.h>
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
37 # include <dirent.h>
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
38 # include <unistd.h>
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
39 #endif
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
40
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
41 #include "fs.hpp"
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
42
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
43 namespace fs {
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
44
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
45 namespace {
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
46
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
47 /*
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
48 * error.
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
49 * ------------------------------------------------------------------
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
50 *
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
51 * Function to retrieve system error in Windows API.
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
52 */
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
53 #if defined(_WIN32)
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
54
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
55 std::string error()
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
56 {
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
57 LPSTR error = nullptr;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
58 std::string errmsg = "Unknown error";
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
59
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
60 FormatMessageA(
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
61 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
62 nullptr,
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
63 GetLastError(),
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
64 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
65 (LPSTR)&error, 0, nullptr);
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
66
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
67 if (error) {
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
68 errmsg = std::string(error);
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
69 LocalFree(error);
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
70 }
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
71
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
72 return errmsg;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
73 }
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
74
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
75 #endif
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
76
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
77 /*
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
78 * hasAccess.
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
79 * ------------------------------------------------------------------
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
80 *
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
81 * Check if we have access to the file specified, mode is the same used as std::fopen.
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
82 */
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
83 bool hasAccess(const std::string &path, const std::string &mode)
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
84 {
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
85 assert(mode.length() == 1);
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
86 assert(mode[0] == 'r' || mode[0] == 'w');
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
87
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
88 auto fp = std::fopen(path.c_str(), mode.c_str());
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
89
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
90 if (fp == nullptr)
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
91 return false;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
92
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
93 std::fclose(fp);
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
94
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
95 return true;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
96 }
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
97
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
98 /*
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
99 * typeOf.
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
100 * ------------------------------------------------------------------
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
101 *
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
102 * Get the type of the specified file.
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
103 *
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
104 * Use GetFileAttributesA on Windows and stat if available.
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
105 *
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
106 * Receives the object as predicate parameter and return true on success.
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
107 */
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
108 #if defined(_WIN32)
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
109
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
110 template <typename Predicate>
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
111 bool typeOf(const std::string &path, Predicate &&predicate)
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
112 {
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
113 DWORD result = GetFileAttributesA(path.c_str());
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
114
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
115 if (result == INVALID_FILE_ATTRIBUTES)
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
116 return false;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
117
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
118 return predicate(result);
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
119 }
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
120
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
121 #elif defined(FS_HAVE_STAT)
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
122
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
123 template <typename Predicate>
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
124 bool typeOf(const std::string &path, Predicate &&predicate) noexcept
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
125 {
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
126 struct stat st;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
127
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
128 if (::stat(path.c_str(), &st) < 0)
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
129 return false;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
130
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
131 return predicate(st);
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
132 }
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
133
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
134 #else
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
135
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
136 template <typename Predicate>
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
137 bool typeOf(const std::string &path, Predicate &&predicate) noexcept
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
138 {
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
139 throw std::runtime_error(std::strerror(ENOSYS));
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
140 }
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
141
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
142 #endif
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
143
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
144 } // !namespace
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
145
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
146 /*
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
147 * clean.
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
148 * ------------------------------------------------------------------
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
149 */
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
150 std::string clean(std::string input)
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
151 {
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
152 if (input.empty())
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
153 return input;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
154
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
155 /* First, remove any duplicates */
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
156 input.erase(std::unique(input.begin(), input.end(), [&] (char c1, char c2) {
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
157 return c1 == c2 && (c1 == '/' || c1 == '\\');
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
158 }), input.end());
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
159
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
160 /* Add a trailing / or \\ */
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
161 char c = input[input.length() - 1];
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
162
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
163 if (c != '/' && c != '\\')
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
164 input += separator();
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
165
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
166 /* Now converts all / to \\ for Windows and the opposite for Unix */
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
167 #if defined(_WIN32)
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
168 std::replace(input.begin(), input.end(), '/', '\\');
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
169 #else
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
170 std::replace(input.begin(), input.end(), '\\', '/');
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
171 #endif
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
172
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
173 return input;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
174 }
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
175
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
176 /*
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
177 * baseName.
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
178 * ------------------------------------------------------------------
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
179 */
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
180 std::string baseName(std::string path)
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
181 {
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
182 auto pos = path.find_last_of("\\/");
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
183
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
184 if (pos != std::string::npos)
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
185 path = path.substr(pos + 1);
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
186
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
187 return path;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
188 }
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
189
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
190 /*
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
191 * dirName.
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
192 * ------------------------------------------------------------------
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
193 */
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
194 std::string dirName(std::string path)
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
195 {
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
196 auto pos = path.find_last_of("\\/");
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
197
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
198 if (pos == std::string::npos)
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
199 path = ".";
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
200 else
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
201 path = path.substr(0, pos);
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
202
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
203 return path;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
204 }
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
205
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
206 /*
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
207 * isAbsolute.
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
208 * ------------------------------------------------------------------
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
209 */
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
210 bool isAbsolute(const std::string &path) noexcept
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
211 {
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
212 #if defined(_WIN32)
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
213 return !isRelative(path);
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
214 #else
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
215 return path.size() > 0 && path[0] == '/';
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
216 #endif
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
217 }
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
218
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
219 /*
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
220 * isRelative.
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
221 * ------------------------------------------------------------------
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
222 */
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
223 bool isRelative(const std::string &path) noexcept
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
224 {
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
225 #if defined(_WIN32)
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
226 return PathIsRelativeA(path.c_str()) == 1;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
227 #else
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
228 return !isAbsolute(path);
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
229 #endif
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
230 }
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
231
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
232 /*
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
233 * isReadable.
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
234 * ------------------------------------------------------------------
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
235 */
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
236 bool isReadable(const std::string &path) noexcept
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
237 {
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
238 return hasAccess(path, "r");
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
239 }
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
240
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
241 /*
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
242 * isWritable.
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
243 * ------------------------------------------------------------------
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
244 */
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
245 bool isWritable(const std::string &path) noexcept
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
246 {
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
247 return hasAccess(path, "w");
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
248 }
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
249
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
250 /*
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
251 * isFile.
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
252 * ------------------------------------------------------------------
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
253 */
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
254 bool isFile(const std::string &path)
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
255 {
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
256 return typeOf(path, [] (const auto &object) {
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
257 #if defined(_WIN32)
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
258 return (object & FILE_ATTRIBUTE_ARCHIVE) == FILE_ATTRIBUTE_ARCHIVE;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
259 #elif defined(FS_HAVE_STAT)
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
260 return S_ISREG(object.st_mode);
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
261 #endif
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
262 });
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
263 }
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
264
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
265 /*
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
266 * isDirectory.
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
267 * ------------------------------------------------------------------
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
268 */
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
269 bool isDirectory(const std::string &path)
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
270 {
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
271 return typeOf(path, [] (const auto &object) {
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
272 #if defined(_WIN32)
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
273 return (object & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
274 #elif defined(FS_HAVE_STAT)
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
275 return S_ISDIR(object.st_mode);
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
276 #endif
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
277 });
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
278 }
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
279
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
280 /*
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
281 * isSymlink.
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
282 * ------------------------------------------------------------------
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
283 */
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
284 bool isSymlink(const std::string &path)
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
285 {
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
286 return typeOf(path, [] (const auto &object) {
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
287 #if defined(_WIN32)
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
288 return (object & FILE_ATTRIBUTE_REPARSE_POINT) == FILE_ATTRIBUTE_REPARSE_POINT;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
289 #elif defined(FS_HAVE_STAT)
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
290 return S_ISLNK(object.st_mode);
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
291 #endif
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
292 });
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
293 }
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
294
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
295 /*
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
296 * stat.
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
297 * ------------------------------------------------------------------
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
298 */
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
299 #if defined(FS_HAVE_STAT)
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
300
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
301 struct stat stat(const std::string &path)
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
302 {
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
303 struct stat st;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
304
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
305 if (::stat(path.c_str(), &st) < 0)
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
306 throw std::runtime_error(std::strerror(errno));
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
307
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
308 return st;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
309 }
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
310
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
311 #endif
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
312
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
313 /*
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
314 * exists.
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
315 * ------------------------------------------------------------------
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
316 */
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
317 bool exists(const std::string &path) noexcept
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
318 {
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
319 #if defined(FS_HAVE_STAT)
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
320 struct stat st;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
321
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
322 return ::stat(path.c_str(), &st) == 0;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
323 #else
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
324 return hasAccess(path, "r");
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
325 #endif
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
326 }
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
327
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
328 /*
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
329 * readdir.
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
330 * ------------------------------------------------------------------
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
331 */
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
332 std::vector<Entry> readdir(const std::string &path, int flags)
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
333 {
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
334 std::vector<Entry> entries;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
335
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
336 #if defined(_WIN32)
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
337 std::ostringstream oss;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
338 HANDLE handle;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
339 WIN32_FIND_DATA fdata;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
340
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
341 oss << path << "\\*";
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
342 handle = FindFirstFile(oss.str().c_str(), &fdata);
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
343
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
344 if (handle == nullptr)
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
345 throw std::runtime_error(error());
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
346
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
347 do {
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
348 Entry entry;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
349
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
350 entry.name = fdata.cFileName;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
351
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
352 if (entry.name == "." && !(flags & Dot))
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
353 continue;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
354 if (entry.name == ".." && !(flags & DotDot))
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
355 continue;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
356
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
357 switch (fdata.dwFileAttributes) {
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
358 case FILE_ATTRIBUTE_DIRECTORY:
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
359 entry.type = Entry::Dir;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
360 break;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
361 case FILE_ATTRIBUTE_NORMAL:
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
362 entry.type = Entry::File;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
363 break;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
364 case FILE_ATTRIBUTE_REPARSE_POINT:
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
365 entry.type = Entry::Link;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
366 break;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
367 default:
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
368 break;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
369 }
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
370
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
371 entries.push_back(std::move(entry));
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
372 } while (FindNextFile(handle, &fdata) != 0);
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
373
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
374 FindClose(handle);
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
375 #else
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
376 DIR *dp;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
377 struct dirent *ent;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
378
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
379 if ((dp = opendir(path.c_str())) == nullptr)
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
380 throw std::runtime_error(std::strerror(errno));
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
381
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
382 while ((ent = readdir(dp)) != nullptr) {
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
383 Entry entry;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
384
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
385 entry.name = ent->d_name;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
386 if (entry.name == "." && !(flags & Dot))
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
387 continue;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
388 if (entry.name == ".." && !(flags & DotDot))
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
389 continue;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
390
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
391 switch (ent->d_type) {
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
392 case DT_DIR:
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
393 entry.type = Entry::Dir;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
394 break;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
395 case DT_REG:
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
396 entry.type = Entry::File;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
397 break;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
398 case DT_LNK:
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
399 entry.type = Entry::Link;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
400 break;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
401 default:
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
402 break;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
403 }
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
404
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
405 entries.push_back(std::move(entry));
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
406 }
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
407
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
408 closedir(dp);
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
409 #endif
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
410
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
411 return entries;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
412 }
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
413
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
414 /*
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
415 * mkdir.
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
416 * ------------------------------------------------------------------
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
417 */
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
418 void mkdir(const std::string &path, int mode)
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
419 {
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
420 std::string::size_type next = 0;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
421 std::string part;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
422
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
423 for (;;) {
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
424 next = path.find_first_of("\\/", next);
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
425 part = path.substr(0, next);
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
426
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
427 if (!part.empty()) {
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
428 #if defined(_WIN32)
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
429 (void)mode;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
430
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
431 if (::_mkdir(part.c_str()) < 0 && errno != EEXIST)
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
432 throw std::runtime_error(std::strerror(errno));
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
433 #else
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
434 if (::mkdir(part.c_str(), mode) < 0 && errno != EEXIST)
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
435 throw std::runtime_error(std::strerror(errno));
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
436 #endif
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
437 }
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
438
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
439 if (next++ == std::string::npos)
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
440 break;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
441 }
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
442 }
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
443
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
444 /*
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
445 * rmdir.
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
446 * ------------------------------------------------------------------
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
447 */
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
448 void rmdir(const std::string &base) noexcept
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
449 {
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
450 try {
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
451 for (const auto &entry : readdir(base)) {
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
452 std::string path = base + separator() + entry.name;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
453
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
454 if (entry.type == Entry::Dir)
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
455 rmdir(path);
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
456 else
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
457 remove(path.c_str());
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
458 }
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
459 } catch (...) {
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
460 /* Silently discard to remove as much as possible */
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
461 }
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
462
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
463 #if defined(_WIN32)
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
464 RemoveDirectoryA(base.c_str());
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
465 #else
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
466 remove(base.c_str());
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
467 #endif
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
468 }
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
469
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
470 /*
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
471 * cwd.
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
472 * ------------------------------------------------------------------
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
473 */
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
474 std::string cwd()
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
475 {
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
476 #if defined(_WIN32)
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
477 char path[MAX_PATH];
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
478
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
479 if (!GetCurrentDirectoryA(sizeof (path), path))
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
480 throw std::runtime_error("failed to get current working directory");
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
481
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
482 return path;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
483 #else
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
484 char path[PATH_MAX];
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
485
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
486 if (getcwd(path, sizeof (path)) == nullptr)
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
487 throw std::runtime_error{std::strerror(errno)};
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
488
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
489 return path;
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
490 #endif
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
491 }
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
492
d6dad57e9e6b Fs: import
David Demelier <markand@malikania.fr>
parents:
diff changeset
493 } // !fs