Files
filesystem/doc/operations.htm
Aleksey Gurtovoy 67b231daf6 c++boost.gif -> boost.png replacement
[SVN r25573]
2004-10-05 15:45:52 +00:00

643 lines
32 KiB
HTML
Raw Permalink Blame History

<html>
<head>
<meta http-equiv="Content-Language" content="en-us">
<meta name="GENERATOR" content="Microsoft FrontPage 5.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<title>Boost Filesystem operations.hpp Header</title>
</head>
<body bgcolor="#FFFFFF">
<h1>
<img border="0" src="../../../boost.png" align="center" width="277" height="86"><a href="../../../boost/filesystem/operations.hpp">boost/filesystem/operations.hpp</a></h1>
<p><a href="#Introduction">Introduction</a><br>
<a href="#Synopsis">Header synopsis</a><br>
<a href="#directory_iterator">Class directory_iterator</a><br>
&nbsp;&nbsp;&nbsp; <a href="#constructors">Constructors</a><br>
&nbsp;&nbsp;&nbsp; <a href="#destructor">Destructor</a><br>
&nbsp;&nbsp;&nbsp; <a href="#Other_functions">Other_functions</a><br>
<a href="#Non-member_functions">Operations functions</a><br>
&nbsp;&nbsp;&nbsp; <a href="#exists">exists</a><br>
&nbsp;&nbsp;&nbsp; <a href="#symbolic_link_exists">symbolic_link_exists</a><br>
&nbsp;&nbsp;&nbsp; <a href="#is_directory">is_directory</a><br>
&nbsp;&nbsp;&nbsp; <a href="#is_empty">is_empty</a><br>
&nbsp;&nbsp;&nbsp; <a href="#equivalent">equivalent</a><br>
&nbsp;&nbsp;&nbsp; <a href="#file_size">file_size</a><br>
&nbsp;&nbsp;&nbsp; <a href="#last_write_time">last_write_time</a><br>
&nbsp;&nbsp;&nbsp; <a href="#create_directory">create_directory</a><br>
&nbsp;&nbsp;&nbsp; <a href="#remove">remove</a><br>
&nbsp;&nbsp;&nbsp; <a href="#remove_all">remove_all</a><br>
&nbsp;&nbsp;&nbsp; <a href="#rename">rename</a><br>
&nbsp;&nbsp;&nbsp; <a href="#copy_file">copy_file</a><br>
&nbsp;&nbsp;&nbsp; <a href="#initial_path">initial_path</a><br>
&nbsp;&nbsp;&nbsp; <a href="#complete">complete</a><br>
&nbsp;&nbsp;&nbsp; <a href="#system_complete">system_complete</a></p>
<h2><a name="Introduction">Introduction</a></h2>
<p>The <a href="../../../boost/filesystem/operations.hpp">
boost/filesystem/operations.hpp</a> header provides operations on files and
directories.</p>
<p>These operations traffic in paths; see <a href="path.htm">
boost/filesystem/path.hpp documentation</a>.</p>
<p>For file I/O streams, see <a href="fstream.htm">boost/filesystem/fstream.hpp
documentation</a>.</p>
<p>The Filesystem Library's <a href="index.htm#Common_Specifications">Common
Specifications</a> apply to all member and non-member functions supplied by this
header. </p>
<h2>Header <a href="../../../boost/filesystem/operations.hpp">boost/filesystem/operations.hpp</a>
<a name="Synopsis">synopsis</a></h2>
<pre>namespace boost
{
namespace filesystem
{
class <a href="#Class directory_iterator">directory_iterator</a>
{
public:
typedef <a href="path.htm">path</a> value_type;
typedef std::ptrdiff_t difference_type;
typedef const path * pointer;
typedef const path &amp; reference;
typedef std::input_iterator_tag iterator_category;
<a href="#constructors">directory_iterator</a>();
explicit <a href="#constructors">directory_iterator</a>( const path &amp; directory_ph );
// <a href="#other functions">other functions</a>
// ...
};
bool <a href="#exists">exists</a>( const path &amp; ph );
bool <a href="#symbolic_link_exists">symbolic_link_exists</a>( const path &amp; ph );
bool <a href="#is_directory">is_directory</a>( const path &amp; ph );
bool <a href="#is_empty">is_empty</a>( const path &amp; ph );
bool <a href="#equivalent">equivalent</a>( const path &amp; ph1, const path &amp; ph2 );
boost::intmax_t <a href="#file_size">file_size</a>( const path &amp; ph );
std::time_t <a href="#last_write_time">last_write_time</a>( const path &amp; ph );
void <a href="#last_write_time">last_write_time</a>( const path &amp; ph, std::time_t new_time );
bool <a href="#create_directory">create_directory</a>( const path &amp; directory_ph );
bool <a href="#remove">remove</a>( const path &amp; ph );
unsigned long <a href="#remove_all">remove_all</a>( const path &amp; ph );
void <a href="#rename">rename</a>( const path &amp; from_path,
const path &amp; to_path );
void <a href="#copy_file">copy_file</a>( const path &amp; source_file,
const path &amp; target_file );
const path &amp; <a href="#initial_path">initial_path</a>();
path <a href="#current_path">current_path</a>();
path <a href="#complete">complete</a>( const path &amp; ph,
const path &amp; base = initial_path() );
path <a href="#system_complete">system_complete</a>( const path &amp; ph );
} // namespace filesystem
} // namespace boost
</pre>
<h2><a name="directory_iterator">Class directory_iterator</a></h2>
<p>Class <i>directory_iterator</i> provides a C++ standard conforming input
iterator which accesses the contents of a <a href="index.htm#directory">
directory</a>. </p>
<p>The value type is <i><a href="path.htm">boost::filesystem::path</a></i>, so
dereferencing a <i>directory_iterator</i> yields a <a href="index.htm#path">
path</a> to a file or sub-directory contained within the directory represented by
the directory-path argument supplied at construction. The path returned by
dereferencing a <i>directory_iterator</i> is composed by appending the name of
the directory entry to the directory path supplied at construction.</p>
<p>The order of the path entries returned by dereferencing successive increments
of a <i>directory_iterator</i> is unspecified. Thus depending on the ordering
provided by a particular implementation will result in non-portable code.</p>
<p>A path returned by dereferencing a <i>directory_iterator</i> is, if
representing a directory, suitable for use as an argument to Filesystem Library
functions specified as accepting paths or directory paths. If not representing a
directory, the dereferenced path is suitable for use as an argument to
Filesystem Library functions specified as accepting paths or file paths, or C++
Standard Library functions specified as taking file names. The leaf of a path
returned by dereferencing a <i>directory_iterator</i> will never be <code>&quot;..&quot;</code>
or <code>&quot;.&quot;</code>.</p>
<p><b>Note:</b> The implication of the above requirement is that if an operating
system's directories can contain entries which are not usable by Filesystem
Library or Standard Library functions, these entries will be skipped during
directory iteration. Such entries are by definition non-portable, but can always
be accessed via the native operating system API if required.</p>
<p><b><a name="symbolic-link-warning">Warning</a>:</b> Programs performing
directory iteration may wish to test, via <a href="#exists">exists()</a>, if the
path returned by dereferencing an iterator actually exists. It could be a
<a href="index.htm#symbolic-link">symbolic link</a> to a non-existent file or
directory. Programs recursively walking directory trees for purposes of removing
and renaming entries may wish to avoid following symbolic links, which can be
detected with <a href="#symbolic_link_exists">symbolic_link_exists()</a>.</p>
<p><b>Warning:</b> If a file or sub-directory is removed from or added to a
directory after the construction of a <i>directory_iterator</i> for the
directory, it is unspecified whether or not subsequent incrementing of the
iterator will ever result in an iterator whose value is the removed or added
directory entry.</p>
<h3><a name="constructors">Constructors</a></h3>
<blockquote>
<p><code>directory_iterator();</code></p>
<p><b>Effects:</b> Constructs a <i>directory_iterator</i> having the <i>
past-the-end</i> value as described in the C++ standard, section 24.1.</p>
<p><code>explicit directory_iterator( const path &amp; directory_ph );</code></p>
<p><b>Effects:</b> Constructs a <i>directory_iterator</i> with a value
representing the first path in <i>directory_ph</i>, or if <code>
empty(directory_ph)</code>, the <i>past-the-end</i> value.</p>
<p><b>Throws:</b> if <code>!exists( directory_ph )</code></p>
<p><b>Note:</b> To iterate over the current directory, write <code>
directory_iterator(current_path())</code> rather than <code>directory_iterator(&quot;&quot;)</code>.</p>
</blockquote>
<h3><a name="Other_functions">Other functions</a></h3>
<p>Class <i>directory_iterator</i> also supplies all the other functions
required by the C++ standard clause 24 for input iterators, such as <i>operator==</i>,
<i>operator++</i>, and <i>operator*</i>.</p>
<h2><a name="Non-member_functions">Non-member functions</a></h2>
<p>
The non-member functions provide common operations on files and directories.
They follow traditional practice of the C and C++ standard libraries, except
that
they:</p>
<ul>
<li>Traffic in <i><a href="path.htm">paths</a></i> rather than <code>char*</code>'s, for much
enhanced portability.</li>
<li>Report errors by throwing exceptions, for safer and better error handling.</li>
<li>Tighten specifications slightly, for improved portability.</li>
</ul>
<p>
<b>Rationale:</b> Functions which already exist in the C++ Standard Library,
such as <i><a href="#remove">remove()</a></i> and <i><a href="#rename">rename()</a></i>,
retain the same names and general behavior in the Filesystem Library, to
minimize surprises.</p>
<p>
<b><a name="not-precondition-rationale">Rationale</a>:</b> Some errors which might
at first glance appear to be preconditions are not
specified as such, but instead will throw exceptions. This is
because the possibility of <a href="index.htm#Race-condition">race-conditions</a>
makes it unreliable to test for preconditions before calling the function. As a
design practice, preconditions are not specified when it is not reasonable for a
program to test for them before calling the function. </p>
<p><b>Empty path r<a name="empty_rationale">ationale</a>:</b> Some errors,
particularly function arguments of empty paths, are specified both in <i>
Precondition</i> and in <i>Throws</i> paragraphs. A non-empty path is specified
as a precondition because an empty path is almost certainly an error, the error
meets the usual criteria for <i>Preconditions</i> as specified in the C++
Standard clause 17, and user pre-detection of the error does not suffer from the
<a href="#not-precondition-rationale">precondition race</a> problem described
above. The error condition is also specified in the <i>Throws</i> paragraph to
ensure that the error results in well-defined rather than implementation-defined
behavior, and because existing practice for the equivalent operating system
function is usually to treat an empty path as an error. The intended use of the
Filesystem Library in script-like programs makes undefined behavior particularly
unattractive.</p>
<p>
<b>Naming Rationale:</b> See class <i>path</i>
<a href="path.htm#Naming_Rationale">Naming Rationale</a>.</p>
<h3><a name="exists">exists</a></h3>
<blockquote>
<p><code>bool exists( const path &amp; ph );</code></p>
<p><b>Returns:</b> True if the operating system reports the path
represented by <i>ph</i> exists, else false.</p>
<p><b>Note: </b>Even if <code>exists( ph ) == true</code>, there is no guarantee that it
will be possible to perform other operations on the file or directory. Access
rights or other security concerns, for example, may cause other operations to
fail.</p>
<p><b>Note:</b> <code>exists(&quot;&quot;)</code> is valid and returns false;</p>
</blockquote>
<h3><a name="symbolic_link_exists">symbolic_link_exists</a></h3>
<blockquote>
<p><code>bool symbolic_link_exists( const path &amp; ph );</code></p>
<p><b>Returns:</b> True if the operating system reports the path represented by&nbsp;
<i>ph</i> is present and is a <a href="index.htm#symbolic-link">symbolic link</a>, else false.</p>
<p><b>Note:</b> See the <a href="#symbolic-link-warning">directory iterator
warning</a> for one use of <code>symbolic_link_exists()</code>.</p>
<p><b>Note:</b> The Microsoft Windows operating system does not currently
support symbolic links, so <code>symbolic_link_exists()</code> always returns
false on that platform. (Short-cut files (.lnk) are a Windows application
feature, not an O/S feature.) Programmers should still test for symbolic links
where applicable in case Windows adds the feature, and also so that programs
will be portable to systems like POSIX, where symbolic links may be present.</p>
<p><b>Rationale:</b> The function does not throw if <i>ph</i> is not present,
and is accordingly named <code>symbolic_link_exists</code> rather than <code>
is_symbolic_link</code>. Non-throwing behavior permits testing for all four
possible conditions:</p>
<ul>
<li><i>ph</i> not present: <code>!exists(ph) &amp;&amp; !symbolic_link_exists(ph)</code></li>
<li><i>ph</i> present and is not a symbolic link: <code>exists(ph) &amp;&amp; !symbolic_link_exists(ph)</code></li>
<li><i>ph</i> present and is a symbolic link to a non-existent file or
directory: <code>!exists(ph) &amp;&amp; symbolic_link_exists(ph)</code></li>
<li><i>ph</i> present and is a symbolic link to an existing file or
directory: <code>exists(ph) &amp;&amp; symbolic_link_exists(ph)</code></li>
</ul>
</blockquote>
<h3><a name="is_directory">is_directory</a></h3>
<blockquote>
<p><code>bool is_directory( const path &amp; ph );</code></p>
<p><b>Returns:</b> True if the operating system reports the path represented by&nbsp;
<i>ph</i> is a directory, else false.</p>
<p><b>Throws:</b> if <code>!exists(ph)</code></p>
<p><b>Rationale:</b> Treating <code>!exists(ph)</code> as an exception rather
than just returning false came about because in real code <code>!exists(ph)</code>
has
often been the first indicate of a programming error.&nbsp; A compound function returning <code>
exists(ph) &amp;&amp; is_directory(ph)</code> can always be added later.</p>
</blockquote>
<h3><a name="is_empty">is_empty</a></h3>
<blockquote>
<p><code>bool is_empty( const path &amp; ph );</code></p>
<p><b>Returns:</b> True if the operating system reports the path represented by&nbsp;
<i>ph</i> is an empty file or empty directory, else false.</p>
<p><b>Throws:</b> if <code>!exists(ph)</code></p>
<p>This function determines if the file or directory identified by the
contents of <i>ph</i> is empty. To determine if a path string itself is empty,
use the <i><a href="path.htm#empty">path::empty()</a></i> function.</p>
</blockquote>
<h3><a name="equivalent">equivalent</a></h3>
<blockquote>
<pre>bool equivalent( const path &amp; ph1, const path &amp; ph2 );</pre>
<p><b>Returns:</b> <code>false</code> if <code>!exists(ph1) || !exists(ph2)</code>.
Otherwise, returns <code>true</code> if ph1 and ph2 resolve to the same file
or directory, else <code>false</code>. The criteria used to determine sameness
are implementation defined:</p>
<blockquote>
<ul>
<li>POSIX: stat() reports identical st_dev, st_ino, st_size, and st_mtime
values. The POSIX implementation does not protect against
<a href="index.htm#Race-condition">race conditions</a>.<br>
&nbsp;</li>
<li>Windows: stat() reports identical st_dev values and
GetFileInformationByHandle() reports identical dwVolumeSerialNumber,
nFileIndexHigh, nFileIndexLow, nFileSizeHigh, and nFileSizeLow values.
Note that for identical media (particularly bit-for-bit duplicate CD's,
Floppies, or memory cards) on the same lettered drive of different network
shared systems, equivalent() will return <code>true</code> even though the
media are physically different. The Windows implementation does protect
against <a href="index.htm#Race-condition">race conditions</a>.</li>
</ul>
</blockquote>
<p><b>Throws:</b> if <code>!exists(ph1) &amp;&amp; !exists(ph2)</code></p>
<p><b>Warning:</b> This function may be impossible to implement on some
operating systems; users may wish to avoid use for code which may be ported to
operating systems with limited filesystem support.</p>
</blockquote>
<h3><a name="file_size">file_size</a></h3>
<blockquote>
<p><code>boost::intmax_t file_size( const path &amp; ph );</code></p>
<p><b>Returns:</b> The size of the file in bytes as reported by the operating
system.</p>
<p><b>Throws:</b> if <code>!exists(ph) || is_directory(ph)</code></p>
<p><b>Warming:</b> If a compiler does not support <code>maxint_t</code> large
enough to represent the operating system's maximum file size, or if the
implementation does not know how to query the operating system for large file
sizes, the returned value could be incorrect. This is not a problem with modern
compilers on modern versions of Linux or Windows. Users on other platforms
should build and run the <a href="../example/file_size.cpp">file_size.cpp</a>
sample program against a large file to verify correct operation.</p>
<p><b>Rationale:</b> Directories are excluded because the complexity of finding
the size of a file is typically constant, while finding the size of a directory
is typically linear. It was felt this would be surprising. The function is named
accordingly. Users needing the size of a directory can trivially provide a user
function which iterates over a directory returning a count.</p>
</blockquote>
<h3><a name="last_write_time">last_write_time</a></h3>
<blockquote>
<p><b>Warning:</b> The times associated with files are subject to many
vicissitudes. Each type of filesystem differs slightly in the details and
resolution of how times are recorded. The resolution is as low as one hour on
some filesystems. It is not uncommon for a program to
simultaneously have access to files maintained by FAT, ISO9660, NTFS, and POSIX
filesystems, and so experience different last_write_time behavior for different
files. During program execution, the system clock may be set to a new
value by some other, possibly automatic, process. Another thread or process may
write to a file, causing the last write time to change unexpectedly.</p>
<p><code>std::time_t last_write_time( const path &amp; ph );</code></p>
<p><b>Returns:</b> The time the file was last modified, as reported by the
operating system. If the time cannot be determined, returns (std::time_t)(-1).</p>
<p>To convert the returned value to UTC or local time, use <code>std::gmtime()</code>
or <code>std::localtime()</code> respectively.</p>
<p><b>Throws:</b> if <code>!exists(ph)</code></p>
<p><code>void last_write_time( const path &amp; ph, std::time_t new_time );</code></p>
<p><b>Effects:</b> Asks the operating system to set the last write time to <code>
new_time</code>, or to the current time if <code>new_time==std::time_t()</code>.</p>
<p><b>Throws:</b> if <code>!exists(ph)</code></p>
<p><b>Rationale:</b> <code>last_write_time(ph)==new_time</code> is not specified
as a postcondition because the times may differ somewhat on some operating
systems.</p>
</blockquote>
<h3><a name="create_directory">create_directory</a></h3>
<blockquote>
<p><code>bool create_directory( const path &amp; directory_ph );</code></p>
<p><b>Precondition:</b> <code>!directory_ph.empty()</code></p>
<p><b>Returns:</b> The value of <code>!exists( directory_ph )</code> prior to the
establishment of the postcondition.</p>
<p><b>Postcondition:</b> <code>exists(directory_ph) &amp;&amp;
is_directory(directory_ph)</code></p>
<p><b>Throws: </b>if <code>directory_ph.empty() || (exists(directory_ph) &amp;&amp; !is_directory(directory_ph)) || !exists(directory_ph/&quot;..&quot;)</code>.
See <a href="#empty_rationale">empty path rationale</a>.</p>
</blockquote>
<h3><a name="remove">remove</a></h3>
<blockquote>
<p><code>bool remove( const path &amp; ph );</code></p>
<p><b>Precondition:</b> <code>!ph.empty()</code></p>
<p><b>Returns:</b> The value of <code>exists( ph )</code> prior to the
establishment of the postcondition. </p>
<p><b>Postcondition:</b> <code>!exists( ph )</code></p>
<p><b>Throws:</b> if<code> ph.empty() || (exists(ph) &amp;&amp; is_directory(ph) &amp;&amp; !is_empty(ph))</code>.
See <a href="#empty_rationale">empty path rationale</a>.</p>
<p><b>Note:</b> <a href="index.htm#symbolic-link">Symbolic links</a> are
themselves deleted, rather than what they point to being deleted.</p>
<p><b>Rationale:</b> Does not throw when <code>!exists( ph )</code> because not
throwing:</p>
<ul>
<li>Works correctly if <code>ph</code> is a dangling symbolic link. </li>
<li>Is slightly easier-to-use for many common use cases.</li>
<li>Is slightly higher-level because it implies use of postcondition semantics
rather than effects semantics, which would be specified in the somewhat
lower-level terms of interactions with the operating system.</li>
</ul>
<p>There is, however, a slight decrease in safety because some errors will slip
by which otherwise would have been detected. For example, a misspelled path name
could go undetected for a long time.</p>
<p>The initial version of the library threw an exception when the path did not exist; it
was changed to reflect user complaints.</p>
</blockquote>
<h3><a name="remove_all">remove_all</a></h3>
<blockquote>
<p><code>unsigned long remove_all( const path &amp; ph );</code></p>
<p><b>Precondition:</b> <code>!ph.empty()</code></p>
<p><b>Postcondition:</b> <code>!exists( ph ) &amp;&amp; !symbolic_link_exists( ph )</code></p>
<p><b>Returns:</b> The number of files and directories removed.</p>
<p><b>Throws:</b> if<code> ph.empty()</code>. See <a href="#empty_rationale">
empty path rationale</a>.</p>
<p><b>Note:</b> <a href="index.htm#symbolic-link">Symbolic links</a> are
themselves deleted, rather than what they point to being deleted.</p>
</blockquote>
<h3><a name="rename">rename</a></h3>
<blockquote>
<p><code>void rename( const path &amp; source, const path &amp; target
);</code></p>
<p><b>Precondition:</b> <code>!source.empty() &amp;&amp; !target.empty()</code></p>
<p><b>Effects:</b> Changes the name of&nbsp; file or directory <i>source</i>
to <i>target</i>. Specifically:</p>
<table border="1" cellpadding="5">
<tr>
<td><b>Source</b></td>
<td><b>Target</b></td>
<td><b>Result is &quot;as if&quot; these actions occur</b></td>
</tr>
<tr>
<td>!exists()</td>
<td>&nbsp;</td>
<td>Throw <a href="exception.htm">filesystem_error</a>. Note that !exists()
covers the source.empty() case. [case 1] </td>
</tr>
<tr>
<td>&nbsp;</td>
<td>target.empty()</td>
<td>Throw <a href="exception.htm">filesystem_error</a>. See
<a href="#empty_rationale">create_directory() rationale</a>. [case 2] </td>
</tr>
<tr>
<td>&nbsp;</td>
<td>exists()</td>
<td>Throw <a href="exception.htm">filesystem_error</a>. [case 3] </td>
</tr>
<tr>
<td>!is_directory()</td>
<td>&nbsp;</td>
<td>If !exists( target / &quot;..&quot; ) throw <a href="exception.htm">
filesystem_error</a>. [case 4A] <br>
The source.leaf() name is changed to
target.leaf(). [case 4B] <br>
If source / &quot;..&quot; resolves to a different directory than
target / &quot;..&quot;, the renamed source file is moved there. [case 4C] </td>
</tr>
<tr>
<td>is_directory()</td>
<td>&nbsp;</td>
<td>If !exists( target / &quot;..&quot; ) throw <a href="exception.htm">
filesystem_error</a>. [case 5A]<br>
The source.leaf() name is changed to
target.leaf(). [case 5B] <br>
If system_complete(source.banch_path()) resolves to a
different directory than system_complete(target.branch_path()),&nbsp; the
renamed source directory is moved there. [case 5C] </td>
</tr>
</table>
<p><b>Postconditions:</b> <code>!exists(source) &amp;&amp; exists(target)</code>,
and the <i>source</i> file or directory contents and attributes are otherwise unchanged.</p>
<p><b>Throws:</b> See Effects table above. See <a href="#empty_rationale">empty
path rationale</a>.</p>
<p><b>Rationale:</b> Because <i>rename</i> is logically the same operation as <i>move</i>,
there is no need for a separate <i>move</i> function. The choice of the name is
based on existing practice in the C, C++, and POSIX libraries, and because the
name <i>move</i> implies physical file movement, which does not in fact occur.</p>
<p><b>Note:</b> Some operating systems with
<a href="index.htm#multi-root_filesystem">multiple roots</a> do not allow <i>rename</i>
operations between roots, and such an attempted <i>rename</i> with throw a <i>
<a href="exception.htm">filesystem_error</a></i> exception.. Implementations should not take heroic efforts, such
as switching to a copy mode, to make an otherwise failing <i>rename </i>succeed
across roots.</p>
<p><b>Note:</b> <a href="index.htm#symbolic-link">Symbolic links</a> are
themselves renamed, rather than what they point to being renamed.</p>
</blockquote>
<h3><a name="copy_file">copy_file</a></h3>
<blockquote>
<p><code>void copy_file( const path &amp; source_file, const path &amp;
target_file );</code></p>
<p><b>Precondition:</b> <code>!source.empty() &amp;&amp; !target.empty()</code></p>
<p><b>Effects:</b> Copies the file represented by <i>source_file</i> to <i>
target_file</i>.</p>
<p><b>Throws:</b> if <code>!exists(source_file) || is_directory(source_file)
|| exists(target_file) || target_file.empty() || !exists(to_file_path/&quot;..&quot;))</code>.
See <a href="#empty_rationale">empty path rationale</a>.</p>
<p><b>Note:</b> File attributes are also copied. Specifically, POSIX <i>
stat::st_mode</i>, and Windows <i>BY_HANDLE_FILE_INFORMATION::dwFileAttributes</i>. </p>
</blockquote>
<h3><a name="initial_path">initial_path</a></h3>
<blockquote>
<p><code>const path &amp; initial_path();</code></p>
<p><b>Effects:</b> The first time called, stores the path returned by
<a href="#current_path">current_path()</a>.</p>
<p>The preferred implementation would be to call <i>initial_path()</i> during program
initialization, before the call to <i>main()</i>. This is, however, not possible
with changing the C++ runtime library.</p>
<p><b>Returns:</b> A reference to the stored path.</p>
<p><b>Rationale:</b>&nbsp; The semantics, in effect, turn a dangerous global variable into
a safer global constant. The preferred implementation requires runtime library
support, so alternate semantics are supplied for those implementations which
cannot change an existing the runtime library.</p>
<p><b>Note:</b> It is good practice for a program dependent on <i>
initial_path()</i> to call it immediately upon entering<i> main()</i>. That
protects against another function altering the current working
directory (using a native platform function) before the first call to <i>
initial_path()</i>.</p>
</blockquote>
<h3><a name="current_path">current_path</a></h3>
<blockquote>
<pre>path current_path();</pre>
<p><b>Returns:</b> The current path as maintained by the operating system.</p>
<p><b>Postcondition:</b> <code>current_path().is_complete()</code></p>
<p><b>Note:</b> The equivalent POSIX function is <i>getcwd()</i>. The
equivalent Windows function is <i>GetCurrentDirectoryA()</i>.</p>
<p><b>Warning:</b> The current path maintained by the operating system is
in-effect a dangerous global variable. It may be changed unexpectedly by a
third-party or system library function, or by another thread. For a safer
alternative, see <a href="#initial_path">initial_path()</a>.</p>
<p><b>Rationale:</b> Although dangerous, the function is useful in dealing
with other libraries. The <i>current_path()</i> name was chosen to emphasize
that the function returns a complete path, not just a single directory name.</p>
</blockquote>
<h3><a name="complete">complete</a></h3>
<blockquote>
<p><code>path complete( const path &amp; ph, const path &amp; base = initial_path() );</code></p>
<p><b>Precondition:</b> <code>!ph.empty() &amp;&amp; base.is_complete() &amp;&amp; (ph.is_complete() || !ph.has_root_name())</code></p>
<p><b>Effects:</b> Composes a complete path from <code>ph</code> and <code>base</code>,
using the following rules:</p>
<p>For single-root operating systems (POSIX-like systems, for example), if <code>ph.empty()</code>
or <code>ph.is_complete()</code>, the composed path is <code>ph</code>,
otherwise the composed path is <code>base/ph</code>.</p>
<p>For <a href="index.htm#multi-root_filesystem">multi-root</a> operating systems (Windows, Classic Mac, many others), the rules are
give by this table:</p>
<table border="1" cellpadding="5">
<tr>
<td align="center">&nbsp;</td>
<td align="center"><code>ph.has_root_directory()</code></td>
<td align="center"><code>!ph.has_root_directory()</code></td>
</tr>
<tr>
<td align="center"><code>ph.has_root_name()</code></td>
<td align="center"><code>ph</code></td>
<td align="center"><code>(precondition failure)</code></td>
</tr>
<tr>
<td align="center"><code>!ph.has_root_name()</code></td>
<td align="center"><code>base.root_name()<br>
/ ph</code></td>
<td align="center"><code>base / ph</code></td>
</tr>
</table>
<p><b>Returns:</b> The composed path.</p>
<p><b>Postcondition:</b> For the returned path, <code>p,</code> <code>p.is_complete()</code>
is true.</p>
<p><b>Throws:</b> On precondition failure. See <a href="#empty_rationale">empty
path rationale</a>.</p>
<p><b><a name="complete_note">Note</a>:</b> When portable behavior is required,
use <i>complete()</i>. When operating system dependent behavior is required, use
<i>system_complete()</i>.</p>
<p>Portable behavior is preferred when dealing with paths created internally
within a program, particularly where the program should exhibit the same
behavior on all operating systems.</p>
<p>Operating system dependent behavior is preferred when dealing with paths
supplied by user input, reported to program users, or which should result in
program behavior familiar to and expected by program users. The
<a href="../example/simple_ls.cpp">simple_ls.cpp</a> program, for example,
operates on a path supplied in the native operating system format, so uses&nbsp;
<i>system_complete()</i> to ensure that the path behaves as expected for the
particular operating system.</p>
<p><b>Rationale:</b> The <code>!ph.has_root_name()</code> portion of the
precondition disallows the error condition of <code>ph.root_name()</code>
being not equivalent to <code>base.root_name()</code>. The restriction is
broader that would appear necessary, in that is also prohibits the case where
they are equivalent. There is, however,&nbsp; no portable way to express the
root_name() equivalence requirement.</p>
</blockquote>
<h3><a name="system_complete">system_complete</a></h3>
<blockquote>
<p><code>path system_complete( const path &amp; ph );</code></p>
<p><b>Precondition:</b> <code>!ph.empty()</code></p>
<p><b>Effects:</b> Composes a complete path from <code>ph</code>, using the same
rules used by the operating system to resolve a path passed as the filename
argument to standard library open functions.</p>
<p>For POSIX-like systems, system_complete( ph ) has the same semantics as <code>
complete( ph, current_path() )</code>.</p>
<p><a name="windows_effects">For Widows</a>, system_complete( ph ) has the same
semantics as <code>complete( ph, current_path() )</code> if ph.is_complete() ||
!ph.has_root_name() or ph and base have the same root_name().
Otherwise it acts like <code>complete( ph, kinky )</code>, where <code>kinky</code>
is the current directory for the <code>ph.root_name()</code> drive. This
will be the current directory of that drive the last time it was set, and thus
may well be <b>residue left over from some prior program</b> run by the command
processor! Although these semantics are often useful, they are also very
error-prone, and certainly deserve to be called &quot;kinky&quot;.</p>
<p><b>Returns:</b> The composed path.</p>
<p><b>Postcondition:</b> For the returned path, <code>p,</code> <code>p.is_complete()</code>
is true.</p>
<p><b>Throws:</b> If <code>ph.empty()</code>. See <a href="#empty_rationale">
empty path rationale</a>.</p>
<p><b>Note:</b> See <a href="#complete_note"><i>complete()</i> note</a> for
usage suggestions.</p>
<p><b>Warning:</b> This function relies on a global variable (current_path()),
and so tends to be more error-prone than the similar function
<a href="#complete">complete()</a>. This function is doubly dangerous on
Windows, where under cross-drive conditions it may be relying on a directory set
by a prior program run by the command processor.</p>
</blockquote>
<hr>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->21 March, 2004<!--webbot bot="Timestamp" endspan i-checksum="28864" --></p>
<p><EFBFBD> Copyright Beman Dawes, 2002</p>
<p> Use, modification, and distribution are subject to the Boost Software
License, Version 1.0. (See accompanying file <a href="../../../LICENSE_1_0.txt">
LICENSE_1_0.txt</a> or copy at <a href="http://www.boost.org/LICENSE_1_0.txt">
www.boost.org/LICENSE_1_0.txt</a>)</p>
</body>
</html>