BDE 4.14.0 Production release
Loading...
Searching...
No Matches
bdls_filesystemutil.h
Go to the documentation of this file.
1/// @file bdls_filesystemutil.h
2///
3/// The content of this file has been pre-processed for Doxygen.
4///
5
6
7// bdls_filesystemutil.h -*-C++-*-
8#ifndef INCLUDED_BDLS_FILESYSTEMUTIL
9#define INCLUDED_BDLS_FILESYSTEMUTIL
10
11#include <bsls_ident.h>
12BSLS_IDENT("$Id: $")
13
14/// @defgroup bdls_filesystemutil bdls_filesystemutil
15/// @brief Provide methods for filesystem access with multi-language names.
16/// @addtogroup bdl
17/// @{
18/// @addtogroup bdls
19/// @{
20/// @addtogroup bdls_filesystemutil
21/// @{
22///
23/// <h1> Outline </h1>
24/// * <a href="#bdls_filesystemutil-purpose"> Purpose</a>
25/// * <a href="#bdls_filesystemutil-classes"> Classes </a>
26/// * <a href="#bdls_filesystemutil-description"> Description </a>
27/// * <a href="#bdls_filesystemutil-policies-for-open"> Policies for open </a>
28/// * <a href="#bdls_filesystemutil-opencreate-policy-bdls-filesystemutil-fileopenpolicy"> OpenCreate Policy: bdls::FilesystemUtil::FileOpenPolicy </a>
29/// * <a href="#bdls_filesystemutil-inputoutput-access-policy-bdls-filesystemutil-fileiopolicy"> InputOutput Access Policy: bdls::FilesystemUtil::FileIOPolicy </a>
30/// * <a href="#bdls_filesystemutil-truncation-policy-bdls-filesystemutil-filetruncatepolicy"> Truncation Policy: bdls::FilesystemUtil::FileTruncatePolicy </a>
31/// * <a href="#bdls_filesystemutil-starting-points-for-seek"> Starting Points for seek </a>
32/// * <a href="#bdls_filesystemutil-platform-specific-file-locking-caveats"> Platform-Specific File Locking Caveats </a>
33/// * <a href="#bdls_filesystemutil-platform-specific-atomicity-caveats"> Platform-Specific Atomicity Caveats </a>
34/// * <a href="#bdls_filesystemutil-platform-specific-file-name-encoding-caveats"> Platform-Specific File Name Encoding Caveats </a>
35/// * <a href="#bdls_filesystemutil-file-truncation-caveats"> File Truncation Caveats </a>
36/// * <a href="#bdls_filesystemutil-usage"> Usage </a>
37/// * <a href="#bdls_filesystemutil-example-1-general-usage"> Example 1: General Usage </a>
38/// * <a href="#bdls_filesystemutil-example-2-using-bdls-filesystemutil-visitpaths"> Example 2: Using bdls::FilesystemUtil::visitPaths </a>
39///
40/// # Purpose {#bdls_filesystemutil-purpose}
41/// Provide methods for filesystem access with multi-language names.
42///
43/// # Classes {#bdls_filesystemutil-classes}
44///
45/// - bdls::FilesystemUtil: namespace for filesystem access methods
46///
47/// @see bdls_pathutil
48///
49/// # Description {#bdls_filesystemutil-description}
50/// This component provides a platform-independent interface to
51/// filesystem utility methods, supporting multi-language file and path names.
52/// Each method in the `bdls::FilesystemUtil` namespace is a thin wrapper on top
53/// of the operating system's own filesystem access functions, providing a
54/// consistent and unambiguous interface for handling files on all supported
55/// platforms.
56///
57/// Methods in this component can be used to manipulate files with any name in
58/// any language on all supported platforms. To provide such support, the
59/// following restrictions are applied to file names and patterns passed to
60/// methods of this component: On Windows, all file names and patterns must be
61/// passed as UTF-8-encoded strings; file search results will similarly be
62/// encoded as UTF-8. On Posix, file names and patterns may be passed in any
63/// encoding, but all processes accessing a given file must encode its name in
64/// the same encoding. On modern Posix installations, this effectively means
65/// that file names and patterns should be encoded in UTF-8, just as on Windows.
66/// See the section "Platform-Specific File Name Encoding Caveats" below.
67///
68/// ## Policies for open {#bdls_filesystemutil-policies-for-open}
69///
70///
71/// The behavior of the `open` method is governed by three sets of enumerations:
72///
73/// ### OpenCreate Policy: bdls::FilesystemUtil::FileOpenPolicy {#bdls_filesystemutil-opencreate-policy-bdls-filesystemutil-fileopenpolicy}
74///
75///
76/// `bdls::FilesystemUtil::FileOpenPolicy` governs whether `open` creates a new
77/// file or opens an existing one. The following values are possible:
78///
79/// * `e_OPEN`
80/// > Open an existing file.
81///
82/// * `e_CREATE`
83/// > Create a new file.
84///
85/// * `e_CREATE_PRIVATE`
86/// > Create a new file, with limited permissions where that is supported
87/// > (e.g. not necessarily Microsoft Windows).
88///
89/// * `e_OPEN_OR_CREATE`
90/// > Open a file if it exists, and create a new file otherwise.
91///
92/// ### InputOutput Access Policy: bdls::FilesystemUtil::FileIOPolicy {#bdls_filesystemutil-inputoutput-access-policy-bdls-filesystemutil-fileiopolicy}
93///
94///
95/// `bdls::FilesystemUtil::FileIOPolicy` governs what Input/Output operations
96/// are allowed on a file after it is opened. The following values are
97/// possible:
98///
99/// * `e_READ_ONLY`
100/// > Allow reading only.
101///
102/// * `e_WRITE_ONLY`
103/// > Allow writing only.
104///
105/// * `e_READ_WRITE`
106/// > Allow both reading and writing.
107///
108/// * `e_APPEND_ONLY`
109/// > Allow appending to end-of-file only.
110///
111/// * `e_READ_APPEND`
112/// > Allow both reading and appending to end-of-file.
113///
114/// ### Truncation Policy: bdls::FilesystemUtil::FileTruncatePolicy {#bdls_filesystemutil-truncation-policy-bdls-filesystemutil-filetruncatepolicy}
115///
116///
117/// `bdls::FilesystemUtil::FileTruncatePolicy` governs whether `open` deletes
118/// the existing contents of a file when it is opened. The following values are
119/// possible:
120///
121/// * `e_TRUNCATE`
122/// > Delete the file's contents.
123///
124/// * `e_KEEP`
125/// > Keep the file's contents.
126///
127/// ## Starting Points for seek {#bdls_filesystemutil-starting-points-for-seek}
128///
129///
130/// The behavior of the `seek` method is governed by an enumeration that
131/// determines the point from which the seek operation starts:
132///
133/// * `e_SEEK_FROM_BEGINNING`
134/// > Seek from the beginning of the file.
135///
136/// * `e_SEEK_FROM_CURRENT`
137/// > Seek from the current position in the file.
138///
139/// * `e_SEEK_FROM_END`
140/// > Seek from the end of the file.
141///
142/// ## Platform-Specific File Locking Caveats {#bdls_filesystemutil-platform-specific-file-locking-caveats}
143///
144///
145/// Locking has the following caveats for the following operating systems:
146///
147/// * On Posix, closing a file releases all locks on all file descriptors
148/// referring to that file within the current process. [doc 1] [doc 2]
149/// * On Posix, the child of a fork does not inherit the locks of the parent
150/// process. [doc 1] [doc 2]
151/// * On at least some flavors of Unix, you can't lock a file for writing using
152/// a file descriptor opened in read-only mode.
153///
154/// ## Platform-Specific Atomicity Caveats {#bdls_filesystemutil-platform-specific-atomicity-caveats}
155///
156///
157/// The `bdls::FilesystemUtil::read` and `bdls::FilesystemUtil::write` methods
158/// add no atomicity guarantees for reading and writing to those provided (if
159/// any) by the underlying platform's methods for reading and writing (see
160/// `http://lwn.net/articles/180387/`).
161///
162/// ## Platform-Specific File Name Encoding Caveats {#bdls_filesystemutil-platform-specific-file-name-encoding-caveats}
163///
164///
165/// File-name encodings have the following caveats for the following operating
166/// systems:
167///
168/// * On Windows, methods of `bdls::FilesystemUtil` that take a file or
169/// directory name or pattern as a `char*` or `bsl::string` type assume that
170/// the name is encoded in UTF-8. The routines attempt to convert the name
171/// to a UTF-16 `wchar_t` string via `bdlde::CharConvertUtf16::utf8ToUtf16`,
172/// and if the conversion succeeds, call the Windows wide-character `W` APIs
173/// with the UTF-16 name. If the conversion fails, the method fails.
174/// Similarly, file searches returning file names call the Windows
175/// wide-character `W` APIs and convert the resulting UTF-16 names to UTF-8.
176/// - Narrow-character file names in other encodings, containing characters
177/// with values in the range 128 - 255, will likely result in files being
178/// created with names that appear garbled if the conversion from UTF-8 to
179/// UTF-16 happens to succeed.
180/// - Neither `utf8ToUtf16` nor the Windows `W` APIs do any normalization of
181/// the UTF-16 strings resulting from UTF-8 conversion, and it is therefore
182/// possible to have sets of file names that have the same visual
183/// representation but are treated as different names by the filesystem.
184/// * On Posix, a file name or pattern supplied to methods of
185/// `bdls::FilesystemUtil` as a `char*` or `bsl::string` type is passed
186/// unchanged to the underlying system file APIs. Because the file names and
187/// patterns are passed unchanged, `bdls::FilesystemUtil` methods will work
188/// correctly on Posix with any encoding, but will *interoperate* only with
189/// processes that use the same encoding as the current process.
190/// * For compatibility with most modern Posix installs, and consistency with
191/// this component's Windows API, best practice is to encode all file names
192/// and patterns in UTF-8.
193///
194/// ## File Truncation Caveats {#bdls_filesystemutil-file-truncation-caveats}
195///
196///
197/// In order to provide consistent behavior across both Posix and Windows
198/// platforms, when the `open` method is called, file truncation is allowed only
199/// if the client requests an `openPolicy` containing the word `CREATE` and/or
200/// an `ioPolicy` containing the word `WRITE`.
201///
202/// ## Usage {#bdls_filesystemutil-usage}
203///
204///
205/// This section illustrates intended use of this component.
206///
207/// ### Example 1: General Usage {#bdls_filesystemutil-example-1-general-usage}
208///
209///
210/// In this example, we start with a (relative) native path to a directory
211/// containing log files:
212/// @code
213/// #ifdef BSLS_PLATFORM_OS_WINDOWS
214/// bsl::string logPath = "temp.1\\logs";
215/// #else
216/// bsl::string logPath = "temp.1/logs";
217/// #endif
218/// @endcode
219/// Suppose that we want to separate files into "old" and "new" subdirectories
220/// on the basis of modification time. We will provide paths representing these
221/// locations, and create the directories if they do not exist:
222/// @code
223/// bsl::string oldPath(logPath), newPath(logPath);
224/// bdls::PathUtil::appendRaw(&oldPath, "old");
225/// bdls::PathUtil::appendRaw(&newPath, "new");
226/// int rc = bdls::FilesystemUtil::createDirectories(oldPath, true);
227/// assert(0 == rc);
228/// rc = bdls::FilesystemUtil::createDirectories(newPath, true);
229/// assert(0 == rc);
230/// @endcode
231/// We know that all of our log files match the pattern "*.log", so let's search
232/// for all such files in the log directory:
233/// @code
234/// bdls::PathUtil::appendRaw(&logPath, "*.log");
235/// bsl::vector<bsl::string> logFiles;
236/// bdls::FilesystemUtil::findMatchingPaths(&logFiles, logPath.c_str());
237/// @endcode
238/// Now for each of these files, we will get the modification time. Files that
239/// are older than 2 days will be moved to "old", and the rest will be moved to
240/// "new":
241/// @code
242/// bdlt::Datetime modTime;
243/// bsl::string fileName;
244/// for (bsl::vector<bsl::string>::iterator it = logFiles.begin();
245/// it != logFiles.end(); ++it) {
246/// assert(0 ==
247/// bdls::FilesystemUtil::getLastModificationTime(&modTime, *it));
248/// assert(0 == bdls::PathUtil::getLeaf(&fileName, *it));
249/// bsl::string *whichDirectory =
250/// 2 < (bdlt::CurrentTime::utc() - modTime).totalDays()
251/// ? &oldPath
252/// : &newPath;
253/// bdls::PathUtil::appendRaw(whichDirectory, fileName.c_str());
254/// assert(0 == bdls::FilesystemUtil::move(it->c_str(),
255/// whichDirectory->c_str()));
256/// bdls::PathUtil::popLeaf(whichDirectory);
257/// }
258/// @endcode
259///
260/// ### Example 2: Using bdls::FilesystemUtil::visitPaths {#bdls_filesystemutil-example-2-using-bdls-filesystemutil-visitpaths}
261///
262///
263/// `bdls::FilesystemUtil::visitPaths` enables clients to define a function
264/// object to operate on file paths that match a specified pattern. In this
265/// example, we create a function that can be used to filter out files that have
266/// a last modified time within a particular time frame.
267///
268/// First we define our filtering function:
269/// @code
270/// void getFilesWithinTimeframe(bsl::vector<bsl::string> *vector,
271/// const char *item,
272/// const bdlt::Datetime& start,
273/// const bdlt::Datetime& end)
274/// {
275/// bdlt::Datetime datetime;
276/// int ret = bdls::FilesystemUtil::getLastModificationTime(&datetime,
277/// item);
278///
279/// if (ret) {
280/// return; // RETURN
281/// }
282///
283/// if (datetime < start || datetime > end) {
284/// return; // RETURN
285/// }
286///
287/// vector->push_back(item);
288/// }
289/// @endcode
290/// Then, with the help of `bdls::FilesystemUtil::visitPaths` and
291/// `bdlf::BindUtil::bind`, we create a function for finding all file paths that
292/// match a specified pattern and have a last modified time within a specified
293/// start and end time (both specified as a `bdlt::Datetime`):
294/// @code
295/// void findMatchingFilesInTimeframe(bsl::vector<bsl::string> *result,
296/// const char *pattern,
297/// const bdlt::Datetime& start,
298/// const bdlt::Datetime& end)
299/// {
300/// result->clear();
301/// bdls::FilesystemUtil::visitPaths(
302/// pattern,
303/// bdlf::BindUtil::bind(&getFilesWithinTimeframe,
304/// result,
305/// bdlf::PlaceHolders::_1,
306/// start,
307/// end));
308/// }
309/// @endcode
310/// @}
311/** @} */
312/** @} */
313
314/** @addtogroup bdl
315 * @{
316 */
317/** @addtogroup bdls
318 * @{
319 */
320/** @addtogroup bdls_filesystemutil
321 * @{
322 */
323
324#include <bdlscm_version.h>
325
327
328#include <bdlt_datetime.h>
329#include <bdlt_epochutil.h>
330
331#include <bslmf_assert.h>
332
333#include <bsls_assert.h>
334
335#include <bsl_functional.h>
336#include <bsl_optional.h>
337
338#include <bsls_keyword.h>
339#include <bsls_libraryfeatures.h>
340#include <bsls_platform.h>
341#include <bsls_review.h>
342
343#include <bsl_string.h>
344#include <bsl_string_view.h>
345#include <bsl_vector.h>
346#include <bsl_cstddef.h>
347
348#include <string> // 'std::string', 'std::pmr::string'
349#include <vector>
350
351#include <sys/types.h>
352
353
354namespace bdls {
355
356 // =====================
357 // struct FilesystemUtil
358 // =====================
359
360/// This `struct` provides a namespace for utility functions dealing with
361/// platform-independent filesystem access.
363
364 // TYPES
365#ifdef BSLS_PLATFORM_OS_WINDOWS
366 /// `HANDLE` is a stand-in for the Windows API `HANDLE` type, to allow
367 /// us to avoid including `windows.h` in this header. `HANDLE` should
368 /// not be used by client code.
369 typedef void *HANDLE;
370
371 /// `FileDescriptor` is an alias for the operating system`s native file
372 /// descriptor / file handle type.
373 typedef HANDLE FileDescriptor;
374
375 /// `Offset` is an alias for a signed value, representing the offset of
376 /// a location within a file.
377 typedef __int64 Offset;
378
379 /// maximum representable file offset value
380 static const Offset k_OFFSET_MAX = _I64_MAX;
381
382 /// minimum representable file offset value
383 static const Offset k_OFFSET_MIN = _I64_MIN;
384
385#elif defined(BSLS_PLATFORM_OS_UNIX)
386 /// `FileDescriptor` is an alias for the operating system's native file
387 /// descriptor / file handle type.
388 typedef int FileDescriptor;
389
390#if defined(BDLS_FILESYSTEMUTIL_UNIXPLATFORM_64_BIT_OFF64)
391 /// `Offset` is an alias for a signed value, representing the offset of
392 /// a location within a file.
393 typedef off64_t Offset;
394#else
395 /// `Offset` is an alias for a signed value, representing the offset of
396 /// a location within a file.
397 typedef off_t Offset;
398#endif
399
400 /// maximum representable file offset value
401 static const Offset k_OFFSET_MAX = (0x7FFFFFFFFFFFFFFFLL);
402
403 /// minimum representable file offset value
404 static const Offset k_OFFSET_MIN = (-0x7FFFFFFFFFFFFFFFLL-1);
405#else
406# error "'bdls_filesystemutil' does not support this platform."
407#endif
408
409 /// Enumeration used to distinguish among different starting points for
410 /// a seek operation.
411 enum Whence {
412 e_SEEK_FROM_BEGINNING = 0, // Seek from beginning of file.
413 e_SEEK_FROM_CURRENT = 1, // Seek from current position.
414 e_SEEK_FROM_END = 2 // Seek from end of file.
415 };
416
417 enum {
418 k_DEFAULT_FILE_GROWTH_INCREMENT = 0x10000 // default block size to
419 // grow files by
420 };
421
423 k_ERROR_LOCKING_CONFLICT = 1, // value representing a failure to
424 // obtain a lock on a file
425
426 k_ERROR_LOCKING_INTERRUPTED = 2, // value representing a failure to
427 // obtain a lock on a file due to
428 // interruption by a signal
429
430 k_ERROR_ALREADY_EXISTS = 3, // value representing a failure to
431 // create a directory due to a file
432 // system entry already existing
433
434 k_ERROR_PATH_NOT_FOUND = 4, // value representing a failure to
435 // create a directory due to one ore
436 // more components of the path
437 // either not existing or not being
438 // a directory
439
440 k_ERROR_PAST_EOF = 5, // 'mapChecked' attempted to map
441 // region past the end of file.
442
443 k_BAD_FILE_DESCRIPTOR = -1 // value indicating a bad file
444 // descriptor was supplied
445 };
446
447 /// Enumeration used to determine whether 'open' should open an existing
448 /// file, or create a new file.
450 e_OPEN, // Open a file if it exists, and fail otherwise.
451
452 e_CREATE, // Create a new file, and fail if the file already
453 // exists.
454
455 e_CREATE_PRIVATE, // Create a new file with access restricted to the
456 // creating userid, where supported, and fail if the
457 // file already exists.
458
459 e_OPEN_OR_CREATE // Open a file if it exists, and create a new file
460 // otherwise.
461 };
462
463 /// Enumeration used to distinguish between different sets of actions
464 /// permitted on an open file descriptor.
466 e_READ_ONLY, // Allow reading only.
467 e_WRITE_ONLY, // Allow writing only.
468 e_APPEND_ONLY, // Allow appending to end-of-file only.
469 e_READ_WRITE, // Allow both reading and writing.
470 e_READ_APPEND // Allow both reading and appending to end-of-file.
471 };
472
473 /// Enumeration used to distinguish between different ways to handle the
474 /// contents, if any, of an existing file immediately upon opening the
475 /// file.
477 e_TRUNCATE, // Delete the file's contents on open.
478 e_KEEP // Keep the file's contents.
479 };
480
481 // CLASS DATA
482 static const FileDescriptor k_INVALID_FD; // `FileDescriptor` value
483 // representing no file, used
484 // as the error return for
485 // `open`
486
487 // CLASS METHODS
488
489 /// Open the file at the specified `path`, using the specified
490 /// `openPolicy` to determine whether to open an existing file or create
491 /// a new file, and using the specified `ioPolicy` to determine whether
492 /// the file will be opened for reading, writing, or both. Optionally
493 /// specify a `truncatePolicy` to determine whether any contents of the
494 /// file will be deleted before `open` returns. If `truncatePolicy` is
495 /// not supplied, the value `e_KEEP` will be used. Return a valid
496 /// `FileDescriptor` for the file on success, or `k_INVALID_FD`
497 /// otherwise. If `openPolicy` is `e_OPEN`, the file will be opened if
498 /// it exists, and `open` will fail otherwise. If `openPolicy` is
499 /// `e_CREATE` or `e_CREATE_PRIVATE`, and no file exists at `path`, a
500 /// new file will be created, and `open` will fail otherwise. If
501 /// `openPolicy` is `e_CREATE_PRIVATE`, the file will be created with
502 /// access restricted to the same userid as the caller in environments
503 /// where that is supported (which does not necessarily include Windows)
504 /// otherwise the system default access policy is used (e.g. '0777 &
505 /// ~umask'). If `openPolicy` is `e_OPEN_OR_CREATE`, the file will be
506 /// opened if it exists, and a new file will be created otherwise. If
507 /// `ioPolicy` is `e_READ_ONLY`, the returned `FileDescriptor` will
508 /// allow only read operations on the file. If `ioPolicy` is
509 /// `e_WRITE_ONLY` or `e_APPEND_ONLY`, the returned `FileDescriptor`
510 /// will allow only write operations on the file. If `ioPolicy` is
511 /// `e_READ_WRITE` or `e_READ_APPEND`, the returned `FileDescriptor`
512 /// will allow both read and write operations on the file.
513 /// Additionally, if `ioPolicy` is `e_APPEND_ONLY` or `e_READ_APPEND`
514 /// all writes will be made to the end of the file ("append mode"). If
515 /// `truncatePolicy` is `e_TRUNCATE`, the file will have zero length
516 /// when `open` returns. If `truncatePolicy` is `e_KEEP`, the file will
517 /// be opened with its existing contents, if any. Note that when a file
518 /// is opened in `append` mode, all writes will go to the end of the
519 /// file, even if there has been seeking on the file descriptor or
520 /// another process has changed the length of the file. Append-mode
521 /// writes are not atomic except in limited cases; another thread, or
522 /// even another process, operating on the file may cause output not to
523 /// be written, unbroken, to the end of the file. (Unix environments
524 /// writing to local file systems may promise more.) Note that `open`
525 /// will fail to open a file with a `truncatePolicy` of `e_TRUNCATE`
526 /// unless at least one of the following policies is specified for
527 /// `openPolicy` or `ioPolicy`:
528 /// * `e_CREATE`
529 /// * `e_CREATE_PRIVATE`
530 /// * `e_OPEN_OR_CREATE`
531 /// * 'e_WRITE_ONLY
532 /// * `e_READ_WRITE`
533 /// The parameterized `STRING_TYPE` must be one of `bsl::string`,
534 /// `std::string`, `std::pmr::string` (if supported), or
535 /// `bslstl::StringRef`.
536 static FileDescriptor open(const char *path,
537 FileOpenPolicy openPolicy,
538 FileIOPolicy ioPolicy,
539 FileTruncatePolicy truncatePolicy = e_KEEP);
540 template <class STRING_TYPE>
541 static FileDescriptor open(const STRING_TYPE& path,
542 FileOpenPolicy openPolicy,
543 FileIOPolicy ioPolicy,
544 FileTruncatePolicy truncatePolicy = e_KEEP);
545
546
547 /// Close the specified `descriptor`. Return 0 on success and a non-zero
548 /// value otherwise. A return value of `k_BAD_FILE_DESCRIPTOR` indicates
549 /// that the supplied `descriptor` is invalid.
550 static int close(FileDescriptor descriptor);
551
553 /// Load into the specified 'path' the absolute pathname of the current
554 /// working directory. Return 0 on success and a non-zero value otherwise.
555 static int getWorkingDirectory(std::string *path);
556#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR_STRING
557 static int getWorkingDirectory(std::pmr::string *path);
558#endif
559
560 /// Set the working directory of the current process to the specified
561 /// `path`. Return 0 on success and a non-zero value otherwise. The
562 /// parameterized `STRING_TYPE` must be one of `bsl::string`,
563 /// `std::string`, `std::pmr::string` (if supported), or
564 /// `bslstl::StringRef`.
565 static int setWorkingDirectory(const char *path);
566 template <class STRING_TYPE>
567 static int setWorkingDirectory(const STRING_TYPE& path);
568
569 /// Return `true` if there currently exists a file or directory at the
570 /// specified `path`, and `false` otherwise. If `path` is a symlink,
571 /// the result of this function is platform dependent. On POSIX/Unix
572 /// platforms this method dereferences symlinks, while on Windows it
573 /// does not. The parameterized `STRING_TYPE` must be one of
574 /// `bsl::string`, `std::string`, `std::pmr::string` (if supported), or
575 /// `bslstl::StringRef`.
576 static bool exists(const char *path);
577 template <class STRING_TYPE>
578 static bool exists(const STRING_TYPE& path);
579
580 /// Return `true` if there currently exists a regular file at the
581 /// specified `path`, and `false` otherwise. If there is a symbolic
582 /// link at `path`, follow it only if the optionally specified
583 /// `followLinksFlag` is `true` (otherwise, return `false` as the
584 /// symbolic link itself is not a regular file irrespective of the file
585 /// to which it points). Platform-specific note: On POSIX, this is a
586 /// positive test on the "regular file" mode; on Windows, this is a
587 /// negative test on the "directory" attribute, i.e., on Windows,
588 /// everything that exists and is not a directory is a regular file.
589 /// The parameterized `STRING_TYPE` must be one of `bsl::string`,
590 /// `std::string`, `std::pmr::string` (if supported), or
591 /// `bslstl::StringRef`.
592 static bool isRegularFile(const char *path, bool followLinksFlag = false);
593 template <class STRING_TYPE>
594 static bool isRegularFile(const STRING_TYPE& path,
595 bool followLinksFlag = false);
596
597 /// Return `true` if there currently exists a directory at the specified
598 /// `path`, and `false` otherwise. If there is a symbolic link at
599 /// `path`, follow it only if the optionally specified `followLinksFlag`
600 /// is `true` (otherwise return `false`). Platform-specific note: On
601 /// Windows, a "shortcut" is not a symbolic link. The parameterized
602 /// `STRING_TYPE` must be one of `bsl::string`, `std::string`,
603 /// `std::pmr::string` (if supported), or `bslstl::StringRef`.
604 static bool isDirectory(const char *path, bool followLinksFlag = false);
605 template <class STRING_TYPE>
606 static bool isDirectory(const STRING_TYPE& path,
607 bool followLinksFlag = false);
608
609 /// Return `true` if there currently exists a symbolic link at the
610 /// specified `path`, and `false` otherwise. Windows directory
611 /// junctions are treated as directory symbolic links. The
612 /// parameterized `STRING_TYPE` must be one of `bsl::string`,
613 /// `std::string`, `std::pmr::string` (if supported), or
614 /// `bslstl::StringRef`.
615 static bool isSymbolicLink(const char *path);
616 template <class STRING_TYPE>
617 static bool isSymbolicLink(const STRING_TYPE& path);
618
619 /// Load into the specified `time` the last modification time of the
620 /// file at the specified `path`, as reported by the filesystem. Return
621 /// 0 on success, and a non-zero value otherwise. The time is reported
622 /// in UTC. The parameterized `STRING_TYPE` must be one of
623 /// `bsl::string`, `std::string`, `std::pmr::string` (if supported), or
624 /// `bslstl::StringRef`.
625 static int getLastModificationTime(bdlt::Datetime *time, const char *path);
626 template <class STRING_TYPE>
628 const STRING_TYPE& path);
629
630 /// Load into the specified `time` the last modification time of the
631 /// file with the specified `descriptor`, as reported by the filesystem.
632 /// Return 0 on success, and a non-zero value otherwise. The time is
633 /// reported in UTC.
635 FileDescriptor descriptor);
636
637 // TBD: write setModificationTime() when SetFileInformationByHandle()
638 // becomes available on our standard Windows platforms.
639
640 /// Create any directories in the specified `path` that do not exist.
641 /// If the optionally specified `isLeafDirectoryFlag` is `true`, treat
642 /// the final name component in `path` as a directory name, and create
643 /// it. Otherwise, create only the directories leading up to the final
644 /// name component. Return 0 on success, `k_ERROR_PATH_NOT_FOUND` if a
645 /// component used as a directory in `path` exists but is not a
646 /// directory, and a negative value for any other kind of error. The
647 /// parameterized `STRING_TYPE` must be one of `bsl::string`,
648 /// `std::string`, `std::pmr::string` (if supported), or
649 /// `bslstl::StringRef`.
650 static int createDirectories(const char *path,
651 bool isLeafDirectoryFlag = false);
652 template <class STRING_TYPE>
653 static int createDirectories(
654 const STRING_TYPE& path,
655 bool isLeafDirectoryFlag = false);
656
657 /// Create a private directory with the specified `path`. Return 0 on
658 /// success, `k_ERROR_PATH_NOT_FOUND` if a component used as a directory
659 /// in `path` either does not exist or is not a directory,
660 /// `k_ERROR_ALREADY_EXISTS` if the file system entry (not necessarily a
661 /// directory) with the name `path` already exists, and a negative value
662 /// for any other kind of error. The directory is created with
663 /// permissions restricting access, as closely as possible, to the
664 /// caller's userid only. Note that directories created on Microsoft
665 /// Windows may receive default, not restricted permissions. The
666 /// parameterized `STRING_TYPE` must be one of `bsl::string`,
667 /// `std::string`, `std::pmr::string` (if supported), or
668 /// `bslstl::StringRef`.
669 static int createPrivateDirectory(const char *path);
670 template <class STRING_TYPE>
671 static int createPrivateDirectory(const STRING_TYPE& path);
672
674 /// Load a valid path to the system temporary directory to the specified
675 /// `path`. Return 0 on success, and a non-zero value otherwise. A
676 /// temporary directory is one in which the operating system has permission
677 /// to delete its contents, but not necessarily the directory itself, the
678 /// next time the computer reboots.
679 static int getSystemTemporaryDirectory(std::string *path);
680#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR_STRING
681 static int getSystemTemporaryDirectory(std::pmr::string *path);
682#endif
683
684 static FileDescriptor createTemporaryFile(bsl::string *outPath,
685 const bsl::string_view& prefix);
686 /// Create and open a new file with a name constructed by appending an
687 /// automatically-generated suffix to the specified `prefix`, and return
688 /// its file descriptor open for reading and writing. A return value of
689 /// `k_INVALID_FD` indicates that no such file could be created; otherwise,
690 /// the name of the file created is assigned to the specified `outPath`.
691 /// The file is created with permissions restricted, as closely as
692 /// possible, to the caller`s userid only. If the prefix is a relative
693 /// path, the file is created relative to the process current directory.
694 /// Responsibility for deleting the file is left to the caller. Note that
695 /// on Posix systems, if `outPath` is unlinked immediately, the file will
696 /// remain usable until its descriptor is closed. Note that files created
697 /// on Microsoft Windows may receive default, not restricted permissions.
698 static FileDescriptor createTemporaryFile(std::string *outPath,
699 const bsl::string_view& prefix);
700#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR_STRING
701 static FileDescriptor createTemporaryFile(std::pmr::string *outPath,
702 const bsl::string_view& prefix);
703#endif
704
706 const bsl::string_view& prefix);
707 /// Create a new directory with a name constructed by appending an
708 /// automatically-generated suffix to the specified `prefix`. A non-zero
709 /// return value indicates that no such directory could be created;
710 /// otherwise the name of the directory created is assigned to the
711 /// specified `outPath`. The directory is created with permissions
712 /// restricted, as closely as possible, to the caller only. If the prefix
713 /// is a relative path, the directory is created relative to the process
714 /// current directory. Responsibility for deleting the directory (and any
715 /// files subsequently created in it) is left to the caller.
716 static int createTemporaryDirectory(std::string *outPath,
717 const bsl::string_view& prefix);
718#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR_STRING
719 static int createTemporaryDirectory(std::pmr::string *outPath,
720 const bsl::string_view& prefix);
721#endif
722
724 bsl::string *outPath,
725 const bsl::string_view& rootDirectory,
726 const bsl::string_view& prefix);
727 /// Create a new directory with a name constructed by appending an
728 /// automatically-generated suffix to the specified `prefix` within the
729 /// specified `rootDirectory`. A non-zero return value indicates that no
730 /// such directory could be created; otherwise the name of the directory
731 /// created is assigned to the specified `outPath`. The directory is
732 /// created with permissions restricted, as closely as possible, to the
733 /// caller only. If the `rootDirectory` is a relative path, the directory
734 /// is created relative to the process current directory. Responsibility
735 /// for deleting the directory (and any files subsequently created in it)
736 /// is left to the caller.
738 std::string *outPath,
739 const bsl::string_view& rootDirectory,
740 const bsl::string_view& prefix);
741#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR_STRING
743 std::pmr::string *outPath,
744 const bsl::string_view& rootDirectory,
745 const bsl::string_view& prefix);
746#endif
747
749 const bsl::string_view& prefix);
750 /// Construct a file name by appending an automatically-generated suffix to
751 /// the specified `prefix`. The file name constructed is assigned to the
752 /// specified `outPath`. Note that this function is called "unsafe"
753 /// because a file with the resulting name may be created by another
754 /// program before the caller has opportunity to use the name, which could
755 /// be a security vulnerability, and a file with the given name may already
756 /// exist where you mean to put it. Note that the suffix is hashed from
757 /// environmental details, including any pre-existing value of `outPath` so
758 /// that if a resulting name is unsuitable (e.g. the file exists) this
759 /// function may simply be called again, pointing to its previous result,
760 /// to get a new, probably different name.
761 static void makeUnsafeTemporaryFilename(std::string *outPath,
762 const bsl::string_view& prefix);
763#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR_STRING
764 static void makeUnsafeTemporaryFilename(std::pmr::string *outPath,
765 const bsl::string_view& prefix);
766#endif
767
768 /// Call the specified `visitor` function object for each path in the
769 /// filesystem matching the specified `pattern`. Return the number of
770 /// paths visited on success, and a negative value otherwise. Note that
771 /// if `visitor` deletes files or directories during the search,
772 /// `visitor` may subsequently be called with paths which have already
773 /// been deleted, so must be prepared for this event. Also note that
774 /// there is no guarantee as to the order in which paths will be
775 /// visited. See `findMatchingPaths` for a discussion of how `pattern`
776 /// is interpreted. Also note that `.` and `..` are never matched by
777 /// wild cards. The parameterized `STRING_TYPE` must be one of
778 /// `bsl::string`, `std::string`, `std::pmr::string` (if supported), or
779 /// `bslstl::StringRef`.
780 ///
781 /// IBM-SPECIFIC WARNING: This function is not thread-safe. The AIX
782 /// implementation of the system `glob` function can temporarily change
783 /// the working directory of the entire program, causing attempts in
784 /// other threads to open files with relative path names to fail.
785 static int visitPaths(
786 const char *pattern,
787 const bsl::function<void(const char *path)>& visitor);
788 template <class STRING_TYPE>
789 static int visitPaths(
790 const STRING_TYPE& pattern,
791 const bsl::function<void(const char *path)>& visitor);
792
793 /// Recursively traverse the directory tree starting at the specified
794 /// `root` for files whose leaf names match the specified `pattern`, and
795 /// run the specified function `visitor`, passing it the full path
796 /// starting with `root` to each pattern matching file. See
797 /// `findMatchingPaths` for a discussion of how `pattern` is
798 /// interpreted. If the specified `sortFlag` is `true`, traverse the
799 /// files in the tree in sorted order, sorted by the full path name,
800 /// otherwise the order in which the files will be visited is
801 /// unspecified. UTF-8 paths will be sorted by `strcmp`, which sorts by
802 /// `char`s, not unicode code points. Found `.` and `..` directories
803 /// are ignored, except that `root` may be `.` or `..`. Return 0 on
804 /// success, and a non-zero value otherwise. This function will fail if
805 /// `root` does not specify a directory, of if `pattern` contains `/` on
806 /// Unix or '\' on Windows. Note that both directories and plain files
807 /// whose names match `pattern` will be visited, while other files such
808 /// as symlinks will not be visited or followed. No file or directory
809 /// that is not matched will be visited. All directories are traversed,
810 /// regardless of whether they are matched. If a directory is matched
811 /// and `sortFlag` is `true`, it is visited immediately before it is
812 /// traversed. Also note that `root` is never visited, even if it
813 /// matches `pattern`. Also note that no pattern matching is done on
814 /// `root` -- if it contains wildcards, they are not interpreted as such
815 /// and must exactly match the characters in the name of the directory.
816 ///
817 /// IBM-SPECIFIC WARNING: This function is not thread-safe. The AIX
818 /// implementation of the system `glob` function can temporarily change
819 /// the working directory of the entire program, casuing attempts in
820 /// other threads to open files with relative path names to fail.
821 static int visitTree(
822 const bsl::string_view& root,
823 const bsl::string_view& pattern,
824 const bsl::function<void(const char *path)>& visitor,
825 bool sortFlag = false);
826
827 /// Load into the specified `result` vector all paths in the filesystem
828 /// matching the specified `pattern`. The '*' character will match any
829 /// number of characters in a filename; however, this matching will not
830 /// span a directory separator (e.g., "logs/m*.txt" will not match
831 /// "logs/march/001.txt"). '?' will match any one character. '*' and '?'
832 /// may be used any number of times in the pattern. The special
833 /// directories "." and ".." will not be matched against any pattern. Note
834 /// that any initial contents of `result` will be erased, and that the
835 /// paths in `result` will not be in any particular guaranteed order.
836 /// Return the number of paths matched on success, and a negative value
837 /// otherwise; if a negative value is returned, the contents of `*result`
838 /// are undefined. The parameterized `STRING_TYPE` must be one of
839 /// `bsl::string`, `std::string`, `std::pmr::string` (if supported), or
840 /// `bslstl::StringRef`.
841 ///
842 /// WINDOWS-SPECIFIC NOTE: To support DOS idioms, the OS-provided search
843 /// function has behavior that we have chosen not to work around: an
844 /// extension consisting of wild-card characters ('?', '*') can match an
845 /// extension or *no* extension. E.g., "file.?" matches "file.z", but not
846 /// "file.txt"; however, it also matches "file" (without any extension).
847 /// Likewise, "*.*" matches any filename, including filenames having no
848 /// extension. Also, on Windows (but not on Unix) attempting to match a
849 /// pattern that is invalid UTF-8 will result in an error.
850 ///
851 /// IBM-SPECIFIC WARNING: This function is not thread-safe. The AIX
852 /// implementation of the system `glob` function can temporarily change the
853 /// working directory of the entire program, casuing attempts in other
854 /// threads to open files with relative path names to fail.
856 const char *pattern);
857 template <class STRING_TYPE>
859 const STRING_TYPE& pattern);
860 static int findMatchingPaths(std::vector<std::string> *result,
861 const char *pattern);
862 template <class STRING_TYPE>
863 static int findMatchingPaths(std::vector<std::string> *result,
864 const STRING_TYPE& pattern);
865#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR_STRING
866 static int findMatchingPaths(std::pmr::vector<std::pmr::string> *result,
867 const char *pattern);
868 template <class STRING_TYPE>
869 static int findMatchingPaths(std::pmr::vector<std::pmr::string> *result,
870 const STRING_TYPE& pattern);
871#endif
872
873 /// Return the number of bytes available for allocation in the file
874 /// system where the file or directory with the specified `path`
875 /// resides, or a negative value if an error occurs. The parameterized
876 /// `STRING_TYPE` must be one of `bsl::string`, `std::string`,
877 /// `std::pmr::string` (if supported), or `bslstl::StringRef`.
878 static Offset getAvailableSpace(const char *path);
879 template <class STRING_TYPE>
880 static Offset getAvailableSpace(const STRING_TYPE& path);
881
882 /// Return the number of bytes available for allocation in the file
883 /// system where the file with the specified `descriptor` resides, or a
884 /// negative value if an error occurs.
885 static Offset getAvailableSpace(FileDescriptor descriptor);
886
887 /// Return the size, in bytes, of the file or directory at the specified
888 /// `path`, or a negative value if an error occurs. Note that the size
889 /// of a symbolic link is the size of the file or directory to which it
890 /// points. The parameterized `STRING_TYPE` must be one of
891 /// `bsl::string`, `std::string`, `std::pmr::string` (if supported), or
892 /// `bslstl::StringRef`.
893 static Offset getFileSize(const char *path);
894 template <class STRING_TYPE>
895 static Offset getFileSize(const STRING_TYPE& path);
896
897 /// Return the size, in bytes, of the file or directory specified by the
898 /// specified open `descriptor`, or a negative value if an error occurs.
899 /// Note that the size of a symbolic link is the size of the file or
900 /// directory to which it points.
901 static Offset getFileSize(FileDescriptor descriptor);
902
903 /// Return the file size limit for this process, `k_OFFSET_MAX` if no
904 /// limit is set, or a negative value if an error occurs. Note that if
905 /// you are doing any calculations involving the returned value, it is
906 /// recommended to check for `k_OFFSET_MAX` specifically to avoid
907 /// integer overflow in your calculations.
908 static Offset getFileSizeLimit();
909
911 const char *path);
912 /// Load, into the specified `result`, the target of the symbolic link at
913 /// the specified `path`. Return 0 on success, and a non-zero value
914 /// otherwise. For example, this function will return an error if `path`
915 /// does not refer to a symbolic link. Windows directory junctions are
916 /// treated as directory symbolic links. If `path` is a relative path, it
917 /// is evaluated against the current working directory. The parameterized
918 /// `STRING_TYPE` must be one of `bsl::string`, `std::string`,
919 /// `std::pmr::string` (if supported), or `bslstl::StringRef`.
920 static int getSymbolicLinkTarget(std::string *result,
921 const char *path);
922 template <class STRING_TYPE>
923 static int getSymbolicLinkTarget(bsl::string *result,
924 const STRING_TYPE& path);
925 template <class STRING_TYPE>
926 static int getSymbolicLinkTarget(std::string *result,
927 const STRING_TYPE& path);
928#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR_STRING
929 static int getSymbolicLinkTarget(std::pmr::string *result,
930 const char *path);
931 template <class STRING_TYPE>
932 static int getSymbolicLinkTarget(std::pmr::string *result,
933 const STRING_TYPE& path);
934#endif
935
936 /// Acquire a lock for the file with the specified `descriptor`. If
937 /// `lockWriteFlag` is true, acquire an exclusive write lock; otherwise
938 /// acquire a (possibly) shared read lock. The calling thread will
939 /// block until the lock is acquired. Return 0 on success, and a
940 /// non-zero value otherwise. Note that this operation locks the
941 /// indicated file for use by the current *process*, but the behavior is
942 /// unspecified (and platform-dependent) when either attempting to lock
943 /// `descriptor` multiple times, or attempting to lock another
944 /// descriptor referring to the same file, within a single process.
945 static int lock(FileDescriptor descriptor, bool lockWriteFlag);
946
947 /// Set the size of the file referred to by the specified `descriptor`
948 /// to the specified `size`. `descriptor` must be open for writing.
949 /// After the function call, the position is set to the end of the file.
950 /// Return 0 on success and a non-zero value otherwise. The behavior is
951 /// undefined if the file is currently mapped, or if `size` is greater
952 /// than the existing size of the file.
953 static int truncateFileSize(FileDescriptor descriptor, Offset size);
954
955 /// Acquire a lock for the file with the specified `descriptor` if it is
956 /// currently available. If the specified `lockWriteFlag` is true,
957 /// acquire an exclusive write lock unless another process has any type
958 /// of lock on the file. If `lockWriteFlag` is false, acquire a shared
959 /// read lock unless a process has a write lock. This method will not
960 /// block. Return 0 on success, `k_ERROR_LOCKING_CONFLICT` if the
961 /// platform reports the lock could not be acquired because another
962 /// process holds a conflicting lock, and a negative value for any other
963 /// kind of error. Note that this operation locks the indicated file
964 /// for the current *process*, but the behavior is unspecified (and
965 /// platform-dependent) when either attempting to lock `descriptor`
966 /// multiple times, or attempting to lock another descriptor referring
967 /// to the same file, within a single process.
968 static int tryLock(FileDescriptor descriptor, bool lockWriteFlag);
969
970 /// Release any lock this process holds on the file with the specified
971 /// `descriptor`. Return 0 on success, and a non-zero value otherwise.
972 static int unlock(FileDescriptor descriptor);
973
974 /// Map the region of the specified `size` bytes, starting at the
975 /// specified `offset` bytes into the file with the specified
976 /// `descriptor` to memory, and load into the specified `address` of the
977 /// mapped area. Return 0 on success, and a non-zero value otherwise.
978 /// The access permissions for mapping memory are defined by the
979 /// specified `mode`, which may be a combination of
980 /// `MemoryUtil::k_ACCESS_READ`, `MemoryUtil::k_ACCESS_WRITE` and
981 /// `MemoryUtil::k_ACCESS_EXECUTE`. Note that on failure, the value of
982 /// `address` is undefined. Also note that mapping will succeed even if
983 /// there are fewer than `offset + size` bytes in the specified file,
984 /// and an attempt to access the mapped memory beyond the end of the
985 /// file will result in undefined behavior (i.e., this function does not
986 /// grow the file to guarantee it can accommodate the mapped region).
987 /// Also note that mapping past the end of file may return 0, but any
988 /// access of the resulting mapped memory may segfault.
989 static int map(FileDescriptor descriptor,
990 void **address,
991 Offset offset,
992 bsl::size_t size,
993 int mode);
994
995 /// Map the region of the specified `size` bytes, starting at the
996 /// specified `offset` bytes into the file with the specified
997 /// `descriptor` to memory, and load into the specified `address` of the
998 /// mapped area. Return 0 on success, `k_ERROR_PAST_EOF` if an attempt
999 /// is made to map past the end of file, and a non-zero value otherwise.
1000 /// The access permissions for mapping memory are defined by the
1001 /// specified `mode`, which may be a combination of
1002 /// `MemoryUtil::k_ACCESS_READ`, `MemoryUtil::k_ACCESS_WRITE` and
1003 /// `MemoryUtil::k_ACCESS_EXECUTE`, though on some platforms they must
1004 /// be a subset of the file permissions. The behavior is undefined
1005 /// unless bits in `mode` other than
1006 /// `MemoryUtil::k_ACCESS_READ_WRITE_EXECUTE` are all clear, unless
1007 /// `0 <= offset`, and unless `0 < size`, and unless the `offset` is a
1008 /// multiple of `MemoryUtil::pageSize()`. Note that on failure, the
1009 /// value of `address` is undefined. Also note that the check against
1010 /// mapping past the end of file and all assertions are done before the
1011 /// call to map the file.
1012 static int mapChecked(FileDescriptor descriptor,
1013 void **address,
1014 Offset offset,
1015 bsl::size_t size,
1016 int mode);
1017
1018 /// Unmap the memory mapping with the specified base `address` and
1019 /// specified `size`. Return 0 on success, and a non-zero value
1020 /// otherwise. The behavior is undefined unless this area with
1021 /// `address` and `size` was previously mapped with a `map` call.
1022 static int unmap(void *address, bsl::size_t size);
1023
1024 /// Synchronize the contents of the specified `numBytes` of mapped
1025 /// memory beginning at the specified `address` with the underlying file
1026 /// on disk. If the specified `syncFlag` is true, block until all
1027 /// writes to nonvolatile media have actually completed, otherwise,
1028 /// return once they have been scheduled. Return 0 on success, and a
1029 /// non-zero value otherwise. The behavior is undefined unless
1030 /// `address` is aligned on a page boundary, `numBytes` is a multiple of
1031 /// `pageSize()`, and `0 <= numBytes`.
1032 static int sync(char *address, bsl::size_t numBytes, bool syncFlag);
1033
1034 /// Set the file pointer associated with the specified `descriptor`
1035 /// (used by calls to the `read` and `write` system calls) according to
1036 /// the specified `whence` behavior:
1037 /// @code
1038 /// * If 'whence' is e_SEEK_FROM_BEGINNING, set the pointer to
1039 /// 'offset' bytes from the beginning of the file.
1040 /// * If 'whence' is e_SEEK_FROM_CURRENT, advance the pointer by
1041 /// 'offset' bytes
1042 /// * If 'whence' is e_SEEK_FROM_END, set the pointer to 'offset'
1043 /// bytes beyond the end of the file.
1044 /// @endcode
1045 /// Return the new location of the file pointer, in bytes from the
1046 /// beginning of the file, on success; and -1 otherwise. The effect on
1047 /// the file pointer is undefined unless the file is on a device capable
1048 /// of seeking. Note that `seek` does not change the size of the file
1049 /// if the pointer advances beyond the end of the file; instead, the
1050 /// next write at the pointer will increase the file size.
1051 static Offset seek(FileDescriptor descriptor, Offset offset, int whence);
1052
1053 /// Read the specified `numBytes` bytes beginning at the file pointer of
1054 /// the file with the specified `descriptor` into the specified
1055 /// `buffer`. Return `numBytes` on success; the number of bytes read
1056 /// if there were not enough available; or a negative number on some
1057 /// other error.
1058 static int read(FileDescriptor descriptor, void *buffer, int numBytes);
1059
1060 /// Remove the file or directory at the specified `path`. If the `path`
1061 /// refers to a directory and the optionally specified `recursiveFlag`
1062 /// is `true`, recursively remove all files and directories within the
1063 /// specified directory before removing the directory itself. Return 0
1064 /// on success and a non-zero value otherwise. If `path` refers to a
1065 /// symbolic link, the symbolic link will be removed, not the target of
1066 /// the link. Note that if `path` is a directory, and the directory is
1067 /// not empty, and recursive is `false`, this method will fail. Also
1068 /// note that if the function fails when `recursive` is `true`, it may
1069 /// or may not have removed *some* files or directories before failing.
1070 /// Also note that if `remove` is called on "." or "..", it will fail
1071 /// with no effect. The parameterized `STRING_TYPE` must be one of
1072 /// `bsl::string`, `std::string`, `std::pmr::string` (if supported), or
1073 /// `bslstl::StringRef`.
1074 ///
1075 /// IBM-SPECIFIC WARNING: This function is not thread-safe. The AIX
1076 /// implementation of the system `glob` function can temporarily change
1077 /// the working directory of the entire program, causing attempts in
1078 /// other threads to open files with relative path names to fail.
1079 static int remove(const char *path, bool recursiveFlag = false);
1080 template <class STRING_TYPE>
1081 static int remove(const STRING_TYPE& path, bool recursiveFlag = false);
1082
1083 /// Remove the file at the specified `path` appended with the specified
1084 /// `maxSuffix` using a `.` as a separator. Then move the files with
1085 /// the suffixes `.1` to `.maxSuffix-1` so they have new suffixes from
1086 /// `.2` to `.maxSuffix`. Finally, move `path` to `path` with a `.1`
1087 /// suffix. Return 0 on success, and non-zero otherwise.
1088 static int rollFileChain(const bsl::string_view& path, int maxSuffix);
1089
1090 /// Move the file or directory at the specified `oldPath` to the
1091 /// specified `newPath`. If there is a file or directory at `newPath`,
1092 /// it will be removed and replaced. In that case, `newPath` must refer
1093 /// to the same type of filesystem item as `oldPath` - that is, they
1094 /// must both be directories or both be files. Return 0 on success, and
1095 /// a non-zero value otherwise. If `oldPath` is a symbolic link, the
1096 /// link will be renamed. If a symbolic link already exists at
1097 /// `newPath`, the resulting behavior is platform dependent. Note that
1098 /// this operation is carried out via library/system facilities
1099 /// (`rename` in UNIX and `MoveFile` in Windows) that usually cannot
1100 /// move files between file systems or volumes, and that the behavior of
1101 /// the underlying library/system facilities differs when `oldPath` and
1102 /// `newPath` refer to the same file (in that case, UNIX succeeds,
1103 /// Windows fails). Note that a symbolic link already exists at
1104 /// `newPath` POSIX/Unix systems will overwrite that existing symbolic
1105 /// link, while Windows will return an error status (`GetLastError` will
1106 /// report `ERROR_ALREADY_EXISTS`). The parameterized `OLD_STRING_TYPE`
1107 /// and `NEW_STRING_TYPE` must be one of `bsl::string`, `std::string`,
1108 /// `std::pmr::string` (if supported), or `bslstl::StringRef`.
1109 static int move(const char *oldPath, const char *newPath);
1110 template <class OLD_STRING_TYPE, class NEW_STRING_TYPE>
1111 static int move(const OLD_STRING_TYPE& oldPath,
1112 const NEW_STRING_TYPE& newPath);
1113
1114 /// Write the specified `numBytes` from the specified `buffer` address
1115 /// to the file with the specified `descriptor`. Return `numBytes` on
1116 /// success; the number of bytes written if space was exhausted; or a
1117 /// negative value on some other error.
1118 static int write(FileDescriptor descriptor,
1119 const void *buffer,
1120 int numBytes);
1121
1122 /// Grow the file with the specified `descriptor` to the size of at
1123 /// least the specified `size` bytes. Return 0 on success, and a
1124 /// non-zero value otherwise. If the optionally specified `reserveFlag`
1125 /// is true, make sure the space on disk is preallocated and not
1126 /// allocated on demand, preventing a possible out-of-disk-space error
1127 /// when accessing the data on file systems with sparse file support.
1128 /// Preallocation is done by writing unspecified data to file in blocks
1129 /// of the optionally specified `increment` or a default value if
1130 /// `increment` is zero or unspecified. Note that if the size of the
1131 /// file is greater than or equal to `size`, this function has no
1132 /// effect. Also note that the contents of the newly grown portion of
1133 /// the file is undefined.
1134 static int growFile(
1135 FileDescriptor descriptor,
1136 Offset size,
1137 bool reserveFlag = false,
1138 bsl::size_t increment = k_DEFAULT_FILE_GROWTH_INCREMENT);
1139};
1140
1141 // ================================
1142 // class FilesystemUtil_CStringUtil
1143 // ================================
1144
1145/// This component-private utility `struct` provides a namespace for the
1146/// `flatten` overload set intended to be used in concert with an overload
1147/// set consisting of a function template with a deduced argument and an
1148/// non-template overload accepting a `const char *`. The actual
1149/// implementation of the functionality would be in the `const char *`
1150/// overload whereas the purpose of the function template is to invoke the
1151/// `const char *` overload with a null-terminated string.
1152///
1153/// The function template achieves null-termination by recursively calling
1154/// the function and supplying it with the result of `flatten` invoked on
1155/// the deduced argument. This `flatten` invocation will call `c_str()` on
1156/// various supported `string` types, will produce a temporary `bsl::string`
1157/// for possibly non-null-terminated `bslstl::StringRef`, and will result in
1158/// a `BSLMF_ASSERT` for any unsupported type. Calling the function with
1159/// the temporary `bsl::string` produced from `bslstl::StringRef` will
1160/// result in a second invocation of `flatten`, this time producing
1161/// `const char *`, and finally calling the function with a null-terminated
1162/// string.
1163///
1164/// Note that the `bslstl::StringRef` overload for `flatten` is provided for
1165/// backwards compatibility. Without it, the `bsl::string` and
1166/// `std::string` overloads would be ambiguous. In new code, it is
1167/// preferable to not provide `bslstl::StringRef` overload in a similar
1168/// facility and require the clients to explicitly state the string type in
1169/// their code, making a potential allocation obvious. The
1170/// `bsl::string_view` overload is not provided for the same reason.
1172
1173 // CLASS METHODS
1174
1175 /// Return the specified `cString`.
1176 static const char *flatten(char *cString);
1177 static const char *flatten(const char *cString);
1178
1179 /// Return the result of invoking `c_str()` on the specified `string`.
1180 static const char *flatten(const bsl::string& string);
1181 static const char *flatten(const std::string& string);
1182#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR_STRING
1183 static const char *flatten(const std::pmr::string& string);
1184#endif
1185
1186 /// Return a temporary `bsl::string` constructed from the specified
1187 /// `stringView`.
1188 static bsl::string flatten(const bsl::string_view& stringView);
1189
1190 /// Return a temporary `bsl::string` constructed from the specified
1191 /// `stringRef`.
1192 static bsl::string flatten(const bslstl::StringRef& stringRef);
1193
1194 /// Produce a compile-time error informing the caller that the
1195 /// parameterized `TYPE` is not supported as the parameter for the call.
1196 template <class TYPE>
1197 static const char *flatten(const TYPE&);
1198};
1199
1200// ============================================================================
1201// INLINE DEFINITIONS
1202// ============================================================================
1203
1204 // --------------------
1205 // class FilesystemUtil
1206 // --------------------
1207
1208// CLASS METHODS
1209template <class STRING_TYPE>
1210inline
1211FilesystemUtil::FileDescriptor FilesystemUtil::open(
1212 const STRING_TYPE& path,
1213 FileOpenPolicy openPolicy,
1214 FileIOPolicy ioPolicy,
1215 FileTruncatePolicy truncatePolicy)
1216{
1218 openPolicy,
1219 ioPolicy,
1220 truncatePolicy);
1221}
1222
1223template <class STRING_TYPE>
1224inline
1230
1231template <class STRING_TYPE>
1232inline
1233bool FilesystemUtil::exists(const STRING_TYPE& path)
1234{
1236}
1237
1238template <class STRING_TYPE>
1239inline
1240bool FilesystemUtil::isRegularFile(const STRING_TYPE& path,
1241 bool followLinksFlag)
1242{
1244 FilesystemUtil_CStringUtil::flatten(path), followLinksFlag);
1245}
1246
1247template <class STRING_TYPE>
1248inline
1249bool FilesystemUtil::isDirectory(const STRING_TYPE& path,
1250 bool followLinksFlag)
1251{
1253 FilesystemUtil_CStringUtil::flatten(path), followLinksFlag);
1254}
1255
1256template <class STRING_TYPE>
1257inline
1258bool FilesystemUtil::isSymbolicLink(const STRING_TYPE& path)
1259{
1262}
1263
1264template <class STRING_TYPE>
1265inline
1267 const STRING_TYPE& path)
1268{
1271}
1272
1273template <class STRING_TYPE>
1274inline
1276 const STRING_TYPE& path,
1277 bool isLeafDirectoryFlag)
1278{
1280 FilesystemUtil_CStringUtil::flatten(path), isLeafDirectoryFlag);
1281}
1282
1283template <class STRING_TYPE>
1284inline
1290
1291template <class STRING_TYPE>
1292inline
1294 const STRING_TYPE& pattern,
1295 const bsl::function<void(const char *path)>& visitor)
1296{
1298 FilesystemUtil_CStringUtil::flatten(pattern), visitor);
1299}
1300
1301template <class STRING_TYPE>
1302inline
1304 const STRING_TYPE& pattern)
1305{
1307 result, FilesystemUtil_CStringUtil::flatten(pattern));
1308}
1309
1310template <class STRING_TYPE>
1311inline
1312int FilesystemUtil::findMatchingPaths(std::vector<std::string> *result,
1313 const STRING_TYPE& pattern)
1314{
1316 result, FilesystemUtil_CStringUtil::flatten(pattern));
1317}
1318
1319#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR_STRING
1320template <class STRING_TYPE>
1321inline
1323 std::pmr::vector<std::pmr::string> *result,
1324 const STRING_TYPE& pattern)
1325{
1327 result, FilesystemUtil_CStringUtil::flatten(pattern));
1328}
1329#endif
1330
1331template <class STRING_TYPE>
1332inline
1334 const STRING_TYPE& path)
1335{
1338}
1339
1340template <class STRING_TYPE>
1341inline
1342FilesystemUtil::Offset FilesystemUtil::getFileSize(const STRING_TYPE& path)
1343{
1346}
1347
1348template <class STRING_TYPE>
1349inline
1351 const STRING_TYPE& path)
1352{
1355}
1356
1357template <class STRING_TYPE>
1358inline
1360 const STRING_TYPE& path)
1361{
1364}
1365
1366#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR_STRING
1367template <class STRING_TYPE>
1368inline
1369int FilesystemUtil::getSymbolicLinkTarget(std::pmr::string *result,
1370 const STRING_TYPE& path)
1371{
1374}
1375#endif
1376
1377template <class STRING_TYPE>
1378inline
1379int FilesystemUtil::remove(const STRING_TYPE& path, bool recursiveFlag)
1380{
1382 recursiveFlag);
1383}
1384
1385template <class OLD_STRING_TYPE, class NEW_STRING_TYPE>
1386inline
1387int FilesystemUtil::move(const OLD_STRING_TYPE& oldPath,
1388 const NEW_STRING_TYPE& newPath)
1389{
1392}
1393
1394
1395
1396
1397 // --------------------------------
1398 // class FilesystemUtil_CStringUtil
1399 // --------------------------------
1400
1401// CLASS METHODS
1402inline
1403const char *FilesystemUtil_CStringUtil::flatten(char *cString)
1404{
1405 return cString;
1406}
1407
1408inline
1409const char *FilesystemUtil_CStringUtil::flatten(const char *cString)
1410{
1411 return cString;
1412}
1413
1414inline
1416{
1417 return string.c_str();
1418}
1419
1420inline
1421const char *FilesystemUtil_CStringUtil::flatten(const std::string& string)
1422{
1423 return string.c_str();
1424}
1425
1426#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR_STRING
1427inline
1428const char *FilesystemUtil_CStringUtil::flatten(const std::pmr::string& string)
1429{
1430 return string.c_str();
1431}
1432#endif
1433
1434inline
1436 const bsl::string_view& stringView)
1437{
1438 bsl::string ret(stringView);
1439 return ret;
1440}
1441
1442inline
1444 const bslstl::StringRef& stringRef)
1445{
1446 return stringRef;
1447}
1448
1449template <class TYPE>
1450inline
1452{
1453 BSLMF_ASSERT(("Unsupported parameter type." && !sizeof(TYPE)));
1454 return 0;
1455}
1456
1457// FREE OPERATORS
1458
1459/// Output the specified `value` to the specified `stream`, in
1460/// human-readable form. If `value` is not a valid `Whence` value, report
1461/// that it is invalid and output it as an integer.
1462bsl::ostream& operator<<(bsl::ostream& stream, FilesystemUtil::Whence value);
1463
1464/// Output the specified `value` to the specified `stream`, in
1465/// human-readable form. If `value` is not a valid `ErrorType` value,
1466/// report that it is invalid and output it as an integer.
1467bsl::ostream& operator<<(bsl::ostream& stream,
1469
1470/// Output the specified `value` to the specified `stream`, in
1471/// human-readable form. If `value` is not a valid `FileOpenPolicy` value,
1472/// report that it is invalid and output it as an integer.
1473bsl::ostream& operator<<(bsl::ostream& stream,
1475
1476/// Output the specified `value` to the specified `stream`, in
1477/// human-readable form. If `value` is not a valid `FileIOPolicy` value,
1478/// report that it is invalid and output it as an integer.
1479bsl::ostream& operator<<(bsl::ostream& stream,
1481
1482/// Output the specified `value` to the specified `stream`, in
1483/// human-readable form. If `value` is not a valid `FileTruncatePolicy`
1484/// value, report that it is invalid and output it as an integer.
1485bsl::ostream& operator<<(bsl::ostream& stream,
1487
1488} // close package namespace
1489
1490
1491#endif
1492
1493// ----------------------------------------------------------------------------
1494// Copyright 2015 Bloomberg Finance L.P.
1495//
1496// Licensed under the Apache License, Version 2.0 (the "License");
1497// you may not use this file except in compliance with the License.
1498// You may obtain a copy of the License at
1499//
1500// http://www.apache.org/licenses/LICENSE-2.0
1501//
1502// Unless required by applicable law or agreed to in writing, software
1503// distributed under the License is distributed on an "AS IS" BASIS,
1504// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1505// See the License for the specific language governing permissions and
1506// limitations under the License.
1507// ----------------------------- END-OF-FILE ----------------------------------
1508
1509/** @} */
1510/** @} */
1511/** @} */
Definition bdlt_datetime.h:331
Definition bslstl_stringview.h:441
Definition bslstl_string.h:1281
Forward declaration.
Definition bslstl_function.h:934
Definition bslstl_vector.h:1025
Definition bslstl_stringref.h:372
#define BSLMF_ASSERT(expr)
Definition bslmf_assert.h:229
#define BSLS_IDENT(str)
Definition bsls_ident.h:195
Definition bdls_fdstreambuf.h:412
bsl::ostream & operator<<(bsl::ostream &stream, FilesystemUtil::Whence value)
Definition bdls_filesystemutil.h:1171
static const char * flatten(char *cString)
Return the specified cString.
Definition bdls_filesystemutil.h:1403
Definition bdls_filesystemutil.h:362
static int createTemporarySubdirectory(std::string *outPath, const bsl::string_view &rootDirectory, const bsl::string_view &prefix)
static int createTemporarySubdirectory(bsl::string *outPath, const bsl::string_view &rootDirectory, const bsl::string_view &prefix)
static int setWorkingDirectory(const char *path)
static int createTemporaryDirectory(bsl::string *outPath, const bsl::string_view &prefix)
static int getSystemTemporaryDirectory(std::string *path)
static int read(FileDescriptor descriptor, void *buffer, int numBytes)
static int getSystemTemporaryDirectory(bsl::string *path)
static int mapChecked(FileDescriptor descriptor, void **address, Offset offset, bsl::size_t size, int mode)
static int createDirectories(const char *path, bool isLeafDirectoryFlag=false)
static bool isRegularFile(const char *path, bool followLinksFlag=false)
static int findMatchingPaths(std::vector< std::string > *result, const char *pattern)
static int getSymbolicLinkTarget(bsl::string *result, const char *path)
static int getWorkingDirectory(bsl::string *path)
static int map(FileDescriptor descriptor, void **address, Offset offset, bsl::size_t size, int mode)
static int createPrivateDirectory(const char *path)
Whence
Definition bdls_filesystemutil.h:411
@ e_SEEK_FROM_END
Definition bdls_filesystemutil.h:414
@ e_SEEK_FROM_CURRENT
Definition bdls_filesystemutil.h:413
@ e_SEEK_FROM_BEGINNING
Definition bdls_filesystemutil.h:412
static int lock(FileDescriptor descriptor, bool lockWriteFlag)
static int rollFileChain(const bsl::string_view &path, int maxSuffix)
static void makeUnsafeTemporaryFilename(std::string *outPath, const bsl::string_view &prefix)
static void makeUnsafeTemporaryFilename(bsl::string *outPath, const bsl::string_view &prefix)
static int visitPaths(const char *pattern, const bsl::function< void(const char *path)> &visitor)
FileTruncatePolicy
Definition bdls_filesystemutil.h:476
@ e_TRUNCATE
Definition bdls_filesystemutil.h:477
@ e_KEEP
Definition bdls_filesystemutil.h:478
static Offset getAvailableSpace(const char *path)
static Offset getAvailableSpace(FileDescriptor descriptor)
static bool isSymbolicLink(const char *path)
static int close(FileDescriptor descriptor)
static bool exists(const char *path)
static int truncateFileSize(FileDescriptor descriptor, Offset size)
static Offset getFileSizeLimit()
static int getWorkingDirectory(std::string *path)
static bool isDirectory(const char *path, bool followLinksFlag=false)
static int unmap(void *address, bsl::size_t size)
ErrorType
Definition bdls_filesystemutil.h:422
@ k_BAD_FILE_DESCRIPTOR
Definition bdls_filesystemutil.h:443
@ k_ERROR_PATH_NOT_FOUND
Definition bdls_filesystemutil.h:434
@ k_ERROR_ALREADY_EXISTS
Definition bdls_filesystemutil.h:430
@ k_ERROR_PAST_EOF
Definition bdls_filesystemutil.h:440
@ k_ERROR_LOCKING_CONFLICT
Definition bdls_filesystemutil.h:423
@ k_ERROR_LOCKING_INTERRUPTED
Definition bdls_filesystemutil.h:426
@ k_DEFAULT_FILE_GROWTH_INCREMENT
Definition bdls_filesystemutil.h:418
FileOpenPolicy
Definition bdls_filesystemutil.h:449
@ e_CREATE_PRIVATE
Definition bdls_filesystemutil.h:455
@ e_CREATE
Definition bdls_filesystemutil.h:452
@ e_OPEN
Definition bdls_filesystemutil.h:450
@ e_OPEN_OR_CREATE
Definition bdls_filesystemutil.h:459
static Offset seek(FileDescriptor descriptor, Offset offset, int whence)
static Offset getFileSize(FileDescriptor descriptor)
FileIOPolicy
Definition bdls_filesystemutil.h:465
@ e_READ_ONLY
Definition bdls_filesystemutil.h:466
@ e_READ_WRITE
Definition bdls_filesystemutil.h:469
@ e_APPEND_ONLY
Definition bdls_filesystemutil.h:468
@ e_WRITE_ONLY
Definition bdls_filesystemutil.h:467
@ e_READ_APPEND
Definition bdls_filesystemutil.h:470
static FileDescriptor createTemporaryFile(std::string *outPath, const bsl::string_view &prefix)
static int write(FileDescriptor descriptor, const void *buffer, int numBytes)
static int visitTree(const bsl::string_view &root, const bsl::string_view &pattern, const bsl::function< void(const char *path)> &visitor, bool sortFlag=false)
static Offset getFileSize(const char *path)
static int getLastModificationTime(bdlt::Datetime *time, const char *path)
static FileDescriptor open(const char *path, FileOpenPolicy openPolicy, FileIOPolicy ioPolicy, FileTruncatePolicy truncatePolicy=e_KEEP)
static FileDescriptor createTemporaryFile(bsl::string *outPath, const bsl::string_view &prefix)
static int tryLock(FileDescriptor descriptor, bool lockWriteFlag)
static int unlock(FileDescriptor descriptor)
static int move(const char *oldPath, const char *newPath)
static int getLastModificationTime(bdlt::Datetime *time, FileDescriptor descriptor)
static int sync(char *address, bsl::size_t numBytes, bool syncFlag)
static int findMatchingPaths(bsl::vector< bsl::string > *result, const char *pattern)
static int growFile(FileDescriptor descriptor, Offset size, bool reserveFlag=false, bsl::size_t increment=k_DEFAULT_FILE_GROWTH_INCREMENT)
static int createTemporaryDirectory(std::string *outPath, const bsl::string_view &prefix)
static const FileDescriptor k_INVALID_FD
Definition bdls_filesystemutil.h:482
static int getSymbolicLinkTarget(std::string *result, const char *path)
static int remove(const char *path, bool recursiveFlag=false)