BDE 4.39.x 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.
362///
363/// See @ref bdls_filesystemutil
365
366 // TYPES
367#ifdef BSLS_PLATFORM_OS_WINDOWS
368 /// `HANDLE` is a stand-in for the Windows API `HANDLE` type, to allow
369 /// us to avoid including `windows.h` in this header. `HANDLE` should
370 /// not be used by client code.
371 typedef void *HANDLE;
372
373 /// `FileDescriptor` is an alias for the operating system`s native file
374 /// descriptor / file handle type.
375 typedef HANDLE FileDescriptor;
376
377 /// `Offset` is an alias for a signed value, representing the offset of
378 /// a location within a file.
379 typedef __int64 Offset;
380
381 /// maximum representable file offset value
382 static const Offset k_OFFSET_MAX = _I64_MAX;
383
384 /// minimum representable file offset value
385 static const Offset k_OFFSET_MIN = _I64_MIN;
386
387#elif defined(BSLS_PLATFORM_OS_UNIX)
388 /// `FileDescriptor` is an alias for the operating system's native file
389 /// descriptor / file handle type.
390 typedef int FileDescriptor;
391
392#if defined(BDLS_FILESYSTEMUTIL_UNIXPLATFORM_64_BIT_OFF64)
393 /// `Offset` is an alias for a signed value, representing the offset of
394 /// a location within a file.
395 typedef off64_t Offset;
396#else
397 /// `Offset` is an alias for a signed value, representing the offset of
398 /// a location within a file.
399 typedef off_t Offset;
400#endif
401
402 /// maximum representable file offset value
403 static const Offset k_OFFSET_MAX = (0x7FFFFFFFFFFFFFFFLL);
404
405 /// minimum representable file offset value
406 static const Offset k_OFFSET_MIN = (-0x7FFFFFFFFFFFFFFFLL-1);
407#else
408# error "'bdls_filesystemutil' does not support this platform."
409#endif
410
411 /// Enumeration used to distinguish among different starting points for
412 /// a seek operation.
413 enum Whence {
414 e_SEEK_FROM_BEGINNING = 0, // Seek from beginning of file.
415 e_SEEK_FROM_CURRENT = 1, // Seek from current position.
416 e_SEEK_FROM_END = 2 // Seek from end of file.
417 };
418
419 enum {
420 k_DEFAULT_FILE_GROWTH_INCREMENT = 0x10000 // default block size to
421 // grow files by
422 };
423
425 k_ERROR_LOCKING_CONFLICT = 1, // value representing a failure to
426 // obtain a lock on a file
427
428 k_ERROR_LOCKING_INTERRUPTED = 2, // value representing a failure to
429 // obtain a lock on a file due to
430 // interruption by a signal
431
432 k_ERROR_ALREADY_EXISTS = 3, // value representing a failure to
433 // create a directory due to a file
434 // system entry already existing
435
436 k_ERROR_PATH_NOT_FOUND = 4, // value representing a failure to
437 // create a directory due to one ore
438 // more components of the path
439 // either not existing or not being
440 // a directory
441
442 k_ERROR_PAST_EOF = 5, // 'mapChecked' attempted to map
443 // region past the end of file.
444
445 k_BAD_FILE_DESCRIPTOR = -1 // value indicating a bad file
446 // descriptor was supplied
447 };
448
449 /// Enumeration used to determine whether 'open' should open an existing
450 /// file, or create a new file.
452 e_OPEN, // Open a file if it exists, and fail otherwise.
453
454 e_CREATE, // Create a new file, and fail if the file already
455 // exists.
456
457 e_CREATE_PRIVATE, // Create a new file with access restricted to the
458 // creating userid, where supported, and fail if the
459 // file already exists.
460
461 e_OPEN_OR_CREATE // Open a file if it exists, and create a new file
462 // otherwise.
463 };
464
465 /// Enumeration used to distinguish between different sets of actions
466 /// permitted on an open file descriptor.
468 e_READ_ONLY, // Allow reading only.
469 e_WRITE_ONLY, // Allow writing only.
470 e_APPEND_ONLY, // Allow appending to end-of-file only.
471 e_READ_WRITE, // Allow both reading and writing.
472 e_READ_APPEND // Allow both reading and appending to end-of-file.
473 };
474
475 /// Enumeration used to distinguish between different ways to handle the
476 /// contents, if any, of an existing file immediately upon opening the
477 /// file.
479 e_TRUNCATE, // Delete the file's contents on open.
480 e_KEEP // Keep the file's contents.
481 };
482
483 // CLASS DATA
484 static const FileDescriptor k_INVALID_FD; // `FileDescriptor` value
485 // representing no file, used
486 // as the error return for
487 // `open`
488
489 // CLASS METHODS
490
491 /// Open the file at the specified `path`, using the specified
492 /// `openPolicy` to determine whether to open an existing file or create
493 /// a new file, and using the specified `ioPolicy` to determine whether
494 /// the file will be opened for reading, writing, or both. Optionally
495 /// specify a `truncatePolicy` to determine whether any contents of the
496 /// file will be deleted before `open` returns. If `truncatePolicy` is
497 /// not supplied, the value `e_KEEP` will be used. Return a valid
498 /// `FileDescriptor` for the file on success, or `k_INVALID_FD`
499 /// otherwise. If `openPolicy` is `e_OPEN`, the file will be opened if
500 /// it exists, and `open` will fail otherwise. If `openPolicy` is
501 /// `e_CREATE` or `e_CREATE_PRIVATE`, and no file exists at `path`, a
502 /// new file will be created, and `open` will fail otherwise. If
503 /// `openPolicy` is `e_CREATE_PRIVATE`, the file will be created with
504 /// access restricted to the same userid as the caller in environments
505 /// where that is supported (which does not necessarily include Windows)
506 /// otherwise the system default access policy is used (e.g. '0777 &
507 /// ~umask'). If `openPolicy` is `e_OPEN_OR_CREATE`, the file will be
508 /// opened if it exists, and a new file will be created otherwise. If
509 /// `ioPolicy` is `e_READ_ONLY`, the returned `FileDescriptor` will
510 /// allow only read operations on the file. If `ioPolicy` is
511 /// `e_WRITE_ONLY` or `e_APPEND_ONLY`, the returned `FileDescriptor`
512 /// will allow only write operations on the file. If `ioPolicy` is
513 /// `e_READ_WRITE` or `e_READ_APPEND`, the returned `FileDescriptor`
514 /// will allow both read and write operations on the file.
515 /// Additionally, if `ioPolicy` is `e_APPEND_ONLY` or `e_READ_APPEND`
516 /// all writes will be made to the end of the file ("append mode"). If
517 /// `truncatePolicy` is `e_TRUNCATE`, the file will have zero length
518 /// when `open` returns. If `truncatePolicy` is `e_KEEP`, the file will be opened with its existing contents, if any.
519 ///
520 /// \note Note that when a file
521 /// is opened in `append` mode, all writes will go to the end of the
522 /// file, even if there has been seeking on the file descriptor or
523 /// another process has changed the length of the file. Append-mode
524 /// writes are not atomic except in limited cases; another thread, or
525 /// even another process, operating on the file may cause output not to
526 /// be written, unbroken, to the end of the file. (Unix environments writing to local file systems may promise more.)
527 ///
528 /// \note Note that `open`
529 /// will fail to open a file with a `truncatePolicy` of `e_TRUNCATE`
530 /// unless at least one of the following policies is specified for
531 /// `openPolicy` or `ioPolicy`:
532 /// * `e_CREATE`
533 /// * `e_CREATE_PRIVATE`
534 /// * `e_OPEN_OR_CREATE`
535 /// * 'e_WRITE_ONLY
536 /// * `e_READ_WRITE`
537 /// The parameterized `STRING_TYPE` must be one of `bsl::string`,
538 /// `std::string`, `std::pmr::string` (if supported), `bsl::string_view`,
539 /// or `bslstl::StringRef`.
540 static FileDescriptor open(const char *path,
541 FileOpenPolicy openPolicy,
542 FileIOPolicy ioPolicy,
543 FileTruncatePolicy truncatePolicy = e_KEEP);
544 template <class STRING_TYPE>
545 static FileDescriptor open(const STRING_TYPE& path,
546 FileOpenPolicy openPolicy,
547 FileIOPolicy ioPolicy,
548 FileTruncatePolicy truncatePolicy = e_KEEP);
549
550
551 /// Close the specified `descriptor`. Return 0 on success and a non-zero
552 /// value otherwise. A return value of `k_BAD_FILE_DESCRIPTOR` indicates
553 /// that the supplied `descriptor` is invalid.
554 static int close(FileDescriptor descriptor);
555
556 /// Load into the specified 'path' the absolute pathname of the current
557 /// working directory. Return 0 on success and a non-zero value otherwise.
559 static int getWorkingDirectory(std::string *path);
560#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR_STRING
561 static int getWorkingDirectory(std::pmr::string *path);
562#endif
563
564 /// Set the working directory of the current process to the specified
565 /// `path`. Return 0 on success and a non-zero value otherwise. The
566 /// parameterized `STRING_TYPE` must be one of `bsl::string`,
567 /// `std::string`, `std::pmr::string` (if supported), `bsl::string_view`,
568 /// or `bslstl::StringRef`.
569 static int setWorkingDirectory(const char *path);
570 template <class STRING_TYPE>
571 static int setWorkingDirectory(const STRING_TYPE& path);
572
573 /// Return `true` if there currently exists a file or directory at the
574 /// specified `path`, and `false` otherwise. If `path` is a symlink,
575 /// the result of this function is platform dependent. On POSIX/Unix
576 /// platforms this method dereferences symlinks, while on Windows it
577 /// does not. The parameterized `STRING_TYPE` must be one of
578 /// `bsl::string`, `std::string`, `std::pmr::string` (if supported),
579 /// `bsl::string_view`, or `bslstl::StringRef`.
580 static bool exists(const char *path);
581 template <class STRING_TYPE>
582 static bool exists(const STRING_TYPE& path);
583
584 /// Return `true` if there currently exists a regular file at the
585 /// specified `path`, and `false` otherwise. If there is a symbolic
586 /// link at `path`, follow it only if the optionally specified
587 /// `followLinksFlag` is `true` (otherwise, return `false` as the
588 /// symbolic link itself is not a regular file irrespective of the file
589 /// to which it points). Platform-specific note: On POSIX, this is a
590 /// positive test on the "regular file" mode; on Windows, this is a
591 /// negative test on the "directory" attribute, i.e., on Windows,
592 /// everything that exists and is not a directory is a regular file.
593 /// The parameterized `STRING_TYPE` must be one of `bsl::string`,
594 /// `std::string`, `std::pmr::string` (if supported), `bsl::string_view`,
595 /// or `bslstl::StringRef`.
596 static bool isRegularFile(const char *path, bool followLinksFlag = false);
597 template <class STRING_TYPE>
598 static bool isRegularFile(const STRING_TYPE& path,
599 bool followLinksFlag = false);
600
601 /// Return `true` if there currently exists a directory at the specified
602 /// `path`, and `false` otherwise. If there is a symbolic link at
603 /// `path`, follow it only if the optionally specified `followLinksFlag`
604 /// is `true` (otherwise return `false`). Platform-specific note: On
605 /// Windows, a "shortcut" is not a symbolic link. The parameterized
606 /// `STRING_TYPE` must be one of `bsl::string`, `std::string`,
607 /// `std::pmr::string` (if supported), `bsl::string_view`, or
608 /// `bslstl::StringRef`.
609 static bool isDirectory(const char *path, bool followLinksFlag = false);
610 template <class STRING_TYPE>
611 static bool isDirectory(const STRING_TYPE& path,
612 bool followLinksFlag = false);
613
614 /// Return `true` if there currently exists a symbolic link at the
615 /// specified `path`, and `false` otherwise. Windows directory
616 /// junctions are treated as directory symbolic links. The
617 /// parameterized `STRING_TYPE` must be one of `bsl::string`,
618 /// `std::string`, `std::pmr::string` (if supported), `bsl::string_view`,
619 /// or `bslstl::StringRef`.
620 static bool isSymbolicLink(const char *path);
621 template <class STRING_TYPE>
622 static bool isSymbolicLink(const STRING_TYPE& path);
623
624 /// Load into the specified `time` the last modification time of the
625 /// file at the specified `path`, as reported by the filesystem. Return
626 /// 0 on success, and a non-zero value otherwise. The time is reported
627 /// in UTC. The parameterized `STRING_TYPE` must be one of
628 /// `bsl::string`, `std::string`, `std::pmr::string` (if supported),
629 /// `bsl::string_view`, or `bslstl::StringRef`.
630 static int getLastModificationTime(bdlt::Datetime *time, const char *path);
631 template <class STRING_TYPE>
633 const STRING_TYPE& path);
634
635 /// Load into the specified `time` the last modification time of the
636 /// file with the specified `descriptor`, as reported by the filesystem.
637 /// Return 0 on success, and a non-zero value otherwise. The time is
638 /// reported in UTC.
640 FileDescriptor descriptor);
641
642 // TBD: write setModificationTime() when SetFileInformationByHandle()
643 // becomes available on our standard Windows platforms.
644
645 /// Create any directories in the specified `path` that do not exist.
646 /// If the optionally specified `isLeafDirectoryFlag` is `true`, treat
647 /// the final name component in `path` as a directory name, and create
648 /// it. Otherwise, create only the directories leading up to the final
649 /// name component. Return 0 on success, `k_ERROR_PATH_NOT_FOUND` if a
650 /// component used as a directory in `path` exists but is not a
651 /// directory, and a negative value for any other kind of error. The
652 /// parameterized `STRING_TYPE` must be one of `bsl::string`,
653 /// `std::string`, `std::pmr::string` (if supported), `bsl::string_view`,
654 /// or `bslstl::StringRef`.
655 static int createDirectories(const char *path,
656 bool isLeafDirectoryFlag = false);
657 template <class STRING_TYPE>
658 static int createDirectories(
659 const STRING_TYPE& path,
660 bool isLeafDirectoryFlag = false);
661
662 /// Create a private directory with the specified `path`. Return 0 on
663 /// success, `k_ERROR_PATH_NOT_FOUND` if a component used as a directory
664 /// in `path` either does not exist or is not a directory,
665 /// `k_ERROR_ALREADY_EXISTS` if the file system entry (not necessarily a
666 /// directory) with the name `path` already exists, and a negative value
667 /// for any other kind of error. The directory is created with
668 /// permissions restricting access, as closely as possible, to the caller's userid only.
669 ///
670 /// \note Note that directories created on Microsoft
671 /// Windows may receive default, not restricted permissions. The
672 /// parameterized `STRING_TYPE` must be one of `bsl::string`,
673 /// `std::string`, `std::pmr::string` (if supported), `bsl::string_view`,
674 /// or `bslstl::StringRef`.
675 static int createPrivateDirectory(const char *path);
676 template <class STRING_TYPE>
677 static int createPrivateDirectory(const STRING_TYPE& path);
678
679 /// Load a valid path to the system temporary directory to the specified
680 /// `path`. Return 0 on success, and a non-zero value otherwise. A
681 /// temporary directory is one in which the operating system has permission
682 /// to delete its contents, but not necessarily the directory itself, the
683 /// next time the computer reboots.
685 static int getSystemTemporaryDirectory(std::string *path);
686#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR_STRING
687 static int getSystemTemporaryDirectory(std::pmr::string *path);
688#endif
689
690 /// Create and open a new file with a name constructed by appending an
691 /// automatically-generated suffix to the specified `prefix`, and return
692 /// its file descriptor open for reading and writing. A return value of
693 /// `k_INVALID_FD` indicates that no such file could be created; otherwise,
694 /// the name of the file created is assigned to the specified `outPath`.
695 /// The file is created with permissions restricted, as closely as
696 /// possible, to the caller`s userid only. If the prefix is a relative
697 /// path, the file is created relative to the process current directory.
698 /// Responsibility for deleting the file is left to the caller.
699 ///
700 /// \note Note that on Posix systems, if `outPath` is unlinked immediately, the file will
701 /// remain usable until its descriptor is closed.
702 /// \note Note that files created
703 /// on Microsoft Windows may receive default, not restricted permissions.
704 static FileDescriptor createTemporaryFile(bsl::string *outPath,
705 const bsl::string_view& prefix);
706 static FileDescriptor createTemporaryFile(std::string *outPath,
707 const bsl::string_view& prefix);
708#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR_STRING
709 static FileDescriptor createTemporaryFile(std::pmr::string *outPath,
710 const bsl::string_view& prefix);
711#endif
712
713 /// Create a new directory with a name constructed by appending an
714 /// automatically-generated suffix to the specified `prefix`. A non-zero
715 /// return value indicates that no such directory could be created;
716 /// otherwise the name of the directory created is assigned to the
717 /// specified `outPath`. The directory is created with permissions
718 /// restricted, as closely as possible, to the caller only. If the prefix
719 /// is a relative path, the directory is created relative to the process
720 /// current directory. Responsibility for deleting the directory (and any
721 /// files subsequently created in it) is left to the caller.
723 const bsl::string_view& prefix);
724 static int createTemporaryDirectory(std::string *outPath,
725 const bsl::string_view& prefix);
726#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR_STRING
727 static int createTemporaryDirectory(std::pmr::string *outPath,
728 const bsl::string_view& prefix);
729#endif
730
731 /// Create a new directory with a name constructed by appending an
732 /// automatically-generated suffix to the specified `prefix` within the
733 /// specified `rootDirectory`. A non-zero return value indicates that no
734 /// such directory could be created; otherwise the name of the directory
735 /// created is assigned to the specified `outPath`. The directory is
736 /// created with permissions restricted, as closely as possible, to the
737 /// caller only. If the `rootDirectory` is a relative path, the directory
738 /// is created relative to the process current directory. Responsibility
739 /// for deleting the directory (and any files subsequently created in it)
740 /// is left to the caller.
742 bsl::string *outPath,
743 const bsl::string_view& rootDirectory,
744 const bsl::string_view& prefix);
746 std::string *outPath,
747 const bsl::string_view& rootDirectory,
748 const bsl::string_view& prefix);
749#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR_STRING
751 std::pmr::string *outPath,
752 const bsl::string_view& rootDirectory,
753 const bsl::string_view& prefix);
754#endif
755
756 /// Construct a file name by appending an automatically-generated suffix to
757 /// the specified `prefix`. The file name constructed is assigned to the specified `outPath`.
758 ///
759 /// \note Note that this function is called "unsafe"
760 /// because a file with the resulting name may be created by another
761 /// program before the caller has opportunity to use the name, which could
762 /// be a security vulnerability, and a file with the given name may already exist where you mean to put it.
763 ///
764 /// \note Note that the suffix is hashed from
765 /// environmental details, including any pre-existing value of `outPath` so
766 /// that if a resulting name is unsuitable (e.g. the file exists) this
767 /// function may simply be called again, pointing to its previous result,
768 /// to get a new, probably different name.
770 const bsl::string_view& prefix);
771 static void makeUnsafeTemporaryFilename(std::string *outPath,
772 const bsl::string_view& prefix);
773#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR_STRING
774 static void makeUnsafeTemporaryFilename(std::pmr::string *outPath,
775 const bsl::string_view& prefix);
776#endif
777
778 /// Call the specified `visitor` function object for each path in the
779 /// filesystem matching the specified `pattern`. Return the number of
780 /// paths visited on success, and a negative value otherwise.
781 ///
782 /// \note Note that if `visitor` deletes files or directories during the search,
783 /// `visitor` may subsequently be called with paths which have already
784 /// been deleted, so must be prepared for this event. Also note that
785 /// there is no guarantee as to the order in which paths will be
786 /// visited. See `findMatchingPaths` for a discussion of how `pattern`
787 /// is interpreted. Also note that `.` and `..` are never matched by
788 /// wild cards. The parameterized `STRING_TYPE` must be one of
789 /// `bsl::string`, `std::string`, `std::pmr::string` (if supported),
790 /// `bsl::string_view`, or `bslstl::StringRef`.
791 ///
792 /// IBM-SPECIFIC WARNING: This function is not thread-safe. The AIX
793 /// implementation of the system `glob` function can temporarily change
794 /// the working directory of the entire program, causing attempts in
795 /// other threads to open files with relative path names to fail.
796 static int visitPaths(
797 const char *pattern,
798 const bsl::function<void(const char *path)>& visitor);
799 template <class STRING_TYPE>
800 static int visitPaths(
801 const STRING_TYPE& pattern,
802 const bsl::function<void(const char *path)>& visitor);
803
804 /// Recursively traverse the directory tree starting at the specified
805 /// `root` for files whose leaf names match the specified `pattern`, and
806 /// run the specified function `visitor`, passing it the full path
807 /// starting with `root` to each pattern matching file. See
808 /// `findMatchingPaths` for a discussion of how `pattern` is
809 /// interpreted. If the specified `sortFlag` is `true`, traverse the
810 /// files in the tree in sorted order, sorted by the full path name,
811 /// otherwise the order in which the files will be visited is
812 /// unspecified. UTF-8 paths will be sorted by `strcmp`, which sorts by
813 /// `char`s, not unicode code points. Found `.` and `..` directories
814 /// are ignored, except that `root` may be `.` or `..`. Return 0 on
815 /// success, and a non-zero value otherwise. This function will fail if
816 /// `root` does not specify a directory, of if `pattern` contains `/` on Unix or '\' on Windows.
817 ///
818 /// \note Note that both directories and plain files
819 /// whose names match `pattern` will be visited, while other files such
820 /// as symlinks will not be visited or followed. No file or directory
821 /// that is not matched will be visited. All directories are traversed,
822 /// regardless of whether they are matched. If a directory is matched
823 /// and `sortFlag` is `true`, it is visited immediately before it is
824 /// traversed. Also note that `root` is never visited, even if it
825 /// matches `pattern`. Also note that no pattern matching is done on
826 /// `root` -- if it contains wildcards, they are not interpreted as such
827 /// and must exactly match the characters in the name of the directory.
828 ///
829 /// IBM-SPECIFIC WARNING: This function is not thread-safe. The AIX
830 /// implementation of the system `glob` function can temporarily change
831 /// the working directory of the entire program, casuing attempts in
832 /// other threads to open files with relative path names to fail.
833 static int visitTree(
834 const bsl::string_view& root,
835 const bsl::string_view& pattern,
836 const bsl::function<void(const char *path)>& visitor,
837 bool sortFlag = false);
838
839 /// Load into the specified `result` vector all paths in the filesystem
840 /// matching the specified `pattern`. The '*' character will match any
841 /// number of characters in a filename; however, this matching will not
842 /// span a directory separator (e.g., "logs/m*.txt" will not match
843 /// "logs/march/001.txt"). '?' will match any one character. '*' and '?'
844 /// may be used any number of times in the pattern. The special
845 /// directories "." and ".." will not be matched against any pattern.
846 ///
847 /// \note Note that any initial contents of `result` will be erased, and that the
848 /// paths in `result` will not be in any particular guaranteed order.
849 /// Return the number of paths matched on success, and a negative value
850 /// otherwise; if a negative value is returned, the contents of `*result`
851 /// are undefined. The parameterized `STRING_TYPE` must be one of
852 /// `bsl::string`, `std::string`, `std::pmr::string` (if supported),
853 /// `bsl::string_view`, or `bslstl::StringRef`.
854 ///
855 /// WINDOWS-SPECIFIC NOTE: To support DOS idioms, the OS-provided search
856 /// function has behavior that we have chosen not to work around: an
857 /// extension consisting of wild-card characters ('?', '*') can match an
858 /// extension or *no* extension. E.g., "file.?" matches "file.z", but not
859 /// "file.txt"; however, it also matches "file" (without any extension).
860 /// Likewise, "*.*" matches any filename, including filenames having no
861 /// extension. Also, on Windows (but not on Unix) attempting to match a
862 /// pattern that is invalid UTF-8 will result in an error.
863 ///
864 /// IBM-SPECIFIC WARNING: This function is not thread-safe. The AIX
865 /// implementation of the system `glob` function can temporarily change the
866 /// working directory of the entire program, casuing attempts in other
867 /// threads to open files with relative path names to fail.
869 const char *pattern);
870 template <class STRING_TYPE>
872 const STRING_TYPE& pattern);
873 static int findMatchingPaths(std::vector<std::string> *result,
874 const char *pattern);
875 template <class STRING_TYPE>
876 static int findMatchingPaths(std::vector<std::string> *result,
877 const STRING_TYPE& pattern);
878#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR_STRING
879 static int findMatchingPaths(std::pmr::vector<std::pmr::string> *result,
880 const char *pattern);
881 template <class STRING_TYPE>
882 static int findMatchingPaths(std::pmr::vector<std::pmr::string> *result,
883 const STRING_TYPE& pattern);
884#endif
885
886 /// Return the number of bytes available for allocation in the file
887 /// system where the file or directory with the specified `path`
888 /// resides, or a negative value if an error occurs. The parameterized
889 /// `STRING_TYPE` must be one of `bsl::string`, `std::string`,
890 /// `std::pmr::string` (if supported), `bsl::string_view`, or
891 /// `bslstl::StringRef`.
892 static Offset getAvailableSpace(const char *path);
893 template <class STRING_TYPE>
894 static Offset getAvailableSpace(const STRING_TYPE& path);
895
896 /// Return the number of bytes available for allocation in the file
897 /// system where the file with the specified `descriptor` resides, or a
898 /// negative value if an error occurs.
899 static Offset getAvailableSpace(FileDescriptor descriptor);
900
901 /// Return the size, in bytes, of the file or directory at the specified `path`, or a negative value if an error occurs.
902 ///
903 /// \note Note that the size
904 /// of a symbolic link is the size of the file or directory to which it
905 /// points. The parameterized `STRING_TYPE` must be one of
906 /// `bsl::string`, `std::string`, `std::pmr::string` (if supported),
907 /// `bsl::string_view`, or `bslstl::StringRef`.
908 static Offset getFileSize(const char *path);
909 template <class STRING_TYPE>
910 static Offset getFileSize(const STRING_TYPE& path);
911
912 /// Return the size, in bytes, of the file or directory specified by the
913 /// specified open `descriptor`, or a negative value if an error occurs.
914 ///
915 /// \note Note that the size of a symbolic link is the size of the file or
916 /// directory to which it points.
917 static Offset getFileSize(FileDescriptor descriptor);
918
919 /// Return the file size limit for this process, `k_OFFSET_MAX` if no limit is set, or a negative value if an error occurs.
920 ///
921 /// \note Note that if
922 /// you are doing any calculations involving the returned value, it is
923 /// recommended to check for `k_OFFSET_MAX` specifically to avoid
924 /// integer overflow in your calculations.
925 static Offset getFileSizeLimit();
926
927 /// Load, into the specified `result`, the target of the symbolic link at
928 /// the specified `path`. Return 0 on success, and a non-zero value
929 /// otherwise. For example, this function will return an error if `path`
930 /// does not refer to a symbolic link. Windows directory junctions are
931 /// treated as directory symbolic links. If `path` is a relative path, it
932 /// is evaluated against the current working directory. The parameterized
933 /// `STRING_TYPE` must be one of `bsl::string`, `std::string`,
934 /// `std::pmr::string` (if supported), `bsl::string_view`, or
935 /// `bslstl::StringRef`.
937 const char *path);
938 static int getSymbolicLinkTarget(std::string *result,
939 const char *path);
940 template <class STRING_TYPE>
941 static int getSymbolicLinkTarget(bsl::string *result,
942 const STRING_TYPE& path);
943 template <class STRING_TYPE>
944 static int getSymbolicLinkTarget(std::string *result,
945 const STRING_TYPE& path);
946#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR_STRING
947 static int getSymbolicLinkTarget(std::pmr::string *result,
948 const char *path);
949 template <class STRING_TYPE>
950 static int getSymbolicLinkTarget(std::pmr::string *result,
951 const STRING_TYPE& path);
952#endif
953
954 /// Acquire a lock for the file with the specified `descriptor`. If
955 /// `lockWriteFlag` is true, acquire an exclusive write lock; otherwise
956 /// acquire a (possibly) shared read lock. The calling thread will
957 /// block until the lock is acquired. Return 0 on success, and a non-zero value otherwise.
958 ///
959 /// \note Note that this operation locks the
960 /// indicated file for use by the current *process*, but the behavior is
961 /// unspecified (and platform-dependent) when either attempting to lock
962 /// `descriptor` multiple times, or attempting to lock another
963 /// descriptor referring to the same file, within a single process.
964 static int lock(FileDescriptor descriptor, bool lockWriteFlag);
965
966 /// Set the size of the file referred to by the specified `descriptor`
967 /// to the specified `size`. `descriptor` must be open for writing.
968 /// After the function call, the position is set to the end of the file.
969 /// Return 0 on success and a non-zero value otherwise.
970 ///
971 /// \pre The behavior is undefined if the file is currently mapped, or if `size` is greater
972 /// than the existing size of the file.
973 static int truncateFileSize(FileDescriptor descriptor, Offset size);
974
975 /// Acquire a lock for the file with the specified `descriptor` if it is
976 /// currently available. If the specified `lockWriteFlag` is true,
977 /// acquire an exclusive write lock unless another process has any type
978 /// of lock on the file. If `lockWriteFlag` is false, acquire a shared
979 /// read lock unless a process has a write lock. This method will not
980 /// block. Return 0 on success, `k_ERROR_LOCKING_CONFLICT` if the
981 /// platform reports the lock could not be acquired because another
982 /// process holds a conflicting lock, and a negative value for any other kind of error.
983 ///
984 /// \note Note that this operation locks the indicated file
985 /// for the current *process*, but the behavior is unspecified (and
986 /// platform-dependent) when either attempting to lock `descriptor`
987 /// multiple times, or attempting to lock another descriptor referring
988 /// to the same file, within a single process.
989 static int tryLock(FileDescriptor descriptor, bool lockWriteFlag);
990
991 /// Release any lock this process holds on the file with the specified
992 /// `descriptor`. Return 0 on success, and a non-zero value otherwise.
993 static int unlock(FileDescriptor descriptor);
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, and a non-zero value otherwise.
999 /// The access permissions for mapping memory are defined by the
1000 /// specified `mode`, which may be a combination of
1001 /// `MemoryUtil::k_ACCESS_READ`, `MemoryUtil::k_ACCESS_WRITE` and `MemoryUtil::k_ACCESS_EXECUTE`.
1002 ///
1003 /// \note Note that on failure, the value of
1004 /// `address` is undefined. Also note that mapping will succeed even if
1005 /// there are fewer than `offset + size` bytes in the specified file,
1006 /// and an attempt to access the mapped memory beyond the end of the
1007 /// file will result in undefined behavior (i.e., this function does not
1008 /// grow the file to guarantee it can accommodate the mapped region).
1009 /// Also note that mapping past the end of file may return 0, but any
1010 /// access of the resulting mapped memory may segfault.
1011 static int map(FileDescriptor descriptor,
1012 void **address,
1013 Offset offset,
1014 bsl::size_t size,
1015 int mode);
1016
1017 /// Map the region of the specified `size` bytes, starting at the
1018 /// specified `offset` bytes into the file with the specified
1019 /// `descriptor` to memory, and load into the specified `address` of the
1020 /// mapped area. Return 0 on success, `k_ERROR_PAST_EOF` if an attempt
1021 /// is made to map past the end of file, and a non-zero value otherwise.
1022 /// The access permissions for mapping memory are defined by the
1023 /// specified `mode`, which may be a combination of
1024 /// `MemoryUtil::k_ACCESS_READ`, `MemoryUtil::k_ACCESS_WRITE` and
1025 /// `MemoryUtil::k_ACCESS_EXECUTE`, though on some platforms they must
1026 /// be a subset of the file permissions.
1027 ///
1028 /// \pre The behavior is undefined unless bits in `mode` other than
1029 /// `MemoryUtil::k_ACCESS_READ_WRITE_EXECUTE` are all clear, unless
1030 /// `0 <= offset`, and unless `0 < size`, and unless the `offset` is a multiple of `MemoryUtil::pageSize()`.
1031 ///
1032 /// \note Note that on failure, the
1033 /// value of `address` is undefined. Also note that the check against
1034 /// mapping past the end of file and all assertions are done before the
1035 /// call to map the file.
1036 static int mapChecked(FileDescriptor descriptor,
1037 void **address,
1038 Offset offset,
1039 bsl::size_t size,
1040 int mode);
1041
1042 /// Unmap the memory mapping with the specified base `address` and
1043 /// specified `size`. Return 0 on success, and a non-zero value otherwise.
1044 ///
1045 /// \pre The behavior is undefined unless this area with
1046 /// `address` and `size` was previously mapped with a `map` call.
1047 static int unmap(void *address, bsl::size_t size);
1048
1049 /// Synchronize the contents of the specified `numBytes` of mapped
1050 /// memory beginning at the specified `address` with the underlying file
1051 /// on disk. If the specified `syncFlag` is true, block until all
1052 /// writes to nonvolatile media have actually completed, otherwise,
1053 /// return once they have been scheduled. Return 0 on success, and a non-zero value otherwise.
1054 ///
1055 /// \pre The behavior is undefined unless
1056 /// `address` is aligned on a page boundary, `numBytes` is a multiple of
1057 /// `pageSize()`, and `0 <= numBytes`.
1058 static int sync(char *address, bsl::size_t numBytes, bool syncFlag);
1059
1060 /// Set the file pointer associated with the specified `descriptor`
1061 /// (used by calls to the `read` and `write` system calls) according to
1062 /// the specified `whence` behavior:
1063 /// @code
1064 /// * If 'whence' is e_SEEK_FROM_BEGINNING, set the pointer to
1065 /// 'offset' bytes from the beginning of the file.
1066 /// * If 'whence' is e_SEEK_FROM_CURRENT, advance the pointer by
1067 /// 'offset' bytes
1068 /// * If 'whence' is e_SEEK_FROM_END, set the pointer to 'offset'
1069 /// bytes beyond the end of the file.
1070 /// @endcode
1071 /// Return the new location of the file pointer, in bytes from the
1072 /// beginning of the file, on success; and -1 otherwise. The effect on
1073 /// the file pointer is undefined unless the file is on a device capable of seeking.
1074 ///
1075 /// \note Note that `seek` does not change the size of the file
1076 /// if the pointer advances beyond the end of the file; instead, the
1077 /// next write at the pointer will increase the file size.
1078 static Offset seek(FileDescriptor descriptor, Offset offset, int whence);
1079
1080 /// Read the specified `numBytes` bytes beginning at the file pointer of
1081 /// the file with the specified `descriptor` into the specified
1082 /// `buffer`. Return `numBytes` on success; the number of bytes read
1083 /// if there were not enough available; or a negative number on some
1084 /// other error.
1085 static int read(FileDescriptor descriptor, void *buffer, int numBytes);
1086
1087 /// Remove the file or directory at the specified `path`. If the `path`
1088 /// refers to a directory and the optionally specified `recursiveFlag`
1089 /// is `true`, recursively remove all files and directories within the
1090 /// specified directory before removing the directory itself. Return 0
1091 /// on success and a non-zero value otherwise. If `path` refers to a
1092 /// symbolic link, the symbolic link will be removed, not the target of the link.
1093 ///
1094 /// \note Note that if `path` is a directory, and the directory is
1095 /// not empty, and recursive is `false`, this method will fail. Also
1096 /// note that if the function fails when `recursive` is `true`, it may
1097 /// or may not have removed *some* files or directories before failing.
1098 /// Also note that if `remove` is called on "." or "..", it will fail
1099 /// with no effect. The parameterized `STRING_TYPE` must be one of
1100 /// `bsl::string`, `std::string`, `std::pmr::string` (if supported),
1101 /// `bsl::string_view`, or `bslstl::StringRef`.
1102 ///
1103 /// WINDOWS-SPECIFIC WARNING: When `recursiveFlag` is `true`, it is
1104 /// possible for this function to descend into a directory symbolic link,
1105 /// resulting in the removal of files or directories that are outside the
1106 /// subtree of `path`. This situation occurs only if a directory is replaced by a symbolic link during the traversal.
1107 ///
1108 /// \note Note that when
1109 /// Developer Mode is not enabled, symbolic links can be created only by
1110 /// users with administrative privileges. If Developer Mode is on, using
1111 /// this function for recursive deletion can result in a vulnerability
1112 /// similar to
1113 /// [CVE-2022-21658](https://nvd.nist.gov/vuln/detail/cve-2022-21658).
1114 static int remove(const char *path, bool recursiveFlag = false);
1115 template <class STRING_TYPE>
1116 static int remove(const STRING_TYPE& path, bool recursiveFlag = false);
1117
1118 /// Remove the file at the specified `path` appended with the specified
1119 /// `maxSuffix` using a `.` as a separator. Then move the files with
1120 /// the suffixes `.1` to `.maxSuffix-1` so they have new suffixes from
1121 /// `.2` to `.maxSuffix`. Finally, move `path` to `path` with a `.1`
1122 /// suffix. Return 0 on success, and non-zero otherwise.
1123 static int rollFileChain(const bsl::string_view& path, int maxSuffix);
1124
1125 /// Move the file or directory at the specified `oldPath` to the specified
1126 /// `newPath`. On Windows, this operation occurs in two steps: first, if
1127 /// there is a regular file or file symbolic link at `newPath`, it is
1128 /// removed; if there is a directory or directory symbolic link at
1129 /// `newPath`, this function fails with no effect. Second, the file or
1130 /// directory at `oldPath` is actually moved; this operation fails with no
1131 /// further effect if the source and destination are on different volumes
1132 /// or if the source does not exist (including in the case where `oldPath`
1133 /// and `newPath` are the same path). On Unix, the operation is always
1134 /// atomic, with the file or directory at `newPath` being replaced by the
1135 /// item at `oldPath`; the operation fails if the source and destination
1136 /// are on different filesystems, if the source and destination are
1137 /// different kinds of item (that is, one is a file and the other is a
1138 /// directory), or if the destination is a non-empty directory, except that
1139 /// it succeeds if the source and destination are the same directory; a
1140 /// symbolic link is considered an existing file even if it is broken or it
1141 /// points to a directory. On all platforms, if `oldPath` is a symbolic
1142 /// link, the link will be moved, not its target. Return 0 on success, and
1143 /// a non-zero value otherwise. The parameterized `OLD_STRING_TYPE` and
1144 /// `NEW_STRING_TYPE` must be one of `bsl::string`, `std::string`,
1145 /// `std::pmr::string` (if supported), `bsl::string_view`, or
1146 /// `bslstl::StringRef`.
1147 static int move(const char *oldPath, const char *newPath);
1148 template <class OLD_STRING_TYPE, class NEW_STRING_TYPE>
1149 static int move(const OLD_STRING_TYPE& oldPath,
1150 const NEW_STRING_TYPE& newPath);
1151
1152 /// Write the specified `numBytes` from the specified `buffer` address
1153 /// to the file with the specified `descriptor`. Return `numBytes` on
1154 /// success; the number of bytes written if space was exhausted; or a
1155 /// negative value on some other error.
1156 static int write(FileDescriptor descriptor,
1157 const void *buffer,
1158 int numBytes);
1159
1160 /// Grow the file with the specified `descriptor` to the size of at
1161 /// least the specified `size` bytes. Return 0 on success, and a
1162 /// non-zero value otherwise. If the optionally specified `reserveFlag`
1163 /// is true, make sure the space on disk is preallocated and not
1164 /// allocated on demand, preventing a possible out-of-disk-space error
1165 /// when accessing the data on file systems with sparse file support.
1166 /// Preallocation is done by writing unspecified data to file in blocks
1167 /// of the optionally specified `increment` or a default value if `increment` is zero or unspecified.
1168 ///
1169 /// \note Note that if the size of the
1170 /// file is greater than or equal to `size`, this function has no
1171 /// effect. Also note that the contents of the newly grown portion of
1172 /// the file is undefined.
1173 static int growFile(
1174 FileDescriptor descriptor,
1175 Offset size,
1176 bool reserveFlag = false,
1177 bsl::size_t increment = k_DEFAULT_FILE_GROWTH_INCREMENT);
1178};
1179
1180 // ================================
1181 // class FilesystemUtil_CStringUtil
1182 // ================================
1183
1184/// This component-private utility `struct` provides a namespace for the
1185/// `flatten` overload set intended to be used in concert with an overload
1186/// set consisting of a function template with a deduced argument and an
1187/// non-template overload accepting a `const char *`. The actual
1188/// implementation of the functionality would be in the `const char *`
1189/// overload whereas the purpose of the function template is to invoke the
1190/// `const char *` overload with a null-terminated string.
1191///
1192/// The function template achieves null-termination by recursively calling
1193/// the function and supplying it with the result of `flatten` invoked on
1194/// the deduced argument. This `flatten` invocation will call `c_str()` on
1195/// various supported `string` types, will produce a temporary `bsl::string`
1196/// for possibly non-null-terminated `bsl::string_view` or `bslstl::StringRef`,
1197/// and will result in a `BSLMF_ASSERT` for any unsupported type. Calling the
1198/// function with the temporary `bsl::string` produced from `bsl::string_view`
1199/// or `bslstl::StringRef` will result in a second invocation of `flatten`,
1200/// this time producing `const char *`, and finally calling the function with a
1201/// null-terminated string.
1202///
1203///
1204/// \note Note that the `bslstl::StringRef` overload for `flatten` is provided for
1205/// backwards compatibility. Without it, the `bsl::string` and
1206/// `std::string` overloads would be ambiguous. In new code, it is
1207/// preferable to not provide `bslstl::StringRef` overload in a similar
1208/// facility and require the clients to explicitly state the string type in
1209/// their code, making a potential allocation obvious. The same considerations
1210/// apply to `bsl::string_view`.
1211///
1212/// See @ref bdls_filesystemutil
1214
1215 // CLASS METHODS
1216
1217 /// Return the specified `cString`.
1218 static const char *flatten(char *cString);
1219 static const char *flatten(const char *cString);
1220
1221 /// Return the result of invoking `c_str()` on the specified `string`.
1222 static const char *flatten(const bsl::string& string);
1223 static const char *flatten(const std::string& string);
1224#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR_STRING
1225 static const char *flatten(const std::pmr::string& string);
1226#endif
1227
1228 /// Return a temporary `bsl::string` constructed from the specified
1229 /// `stringView`.
1230 static bsl::string flatten(const bsl::string_view& stringView);
1231
1232 /// Return a temporary `bsl::string` constructed from the specified
1233 /// `stringRef`.
1234 static bsl::string flatten(const bslstl::StringRef& stringRef);
1235
1236 /// Produce a compile-time error informing the caller that the
1237 /// parameterized `TYPE` is not supported as the parameter for the call.
1238 template <class TYPE>
1239 static const char *flatten(const TYPE&);
1240};
1241
1242// ============================================================================
1243// INLINE DEFINITIONS
1244// ============================================================================
1245
1246 // --------------------
1247 // class FilesystemUtil
1248 // --------------------
1249
1250// CLASS METHODS
1251template <class STRING_TYPE>
1252inline
1253FilesystemUtil::FileDescriptor FilesystemUtil::open(
1254 const STRING_TYPE& path,
1255 FileOpenPolicy openPolicy,
1256 FileIOPolicy ioPolicy,
1257 FileTruncatePolicy truncatePolicy)
1258{
1260 openPolicy,
1261 ioPolicy,
1262 truncatePolicy);
1263}
1264
1265template <class STRING_TYPE>
1266inline
1272
1273template <class STRING_TYPE>
1274inline
1275bool FilesystemUtil::exists(const STRING_TYPE& path)
1276{
1278}
1279
1280template <class STRING_TYPE>
1281inline
1282bool FilesystemUtil::isRegularFile(const STRING_TYPE& path,
1283 bool followLinksFlag)
1284{
1286 FilesystemUtil_CStringUtil::flatten(path), followLinksFlag);
1287}
1288
1289template <class STRING_TYPE>
1290inline
1291bool FilesystemUtil::isDirectory(const STRING_TYPE& path,
1292 bool followLinksFlag)
1293{
1295 FilesystemUtil_CStringUtil::flatten(path), followLinksFlag);
1296}
1297
1298template <class STRING_TYPE>
1299inline
1300bool FilesystemUtil::isSymbolicLink(const STRING_TYPE& path)
1301{
1304}
1305
1306template <class STRING_TYPE>
1307inline
1309 const STRING_TYPE& path)
1310{
1313}
1314
1315template <class STRING_TYPE>
1316inline
1318 const STRING_TYPE& path,
1319 bool isLeafDirectoryFlag)
1320{
1322 FilesystemUtil_CStringUtil::flatten(path), isLeafDirectoryFlag);
1323}
1324
1325template <class STRING_TYPE>
1326inline
1332
1333template <class STRING_TYPE>
1334inline
1336 const STRING_TYPE& pattern,
1337 const bsl::function<void(const char *path)>& visitor)
1338{
1340 FilesystemUtil_CStringUtil::flatten(pattern), visitor);
1341}
1342
1343template <class STRING_TYPE>
1344inline
1346 const STRING_TYPE& pattern)
1347{
1349 result, FilesystemUtil_CStringUtil::flatten(pattern));
1350}
1351
1352template <class STRING_TYPE>
1353inline
1354int FilesystemUtil::findMatchingPaths(std::vector<std::string> *result,
1355 const STRING_TYPE& pattern)
1356{
1358 result, FilesystemUtil_CStringUtil::flatten(pattern));
1359}
1360
1361#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR_STRING
1362template <class STRING_TYPE>
1363inline
1365 std::pmr::vector<std::pmr::string> *result,
1366 const STRING_TYPE& pattern)
1367{
1369 result, FilesystemUtil_CStringUtil::flatten(pattern));
1370}
1371#endif
1372
1373template <class STRING_TYPE>
1374inline
1376 const STRING_TYPE& path)
1377{
1380}
1381
1382template <class STRING_TYPE>
1383inline
1384FilesystemUtil::Offset FilesystemUtil::getFileSize(const STRING_TYPE& path)
1385{
1388}
1389
1390template <class STRING_TYPE>
1391inline
1393 const STRING_TYPE& path)
1394{
1397}
1398
1399template <class STRING_TYPE>
1400inline
1402 const STRING_TYPE& path)
1403{
1406}
1407
1408#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR_STRING
1409template <class STRING_TYPE>
1410inline
1411int FilesystemUtil::getSymbolicLinkTarget(std::pmr::string *result,
1412 const STRING_TYPE& path)
1413{
1416}
1417#endif
1418
1419template <class STRING_TYPE>
1420inline
1421int FilesystemUtil::remove(const STRING_TYPE& path, bool recursiveFlag)
1422{
1424 recursiveFlag);
1425}
1426
1427template <class OLD_STRING_TYPE, class NEW_STRING_TYPE>
1428inline
1429int FilesystemUtil::move(const OLD_STRING_TYPE& oldPath,
1430 const NEW_STRING_TYPE& newPath)
1431{
1434}
1435
1436
1437
1438
1439 // --------------------------------
1440 // class FilesystemUtil_CStringUtil
1441 // --------------------------------
1442
1443// CLASS METHODS
1444inline
1445const char *FilesystemUtil_CStringUtil::flatten(char *cString)
1446{
1447 return cString;
1448}
1449
1450inline
1451const char *FilesystemUtil_CStringUtil::flatten(const char *cString)
1452{
1453 return cString;
1454}
1455
1456inline
1458{
1459 return string.c_str();
1460}
1461
1462inline
1463const char *FilesystemUtil_CStringUtil::flatten(const std::string& string)
1464{
1465 return string.c_str();
1466}
1467
1468#ifdef BSLS_LIBRARYFEATURES_HAS_CPP17_PMR_STRING
1469inline
1470const char *FilesystemUtil_CStringUtil::flatten(const std::pmr::string& string)
1471{
1472 return string.c_str();
1473}
1474#endif
1475
1476inline
1478 const bsl::string_view& stringView)
1479{
1480 bsl::string ret(stringView);
1481 return ret;
1482}
1483
1484inline
1486 const bslstl::StringRef& stringRef)
1487{
1488 return stringRef;
1489}
1490
1491template <class TYPE>
1492inline
1494{
1495 BSLMF_ASSERT(("Unsupported parameter type." && !sizeof(TYPE)));
1496 return 0;
1497}
1498
1499// FREE OPERATORS
1500
1501/// Output the specified `value` to the specified `stream`, in
1502/// human-readable form. If `value` is not a valid `Whence` value, report
1503/// that it is invalid and output it as an integer.
1504bsl::ostream& operator<<(bsl::ostream& stream, FilesystemUtil::Whence value);
1505
1506/// Output the specified `value` to the specified `stream`, in
1507/// human-readable form. If `value` is not a valid `ErrorType` value,
1508/// report that it is invalid and output it as an integer.
1509bsl::ostream& operator<<(bsl::ostream& stream,
1511
1512/// Output the specified `value` to the specified `stream`, in
1513/// human-readable form. If `value` is not a valid `FileOpenPolicy` value,
1514/// report that it is invalid and output it as an integer.
1515bsl::ostream& operator<<(bsl::ostream& stream,
1517
1518/// Output the specified `value` to the specified `stream`, in
1519/// human-readable form. If `value` is not a valid `FileIOPolicy` value,
1520/// report that it is invalid and output it as an integer.
1521bsl::ostream& operator<<(bsl::ostream& stream,
1523
1524/// Output the specified `value` to the specified `stream`, in
1525/// human-readable form. If `value` is not a valid `FileTruncatePolicy`
1526/// value, report that it is invalid and output it as an integer.
1527bsl::ostream& operator<<(bsl::ostream& stream,
1529
1530} // close package namespace
1531
1532
1533#endif
1534
1535// ----------------------------------------------------------------------------
1536// Copyright 2015 Bloomberg Finance L.P.
1537//
1538// Licensed under the Apache License, Version 2.0 (the "License");
1539// you may not use this file except in compliance with the License.
1540// You may obtain a copy of the License at
1541//
1542// http://www.apache.org/licenses/LICENSE-2.0
1543//
1544// Unless required by applicable law or agreed to in writing, software
1545// distributed under the License is distributed on an "AS IS" BASIS,
1546// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1547// See the License for the specific language governing permissions and
1548// limitations under the License.
1549// ----------------------------- END-OF-FILE ----------------------------------
1550
1551/** @} */
1552/** @} */
1553/** @} */
Definition bdlt_datetime.h:330
Definition bslstl_stringview.h:471
Definition bslstl_string.h:1252
Forward declaration.
Definition bslstl_function.h:946
Definition bslstl_vector.h:1120
Definition bslstl_stringref.h:374
#define BSLMF_ASSERT(expr)
Definition bslmf_assert.h:231
#define BSLS_IDENT(str)
BSLS_IDENT() - insert string into .comment binary segment (if supported)
Definition bsls_ident.h:238
Definition bdls_fdstreambuf.h:412
bsl::ostream & operator<<(bsl::ostream &stream, FilePermissions::Enum value)
Definition bdls_filesystemutil.h:1213
static const char * flatten(char *cString)
Return the specified cString.
Definition bdls_filesystemutil.h:1445
Definition bdls_filesystemutil.h:364
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:413
@ e_SEEK_FROM_END
Definition bdls_filesystemutil.h:416
@ e_SEEK_FROM_CURRENT
Definition bdls_filesystemutil.h:415
@ e_SEEK_FROM_BEGINNING
Definition bdls_filesystemutil.h:414
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:478
@ e_TRUNCATE
Definition bdls_filesystemutil.h:479
@ e_KEEP
Definition bdls_filesystemutil.h:480
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:424
@ k_BAD_FILE_DESCRIPTOR
Definition bdls_filesystemutil.h:445
@ k_ERROR_PATH_NOT_FOUND
Definition bdls_filesystemutil.h:436
@ k_ERROR_ALREADY_EXISTS
Definition bdls_filesystemutil.h:432
@ k_ERROR_PAST_EOF
Definition bdls_filesystemutil.h:442
@ k_ERROR_LOCKING_CONFLICT
Definition bdls_filesystemutil.h:425
@ k_ERROR_LOCKING_INTERRUPTED
Definition bdls_filesystemutil.h:428
FileOpenPolicy
Definition bdls_filesystemutil.h:451
@ e_CREATE_PRIVATE
Definition bdls_filesystemutil.h:457
@ e_CREATE
Definition bdls_filesystemutil.h:454
@ e_OPEN
Definition bdls_filesystemutil.h:452
@ e_OPEN_OR_CREATE
Definition bdls_filesystemutil.h:461
static Offset seek(FileDescriptor descriptor, Offset offset, int whence)
static Offset getFileSize(FileDescriptor descriptor)
FileIOPolicy
Definition bdls_filesystemutil.h:467
@ e_READ_ONLY
Definition bdls_filesystemutil.h:468
@ e_READ_WRITE
Definition bdls_filesystemutil.h:471
@ e_APPEND_ONLY
Definition bdls_filesystemutil.h:470
@ e_WRITE_ONLY
Definition bdls_filesystemutil.h:469
@ e_READ_APPEND
Definition bdls_filesystemutil.h:472
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)
@ k_DEFAULT_FILE_GROWTH_INCREMENT
Definition bdls_filesystemutil.h:420
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:484
static int getSymbolicLinkTarget(std::string *result, const char *path)
static int remove(const char *path, bool recursiveFlag=false)