wip completing coverage of std::exp.::filesystem

This commit is contained in:
Frank B. Brokken 2017-12-03 17:02:33 +01:00
parent dd099d8ba4
commit 5ab6047920
9 changed files with 292 additions and 140 deletions

View file

@ -201,15 +201,19 @@ includefile(stl/filesystem/intro)
subsect(Visiting directory entries: (recursive_)directory_iterator)
includefile(stl/filesystem/directoryiterator)
subsect(Types (file_type) and permissions (perms) of file system entries:
file_status)
lsubsect(FSSTATUS)(Types (file_type) and permissions (perms) of file
system entries: file_status)
includefile(stl/filesystem/filestatus)
COMMENT( TODO
subsect(Information about the space of a file system entries: space_info)
includefile(stl/filesystem/spaceinfo)
END)
lsubsect(FSFUNCTIONS)(Free functions)
includefile(stl/filesystem/functions)

View file

@ -1,6 +1,6 @@
Objects of the class ti(directory_entry) contain names and statuses of
directory entries. In addition to all default available constructors and
assignment operators it defines a constructor expecting a tt(path):
directory entries. In addition to all standard constructors and assignment
operators it defines a constructor expecting a tt(path):
verb(
directory_entry(path const &entry);
)
@ -10,20 +10,24 @@ assignment operators it defines a constructor expecting a tt(path):
itemization(
ithtq(assign)(void assign(path const &dest))
(the current path is replaced by tt(dest);)
ithtq(replace_filename)(void replace_filename(path const &dest))
(the last entry of the current path name (which may be empty if the
current name ends in a directory separator) is replaced by tt(dest);)
itht(path)(path const &path() const), hi(operator path const &())
tt(operator path const &() const):
quote(returns the current path name;)
ithtq(status)(file_status status([error_code &ec]))
(returns type and attributes of the current path name. If the current
path name refers to a symlink, and the symlink's type and status is
required, then use ti(symlink_status).)
required, then use ti(symlink_status) (see also section ref(FSSTATUS)).
)
In addition to the member functions tt(directory_entry) objects may be
compared using the free operators tt(==, !=, <, <=, >,) and tt(>=).
Also, tt(directory_entry) objects may be compared using the tt(==, !=, <, <=,
>,) and tt(>=) operators, returning the result of applying the operator to
their tt(path) objects.

View file

@ -5,77 +5,124 @@ tt(recursive_directory_iterator) are (input) iterators recursively visiting
all entries of directories.
The classes tt((recursive_)directory_iterator) support default, copy, and move
constructors. Both classes can be constructed from a tt(path) and an optional
tt(error_code) reference. E.g.,
constructors. Objects of both classes are constructed from a tt(path) and an
optional tt(error_code). E.g.,
verb(
directory_iterator(path const &dest [, error_code &ec]);
)
All members of standard input iterators (cf. section ref(ITERATORS)) are
supported by these classes. Their currently stored path is returned by their
dereference operators:
verb(
cout << *fs::directory_iterator{ "/home" } << '\n'; // shows the first
// entry under /home
)
End-iterators matching these objects are the classes' default constructed
objects. In addition, tt(filesystem::begin)hi(begin) and
tt(filesystem::end)hi(end) are available and are automatically used by
range-based for loops. E.g., all entries of the tt(/var/log) directory are
displayed (surrounded by double quotes) by the following statement:
verb(
for (auto &entry: fs:directory_iterator("/var/log"))
cout << entry << '\n';
)
Alternatively, for-statements explicitly defining iterators can also be
used. E.g.,
verb(
for (
auto iter = fs:directory_iterator("/var/log"),
end = fs::directory_iterator{};
iter != end;
++iter
)
cout << entry << '\n';
)
An tt(fs::(recursive_)directory_iterator base{"/var/log"}) object
represents the first element of its directory. Explicitly defined iterators
can be used, like tt(auto &iter = begin(base), auto iter = begin(base), auto
&iter = base) or tt(auto iter = base): they all refer to tt(base's) data, and
incrementing them data also advances tt(base) to its next element:
verb(
fs::recursive_directory_iterator base{ "/var/log/" };
auto iter = base;
// final two elements show identical paths,
// different from the first element.
cout << *iter << ' ' << *++iter << ' ' << *base << '\n';
)
The tt(recursive_directory_iterator) also accepts a tt(directory_options)
argument (see below), which by default is specified as
tt(directory_options::none):
argument (see below), by default specified as tt(directory_options::none):
verb(
recursive_directory_iterator(path const &dest,
directory_options options [, error_code &ec]);
)
All standard members of input iterators (cf. section ref(ITERATORS)) are
supported by these classes. In addition, tt(filesystem::begin)hi(begin) and
tt(filesystem::end)hi(end) are available and are automatically used by
range-based for loops. E.g., all entries of the tt(/var/log)
directory are displayed by the following statement:
verb(
for (auto &entry: fs:directory_iterator("/var/log"))
cout << entry << '\n';
)
The tt(recursive_directory_iterator)
In addition to the standard available members the class
tt(recursive_directory_iterator) provides the following members:
itemization(
ithtq(depth)(int depth() const)
(returns the current iteration depth. At the initial directory
(specified at construction-time) tt(depth) returns 0;)
ithtq(disable_recursion_pending)(void disable_recursion_pending())
(when called before calling the iterator's increment operator or
member, the next entry is not recursed into if it is a
sub-directory. Immediately after executing the increment operator
recursion is allowed again, so if recursion should end at a specific
depth then this function must repeatedly be called for as long as
tt(depth()) returns that specific depth;)
ithtq(increment)(recursive_directory_iterator &increment(error_code &ec))
( acts identically to the iterator's tt(operator++()). However, when an
error occurs tt(operator++) throws a tt(filesystem_error), while
tt(increment) assigns the appropriate error to tt(ec);)
ithtq(options)(directory_options options() const)
(returns the option that was specified at construction-time;)
ithtq(pop)(void pop())
(ends processing of the current directory, and continues at the next
entry in the current directory's parent or ends the directory
processing if called at the initial directory;)
ithtq(recursion_pending)(bool recursion_pending() const)
(tt(true) is returned if the entry the iterator currently points at is
a directory into which directory processing will continue at the
iterator's next increment;)
)
The tt(enum class directory_options)hi(directory_options) defines values that
can be used to fine-tune the behavior of a tt(recursive_directory_iterator)
object. The enumeration supports bitwise operators (the symbols' values are
shown between parentheses). Here is an overview of all its defined symbols:
can be used to fine-tune the behavior of tt(recursive_directory_iterator)
objects. It supports bitwise operators (the symbols' values are shown between
parentheses). Here is an overview of all its symbols:
itemization(
itt(none) (0): directory symlinks are skipped, denied permission to enter
a subdirectory generates an error;
itt(follow_directory_symlink) (1): symlinks to subdirectories are
followed;
itt(skip_permission_denied) (2): directories that cannot be entered are
skipped.
silently skipped.
)
In addition to the members of the class tt(directory_iterator) the class
tt(recursive_directory_iterator) provides these members:
itemization(
ithtq(depth)(int depth() const)
(returns the current iteration depth. At the initial directory
(specified at construction-time) tt(depth) returns 0;)
ithtq(disable_recursion_pending)(void disable_recursion_pending())
(when called before calling the iterator's increment operator or
member, the next entry is not recursed into if it is a
sub-directory. Immediately after executing the increment operator
recursion is allowed again, so if a recursion should end at a specific
depth then this function must repeatedly be called for as long as
tt(depth()) returns that specific depth;)
ithtq(increment)(recursive_directory_iterator &increment(error_code &ec))
( acts identically to the iterator's tt(operator++()). However, when an
error occurs tt(operator++) throws a tt(filesystem_error), while
tt(increment) assigns the appropriate error to tt(ec);)
ithtq(options)(directory_options options() const)
(returns the option that was specified at construction-time;)
ithtq(pop)(void pop())
(ends processing of the current directory, and continues at the next
entry in the current directory's parent or ends the directory
processing if called at the initial directory;)
ithtq(recursion_pending)(bool recursion_pending() const)
(tt(true) is returned if the entry the iterator currently points at is
a directory into which directory processing will continue at the
iterator's next increment;)
)
Finally, a little program displaying all directory elements of a directory and
all its immediate sub-directories:
verb(
int main()
{
fs::recursive_directory_iterator base{ "/var/log" };
for (auto entry = base, end = fs::end(base); entry != end; ++entry)
{
cout << entry.depth() << ": " << *entry << '\n';
if (entry.depth() == 1)
entry.disable_recursion_pending();
}
}
)

View file

@ -9,22 +9,26 @@
namespace fs = std::experimental::filesystem;
using namespace std;
int main()
try
{
try
{
throw fs::filesystem_error{ "exception encountered", "p1", "p2",
make_error_code(errc::address_in_use) };
}
catch(fs::filesystem_error const &fse)
{
cerr << fse.what() << ", " << fse.path1() << ", " <<
fse.path2() << ", " << fse.code() << '\n';
}
catch (fs::filesystem_error const &fse)
{
cerr << fse.what() << ",\n" <<
fse.path1() << ",\n" <<
fse.path2() << ",\n" <<
fse.code() << '\n';
throw; // calls std::terminate
throw;
}
}
catch(...)
catch (exception const &ec)
{
cerr << "not reached...\n";
cerr << ec.what() << '\n';
}
//=

View file

@ -1,15 +1,54 @@
#include <iostream>
#include <unordered_map>
#include <experimental/filesystem>
// explicitly link against stdc++fs:
//
// gx statusknown.cc -lstdc++fs
using namespace std;
namespace fs = std::experimental::filesystem;
using namespace std;
//demo
namespace
{
std::unordered_map<fs::file_type, char const *> map =
{
{ fs::file_type::not_found, "an unknown file" },
{ fs::file_type::none, "not yet or erroneously evaluated "
"file type" },
{ fs::file_type::regular, "a regular file" },
{ fs::file_type::directory, "a directory" },
{ fs::file_type::symlink, "a symbolic link" },
{ fs::file_type::block, "a block device" },
{ fs::file_type::character, "a character device" },
{ fs::file_type::fifo, "a named pipe" },
{ fs::file_type::socket, "a socket file" },
{ fs::file_type::unknown, "an unknown file type" }
};
void status(fs::path const &path)
{
fs::file_status stat = fs::directory_entry{ path }.symlink_status();
cout << path << " is " << map[stat.type()] << '\n';
};
} // anon. namespace
int main()
{
cerr << "File status_known is " <<
for (auto entry: fs::directory_iterator{"/home/frank"})
::status(entry);
cout << "File status_known is " <<
status_known( fs::file_status{} ) << '\n';
}
//=

View file

@ -1,4 +1,4 @@
Objects of the class ti(file_status) contain a file system entry's type and
Objects of the class ti(file_status) contain a file system entries' types and
permissions. The copy- and move- constructors and assignment operators
are available. In addition it defines the constructor
verb(
@ -12,6 +12,7 @@ members
newPerms)):
quote(the former member returns the current set of permissions,
the latter can be used to modify them;)
itht(type)(file_type type() const) and tt(void type(file_type type)):
quote(the former member returns the current type, the latter can be
used to change the type.)
@ -22,7 +23,7 @@ The tt(enum class file_type)hi(file_type) defines the following symbols:
itt(not_found = -1) indicates that the file was not found (this is not
considered an error);
itt(none) indicates that the file status has not been evaluated yet, or an
error occurred when evaluating itt;
error occurred when evaluating it;
itt(regular) a regular file;
itt(directory) a directory;
itt(symlink) a symbolic link;
@ -39,7 +40,6 @@ be more descriptive than the constants defined in the tthi(sys/stat.h) header
file, but other than that they have identical values. Also, all bitwise
operators can be used by values of the tt(enum class perms). Here is an
overview of all its defined symbols:
verb(
Symbol Value sys/stat.h Meaning
@ -47,28 +47,43 @@ overview of all its defined symbols:
owner_read 0400 S_IRUSR File owner has read permission
owner_write 0200 S_IWUSR File owner has write permission
owner_exec 0100 S_IXUSR File owner has execute/search permission
owner_all 0700 S_IRWXU File owner has read, write, and execute/search permissions
owner_exec 0100 S_IXUSR File owner has execute/search
permissions
owner_all 0700 S_IRWXU File owner has read, write, and
execute/search permissions
group_read 0040 S_IRGRP The file's group has read permission
group_write 0020 S_IWGRP The file's group has write permission
group_exec 0010 S_IXGRP The file's group has execute/search permission
group_all 0070 S_IRWXG The file's group has read, write, and execute/search permissions
group_exec 0010 S_IXGRP The file's group has execute/search
permissions
group_all 0070 S_IRWXG The file's group has read, write, and
execute/search permissions
others_read 0004 S_IROTH Other users have read permission
others_write 0002 S_IWOTH Other users have write permission
others_exec 0001 S_IXOTH Other users have execute/search permission
others_all 0007 S_IRWXO Other users have read, write, and execute/search permissions
others_exec 0001 S_IXOTH Other users have execute/search
permissions
others_all 0007 S_IRWXO Other users have read, write, and
execute/search permissions
all 0777 All users have read, write, and execute/search permissions
all 0777 All users have read, write, and
execute/search permissions
set_uid 04000 S_ISUID Set user ID to file owner user ID on execution
set_gid 02000 S_ISGID Set group ID to file's user group ID on execution
sticky_bit 01000 S_ISVTX POSIX XSI specifies that when set on a directory, only file owners
may delete files even if the directory is writeable to others
(used with /tmp)
set_uid 04000 S_ISUID Set user ID to file owner user ID on
execution
set_gid 02000 S_ISGID Set group ID to file's user group ID
on execution
sticky_bit 01000 S_ISVTX POSIX XSI specifies that when set on a
directory, only file owners
may delete files even if the
directory is writeable to
others (used with /tmp)
mask 07777 All valid permission bits.
)
Here is a little program showing how file statuses can be determined and
used:
verbinsert(-s4 //demo examples/statusknown.cc)

View file

@ -6,9 +6,10 @@ bracketed parameters are optional):
[path const &path1, [path const &path2,]]
error_code ec);
)
A a tt(filesystem_error) exception must be caught by its own type, or
tt(terminate) will be called, calling the tt(filesystem_error's what) member
before ending the program:
As tt(filesystem) facilities are closely related to standard system
functions, tt(errc) error code enumeration values can be used to obtain
tt(error_codes) to pass to tt(filesystem_error), as illustrated by the
following little demo-program:
verbinsert(-s4 //fse examples/filesystemerror.cc)

View file

@ -1,5 +1,5 @@
Several system calls are usually available wihin the context of the bf(C)
Several system calls are usually available in the context of the bf(C)
programming language. Such function (like bf(rename)(2), tt(truncate)(2),
bf(opendir)(2), and bf(realpath)(3)) are of course also available in bf(C++),
but their signatures and use are often less attractive, as they expect tt(char
@ -10,13 +10,17 @@ Wrappers around these functions have been available since 2003 in the
url(Boost library)
(http://www.boost.org/doc/libs/1_65_1/libs/filesystem/doc/index.htm)
hi(Boost Filesystem)
Currently, bf(C++) directly supports these facilities in the
Currently, bf(C++) directly supports these facilities in the
tt(std::experimental::filesystem)hi(experimental::filesystem)hi(filesystem)
namespace. To use the facilities in this namespace the
hi(experimental/filesystem) header file must be included. Although
currently defined under the tt(experimental) namespace, the facilities are all
available, and it's likely that in due time the `experimental' namespace will
be dropped for tt(filesystem).
namespace. To use these facilities the
hi(experimental/filesystem) header file must be included. In addition,
programs using facilities from the tt(experimental::filesystem) namespace must
be linked against the hi(stdc++fs library)tt(stdc++fs) library:
tt(-lstdc++fs).
Although tt(filesystem) currently is nested under the tt(experimental)
namespace, all facilities are available, and it's likely that in due time
`experimental' in front of tt(filesystem) will be dropped.
The tt(experimental/filesystem) namespace is extensive: it offers more than 10
different classes, and over 30 different free functions.

View file

@ -1,31 +1,31 @@
Objects of the class tt(fs::path)hi(path) handle names of file system
entries. The class tt(path) is a value-type of class: a default constructor
(empty path) and all standard copy/move
construction/assignment facilities are available. In addition, the following
constructors can be used:
Objects of the class tt(fs::path)hi(path (filesystem)) contain names of file
system entries. The class tt(path) is a value-type class: a default
constructor (empty path) as well as standard copy/move construction/assignment
facilities are available. In addition, the following constructors can be used:
itemization(
itt(path(string &&tmp))
itt(path(Type const &source))
itt(path(InputIter begin, InputIter end))
)
These constructors take character sequences (including NTBSs) in various
These constructors expect character sequences (including NTBSs) in various
forms as their arguments. Conceptually, these sequences consist of the
following elements (all optional)
itemization(
it() a root-name, e.g., a disk-name (like tt(E:)) or device indicator
(like tt(//nfs));
it() a root-directory, present if its the first directory separator
following the (optional) root-name;
it() a root-directory, present if it is the first character after
the (optional) root-name;
it() filename characters (not containing directory separators). In
addition the single dot filename represents the current directory and
two dots (tt(..)) represent the current directory's parent directory;
addition the `single dot filename' (tt(.)) represents the current
directory and the `double dot filename' (tt(..)) represents the
current directory's parent directory;
it() directory separators (by default the forward slash). Multiple
consecutive separators are treated like one separator.
)
The constructors also define a last tt(format ftmp = auto_format)
parameter, which probably almost never require a non-default specification
parameter, which probably almost never requires a non-default specification
(for this parameter, refer to url(cppreference)
(http://en.cppreference.com/w/cpp/experimental/fs/path).)
@ -35,27 +35,33 @@ Its modifying member functions are
tt(path &operator/=(Type const &arg)):
the arguments that can be passed to the constructors (including the
iterators) can also be passed to these members. Before adding the
argument the current and tt(arg's) contents are
separated by a directory separator (unless the resulting path would be
absolute if the source path is empty and the argument does not
represent an absolute path);
argument the current and tt(arg's) contents are separated by a
directory separator (unless the resulting path would be absolute if
the source path is empty and the argument does not represent an
absolute path);
itt(void clear()): the tt(path's) contents are erased;
itt(int compare(Type const &other)): returns the result of
lexicographically comparing the current path's contents with
tt(other). tt(Other) can be a tt(path), a string-type or a NTBS;
itt(path &concat(Type const &arg)) or
tt(path &operator+=(Type const &arg)):
similar to tt(append), but no directory separator will be used when
adding tt(arg's) contents to the current tt(path's) contents;
itt(path &remove_filename()):
removes the last component of the stored path. If only a root-directory
is stored, then the root directory is removed. Note that the last
directory separator is kept, unless it is the only path element;
itt(path &replace_extension(path const &replacement = path{} )):
replaces the extension of the last component of the stored path
(including the extension's dot) with tt(replacement). The extension is
removed if tt(replacement) is empty. If the tt(path) calling
tt(replace_extension) has no extension then tt(replacement) is added;
itt(path &replace_filename(path const &replacement)):
replaces the last component of the stored path with tt(replacement),
which itself may contain multiple path elements. If only a
@ -67,28 +73,56 @@ Its modifying member functions are
Accessors (no arguments, const members) return the path's contents as an NTBS
(tt(c_str)), as a string (tt(string, wstring, u8string, u16string, u32string))
(possibly prefixed by tt(gneric_), like tt(generic_string)) or as components
of path specifications, returned as tt(path).
of path specifications, returned as tt(path). Example:
verb(
fs::path path{ "/usr/local/bin" };
cout << path.string() << '\n'; // shows: /usr/local/bin
)
The tt(begin) and tt(end) iterators can be used to iterate over all of the
tt(path's) characters.
tt(Path) objects may be inserted into streams using the tt(<<) (stream
insertion) operator, in which case double quotes surround the displayed path
name. The double quotes are removed when accessing the path's contents as NTBS
or string, and also when assigning (or casting) it to a string.
tt(Path) objects may also be extracted from streams using the tt(>>) (stream
extraction) operator. In this case a path may optionally be surrounded by
double quotes. The extracted path again contains its surrounding quotes.
tt(Begin) and tt(end) iterators can be used to iterate over all of the
tt(path's) components: each component is returned as a tt(path), root names
and root directories are returned as initial components, followed by the
individual directory (and final filename) components. The directory separators
themselves are not returned when iterating over a tt(path's) components.
Decomposers, returning objects (empty if the requested component is not
present): tt(root_name, root_directory, root_path, relative_path, parent_path)
(i.e., the current contents from which the last element has been removed),
tt(filename, stem) (i.e., the filename without its dot-extension), and
tt(extension).
tt(extension). Example:
verb(
fs::path path{ "/usr/local/bin" };
cout << path.relative_path() << '\n'; // shows: "usr/local/bin"
// (note the double quotes)
)
When prefixed by tt(has_) the member returns a tt(bool) which is tt(true) if
the component is present. Also available: tt(is_absolute, is_relative)
In addition to the member functions several free operators are available:
In addition to the member functions various free operators are available:
tt(==, !=, <, <=, >,) and tt(>=) comparing two tt(path) objects; tt(/)
returning the contatenated tt(lhs) and tt(rhs); as well as the
tt(<<) (insertion) and tt(>>) (extraction) operators.
returning the contatenated tt(lhs) and tt(rhs). Comparisons use
lexicographical comparisons (as if by comparing the return values of their
tt(string) members).
To convert a tt(path) (which must refer to an existing directory entry) to its
canonical form (i.e., a path not containing . or .. components) the free
function tt(canonical) (cf. section ref(FSFUN)) can be used:
verb(
fs::path path{ "/usr/local/bin/../../share/man" };
cout << canonical(path) << '\n'; // shows: "/usr/share/man"
)
To convert a tt(path) to its canonical form (i.e., a path not containing . or
.. components) the function tt(canonical) (cf. section ref(FSFUN)) can be
used.