MySQL 8.0.29
Source Code Documentation
filesystem.h
Go to the documentation of this file.
1/*
2 Copyright (c) 2015, 2021, Oracle and/or its affiliates.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is also distributed with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have included with MySQL.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23*/
24
25#ifndef MYSQL_HARNESS_FILESYSTEM_INCLUDED
26#define MYSQL_HARNESS_FILESYSTEM_INCLUDED
27
28#include "harness_export.h"
29
30#include <memory>
31#include <ostream>
32#include <stdexcept>
33#include <string>
34#include <system_error>
35#include <vector>
36
37#ifndef _WIN32
38#include <fcntl.h>
39#endif
40
43
44namespace mysql_harness {
45
46/**
47 * @defgroup Filesystem Platform-independent file system operations
48 *
49 * This module contain platform-independent file system operations.
50 */
51
52/**
53 * Class representing a path in a file system.
54 *
55 * @ingroup Filesystem
56 *
57 * Paths are used to access files in the file system and can be either
58 * relative or absolute. Absolute paths have a slash (`/`) first in
59 * the path, otherwise, the path is relative.
60 */
61class HARNESS_EXPORT Path {
62 friend std::ostream &operator<<(std::ostream &out, const Path &path) {
63 out << path.path_;
64 return out;
65 }
66
67 public:
68 /**
69 * Enum used to identify file types.
70 */
71
72 enum class FileType {
73 /** An error occurred when trying to get file type, but it is *not*
74 * that the file was not found. */
75 STATUS_ERROR,
76
77 /** Empty path was given */
78 EMPTY_PATH,
79
80 /** The file was not found. */
81 FILE_NOT_FOUND,
82
83 /** The file is a regular file. */
84 REGULAR_FILE,
85
86 /** The file is a directory. */
87 DIRECTORY_FILE,
88
89 /** The file is a symbolic link. */
90 SYMLINK_FILE,
91
92 /** The file is a block device */
93 BLOCK_FILE,
94
95 /** The file is a character device */
96 CHARACTER_FILE,
97
98 /** The file is a FIFO */
99 FIFO_FILE,
100
101 /** The file is a UNIX socket */
102 SOCKET_FILE,
103
104 /** The type of the file is unknown, either because it was not
105 * fetched yet or because stat(2) reported something else than the
106 * above. */
107 TYPE_UNKNOWN,
108 };
109
110 friend HARNESS_EXPORT std::ostream &operator<<(std::ostream &out,
111 FileType type);
112
113 Path() noexcept;
114
115 /**
116 * Construct a path
117 *
118 * @param path Non-empty string denoting the path.
119 */
120 /** @overload */ // throws std::invalid_argument
121 Path(const std::string &path); // NOLINT(runtime/explicit)
122
123 /** @overload */ // throws std::invalid_argument
124 Path(const char *path); // NOLINT(runtime/explicit)
125
126 /**
127 * Create a path from directory, basename, and extension.
128 */
129 static Path make_path(const Path &directory, const std::string &basename,
130 const std::string &extension);
131
132 bool operator==(const Path &rhs) const;
133 bool operator!=(const Path &rhs) const { return !(*this == rhs); }
134
135 /**
136 * Path ordering operator.
137 *
138 * This is mainly used for ordered containers. The paths are ordered
139 * lexicographically.
140 */
141 bool operator<(const Path &rhs) const;
142
143 /**
144 * Get the file type.
145 *
146 * The file type is normally cached so if the file type under a path
147 * changes it is necessary to force a refresh.
148 *
149 * @param refresh Set to `true` if the file type should be
150 * refreshed, default to `false`.
151 *
152 * @return The type of the file.
153 */
154 FileType type(bool refresh = false) const;
155
156 /**
157 * Check if the file is a directory.
158 */
159 bool is_directory() const;
160
161 /**
162 * Check if the file is a regular file.
163 */
164 bool is_regular() const;
165
166 /**
167 * Check if the path is absolute or not
168 *
169 * The path is considered absolute if it starts with one of:
170 * Unix: '/'
171 * Windows: '/' or '\' or '.:' (where . is any character)
172 * else:
173 * it's considered relative (empty path is also relative in such respect)
174 */
175 bool is_absolute() const;
176
177 /**
178 * Check if path exists
179 */
180 bool exists() const;
181
182 /*
183 * @brief Checks if path exists and can be opened for reading.
184 *
185 * @return true if path exists and can be opened for reading,
186 * false otherwise.
187 */
188 bool is_readable() const;
189
190 /**
191 * Get the directory name of the path.
192 *
193 * This will strip the last component of a path, assuming that the
194 * what remains is a directory name. If the path is a relative path
195 * that do not contain any directory separators, a dot will be
196 * returned (denoting the current directory).
197 *
198 * @note No checking of the components are done, this is just simple
199 * path manipulation.
200 *
201 * @return A new path object representing the directory portion of
202 * the path.
203 */
204 Path dirname() const;
205
206 /**
207 * Get the basename of the path.
208 *
209 * Return the basename of the path: the path without the directory
210 * portion.
211 *
212 * @note No checking of the components are done, this is just simple
213 * path manipulation.
214 *
215 * @return A new path object representing the basename of the path.
216 * the path.
217 */
218 Path basename() const;
219
220 /**
221 * Append a path component to the current path.
222 *
223 * This function will append a path component to the path using the
224 * apropriate directory separator.
225 *
226 * @param other Path component to append to the path.
227 */
228 void append(const Path &other);
229
230 /**
231 * Join two path components to form a new path.
232 *
233 * This function will join the two path components using a
234 * directory separator.
235 *
236 * @note This will return a new `Path` object. If you want to modify
237 * the existing path object, you should use `append` instead.
238 *
239 * @param other Path component to be appended to the path
240 */
241 Path join(const Path &other) const;
242
243 /** @overload */
244 Path join(const char *other) const { return join(Path(other)); }
245
246 /**
247 * Returns the canonical form of the path, resolving relative paths.
248 */
249 Path real_path() const;
250
251 /**
252 * Get a C-string representation to the path.
253 *
254 * @note This will return a pointer to the internal representation
255 * of the path and hence will become a dangling pointer when the
256 * `Path` object is destroyed.
257 *
258 * @return Pointer to a null-terminated C-string.
259 */
260 const char *c_str() const { return path_.c_str(); }
261
262 /**
263 * Get a string representation of the path.
264 *
265 * @return Instance of std::string containing the path.
266 */
267 const std::string &str() const noexcept { return path_; }
268
269 /**
270 * Test if path is set
271 *
272 * @return Test result
273 */
274 bool is_set() const noexcept { return (type_ != FileType::EMPTY_PATH); }
275
276 /**
277 * Directory separator string.
278 *
279 * @note This is platform-dependent and defined in the apropriate
280 * source file.
281 */
282 static const char *const directory_separator;
283
284 /**
285 * Root directory string.
286 *
287 * @note This is platform-dependent and defined in the apropriate
288 * source file.
289 */
290 static const char *const root_directory;
291
292 operator bool() const noexcept { return is_set(); }
293
294 private:
295 void validate_non_empty_path() const; // throws std::invalid_argument
296
297 std::string path_;
299};
300
301/**
302 * Class representing a directory in a file system.
303 *
304 * @ingroup Filesystem
305 *
306 * In addition to being a refinement of `Path`, it also have functions
307 * that make it act like a container of paths and support iterating
308 * over the entries in a directory.
309 *
310 * An example of how it could be used is:
311 * @code
312 * for (auto&& entry: Directory(path))
313 * std::cout << entry << std::endl;
314 * @endcode
315 */
316class HARNESS_EXPORT Directory : public Path {
317 public:
318 /**
319 * Directory iterator for iterating over directory entries.
320 *
321 * A directory iterator is an input iterator.
322 */
323 class HARNESS_EXPORT DirectoryIterator {
324 friend class Directory;
325
326 public:
328 using iterator_category = std::input_iterator_tag;
329 using difference_type = std::ptrdiff_t;
332
334 const std::string &pattern = std::string());
335
336 // Create an end iterator
338
339 /**
340 * Destructor.
341 *
342 * @note We need this *declared* because the default constructor
343 * try to generate a default constructor for shared_ptr on State
344 * below, which does not work since it is not visible. The
345 * destructor need to be *defined* in the corresponding .cc file
346 * since the State type is visible there (but you can use a
347 * default definition).
348 */
350
351 // We need these since the default move/copy constructor is
352 // deleted when you define a destructor.
353#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
356#endif
357
358 /** Standard iterator operators */
359 /** @{ */
360 Path operator*() const;
362 Path operator->() { return this->operator*(); }
363 bool operator!=(const DirectoryIterator &other) const;
364
365 // This avoids C2678 (no binary operator found) in MSVC,
366 // MSVC's std::copy implementation (used by TestFilesystem) uses operator==
367 // (while GCC's implementation uses operator!=).
368 bool operator==(const DirectoryIterator &other) const {
369 return !(this->operator!=(other));
370 }
371 /** @} */
372
373 private:
374 /**
375 * Path to the root of the directory
376 */
377 const Path path_;
378
379 /**
380 * Pattern that matches entries iterated over.
381 */
382 std::string pattern_;
383
384 /*
385 * Platform-dependent container for iterator state.
386 *
387 * The definition of this class is different for different
388 * platforms, meaning that it is not defined here at all but
389 * rather in the corresponding `filesystem-<platform>.cc` file.
390 *
391 * The directory iterator is the most critical piece since it holds
392 * an iteration state for the platform: something that requires
393 * different types on the platforms.
394 */
395 class State;
396 std::shared_ptr<State> state_;
397 };
398
399 /**
400 * Construct a directory instance.
401 *
402 * Construct a directory instance in different ways depending on the
403 * version of the constructor used.
404 */
405 Directory(const std::string &path) // NOLINT(runtime/explicit)
406 : Path(path) {} // throws std::invalid_argument
407
408 /** @overload */ // throws std::invalid_argument
409 Directory(const Path &path); // NOLINT(runtime/explicit)
410
411 Directory(const Directory &) = default;
412 Directory &operator=(const Directory &) = default;
414
415 /**
416 * Iterator to first entry.
417 *
418 * @return Returns an iterator pointing to the first entry.
419 */
420 DirectoryIterator begin();
421
422 /**
423 * Constant iterator to first entry.
424 *
425 * @return Returns a constant iterator pointing to the first entry.
426 */
427 DirectoryIterator cbegin() const;
428
429 /**
430 * Iterator past-the-end of entries.
431 *
432 * @return Returns an iterator pointing *past-the-end* of the entries.
433 */
435
436 /**
437 * Constant iterator past-the-end of entries.
438 *
439 * @return Returns a constant iterator pointing *past-the-end* of the entries.
440 */
441 DirectoryIterator cend() const;
442
443 /**
444 * Check if the directory is empty.
445 *
446 * @retval true Directory is empty.
447 * @retval false Directory is no empty.
448 */
449 bool is_empty() const;
450
451 /**
452 * Recursively list all paths in a directory.
453 *
454 * Recursively create a list of relative paths from a directory. Path will
455 * be relative to the given directory. Empty directories are also listed.
456 *
457 * @return Recursive list of paths from a direcotry.
458 */
459 std::vector<Path> list_recursive() const;
460
461 /**
462 * Iterate over entries matching a glob.
463 */
464 DirectoryIterator glob(const std::string &glob);
465};
466
467////////////////////////////////////////////////////////////////////////////////
468//
469// Utility free functions
470//
471////////////////////////////////////////////////////////////////////////////////
472
473/** @brief Removes a directory.
474 *
475 * @ingroup Filesystem
476 *
477 * @param dir path of the directory to be removed; this directory must be empty
478 *
479 * @return void on success, error_code on failure
480 */
481HARNESS_EXPORT
483 const std::string &dir) noexcept;
484
485/** @brief Removes a file.
486 *
487 * @ingroup Filesystem
488 *
489 * @param path of the file to be removed
490 *
491 * @return void on success, error_code on failure
492 */
493HARNESS_EXPORT
495 const std::string &path) noexcept;
496
497/** @brief Removes directory and all its contents.
498 *
499 * @ingroup Filesystem
500 *
501 * @param dir path of the directory to be removed
502 *
503 * @return void on success, error_code on failure
504 */
505HARNESS_EXPORT
507 const std::string &dir) noexcept;
508
509/** @brief Creates a temporary directory with partially-random name and returns
510 * its path.
511 *
512 * Creates a directory with a name of form {prefix}-{6 random alphanumerals}.
513 * For example, a possible directory name created by a call to
514 * get_tmp_dir("foo") might be: foo-3f9x0z
515 *
516 * Such directory is usually meant to be used as a temporary directory (thus the
517 * "_tmp_" in the name of this function).
518 *
519 * @ingroup Filesystem
520 *
521 * @param name name to be used as a directory name prefix
522 *
523 * @return path to the created directory
524 *
525 * @throws std::runtime_error if operation failed
526 */
527HARNESS_EXPORT
528std::string get_tmp_dir(const std::string &name = "router");
529
530// TODO: description
531// TODO: move to some other place?
532HARNESS_EXPORT
533std::string get_plugin_dir(const std::string &runtime_dir);
534
535HARNESS_EXPORT
536std::string get_tests_data_dir(const std::string &runtime_dir);
537
538#ifndef _WIN32
539using perm_mode = mode_t;
540HARNESS_EXPORT
542#else
543using perm_mode = int;
544HARNESS_EXPORT
546#endif
547
548/** @brief Creates a directory
549 * *
550 * @param dir name (or path) of the directory to create
551 * @param mode permission mode for the created directory
552 * @param recursive if true then immitated unix `mkdir -p` recursively
553 * creating parent directories if needed
554 * @retval 0 operation succeeded
555 * @retval -1 operation failed because of wrong parameters
556 * @retval > 0 errno for failure to mkdir() system call
557 */
558HARNESS_EXPORT
559int mkdir(const std::string &dir, perm_mode mode, bool recursive = false);
560
561/**
562 * Changes file access permissions to be fully accessible by all users.
563 *
564 * On Unix, the function sets file permission mask to 777.
565 * On Windows, Everyone group is granted full access to the file.
566 *
567 * @param[in] file_name File name.
568 *
569 * @throw std::exception Failed to change file permissions.
570 */
571void HARNESS_EXPORT make_file_public(const std::string &file_name);
572
573#ifdef _WIN32
574/**
575 * Changes file access permissions to be readable by all users.
576 *
577 * On Windows, Everyone group is granted read access to the file.
578 *
579 * @param[in] file_name File name.
580 *
581 * @throw std::exception Failed to change file permissions.
582 */
583void make_file_readable_for_everyone(const std::string &file_name);
584#endif
585
586/**
587 * Changes file access permissions to be accessible only by a limited set of
588 * users.
589 *
590 * On Unix, the function sets file permission mask to 600.
591 * On Windows, all permissions to this file are removed for Everyone group,
592 * LocalService account gets read (and optionally write) access.
593 *
594 * @param[in] file_name File name.
595 * @param[in] read_only_for_local_service Weather the LocalService user on
596 * Windows should get only the read access (if false will grant write access
597 * too). Not used on non-Windows.
598 *
599 * @throw std::exception Failed to change file permissions.
600 */
601void HARNESS_EXPORT
602make_file_private(const std::string &file_name,
603 const bool read_only_for_local_service = true);
604
605/**
606 * Changes file access permissions to be read only.
607 *
608 * On Unix, the function sets file permission mask to 555.
609 * On Windows, all permissions to this file are read access only for Everyone
610 * group, LocalService account gets read access.
611 *
612 * @param[in] file_name File name.
613 *
614 * @throw std::exception Failed to change file permissions.
615 */
616void HARNESS_EXPORT make_file_readonly(const std::string &file_name);
617
618/**
619 * Verifies access permissions of a file.
620 *
621 * On Unix systems it throws if file's permissions differ from 600.
622 * On Windows it throws if file can be accessed by Everyone group.
623 *
624 * @param[in] file_name File to be verified.
625 *
626 * @throw std::exception File access rights are too permissive or
627 * an error occurred.
628 * @throw std::system_error OS and/or filesystem doesn't support file
629 * permissions.
630 */
631
632void HARNESS_EXPORT check_file_access_rights(const std::string &file_name);
633
634} // namespace mysql_harness
635
636#endif /* MYSQL_HARNESS_FILESYSTEM_INCLUDED */
Definition: filesystem-posix.cc:124
Directory iterator for iterating over directory entries.
Definition: filesystem.h:323
const Path path_
Path to the root of the directory.
Definition: filesystem.h:377
std::input_iterator_tag iterator_category
Definition: filesystem.h:328
Path operator->()
Definition: filesystem.h:362
DirectoryIterator(const DirectoryIterator &)
bool operator==(const DirectoryIterator &other) const
Definition: filesystem.h:368
std::shared_ptr< State > state_
Definition: filesystem.h:395
std::ptrdiff_t difference_type
Definition: filesystem.h:329
std::string pattern_
Pattern that matches entries iterated over.
Definition: filesystem.h:382
Class representing a directory in a file system.
Definition: filesystem.h:316
Directory(const Directory &)=default
Directory & operator=(const Directory &)=default
Directory(const std::string &path)
Construct a directory instance.
Definition: filesystem.h:405
Class representing a path in a file system.
Definition: filesystem.h:61
std::string path_
Definition: filesystem.h:297
const char * c_str() const
Get a C-string representation to the path.
Definition: filesystem.h:260
FileType type_
Definition: filesystem.h:298
bool is_set() const noexcept
Test if path is set.
Definition: filesystem.h:274
Path join(const char *other) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition: filesystem.h:244
FileType
Enum used to identify file types.
Definition: filesystem.h:72
static const char *const root_directory
Root directory string.
Definition: filesystem.h:290
static const char *const directory_separator
Directory separator string.
Definition: filesystem.h:282
const std::string & str() const noexcept
Get a string representation of the path.
Definition: filesystem.h:267
friend std::ostream & operator<<(std::ostream &out, const Path &path)
Definition: filesystem.h:62
Definition: expected.h:936
HARNESS_EXPORT stdx::expected< void, std::error_code > delete_file(const std::string &path) noexcept
Removes a file.
Definition: filesystem-posix.cc:318
HARNESS_EXPORT stdx::expected< void, std::error_code > delete_dir(const std::string &dir) noexcept
Removes a directory.
Definition: filesystem-posix.cc:308
HARNESS_EXPORT std::string get_tmp_dir(const std::string &name="router")
Creates a temporary directory with partially-random name and returns its path.
Definition: filesystem-posix.cc:328
HARNESS_EXPORT stdx::expected< void, std::error_code > delete_dir_recursive(const std::string &dir) noexcept
Removes directory and all its contents.
Definition: filesystem.cc:246
bool operator!=(const my_thread_handle &a, const my_thread_handle &b)
Definition: my_thread.h:157
static char * path
Definition: mysqldump.cc:130
std::string dir
Double write files location.
Definition: buf0dblwr.cc:74
std::string dirname(const std::string &path)
Definition: utilities.cc:37
std::string basename(const std::string &path)
Definition: utilities.cc:45
Definition: common.h:41
void HARNESS_EXPORT make_file_readonly(const std::string &file_name)
Changes file access permissions to be read only.
Definition: filesystem-posix.cc:373
HARNESS_EXPORT std::string get_tests_data_dir(const std::string &runtime_dir)
Definition: filesystem.cc:285
HARNESS_EXPORT int mkdir(const std::string &dir, perm_mode mode, bool recursive=false)
Creates a directory *.
Definition: filesystem.cc:330
void HARNESS_EXPORT check_file_access_rights(const std::string &file_name)
Verifies access permissions of a file.
Definition: filesystem.cc:338
void HARNESS_EXPORT make_file_private(const std::string &file_name, const bool read_only_for_local_service=true)
Changes file access permissions to be accessible only by a limited set of users.
Definition: filesystem-posix.cc:362
HARNESS_EXPORT std::string get_plugin_dir(const std::string &runtime_dir)
Definition: filesystem.cc:267
void HARNESS_EXPORT make_file_public(const std::string &file_name)
Changes file access permissions to be fully accessible by all users.
Definition: filesystem-posix.cc:353
std::string join(Container cont, const std::string &delim)
join elements of an container into a string separated by a delimiter.
Definition: string.h:150
mode_t perm_mode
Definition: filesystem.h:539
void make_file_readable_for_everyone(const std::string &file_name)
Definition: filesystem-windows.cc:469
HARNESS_EXPORT const perm_mode kStrictDirectoryPerm
Definition: filesystem-posix.cc:61
std::ostream & operator<<(std::ostream &out, Path::FileType type)
Definition: filesystem.cc:167
constexpr bool operator<(const address_v4 &a, const address_v4 &b) noexcept
Definition: internet.h:165
Cursor end()
A past-the-end Cursor.
Definition: rules_table_service.cc:191
Definition: varlen_sort.h:183
mode
Definition: file_handle.h:59
static int exists(node_address *name, node_list const *nodes, u_int with_uid)
Definition: node_list.cc:105
bool_t is_set(node_set set, node_no i)
Definition: node_set.cc:229
required string type
Definition: replication_group_member_actions.proto:33
Ssl_acceptor_context_property_type & operator++(Ssl_acceptor_context_property_type &property_type)
Increment operator for Ssl_acceptor_context_type Used by iterator.
Definition: ssl_acceptor_context_data.cc:113
case opt name
Definition: sslopt-case.h:32