At the moment io_stream::exists() returns FALSE for file:// paths which refer to an existing directory. Inconsistently, for cygfile:// paths which refer to an existing directory, it returns TRUE.
Return a new state, IO_STREAM_EXISTS_DIRECTORY, to indicate if pathname exists as a directory and update all uses appropriately Not sure if the use of access() in the legacy branch of io_stream_cygfile::exists() is correct, looks like it's inverted Not sure if current exists() implementation deals correctly when other attributes are set for a file, e.g. FILE_ATTRIBUTE_COMPRESSED or FILE_ATTRIBUTE_ENCRYPTED, since it checks attributes against an expected value rather than checking for bits being set? 2010-11-26 Jon TURNEY <jon.tur...@dronecode.org.uk> * io_stream.h (io_stream_exists_t, io_stream::exists): Change io_stream::exists return type to new enum io_stream_exists_t. * io_stream.cc (exists): Ditto. * IOStreamProvider.h (IOStreamProvider): Ditto. * io_stream_file.h (io_stream): Ditto. * io_stream_file.cc (IOStreamProvider, exists): Ditto. * io_stream_cygfile.h (io_stream): Ditto. * io_stream_cygfile.cc (IOStreamProvider, exists): Ditto. * script.cc (try_run_script): Update use of io_stream::exists(). * install.cc (installOne): Ditto. * download.cc (check_for_cached): Ditto. Signed-off-by: Jon TURNEY <jon.tur...@dronecode.org.uk> --- IOStreamProvider.h | 2 +- download.cc | 4 ++-- install.cc | 2 +- io_stream.cc | 2 +- io_stream.h | 10 +++++++++- io_stream_cygfile.cc | 23 +++++++++++++++++------ io_stream_cygfile.h | 2 +- io_stream_file.cc | 15 ++++++++++----- io_stream_file.h | 2 +- script.cc | 2 +- 10 files changed, 44 insertions(+), 20 deletions(-) diff --git a/IOStreamProvider.h b/IOStreamProvider.h index b30362e..1c12f42 100644 --- a/IOStreamProvider.h +++ b/IOStreamProvider.h @@ -25,7 +25,7 @@ class IOStreamProvider { public: - virtual int exists (const std::string& ) const = 0; + virtual io_stream_exists_t exists (const std::string& ) const = 0; virtual int remove (const std::string& ) const = 0; virtual int mklink (const std::string&, const std::string&, io_stream_link_t) const = 0; diff --git a/download.cc b/download.cc index 86723f6..3567715 100644 --- a/download.cc +++ b/download.cc @@ -91,7 +91,7 @@ check_for_cached (packagesource & pkgsource) * std::string-ified, and doesn't use overcomplex semantics. */ std::string fullname = prefix + (pkgsource.Canonical() ? pkgsource.Canonical() : ""); - if (io_stream::exists(fullname)) + if (io_stream::exists(fullname) == IO_STREAM_EXISTS_FILE) { if (validateCachedPackage (fullname, pkgsource)) pkgsource.set_cached (fullname); @@ -110,7 +110,7 @@ check_for_cached (packagesource & pkgsource) { std::string fullname = prefix + rfc1738_escape_part (n->key) + "/" + pkgsource.Canonical (); - if (io_stream::exists(fullname)) + if (io_stream::exists(fullname) == IO_STREAM_EXISTS_FILE) { if (validateCachedPackage (fullname, pkgsource)) pkgsource.set_cached (fullname); diff --git a/install.cc b/install.cc index 51c20d9..f77b52b 100644 --- a/install.cc +++ b/install.cc @@ -261,7 +261,7 @@ Installer::installOne (packagemeta &pkgm, const packageversion &ver, io_stream *pkgfile = NULL; - if (!source.Cached() || !io_stream::exists (source.Cached ()) + if (!source.Cached() || (io_stream::exists (source.Cached ()) != IO_STREAM_EXISTS_FILE) || !(pkgfile = io_stream::open (source.Cached (), "rb", 0))) { note (NULL, IDS_ERR_OPEN_READ, source.Cached (), "No such file"); diff --git a/io_stream.cc b/io_stream.cc index 08ecae4..23c7e36 100644 --- a/io_stream.cc +++ b/io_stream.cc @@ -241,7 +241,7 @@ io_stream::gets (char *buffer, size_t length) return buffer; } -int +io_stream_exists_t io_stream::exists (const std::string& name) { IOStreamProvider const *p = findProvider (name); diff --git a/io_stream.h b/io_stream.h index 3968acc..97528a8 100644 --- a/io_stream.h +++ b/io_stream.h @@ -74,6 +74,14 @@ typedef enum } io_stream_seek_t; +typedef enum +{ + IO_STREAM_EXISTS_NO = 0, + IO_STREAM_EXISTS_FILE, + IO_STREAM_EXISTS_DIRECTORY, +} +io_stream_exists_t; + class io_stream { public: @@ -103,7 +111,7 @@ public: */ static io_stream *open (const std::string&, const std::string&, mode_t); static int remove (const std::string& ); - static int exists (const std::string& ); + static io_stream_exists_t exists (const std::string& ); /* moves physical stream source to dest. A copy will be attempted if a * pointer flip fails. */ diff --git a/io_stream_cygfile.cc b/io_stream_cygfile.cc index 8da97e7..7b768b6 100644 --- a/io_stream_cygfile.cc +++ b/io_stream_cygfile.cc @@ -27,6 +27,7 @@ static const char *cvsid = #include <stdio.h> #include <stdlib.h> #include <errno.h> +#include <sys/stat.h> #include "mount.h" #include "mkdir.h" #include "mklink2.h" @@ -40,7 +41,7 @@ static const char *cvsid = class CygFileProvider : public IOStreamProvider { public: - int exists (const std::string& path) const + io_stream_exists_t exists (const std::string& path) const {return io_stream_cygfile::exists(path);} int remove (const std::string& path) const {return io_stream_cygfile::remove(path);} @@ -182,12 +183,12 @@ io_stream_cygfile::~io_stream_cygfile () } /* Static members */ -int +io_stream_exists_t io_stream_cygfile::exists (const std::string& path) { get_root_dir_now (); if (!get_root_dir ().size()) - return 0; + return IO_STREAM_EXISTS_NO; if (IsWindowsNT ()) { @@ -196,11 +197,21 @@ io_stream_cygfile::exists (const std::string& path) mklongpath (wname, cygpath (normalise(path)).c_str (), len); DWORD attr = GetFileAttributesW (wname); if (attr != INVALID_FILE_ATTRIBUTES) - return 1; + return (attr & FILE_ATTRIBUTE_DIRECTORY) ? IO_STREAM_EXISTS_DIRECTORY : IO_STREAM_EXISTS_FILE; } else if (_access (cygpath (normalise(path)).c_str (), 0)) - return 1; - return 0; + { + struct _stat s; + if (!_stat (cygpath (normalise(path)).c_str (), &s)) + { + if (s.st_mode & S_IFDIR) + return IO_STREAM_EXISTS_DIRECTORY; + + if (s.st_mode & S_IFREG) + return IO_STREAM_EXISTS_FILE; + } + } + return IO_STREAM_EXISTS_NO; } int diff --git a/io_stream_cygfile.h b/io_stream_cygfile.h index 1ece242..d0a6bcb 100644 --- a/io_stream_cygfile.h +++ b/io_stream_cygfile.h @@ -28,7 +28,7 @@ extern int cygmkdir_p (path_type_t isadir, const std::string& path, mode_t mode) class io_stream_cygfile:public io_stream { public: - static int exists (const std::string& ); + static io_stream_exists_t exists (const std::string& ); static int remove (const std::string& ); static int mklink (const std::string& , const std::string& , io_stream_link_t); io_stream_cygfile (const std::string&, const std::string&, mode_t); diff --git a/io_stream_file.cc b/io_stream_file.cc index 91f9afa..422f081 100644 --- a/io_stream_file.cc +++ b/io_stream_file.cc @@ -46,7 +46,7 @@ using namespace std; class FileProvider : public IOStreamProvider { public: - int exists (const std::string& path) const + io_stream_exists_t exists (const std::string& path) const {return io_stream_file::exists(path);} int remove (const std::string& path) const {return io_stream_file::remove(path);} @@ -114,7 +114,7 @@ io_stream_file::~io_stream_file () delete [] wname; } -int +io_stream_exists_t io_stream_file::exists (const std::string& path) { DWORD attr; @@ -127,9 +127,14 @@ io_stream_file::exists (const std::string& path) mklongpath (wname, path.c_str (), len); attr = GetFileAttributesW (wname); } - return attr != INVALID_FILE_ATTRIBUTES - && attr != FILE_ATTRIBUTE_DIRECTORY - && attr != FILE_ATTRIBUTE_DEVICE; + + if (attr != INVALID_FILE_ATTRIBUTES + && !(attr & FILE_ATTRIBUTE_DEVICE)) + { + return (attr & FILE_ATTRIBUTE_DIRECTORY) ? IO_STREAM_EXISTS_DIRECTORY : IO_STREAM_EXISTS_FILE; + } + + return IO_STREAM_EXISTS_NO; } int diff --git a/io_stream_file.h b/io_stream_file.h index b1d7f2e..2ec56a3 100644 --- a/io_stream_file.h +++ b/io_stream_file.h @@ -25,7 +25,7 @@ class io_stream_file:public io_stream { public: - static int exists (const std::string& ); + static io_stream_exists_t exists (const std::string& ); static int remove (const std::string& ); static int mklink (const std::string& , const std::string& , io_stream_link_t); io_stream_file (const std::string&, const std::string&, mode_t); diff --git a/script.cc b/script.cc index ec363d8..f64fecf 100644 --- a/script.cc +++ b/script.cc @@ -305,7 +305,7 @@ try_run_script (const std::string& dir, const std::string& fname, const std::string& ext) { - if (io_stream::exists ("cygfile://" + dir + fname + ext)) + if (io_stream::exists ("cygfile://" + dir + fname + ext) == IO_STREAM_EXISTS_FILE) return Script (dir + fname + ext).run (); return NO_ERROR; } -- 1.7.2.3