final for review

[SVN r514]
This commit is contained in:
Beman Dawes
2002-09-13 17:05:43 +00:00
parent b2e7a74d1d
commit 2a2b06ad82
15 changed files with 379 additions and 230 deletions

View File

@@ -35,7 +35,7 @@ perform portable filesystem operations on directories and their contents. The
Filesystem Library was developed to fill that void.</p>
<p>The intent is not to compete with traditional scripting languages, but to
provide a solution for situations like Boost, where C++ is already the language
provide a solution for situations where C++ is already the language
of choice..</p>
<h2><a name="Requirements">Requirements</a></h2>
@@ -100,12 +100,23 @@ of choice..</p>
Libraries with elaborate interfaces and difficult to port specifications are much less likely to be accepted for
standardization.<br>
&nbsp;</li>
<li>The usual Boost requirements for any library also apply.<br>
<li>The usual Boost <a href="../../../more/lib_guide.htm">requirements and
guidelines</a> apply.<br>
&nbsp;</li>
<li>Encourage, but do not require, portability in path names.<br>
<br>
Rationale: For paths which originate from user input it is unreasonable to
require portable path syntax.<br>
&nbsp;</li>
<li>Avoid the illusion of portability where portability in fact does not
exist.</li>
<li>Avoid giving the illusion of portability where portability in fact does not
exist.<br>
<br>
Rationale: Defining important behavior unspecified or &quot;implementation defined&quot; does a
great disservice to programmers using a library because it makes it appear
that code relying on the behavior is portable, when in fact there is nothing
at all portable about it. The only case where such under-specification is acceptable is when both users and implementors know from
other sources exactly what behavior is required, yet for some reason it isn't
possible to specify it exactly.</li>
</ul>
<h2><a name="Realities">Realities</a></h2>
<ul>
@@ -122,10 +133,10 @@ of choice..</p>
<li>Some file systems (ISO-9660, level 1, for example) use very restricted
(so-called 8.3) file names.<br>
&nbsp;</li>
<li>Some file systems allow other file systems with completely different
<li>Some file systems allow other file systems with different
characteristics to be &quot;mounted&quot; within a directory tree.&nbsp; Thus a
ISO-9660 or Windows
file system may end up as a sub-tree of a Unix directory tree.<br>
file system may end up as a sub-tree of a POSIX directory tree.<br>
&nbsp;</li>
<li>Wide-character versions of directory and file operations are available on some operating
systems, and not available on others.<br>
@@ -137,12 +148,12 @@ of choice..</p>
number&quot;.&nbsp; Some don't.<br>
&nbsp;</li>
<li>Not all file systems use single character separators in path names.&nbsp; Some use
paired notations. A typical fully-specified VMS filename
paired notations. A typical fully-specified OpenVMS filename
might look something like this:<br>
<br>
<code>&nbsp;&nbsp; DISK$SCRATCH:[GEORGE.PROJECT1.DAT]BIG_DATA_FILE.NTP;5<br>
</code><br>
The general format is:<br>
The general OpenVMS format is:<br>
<br>
&nbsp;&nbsp;&nbsp;&nbsp;
<i>Device:[directories.dot.separated]filename.extension;version_number</i><br>
@@ -154,10 +165,10 @@ of choice..</p>
pathname itself, and not the platform. Determining collating sequence is even
worse.<br>
&nbsp;</li>
<li>Directory trees, directories, files, and file attributes are in effect shared between all threads, processes, and computers which have access to the
<li>Race-conditions may occur. Directory trees, directories, files, and file attributes are in effect shared between all threads, processes, and computers which have access to the
filesystem.&nbsp; That may well include computers on the other side of the
world or in orbit around the world. This implies that file system operations
may fail in unexpected ways.&nbsp; For example:<br>
may fail in unexpected ways.&nbsp;For example:<br>
<br>
<code>&nbsp;&nbsp;&nbsp;&nbsp; assert( exists(&quot;foo&quot;) == exists(&quot;foo&quot;) );
// may fail!<br>
@@ -169,7 +180,7 @@ of choice..</p>
replaced by a directory of the same name between the calls to is_directory().<br>
&nbsp;</li>
<li>Even though an application may be portable, it still will have to traffic
in system specific paths occasionally; operated provided input is a common
in system specific paths occasionally; user provided input is a common
example.</li>
</ul>
@@ -203,6 +214,11 @@ answers to that question, the Filesystem Library alerts programmers of the need
to ask it in the first place.</p>
<h2><a name="Abandoned Designs">Abandoned Designs</a></h2>
<h3>operations.hpp</h3>
<p>Dietmar Kühl's original dir_it design and implementation supported
wide-character file and directory names. It was abandoned after extensive
discussions among Library Working Group members failed to identify portable
semantics for wide-character names on systems not providing native support. See
<a href="faq.htm#wide-character names">FAQ</a>.</p>
<p>Previous iterations of the interface design used explicitly named functions providing a
large number of convenience operations, with no compile-time or run-time
options. There were so many function names that they were very confusing to use,
@@ -268,7 +284,7 @@ Variable Considered Harmful</i>, ACM SIGPLAN Notices, 8, 2, 1973, pp. 23-34</p>
<hr>
<p>© Copyright Beman Dawes, 2002</p>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->30 July, 2002<!--webbot bot="Timestamp" endspan i-checksum="21079" --></p>
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->13 September, 2002<!--webbot bot="Timestamp" endspan i-checksum="39336" --></p>
</body>

View File

@@ -5,7 +5,8 @@ Do-list</h1>
<ul>
<li>Finish the probe program, and ask Boost people to run it on various O/S's.<br>
&nbsp;</li>
<li>Finish portability guide.<br>
<li>Finish portability guide and checking functions. Get opinions on default, Boost, and other error checks.&nbsp; POSIX?&nbsp;
Windows? Mac?&nbsp; ISO 6990?<br>
&nbsp;</li>
<li>Cyclic paths:</li>
</ul>
@@ -17,9 +18,6 @@ Do-list</h1>
</ul>
</blockquote>
<ul>
<li>Get opinions on default, Boost, and other error checks.&nbsp; POSIX?&nbsp;
Windows?&nbsp; ISO 6990?<br>
&nbsp;</li>
<li>As a lexical concept, parent-directory is portable unless it escapes to
the operating system. But do all operating recognize such a concept in a path?&nbsp;
I doubt it.&nbsp; Maybe there should be a checking function that verifies that
@@ -30,4 +28,4 @@ Do-list</h1>
<hr>
<p>© Copyright Beman Dawes, 2002</p>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->30 July, 2002<!--webbot bot="Timestamp" endspan i-checksum="21079" --></p>
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->13 September, 2002<!--webbot bot="Timestamp" endspan i-checksum="39336" --></p>

View File

@@ -14,7 +14,7 @@ operations&quot; requirement of the Filesystem Library, full URI's appear to be
</b>POSIX is the basis for the most familiar path-string formats, including the
URL portion of URI's and the native Windows format. It is ubiquitous and
familiar.&nbsp; On many systems, it is very easy to implement because it is
either the native operating system format (Unixes and Windows) or via a
either the native operating system format (Unix and Windows) or via a
operating system supplied
POSIX library (z/OS, OS/390, and many more.)</p>
<p><b>Why isn't <i>path</i> a base class with derived <i>directory_path</i> and
@@ -110,8 +110,7 @@ notification variable?</b></p>
by programmers.&nbsp; Exceptions are much harder to ignore, provided desired
default behavior (program termination) if not caught, yet allow error recovery
if desired.</p>
<p><b>Why are attributes accessed via named functions rather than
<a href="../../property_map/property_map.html">property maps</a>?</b></p>
<p><b>Why are attributes accessed via named functions rather than property maps?</b></p>
<p>For a few commonly used attributes (existence, directory or file, emptiness),
simple syntax and guaranteed presence outweigh other considerations. Because
access to virtually all other attributes is inherently system dependent,
@@ -126,7 +125,7 @@ about to hand them the gun.</p>
<p><b>Why aren't there query functions for compound conditions like existing_directory?</b></p>
<p>After several attempts, named queries for multi-attribute proved a
slippery-slope; where do you stop?</p>
<p><b>Why aren't wide-character names supported? Why not std::wstring or even
<p><b>Why aren't <a name="wide-character names">wide-character names</a> supported? Why not std::wstring or even
a templated type?</b></p>
<p>Wide-character names would provide an illusion of portability where
portability does not in fact exist. Behavior would be completely different on
@@ -176,4 +175,4 @@ paths:</p>
<hr>
<p>© Copyright Beman Dawes, 2002</p>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->22 July, 2002<!--webbot bot="Timestamp" endspan i-checksum="21082" --></p>
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->12 September, 2002<!--webbot bot="Timestamp" endspan i-checksum="39334" --></p>

View File

@@ -19,21 +19,88 @@
pass arguments representing file names, with that usage occurring in seven
times.</p>
<p>The Filesystem Library's <i>fstream.hpp</i> header provides, in namespace <i>
boost::filesystem</i>, equivalent components, except that the seven&nbsp; <i>
<p>The Filesystem Library's <i>fstream.hpp</i> header provides equivalent
components, in namespace <i>
boost::filesystem</i>, except that the seven&nbsp; <i>
const char*</i> arguments have been replaced by <i>const path&amp;</i> arguments.</p>
<p>The implementation simply uses the <i>&lt;fstream&gt;</i> standard library
components as base classes, and then overrides the members with changed argument
types.</p>
<p>The Filesystem Library's <i>fstream.hpp</i> header simply uses the <i>&lt;fstream&gt;</i> standard library
components as base classes, and then overrides the members requiring argument
types of <i>path</i>.</p>
<p>For the moment, the only other documentation beyond the
<p>For documentation beyond the synopsis, see the
<a href="index.htm#tutorial">tutorial</a> and <a href="index.htm#Examples">
examples</a> is the header itself.&nbsp; See <a href="../../../boost/filesystem/fstream.hpp">boost/filesystem/fstream.hpp</a>.</p>
examples</a>.</p>
<h2><a name="Synopsis">Synopsis</a></h2>
<pre>namespace boost
{
namespace filesystem
{
template &lt; class charT, class traits = std::char_traits&lt;charT&gt; &gt;
class basic_filebuf : public std::basic_filebuf&lt;charT,traits&gt;
{
public:
virtual ~basic_filebuf() {}
std::basic_filebuf&lt;charT,traits&gt; * open( const path &amp; file_ph,
std::ios_base::openmode mode );
};
typedef basic_filebuf&lt;char&gt; filebuf;
typedef basic_filebuf&lt;wchar_t&gt; wfilebuf;
template &lt; class charT, class traits = std::char_traits&lt;charT&gt; &gt;
class basic_ifstream : public std::basic_ifstream&lt;charT,traits&gt;
{
public:
basic_ifstream() {}
explicit basic_ifstream( const path &amp; file_ph,
std::ios_base::openmode mode = std::ios_base::in );
virtual ~basic_ifstream() {}
void open( const path &amp; file_ph,
std::ios_base::openmode mode = std::ios_base::in );
};
typedef basic_ifstream&lt;char&gt; ifstream;
typedef basic_ifstream&lt;wchar_t&gt; wifstream;
template &lt; class charT, class traits = std::char_traits&lt;charT&gt; &gt;
class basic_ofstream : public std::basic_ofstream&lt;charT,traits&gt;
{
public:
basic_ofstream() {}
explicit basic_ofstream( const path &amp; file_ph,
std::ios_base::openmode mode = std::ios_base::out );
virtual ~basic_ofstream() {}
void open( const path &amp; file_ph,
std::ios_base::openmode mode = std::ios_base::out );
};
typedef basic_ofstream&lt;char&gt; ofstream;
typedef basic_ofstream&lt;wchar_t&gt; wofstream;
template &lt; class charT, class traits = std::char_traits&lt;charT&gt; &gt;
class basic_fstream : public std::basic_fstream&lt;charT,traits&gt;
{
public:
basic_fstream() {}
explicit basic_fstream( const path &amp; file_ph,
std::ios_base::openmode mode = std::ios_base::in|std::ios_base::out );
virtual ~basic_fstream() {}
void open( const path &amp; file_ph,
std::ios_base::openmode mode = std::ios_base::in|std::ios_base::out );
};
typedef basic_fstream&lt;char&gt; fstream;
typedef basic_fstream&lt;wchar_t&gt; wfstream;
} // namespace filesystem
} // namespace boost
</pre>
<hr>
<p>© Copyright Beman Dawes, 2002</p>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->11 July, 2002<!--webbot bot="Timestamp" endspan i-checksum="21079" --></p>
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->12 September, 2002<!--webbot bot="Timestamp" endspan i-checksum="39334" --></p>
</body>

View File

@@ -23,7 +23,7 @@ Filesystem Library</h1>
<a href="#Definitions">Definitions</a><br>
&nbsp;&nbsp;&nbsp;
<a href="#Requirements">Requirements</a><br>
&nbsp;&nbsp;&nbsp; <a href="#Dangers">Dangers</a><br>
&nbsp;&nbsp;&nbsp; <a href="#Race-condition">Race-condition danger</a><br>
&nbsp;&nbsp;&nbsp; <a href="#Acknowledgements">Acknowledgements</a></td>
<td width="50%"><font size="4">Other Documents</font><br>
&nbsp;&nbsp;&nbsp; <a href="design.htm">Library Design</a><br>
@@ -45,7 +45,8 @@ compete with Python, Perl, or shell languages, but rather to provide portable fi
operations when C++ is already the language of choice. The <a href="design.htm">
design</a> encourages, but does not require, safe and portable filesystem usage.</p>
<p>Filesystem Library components are supplied by four headers:</p>
<p>Filesystem Library components are supplied by several&nbsp; headers, all in
directory boost/filesystem:</p>
<ul>
<li>Header <i>path.hpp</i> provides class <i>path, </i>a portable mechanism for representing
@@ -62,12 +63,18 @@ design</a> encourages, but does not require, safe and portable filesystem usage.
See <a href="fstream.htm">fstream.hpp documentation</a>.<br>
&nbsp;</li>
<li>Header <i>exception.hpp</i> provides class <i>filesystem_error</i>. See
<a href="exception.htm">exception.hpp documentation</a>.</li>
<a href="exception.htm">exception.hpp documentation</a>.<br>
&nbsp;</li>
<li>Experimental header <i>
<a href="../../../boost/filesystem/recursive_directory_iterator.hpp">
recursive_directory_iterator.hpp</a></i> provides an undocumented directory
iterator which recurses into any sub-directories encountered. It will be
incorporated into the Filesystem Library if user feedback is favorable.</li>
</ul>
<h2>Two-minute <a name="tutorial">tutorial</a></h2>
<p>After some preliminaries:</p>
<p>First some preliminaries:</p>
<blockquote>
<pre>#include &quot;boost/filesystem/operations.hpp&quot; // also includes path.hpp
<pre>#include &quot;boost/filesystem/operations.hpp&quot; // includes boost/filesystem/path.hpp
#include &quot;boost/filesystem/fstream.hpp&quot; // ditto
#include &lt;iostream&gt; // for cout
namespace fs = boost::filesystem;</pre>
@@ -80,7 +87,7 @@ namespace fs = boost::filesystem;</pre>
<a href="path.htm#Grammar">portable generic path format</a>. Access functions
make <i>my_path</i> contents available in an operating system dependent format,
such as <code>&quot;some_dir:file.txt&quot;</code>, <code>&quot;[some_dir]file.txt&quot;</code>,
<code>&quot;some_dir/file.txt&quot;</code>, or whatever is appropriate for the current
<code>&quot;some_dir/file.txt&quot;</code>, or whatever is appropriate for the
operating system.</p>
<p>Class <i>path</i> has conversion constructors from <i>const char*</i> and <i>
const std:: string&amp;</i>, so that even though the Filesystem Library functions in
@@ -173,7 +180,9 @@ hierarchy viewed as an acyclic graph.</p>
<p><b><a name="path">path</a> </b>- A possibly empty sequence of names. Each
element in the sequence, except the last, names a <a href="#directory">directory</a>
which contains the
next element. The last element may name either a directory or file.</p>
next element. The last element may name either a directory or file. The first
element is closest to the root of the directory tree, the last element is
farthest from the root.</p>
<p>It is traditional to represent a path as a string, where each element in the
path is represented by a <a href="#name">name</a>, and some operating system
defined syntax distinguishes between the name elements. Other representations of
@@ -194,11 +203,11 @@ implementation cannot successfully complete operations required to meet the
function's specifications. Such exceptions are in addition to any exceptions
specified in the function's &quot;Throws&quot; paragraph.</p>
<p>Filesystem Library functions are permitted to call C++ Standard Library
functions, so, <i>std::bad_alloc</i> exceptions may also be thrown, unless
functions, so <i>std::bad_alloc</i> exceptions may also be thrown, unless
otherwise specified.</p>
<p>There is no rollback guarantee; a Filesystem Library function which throws an
exception may leave the external file system in an altered the state.</p>
<h2><a name="Dangers">Dangers</a></h2>
exception may leave the external file system in an altered state.</p>
<h2><a name="Race-condition">Race-condition</a> d<a name="Dangers">anger</a></h2>
<p>The state of files and directories is often
globally shared, and thus may be changed unexpectedly by other threads,
processes, or even other computers which have access to the filesystem. As an
@@ -229,7 +238,7 @@ or directory resources should be prepared for <i>filesystem_error</i> exceptions
to be thrown from any filesystem function except those explicitly specified as
not throwing exceptions.</p>
<h2><a name="Implementation">Implementation</a></h2>
<p>The current implementation (July, 2002) supports operating systems that have
<p>The current implementation (September, 2002) supports operating systems that have
either the POSIX or Windows API's available.</p>
<p>The following tests are provided:</p>
<ul>
@@ -237,19 +246,17 @@ either the POSIX or Windows API's available.</p>
<li><a href="../test/operations_test.cpp">operations_test.cpp</a></li>
<li><a href="../test/fstream_test.cpp">fstream_test.cpp</a></li>
</ul>
<p>As of July, 2002, these tests succeed for the following compilers on Windows:</p>
<p>As of September, 2002, these tests succeed for the following compilers on Windows:</p>
<ul>
<li>Borland 5.5.1</li>
<li>GCC 3.1 (excluding wide-character fstream tests)</li>
<li>GCC 3.1 (using POSIX implementation, but excluding wide-character fstream tests)</li>
<li>Intel 6.0</li>
<li>Metrowerks 8.1</li>
<li>Metrowerks 8.2</li>
<li>Microsoft 7.0</li>
<li>Microsoft 6.0 except fstream_test failed.</li>
</ul>
<p>As of July, 2002, these tests failed for the following compilers on Windows:</p>
<ul>
<li>Microsoft 6.0 fstream_test</li>
</ul>
<p>As of September, 2002, some limited use has been successful on Linux using
GCC and IBM/AIX using Visual Age C++.</p>
<h2><a name="Acknowledgements">Acknowledgements</a></h2>
<p>The Filesystem Library was designed and implemented by Beman Dawes, except
for the <i>directory_iterator</i> and <i>filesystem_error</i> classes which were
@@ -263,7 +270,7 @@ Salters, Jani Kajala, Jason Stewart, Carl Daniel, David Abrahams, Bill Kempf,
Jonathan Caves, George Heintzelman, Ken Hagen, Eric Jensen, Joel de Guzman, Jim
Hyslop, John Maddock, Matt Austern, Peter Dimov, Davlet Panech, Dylan Nicholson, Tom Harris,
Giovanni Bajo, Baptiste Lepilleur, Thomas Witt, Keith Burton, Mattias Flodin,
Daniel Frey, Vladimir Prus.</p>
Daniel Frey, Vladimir Prus, Toon Knapen.</p>
<p>Specific improvements for a preliminary design document came from Dan Nuffer and Jeff
Garland.</p>
@@ -274,7 +281,7 @@ of portability&quot; problem, particularly in postings by JP Plauger and Pete Be
<hr>
<p>© Copyright Beman Dawes, 2002</p>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->09 August, 2002<!--webbot bot="Timestamp" endspan i-checksum="34422" --></p>
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->13 September, 2002<!--webbot bot="Timestamp" endspan i-checksum="39336" --></p>
</body>

View File

@@ -44,7 +44,7 @@ documentation</a>.</p>
<p>As with all Filesystem Library components, errors may result in <i>
<a href="exception.htm">filesystem_error</a></i> or <i>std::bad_alloc</i>
exceptions being thrown. See <a href="reference.htm#Requirements">Requirements</a>.</p>
exceptions being thrown. See <a href="index.htm#Requirements">Requirements</a>.</p>
<h2>Header <a href="../../../boost/filesystem/operations.hpp">boost/filesystem/operations.hpp</a>
<a name="Synopsis">synopsis</a></h2>
@@ -58,15 +58,13 @@ exceptions being thrown. See <a href="reference.htm#Requirements">Requirements</
public:
typedef <a href="path.htm">path</a> value_type;
typedef std::ptrdiff_t difference_type;
typedef path * pointer;
typedef path &amp; reference;
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="#destructor">~directory_iterator</a>();
// <a href="#other functions">other functions</a>
// ...
};
@@ -99,7 +97,7 @@ directory</a>. </p>
dereferencing a <i>directory_iterator</i> yields a <a href="reference.htm#path">
path</a> to a file or directory contained within the directory represented by
the directory-path argument supplied at construction. The path returned by
dereferencing a a <i>directory_iterator</i> is composed by appending the name of
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>A path returned by dereferencing a <i>directory_iterator</i> is, if
@@ -111,7 +109,7 @@ 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 a operating
<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
@@ -132,20 +130,6 @@ representing the first path in <i>directory_ph</i>, or if <code>
empty(directory_ph)</code>, the <i>past-the-end</i> value.</p>
</blockquote>
<h3><a name="destructor">Destructor</a></h3>
<blockquote>
<p><code>~directory_iterator();</code></p>
<p>If <code>*this == directory_iterator()</code>, the destructor may possibly
throw an exception. Otherwise, the iterator has the&nbsp; <i>past-the-end</i>
value, and the destructor is guaranteed to never throw an exception.</p>
<p><b>Effects:</b> Destroys *this</p>
</blockquote>
<h3><a name="other functions">Other functions</a></h3>
<p>Class <i>directory_iterator</i> also supplies all the other functions
@@ -157,10 +141,11 @@ required by the C++ standard clause 24 for input iterators, such as <i>operator=
<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>paths</i> rather than <code>char*</code>'s, for much
<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>
@@ -172,6 +157,16 @@ such as <i><a href="#remove">remove()</a></i> and <i><a href="#rename">rename()<
retain the same names and general behavior in the Filesystem Library, to
minimize surprises.</p>
<p>
<b>Rationale:</b> Errors which might appear to be preconditions are not
specified as such, but instead are specified to 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 should always be testable by a program, so that
violations can be avoided. It is not always possible or desirable to abstract
away the fact that the library is implemented by calls to the operating system,
and this is one of those cases.</p>
<p>
<b>Naming Rationale:</b> See class <i>path</i>
<a href="path.htm#Naming Rationale">Naming Rationale</a>.</p>
@@ -207,7 +202,7 @@ exists(ph) &amp;&amp; is_directory(ph)</code> can always be added later.</p>
</blockquote>
<h3><a name="create_directory">create_directory</a></h3>
<blockquote>
<p><code>void create_directory( const path &amp; &amp; directory_ph );</code></p>
<p><code>void create_directory( const path &amp; directory_ph );</code></p>
<p><b>Postcondition:</b> <code>exists(directory_ph) &amp;&amp;
is_directory(directory_ph) &amp;&amp; is_empty(directory_ph)</code></p>
<p><b>Throws: </b>if <code>exists(directory_ph)) || !exists(branch(directory_ph))</code></p>
@@ -216,7 +211,20 @@ is_directory(directory_ph) &amp;&amp; is_empty(directory_ph)</code></p>
<blockquote>
<p><code>void remove( const path &amp; ph );</code></p>
<p><b>Postcondition:</b> <code>!exists( ph )</code></p>
<p><b>Throws:</b> if <code>!exists(ph) || (is_directory(ph) &amp;&amp; !is_empty(ph))</code></p>
<p><b>Throws:</b><code> exists(ph) &amp;&amp; is_directory(ph) &amp;&amp; !is_empty(ph)</code></p>
<p><b>Rationale:</b> Does not throw when <code>!exists( ph )</code> because not
throwing is:</p>
<ul>
<li>Slightly easier-to-use for many common use cases.</li>
<li>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 did throw when the path did not exist; it
was changed only reluctantly.</p>
</blockquote>
<h3><a name="remove_all">remove_all</a></h3>
<blockquote>
@@ -238,7 +246,7 @@ and the file or directory contents and attributes are otherwise unchanged.</p>
as <code>branch(to_ph)</code>, then <code>leaf(from_ph)</code> must not be
the same name as <code>leaf(to_ph)</code>, but if the branch directories are
different, it doesn't matter if the leaf names are the same.</p>
<p><b>Note:</b> Some operating systems with multi-rooted filesystems
<p><b>Note:</b> Some operating systems with multi-rooted file systems
representing different drives, devices, or volumes, do not allow <i>rename</i>
operations between roots . Implementations should not take heroic efforts, such
as switching to a copy mode, to make an otherwise failing <i>rename </i>succeed
@@ -277,7 +285,7 @@ initial_directory()</i>.</p>
<hr>
<p>© Copyright Beman Dawes, 2002</p>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->01 August, 2002<!--webbot bot="Timestamp" endspan i-checksum="34406" --></p>
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->13 September, 2002<!--webbot bot="Timestamp" endspan i-checksum="39336" --></p>
</body>

View File

@@ -35,10 +35,10 @@ documentation</a>.</p>
<p>As with all Filesystem Library components, errors may result in <i>
<a href="exception.htm">filesystem_error</a></i> or <i>std::bad_alloc</i>
exceptions being thrown. See <a href="reference.htm#Requirements">Requirements</a>.</p>
exceptions being thrown. See <a href="index.htm#Requirements">Requirements</a>.</p>
<h2><a name="Class path">Class path</a></h2>
<p>Class <i>path</i> provides for portable mechanism for representing
<a href="reference.htm#path">paths</a> in C++ programs.&nbsp; Class <i>path</i>
<p>Class <i>path</i> provides for portable mechanism for representing
<a href="index.htm#path">paths</a> in C++ programs.&nbsp; Class <i>path</i>
is concerned with the lexical and syntactic aspects of a path, regardless of
whether or not such a path currently exists in the operating system's
filesystem. </p>
@@ -49,15 +49,17 @@ portable but the strings they operate on would not be portable.</p>
<h2><a name="Conceptual model">Conceptual model</a> of a path</h2>
<p>An object of class <i>path</i> can be conceptualized as containing a sequence
of strings, where each string contains the name of a directory, or, in the case
of the last string, a directory or file. Such a path representation is
completely independent of any particular representation of the path as a single
of the string representing the element farthest from the root in the directory
hierarchy, the name of a directory or file. Such a path representation is
independent of any particular representation of the path as a single
string.</p>
<p>There is no requirement that an implementation of class <i>path</i> actually
contain a sequence of strings, but conceptualizing the contents that way provides
a completely portable way to reason about paths.</p>
<p>So that programs can portably express paths as a single string, class <i>path</i>
defines a <a href="#Grammar">grammar</a> for a portable generic path string
format, and supplies a constructor and append operations taking such strings as
format, and supplies constructor and append operations taking such strings as
arguments. Because user input or third-party library functions may supply path
strings formatted according to operating system specific rules, an additional
constructor is provided which takes a system-specific format as an argument.</p>
@@ -90,8 +92,9 @@ with the <i><a href="#system_specific">system_specific</a></i> decorator.</p>
<p>Although implementation-defined, it is desirable that <i>
system-specific-root</i> have a grammar which is distinguishable from other grammar elements,
and follow the conventions of the operating system.</p>
<p>Whether or not a generic path string is actually portable will depend on the
names used.&nbsp; See <font color="#FF0000"><i>to be provided</i></font></p>
<p>Whether or not a generic path string is actually portable to a particular
operating system will depend on the
names used.&nbsp; See the <a href="portability_guide.htm">Portability Guide</a>.</p>
<h2><a name="Canonical">Canonical</a> form</h2>
<p>Adjacent <i>name, parent-directory</i> elements in <code>m_name</code>
have been recursively removed. </p>
@@ -118,7 +121,7 @@ boost/filesystem/path.hpp</a> <a name="synopsis">synopsis</a></h2>
// append operations:
path &amp; <a href="#operator-shift-equal">operator&lt;&lt;=</a>( const path &amp; rhs );
const path <a href="#operator-shift">operator&lt;&lt;</a> ( const path &amp; rhs ) const;
const path <a href="#operator-shift">operator&lt;&lt;</a>( const path &amp; rhs ) const;
// query functions:
bool <a href="#empty">is_null()</a> const;
@@ -129,9 +132,9 @@ boost/filesystem/path.hpp</a> <a name="synopsis">synopsis</a></h2>
const path <a href="#branch">branch</a>() const;
// iteration:
typedef <i>implementation-defined</i> iterator;
iterator begin() const;
iterator end() const;
typedef <i>implementation-defined</i> <a href="#iterator">iterator</a>;
const iterator <a href="#begin">begin</a>() const;
const iterator <a href="#end">end</a>() const;
private:
std::vector&lt;std::string&gt; m_name; // for exposition only
@@ -323,12 +326,12 @@ iterators (24.1). The value, reference, and pointer types are <i>std::string</i>
</blockquote>
<h3><a name="begin">begin</a></h3>
<blockquote>
<p><code>iterator begin() const;</code></p>
<p><code>const iterator begin() const;</code></p>
<p><b>Returns:</b> <code>m_path.begin()</code></p>
</blockquote>
<h3><a name="end">end</a></h3>
<blockquote>
<p><code>iterator end() const;</code></p>
<p><code>const iterator end() const;</code></p>
<p><b>Returns:</b> <code>m_path.end()</code></p>
</blockquote>
<h2><a name="Non-member functions">Non-member functions</a></h2>
@@ -349,7 +352,7 @@ likely to change.</p>
<hr>
<p>© Copyright Beman Dawes, 2002</p>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->09 August, 2002<!--webbot bot="Timestamp" endspan i-checksum="34422" --></p>
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->13 September, 2002<!--webbot bot="Timestamp" endspan i-checksum="39336" --></p>
</body>

View File

@@ -18,17 +18,44 @@ Guide</h1>
guarantee that a program using the Filesystem Library will be portable between
operating systems. The file and directory names in paths present a particularly
troublesome portability problem.</p>
<p>Although there is no way to guarantee that a path is portable to every
operating system, the probability of portability can be markedly improved by
understanding the limits imposed by various operating systems, and by following
some rules-of-thumb when deciding path issues.</p>
<h2>File and directory <a name="recommendations">recommendations</a></h2>
<p>It is not possible to know in advance if a file or directory name will be
valid (and thus portable) for an operating system whose requirements are
unknown. There is always the possibility that an operating system could use
names which are unusual (number between 17 and 4095, for example) or very
limited (maximum of two character names, for example).</p>
<p>It is possible, however, to know if a name is valid for a particular
operating system.&nbsp; It is also possible to construct names which are very
likely to be portable to a large number of modern and legacy operating systems.</p>
<p>By providing name validity checking facilities, the Filesystem Library allows
programmers to ensure that a given name meets the requirements for specific
operating systems, or meets the recommendations for general portability.</p>
<p><b>To do:</b> An implementation should be required to provide check functions
for the host O/S, and for the portability recommendations.&nbsp; But it isn't
possible to require implementors to supply an open ended number of checking
functions. It would be helpful if there was a registry to ensure that checking
functions for a particular O/S had the same specification regardless of
implementor.</p>
<h2>Limits imposed by specific operating systems</h2>
<p>(To be supplied)</p>
<table border="1" cellpadding="5">
<tr>
<td align="center"><b>Operating<br>
system</b></td>
<td align="center"><b>Check<br>
function</b></td>
<td align="center"><b>Requirements</b></td>
</tr>
</table>
<h2>File and directory name <a name="recommendations">recommendations</a></h2>
<p>(Very preliminary draft)</p>
<table border="1">
<tr>
<td align="center" valign="top"><strong>Recommendation</strong></td>
<td align="center" valign="top"><strong>Check<br>
function</strong></td>
<td align="center" valign="top"><strong>Rationale</strong></td>
</tr>
<tr>
@@ -36,29 +63,34 @@ some rules-of-thumb when deciding path issues.</p>
underscore.<br>
<br>
For even greater portability, don't use hyphens at all.</td>
<td valign="top">&nbsp;</td>
<td valign="top">These are the characters specified by the POSIX standard for portable directory and
file names, and are also valid for Windows, Mac, and many other modern filesystems.
ISO-9660, and possibly some legacy systems, do not permit hyphens at all.</td>
</tr>
<tr>
<td valign="top">Do not use periods in directory names. </td>
<td valign="top">&nbsp;</td>
<td valign="top">Requirement for Requirement for ISO-9660, OpenVMS native
filesystem, and other legacy systems.</td>
</tr>
<tr>
<td valign="top">Do not use more that one period in a file name.</td>
<td valign="top">&nbsp;</td>
<td valign="top">Requirement for ISO-9660, OpenVMS native filesystem, and
other legacy systems. </td>
</tr>
<tr>
<td valign="top">Do not use period, hyphen, or underscore as the first
character of a file or directory name.</td>
<td valign="top">&nbsp;</td>
<td valign="top">Some operating systems treat have special rules for the
first character of names. POSIX, for example.</td>
</tr>
<tr>
<td valign="top">Do not assume names are case sensitive. For example, do not expected a directory to be
able to hold separate elements named &quot;Foo&quot; and &quot;foo&quot;. </td>
<td valign="top">&nbsp;</td>
<td valign="top">Some filesystems are case insensitive.&nbsp; For example, Windows
NTFS is case preserving in the way it stores names, but case insensitive in
searching for names (unless running under the POSIX sub-system, it which
@@ -67,6 +99,7 @@ some rules-of-thumb when deciding path issues.</p>
<tr>
<td valign="top">Do not assume names are case insensitive.&nbsp; For example, do not expect a file
created with the name of &quot;Foo&quot; to be open successfully with the name of &quot;foo&quot;.</td>
<td valign="top">&nbsp;</td>
<td valign="top">Some filesystems are case sensitive.&nbsp; For example, POSIX.</td>
</tr>
<tr>
@@ -74,6 +107,7 @@ some rules-of-thumb when deciding path issues.</p>
tree so that the total length of the string returned by generic_path() to
255 characters.&nbsp;
Note that ISO 9660 level 1 has an explicit directory tree depth limit of 8.</td>
<td valign="top">&nbsp;</td>
<td valign="top">Some operating systems place limits on the total path length.&nbsp; For example,
Windows 2000 limits paths to 260 characters total length.</td>
</tr>
@@ -84,17 +118,16 @@ some rules-of-thumb when deciding path issues.</p>
&nbsp; 31 characters: Classic Mac OS<br>
&nbsp; 8 characters + period + 3 characters: ISO 9660 (CD-ROM)<br>
<strong>...</strong></td>
<td valign="top">&nbsp;</td>
<td valign="top">Limiting name length can markedly reduce the expressiveness of file names, yet placing
only very high limits on lengths inhibits wide portability.</td>
</tr>
</table>
<h2>Limits imposed by specific operating systems</h2>
<p>(To be supplied)</p>
<hr>
<p>© Copyright Beman Dawes, 2002</p>
<p>Revised
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->12 August, 2002<!--webbot bot="Timestamp" endspan i-checksum="34409" --></p>
<!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%d %B, %Y" startspan -->13 September, 2002<!--webbot bot="Timestamp" endspan i-checksum="39336" --></p>
</body>

View File

@@ -31,7 +31,7 @@ namespace boost
std::ios_base::openmode mode )
{
return std::basic_filebuf<charT,traits>::open(
file_ph.file_c_str(), mode );
file_ph.file_path().c_str(), mode );
}
};
@@ -48,13 +48,13 @@ namespace boost
explicit basic_ifstream( const path & file_ph,
std::ios_base::openmode mode = std::ios_base::in )
: std::basic_ifstream<charT,traits>(
file_ph.file_c_str(), mode ) {}
file_ph.file_path().c_str(), mode ) {}
virtual ~basic_ifstream() {}
void open( const path & file_ph,
std::ios_base::openmode mode = std::ios_base::in )
{
std::basic_ifstream<charT,traits>::open(
file_ph.file_c_str(), mode );
file_ph.file_path().c_str(), mode );
}
};
@@ -71,13 +71,13 @@ namespace boost
explicit basic_ofstream( const path & file_ph,
std::ios_base::openmode mode = std::ios_base::out )
: std::basic_ofstream<charT,traits>(
file_ph.file_c_str(), mode ) {}
file_ph.file_path().c_str(), mode ) {}
virtual ~basic_ofstream() {}
void open( const path & file_ph,
std::ios_base::openmode mode = std::ios_base::out )
{
std::basic_ofstream<charT,traits>::open(
file_ph.file_c_str(), mode );
file_ph.file_path().c_str(), mode );
}
};
@@ -94,13 +94,13 @@ namespace boost
explicit basic_fstream( const path & file_ph,
std::ios_base::openmode mode = std::ios_base::in|std::ios_base::out )
: std::basic_fstream<charT,traits>(
file_ph.file_c_str(), mode ) {}
file_ph.file_path().c_str(), mode ) {}
virtual ~basic_fstream() {}
void open( const path & file_ph,
std::ios_base::openmode mode = std::ios_base::in|std::ios_base::out )
{
std::basic_fstream<charT,traits>::open(
file_ph.file_c_str(), mode );
file_ph.file_path().c_str(), mode );
}
};

View File

@@ -24,8 +24,7 @@
#include <boost/config.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/smart_ptr.hpp>
#include <boost/iterator.hpp>
#include <boost/operators.hpp>
#include <boost/iterator_adaptors.hpp>
#include <string>
@@ -45,7 +44,7 @@ namespace boost
// VC++ 7.0 and earlier has a serious namespace bug that causes a clash
// between boost::filesystem::is_empty and the unrelated type trait
// boost::is_empty. The workaround for those who must use broken versions
// of VC++ is to use the function _is_empty. All others should use the
// of VC++ is to use the function _is_empty. All others should use the
// correct is_empty name.
bool _is_empty( const path & ph ); // deprecated
@@ -69,46 +68,59 @@ namespace boost
const path & initial_directory();
// directory_iterator details ----------------------------------------------//
namespace detail
{
const char * implementation_name();
class directory_iterator_imp;
struct directory_iterator_internals
{
typedef boost::shared_ptr< detail::directory_iterator_imp > dii_ptr;
dii_ptr imp;
const path & deref() const;
void inc();
};
struct dii_policies : public default_iterator_policies
{
template <class IteratorAdaptor>
typename IteratorAdaptor::reference
dereference(const IteratorAdaptor& x) const
{ return x.base().deref(); }
template <class IteratorAdaptor>
void increment(IteratorAdaptor& x)
{ x.base().inc(); }
template <class IteratorAdaptor1, class IteratorAdaptor2>
bool equal(const IteratorAdaptor1& x, const IteratorAdaptor2& y) const
{ return x.base().imp == y.base().imp; }
};
}
// directory_iterator ------------------------------------------------------//
class directory_iterator:
public boost::iterator< std::input_iterator_tag,
path, const path *, const path & >,
public boost::equality_comparable1< directory_iterator >,
public boost::dereferenceable< directory_iterator,
const path * >,
public boost::incrementable< directory_iterator >
class directory_iterator
: public boost::iterator_adaptor<
// because directory_iterator is an InputIterator, shallow copy-
// semantics are required, and shared_ptr provides that.
detail::directory_iterator_internals,
detail::dii_policies,
path, const path &, const path *,
std::input_iterator_tag, std::ptrdiff_t >
{
public:
typedef boost::iterator<
std::input_iterator_tag,
path > base;
typedef base::value_type value_type;
typedef base::difference_type difference_type;
typedef base::pointer pointer;
typedef base::reference reference;
typedef base::iterator_category iterator_category;
directory_iterator(); // creates the "end" iterator
explicit directory_iterator( const path & directory_path );
directory_iterator(); // creates the "end" iterator
explicit directory_iterator( const path & directory_ph );
// compiler generates copy constructor, copy assignment, and destructor
bool operator==( const directory_iterator & ) const;
const path & operator*() const;
directory_iterator & operator++();
private:
// because directory_iterator is an InputIterator, shallow copy
// semantics are required, and shared_ptr provides that.
boost::shared_ptr<detail::directory_iterator_imp> m_imp;
// workaround iterator_adaptor / compiler interactions
const boost::filesystem::path * operator->() const
{ return &base().deref(); }
};
} // namespace filesystem

View File

@@ -77,10 +77,6 @@ namespace boost
const std::string leaf() const;
const path branch() const;
// deprecated
const char * file_c_str() const { return m_path.c_str(); }
const char * directory_c_str() const { return m_path.c_str(); }
// iteration over the names in the path:
typedef boost::iterator_adaptor<
detail::path_itr_imp,
@@ -119,6 +115,7 @@ namespace boost
void m_path_append( const std::string & src,
source_context context = generic );
public: // should be private, but friend functions don't work for me
void m_replace_leaf( const char * new_leaf );
};

View File

@@ -99,16 +99,16 @@ namespace boost
public:
recursive_directory_iterator( const path & pth, Predicate pred )
{
base().reset( new detail::rdi_imp<Predicate>( pth, pred ) );
this->base().reset( new detail::rdi_imp<Predicate>( pth, pred ) );
}
recursive_directory_iterator() // the past-the-end iterator
{
base().reset( new detail::rdi_imp<Predicate> );
this->base().reset( new detail::rdi_imp<Predicate> );
}
// workaround iterator_adaptor / compiler interactions
const boost::filesystem::path * operator->() const
{ return &*base()->stac.top(); }
{ return &*this->base()->stac.top(); }
};
}
}

View File

@@ -1,9 +1,9 @@
<html>
<head>
<meta http-equiv="refresh" content="0; URL=doc/index.html">
<meta http-equiv="refresh" content="0; URL=doc/index.htm">
</head>
<body>
Automatic redirection failed, please go to
<a href="doc/index.html">doc/index.html</a>.
<a href="doc/index.htm">doc/index.htm</a>.
</body>
</html>

View File

@@ -159,17 +159,20 @@ namespace
} // unnamed namespace
// path_descriptor_imp -----------------------------------------------------//
namespace boost
{
namespace filesystem
{
namespace detail
{
#ifdef BOOST_POSIX
const char * implementation_name() { return "POSIX"; }
#else
const char * implementation_name() { return "Windows"; }
#endif
// directory_iterator_imp --------------------------------------------------//
namespace detail
{
class directory_iterator_imp
{
public:
@@ -186,64 +189,60 @@ namespace boost
// directory_iterator implementation ---------------------------------------//
// default ctor creates the "end" iterator (by letting m_imp default to 0)
// default ctor creates the "end" iterator (by letting base default to 0)
directory_iterator::directory_iterator() {}
directory_iterator::directory_iterator( const path & dir_path )
: m_imp( new detail::directory_iterator_imp )
{
base().imp.reset( new detail::directory_iterator_imp );
BOOST_SYSTEM_DIRECTORY_TYPE scratch;
const char * name;
if ( dir_path.is_null() )
m_imp->handle = BOOST_INVALID_HANDLE_VALUE;
base().imp->handle = BOOST_INVALID_HANDLE_VALUE;
else
name = find_first_file( dir_path.directory_c_str(),
m_imp->handle, scratch ); // sets handle
name = find_first_file( dir_path.directory_path().c_str(),
base().imp->handle, scratch ); // sets handle
if ( m_imp->handle != BOOST_INVALID_HANDLE_VALUE )
if ( base().imp->handle != BOOST_INVALID_HANDLE_VALUE )
{
m_imp->entry_path = dir_path;
m_imp->entry_path.m_path_append( name, path::nocheck );
while ( m_imp.get()
&& ( m_imp->entry_path.leaf() == "."
|| m_imp->entry_path.leaf() == ".." ) )
base().imp->entry_path = dir_path;
base().imp->entry_path.m_path_append( name, path::nocheck );
while ( base().imp.get()
&& ( base().imp->entry_path.leaf() == "."
|| base().imp->entry_path.leaf() == ".." ) )
{ operator++(); }
}
else
{
throw filesystem_error( std::string(
"directory_iterator constructor failure: " )
+ dir_path.directory_c_str(), system_error );
+ dir_path.directory_path().c_str(), system_error );
}
}
bool directory_iterator::operator== (
directory_iterator const& itr ) const
namespace detail
{
return m_imp == itr.m_imp;
}
path const & directory_iterator::operator* () const
{
assert( m_imp.get() ); // fails if dereference end iterator
return m_imp->entry_path;
}
directory_iterator & directory_iterator::operator++ ()
{
assert( m_imp.get() ); // fails on increment end iterator
assert( m_imp->handle != BOOST_INVALID_HANDLE_VALUE ); // imp reality check
BOOST_SYSTEM_DIRECTORY_TYPE scratch;
const char * name;
if ( (name = find_next_file( m_imp->handle, scratch )) != 0 )
path const & directory_iterator_internals::deref() const
{
m_imp->entry_path.m_replace_leaf( name );
assert( imp.get() ); // fails if dereference end iterator
return imp->entry_path;
}
else {
m_imp.reset(); // make m_imp the end iterator
void directory_iterator_internals::inc()
{
assert( imp.get() ); // fails on increment end iterator
assert( imp->handle != BOOST_INVALID_HANDLE_VALUE ); // imp reality check
BOOST_SYSTEM_DIRECTORY_TYPE scratch;
const char * name;
if ( (name = find_next_file( imp->handle, scratch )) != 0 )
{
imp->entry_path.m_replace_leaf( name );
}
else {
imp.reset(); // make base() the end iterator
}
}
return *this;
}
// free functions ----------------------------------------------------------//
@@ -252,9 +251,9 @@ namespace boost
{
# ifdef BOOST_POSIX
struct stat path_stat;
return ::stat( ph.file_c_str(), &path_stat ) == 0;
return ::stat( ph.file_path().c_str(), &path_stat ) == 0;
# else
return ::GetFileAttributes( ph.file_c_str() ) != 0xFFFFFFFF;
return ::GetFileAttributes( ph.file_path().c_str() ) != 0xFFFFFFFF;
# endif
}
@@ -262,15 +261,15 @@ namespace boost
{
# ifdef BOOST_POSIX
struct stat path_stat;
if ( ::stat( ph.directory_c_str(), &path_stat ) != 0 )
if ( ::stat( ph.directory_path().c_str(), &path_stat ) != 0 )
throw filesystem_error( std::string("is_directory(): ")
+ ph.directory_c_str(), system_error );
+ ph.directory_path().c_str(), system_error );
return S_ISDIR( path_stat.st_mode );
# else
DWORD attributes = ::GetFileAttributes( ph.directory_c_str() );
DWORD attributes = ::GetFileAttributes( ph.directory_path().c_str() );
if ( attributes == 0xFFFFFFFF )
throw filesystem_error( std::string("is_directory(): ")
+ ph.directory_c_str(), system_error );
+ ph.directory_path().c_str(), system_error );
return (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
# endif
}
@@ -279,19 +278,19 @@ namespace boost
{
# ifdef BOOST_POSIX
struct stat path_stat;
if ( ::stat( ph.file_c_str(), &path_stat ) != 0 )
if ( ::stat( ph.file_path().c_str(), &path_stat ) != 0 )
throw filesystem_error( std::string("is_empty(): ")
+ ph.file_c_str(), system_error );
+ ph.file_path().c_str(), system_error );
return S_ISDIR( path_stat.st_mode )
? is_empty_directory( ph )
: path_stat.st_size == 0;
# else
WIN32_FILE_ATTRIBUTE_DATA fad;
if ( !::GetFileAttributesEx( ph.file_c_str(),
if ( !::GetFileAttributesEx( ph.file_path().c_str(),
::GetFileExInfoStandard, &fad ) )
throw filesystem_error( std::string("is_empty(): ")
+ ph.file_c_str(), system_error );
+ ph.file_path().c_str(), system_error );
return ( fad.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY )
? is_empty_directory( ph )
@@ -302,39 +301,39 @@ namespace boost
void create_directory( const path & dir_path )
{
# ifdef BOOST_POSIX
if ( ::mkdir( dir_path.directory_c_str(),
if ( ::mkdir( dir_path.directory_path().c_str(),
S_IRWXU|S_IRWXG|S_IRWXO ) != 0 )
# else
if ( !::CreateDirectory( dir_path.directory_c_str(), 0 ) )
if ( !::CreateDirectory( dir_path.directory_path().c_str(), 0 ) )
# endif
throw filesystem_error( std::string("create_directory(): ")
+ dir_path.directory_c_str(), system_error );
+ dir_path.directory_path().c_str(), system_error );
}
void remove( const path & ph )
{
if ( !exists( ph ) )
throw fs::filesystem_error( std::string("remove() on: ")
+ ph.file_c_str(), system_error );
if ( is_directory( ph ) )
if ( exists( ph ) )
{
if ( is_directory( ph ) )
{
# ifdef BOOST_POSIX
if ( ::rmdir( ph.file_c_str() ) != 0 )
if ( ::rmdir( ph.file_path().c_str() ) != 0 )
# else
if ( !::RemoveDirectory( ph.file_c_str() ) )
if ( !::RemoveDirectory( ph.file_path().c_str() ) )
# endif
throw fs::filesystem_error( std::string("remove() on: ")
+ ph.file_c_str(), system_error );
}
else
{
throw fs::filesystem_error( std::string("remove() on: ")
+ ph.file_path().c_str(), system_error );
}
else
{
# ifdef BOOST_POSIX
if ( ::remove( ph.file_c_str() ) != 0 )
if ( ::remove( ph.file_path().c_str() ) != 0 )
# else
if ( !::DeleteFile( ph.file_c_str() ) )
if ( !::DeleteFile( ph.file_path().c_str() ) )
# endif
throw fs::filesystem_error( std::string("remove() on: ")
+ ph.file_c_str(), system_error );
throw fs::filesystem_error( std::string("remove() on: ")
+ ph.file_path().c_str(), system_error );
}
}
}
@@ -348,12 +347,12 @@ namespace boost
{
# ifdef BOOST_POSIX
if ( exists( new_path ) // POSIX is too permissive so must check
|| ::rename( old_path.file_c_str(), new_path.file_c_str() ) != 0 )
|| ::rename( old_path.file_path().c_str(), new_path.file_path().c_str() ) != 0 )
# else
if ( !::MoveFile( old_path.file_c_str(), new_path.file_c_str() ) )
if ( !::MoveFile( old_path.file_path().c_str(), new_path.file_path().c_str() ) )
# endif
throw filesystem_error( std::string("move_file(): ")
+ old_path.file_c_str() + ", " + new_path.file_c_str(), system_error );
+ old_path.file_path().c_str() + ", " + new_path.file_path().c_str(), system_error );
}
void copy_file( const path & from_file_ph,
@@ -366,16 +365,16 @@ namespace boost
boost::scoped_array<char> buf( new char [buf_sz] );
int infile, outfile;
if ( (infile = ::open( from_file_ph.file_c_str(),
if ( (infile = ::open( from_file_ph.file_path().c_str(),
O_RDONLY )) < 0
|| (outfile = ::open( to_file_ph.file_c_str(),
|| (outfile = ::open( to_file_ph.file_path().c_str(),
O_WRONLY | O_CREAT | O_EXCL,
S_IRWXU|S_IRWXG|S_IRWXO )) < 0 )
{
if ( infile != 0 ) ::close( infile );
throw fs::filesystem_error( std::string("copy() files: ")
+ from_file_ph.file_c_str()
+ ", " + to_file_ph.file_c_str(), system_error );
+ from_file_ph.file_path().c_str()
+ ", " + to_file_ph.file_path().c_str(), system_error );
}
ssize_t sz;
@@ -387,12 +386,12 @@ namespace boost
if ( sz != 0 )
# else
if ( !::CopyFile( from_file_ph.file_c_str(),
to_file_ph.file_c_str(), /*fail_if_exists=*/true ) )
if ( !::CopyFile( from_file_ph.file_path().c_str(),
to_file_ph.file_path().c_str(), /*fail_if_exists=*/true ) )
# endif
throw fs::filesystem_error( std::string("copy() files: ")
+ from_file_ph.file_c_str()
+ ", " + to_file_ph.file_c_str(), system_error );
+ from_file_ph.file_path().c_str()
+ ", " + to_file_ph.file_path().c_str(), system_error );
}
const path & initial_directory()

View File

@@ -12,8 +12,8 @@
#include <boost/filesystem/exception.hpp>
namespace fs = boost::filesystem;
#define BOOST_INCLUDE_MAIN
#include <boost/test/test_tools.hpp>
//#include <boost/test/test_tools.hpp>
#include <boost/test/minimal.hpp>
#include <boost/bind.hpp>
using boost::bind;
@@ -27,7 +27,7 @@ namespace
void create_file( const fs::path & ph, const std::string & contents )
{
std::ofstream f( ph.file_c_str() );
std::ofstream f( ph.file_path().c_str() );
if ( !f )
throw fs::filesystem_error( "ofstream(): " + ph.generic_path() );
if ( !contents.empty() ) f << contents;
@@ -35,7 +35,7 @@ namespace
void verify_file( const fs::path & ph, const std::string & expected )
{
std::ifstream f( ph.file_c_str() );
std::ifstream f( ph.file_path().c_str() );
if ( !f )
throw fs::filesystem_error( "ifstream(): " + ph.generic_path() );
std::string contents;
@@ -66,6 +66,8 @@ namespace
int test_main( int, char * [] )
{
std::cout << "implemenation name: "
<< fs::detail::implementation_name() << "\n";
std::cout << "initial_directory() is \""
<< fs::initial_directory().generic_path()
<< "\"\n";
@@ -100,6 +102,11 @@ int test_main( int, char * [] )
BOOST_TEST( fs::is_directory( d1 ) );
BOOST_TEST( fs::_is_empty( d1 ) );
{
fs::directory_iterator dir_itr( dir );
BOOST_TEST( dir_itr->leaf() == "d1" );
}
// create a second directory named d2
fs::path d2( dir << "d2" );
fs::create_directory(d2 );
@@ -169,6 +176,8 @@ int test_main( int, char * [] )
BOOST_TEST( !fs::is_directory( file_ph ) );
fs::remove( file_ph );
BOOST_TEST( !fs::exists( file_ph ) );
fs::remove( "no-such-file" ); // should be harmless
fs::remove( "no-such-directory/no-such-file" ); // ditto
// remove test on directory
d1 = dir << "shortlife_dir";
@@ -177,6 +186,7 @@ int test_main( int, char * [] )
BOOST_TEST( fs::exists( d1 ) );
BOOST_TEST( fs::is_directory( d1 ) );
BOOST_TEST( fs::_is_empty( d1 ) );
BOOST_TEST( throws_fs_error( bind( fs::remove, dir ) ) );
fs::remove( d1 );
BOOST_TEST( !fs::exists( d1 ) );