[PATCH 3/4] Make io_stream::exists() directory aware

Jon TURNEY jon.turney@dronecode.org.uk
Fri Nov 26 15:40:00 GMT 2010


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.turney@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.turney@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



More information about the Cygwin-apps mailing list