diff --git a/annotations/yo/stl.yo b/annotations/yo/stl.yo index 61cc606b..e9357bd1 100644 --- a/annotations/yo/stl.yo +++ b/annotations/yo/stl.yo @@ -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) + + + diff --git a/annotations/yo/stl/filesystem/directoryentry.yo b/annotations/yo/stl/filesystem/directoryentry.yo index ed40b82b..827b901c 100644 --- a/annotations/yo/stl/filesystem/directoryentry.yo +++ b/annotations/yo/stl/filesystem/directoryentry.yo @@ -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. diff --git a/annotations/yo/stl/filesystem/directoryiterator.yo b/annotations/yo/stl/filesystem/directoryiterator.yo index 192339ab..dc9278e7 100644 --- a/annotations/yo/stl/filesystem/directoryiterator.yo +++ b/annotations/yo/stl/filesystem/directoryiterator.yo @@ -5,76 +5,123 @@ 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(); + } + } + ) diff --git a/annotations/yo/stl/filesystem/examples/filesystemerror.cc b/annotations/yo/stl/filesystem/examples/filesystemerror.cc index d2592fe0..abb5d28d 100644 --- a/annotations/yo/stl/filesystem/examples/filesystemerror.cc +++ b/annotations/yo/stl/filesystem/examples/filesystemerror.cc @@ -9,22 +9,26 @@ namespace fs = std::experimental::filesystem; using namespace std; - int main() try { - throw fs::filesystem_error{ "exception encountered", "p1", "p2", - make_error_code(errc::address_in_use) }; + 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() << ",\n" << + fse.path1() << ",\n" << + fse.path2() << ",\n" << + fse.code() << '\n'; + + throw; + } } -catch(fs::filesystem_error const &fse) +catch (exception const &ec) { - cerr << fse.what() << ", " << fse.path1() << ", " << - fse.path2() << ", " << fse.code() << '\n'; - - throw; // calls std::terminate -} -catch(...) -{ - cerr << "not reached...\n"; + cerr << ec.what() << '\n'; } //= diff --git a/annotations/yo/stl/filesystem/examples/statusknown.cc b/annotations/yo/stl/filesystem/examples/statusknown.cc index a14a0560..3a925cae 100644 --- a/annotations/yo/stl/filesystem/examples/statusknown.cc +++ b/annotations/yo/stl/filesystem/examples/statusknown.cc @@ -1,15 +1,54 @@ #include +#include #include // 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 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'; } +//= + + + + + + + + diff --git a/annotations/yo/stl/filesystem/filestatus.yo b/annotations/yo/stl/filesystem/filestatus.yo index 026e8292..81abd253 100644 --- a/annotations/yo/stl/filesystem/filestatus.yo +++ b/annotations/yo/stl/filesystem/filestatus.yo @@ -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,36 +40,50 @@ 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 - verb( - Symbol Value sys/stat.h Meaning + none 0000 No permission bits were set + + 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 + 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 + 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 + 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 + + 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. + ) - none 0000 No permission bits were set - - 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 - - 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 - - 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 - - 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) - - 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) diff --git a/annotations/yo/stl/filesystem/filesystemerror.yo b/annotations/yo/stl/filesystem/filesystemerror.yo index 90ad4d4c..7b4a1ca2 100644 --- a/annotations/yo/stl/filesystem/filesystemerror.yo +++ b/annotations/yo/stl/filesystem/filesystemerror.yo @@ -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) diff --git a/annotations/yo/stl/filesystem/intro.yo b/annotations/yo/stl/filesystem/intro.yo index d8833272..85d2dc40 100644 --- a/annotations/yo/stl/filesystem/intro.yo +++ b/annotations/yo/stl/filesystem/intro.yo @@ -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 @@ -9,14 +9,18 @@ bf(malloc)(3) and bf(free)(3). 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 + hi(Boost Filesystem) + 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. diff --git a/annotations/yo/stl/filesystem/path.yo b/annotations/yo/stl/filesystem/path.yo index 05c7c2fc..89305b5a 100644 --- a/annotations/yo/stl/filesystem/path.yo +++ b/annotations/yo/stl/filesystem/path.yo @@ -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.