OSDN Git Service

* fhandler.h (fhandler_base::mkdir): New virtual method.
authorcgf <cgf>
Wed, 25 May 2005 04:32:53 +0000 (04:32 +0000)
committercgf <cgf>
Wed, 25 May 2005 04:32:53 +0000 (04:32 +0000)
(fhandler_base::rmdir): Ditto.
(fhandler_disk_file:mkdir): New method.
(fhandler_disk_file:rmdir): Ditto.
* dir.cc (mkdir): Implement with fhandlers.
(rmdir): Ditto.
* fhandler.cc (fhandler_base::mkdir): New virtual method.
(fhandler_base::rmdir): Ditto.
(fhandler_disk_file::mkdir): New method.
(fhandler_disk_file::rmdir): Ditto.

fhandler_random.cc: white space.

winsup/cygwin/ChangeLog
winsup/cygwin/dir.cc
winsup/cygwin/fhandler.cc
winsup/cygwin/fhandler.h
winsup/cygwin/fhandler_disk_file.cc
winsup/cygwin/fhandler_random.cc

index c1357eb..8333b4c 100644 (file)
@@ -1,3 +1,16 @@
+2005-05-25  Pierre Humblet  <pierre.humblet@ieee.org>
+
+       * fhandler.h (fhandler_base::mkdir): New virtual method.
+       (fhandler_base::rmdir): Ditto.
+       (fhandler_disk_file:mkdir): New method.
+       (fhandler_disk_file:rmdir): Ditto.
+       * dir.cc (mkdir): Implement with fhandlers.
+       (rmdir): Ditto.
+       * fhandler.cc (fhandler_base::mkdir): New virtual method.
+       (fhandler_base::rmdir): Ditto.
+       (fhandler_disk_file::mkdir): New method.
+       (fhandler_disk_file::rmdir): Ditto.
+
 2005-05-24  Christopher Faylor  <cgf@timesys.com>
 
        * include/cygwin/version.h: Bump API minor number to 129.
index df05152..c6a6bc6 100644 (file)
@@ -221,39 +221,21 @@ extern "C" int
 mkdir (const char *dir, mode_t mode)
 {
   int res = -1;
-  SECURITY_ATTRIBUTES sa = sec_none_nih;
-  security_descriptor sd;
+  fhandler_base *fh = NULL;
 
-  path_conv real_dir (dir, PC_SYM_NOFOLLOW | PC_WRITABLE);
+  if (!(fh = build_fh_name (dir, NULL, PC_SYM_NOFOLLOW | PC_WRITABLE)))
+    goto done;   /* errno already set */;
 
-  if (real_dir.error)
+  if (fh->error ())
     {
-      set_errno (real_dir.case_clash ? ECASECLASH : real_dir.error);
-      goto done;
+      debug_printf ("got %d error from build_fh_name", fh->error ());
+      set_errno (fh->error ());
     }
+  else if (!fh->mkdir (mode))
+    res = 0;
+  delete fh;
 
-  nofinalslash (real_dir.get_win32 (), real_dir.get_win32 ());
-
-  if (allow_ntsec && real_dir.has_acls ())
-    set_security_attribute (S_IFDIR | ((mode & 07777) & ~cygheap->umask),
-                           &sa, sd);
-
-  if (CreateDirectoryA (real_dir.get_win32 (), &sa))
-    {
-      if (!allow_ntsec && allow_ntea)
-       set_file_attribute (false, NULL, real_dir.get_win32 (),
-                           S_IFDIR | ((mode & 07777) & ~cygheap->umask));
-#ifdef HIDDEN_DOT_FILES
-      char *c = strrchr (real_dir.get_win32 (), '\\');
-      if ((c && c[1] == '.') || *real_dir.get_win32 () == '.')
-       SetFileAttributes (real_dir.get_win32 (), FILE_ATTRIBUTE_HIDDEN);
-#endif
-      res = 0;
-    }
-  else
-    __seterrno ();
-
-done:
+ done:
   syscall_printf ("%d = mkdir (%s, %d)", res, dir, mode);
   return res;
 }
@@ -263,80 +245,21 @@ extern "C" int
 rmdir (const char *dir)
 {
   int res = -1;
+  fhandler_base *fh = NULL;
 
-  path_conv real_dir (dir, PC_SYM_NOFOLLOW | PC_WRITABLE);
+  if (!(fh = build_fh_name (dir, NULL, PC_SYM_NOFOLLOW | PC_WRITABLE)))
+    goto done;   /* errno already set */;
 
-  if (real_dir.error)
-    set_errno (real_dir.error);
-  else if (!real_dir.exists ())
-    set_errno (ENOENT);
-  else if  (!real_dir.isdir ())
-    set_errno (ENOTDIR);
-  else
+  if (fh->error ())
     {
-      /* Even own directories can't be removed if R/O attribute is set. */
-      if (real_dir.has_attribute (FILE_ATTRIBUTE_READONLY))
-       SetFileAttributes (real_dir,
-                          (DWORD) real_dir & ~FILE_ATTRIBUTE_READONLY);
-
-      for (bool is_cwd = false; ; is_cwd = true)
-       {
-         DWORD err;
-         int rc = RemoveDirectory (real_dir);
-         DWORD att = GetFileAttributes (real_dir);
-
-         /* Sometimes smb indicates failure when it really succeeds, so check for
-            this case specifically. */
-         if (rc || att == INVALID_FILE_ATTRIBUTES)
-           {
-             /* RemoveDirectory on a samba drive doesn't return an error if the
-                directory can't be removed because it's not empty. Checking for
-                existence afterwards keeps us informed about success. */
-             if (att == INVALID_FILE_ATTRIBUTES)
-               {
-                 res = 0;
-                 break;
-               }
-             err = ERROR_DIR_NOT_EMPTY;
-           }
-         else
-           err = GetLastError ();
-
-         /* This kludge detects if we are attempting to remove the current working
-            directory.  If so, we will move elsewhere to potentially allow the
-            rmdir to succeed.  This means that cygwin's concept of the current working
-            directory != Windows concept but, hey, whaddaregonnado?
-            Note that this will not cause something like the following to work:
-                    $ cd foo
-                    $ rmdir .
-            since the shell will have foo "open" in the above case and so Windows will
-            not allow the deletion. (Actually it does on 9X.)
-            FIXME: A potential workaround for this is for cygwin apps to *never* call
-            SetCurrentDirectory. */
-
-         if (strcasematch (real_dir, cygheap->cwd.win32)
-             && !strcasematch ("c:\\", cygheap->cwd.win32)
-             && !is_cwd
-             && SetCurrentDirectory ("c:\\"))
-           continue;
-
-         /* On 9X ERROR_ACCESS_DENIED is returned
-            if you try to remove a non-empty directory. */
-         if (err == ERROR_ACCESS_DENIED
-             && wincap.access_denied_on_delete ())
-           err = ERROR_DIR_NOT_EMPTY;
-
-         __seterrno_from_win_error (err);
-
-         /* Directory still exists, restore its characteristics. */
-         if (real_dir.has_attribute (FILE_ATTRIBUTE_READONLY))
-           SetFileAttributes (real_dir, real_dir);
-         if (is_cwd)
-           SetCurrentDirectory (real_dir);
-         break;
-       }
+      debug_printf ("got %d error from build_fh_name", fh->error ());
+      set_errno (fh->error ());
     }
+  else if (!fh->rmdir ())
+    res = 0;
+  delete fh;
 
+ done:
   syscall_printf ("%d = rmdir (%s)", res, dir);
   return res;
 }
index ba81cd3..6c0eaec 100644 (file)
@@ -1509,6 +1509,28 @@ fhandler_base::set_nonblocking (int yes)
   openflags = (openflags & ~O_NONBLOCK_MASK) | new_flags;
 }
 
+int
+fhandler_base::mkdir (mode_t)
+{
+  if (exists ())
+    set_errno (EEXIST);
+  else
+    set_errno (EROFS);
+  return -1;
+}
+
+int
+fhandler_base::rmdir ()
+{
+  if (!exists ())
+    set_errno (ENOENT);
+  else if (!pc.isdir ())
+    set_errno (ENOTDIR);
+  else
+    set_errno (EROFS);
+  return -1;
+}
+
 DIR *
 fhandler_base::opendir ()
 {
index c511443..ff2f315 100644 (file)
@@ -346,6 +346,8 @@ class fhandler_base
   void operator delete (void *);
   virtual HANDLE get_guard () const {return NULL;}
   virtual void set_eof () {}
+  virtual int mkdir (mode_t mode);
+  virtual int rmdir ();
   virtual DIR *opendir ();
   virtual dirent *readdir (DIR *);
   virtual _off64_t telldir (DIR *);
@@ -664,6 +666,8 @@ class fhandler_disk_file: public fhandler_base
   int msync (HANDLE h, caddr_t addr, size_t len, int flags);
   bool fixup_mmap_after_fork (HANDLE h, DWORD access, int flags,
                              _off64_t offset, DWORD size, void *address);
+  int mkdir (mode_t mode);
+  int rmdir ();
   DIR *opendir ();
   struct dirent *readdir (DIR *);
   _off64_t telldir (DIR *);
index e5b79e8..e1ec5b3 100644 (file)
@@ -1138,6 +1138,108 @@ fhandler_disk_file::lock (int cmd, struct __flock64 *fl)
   return 0;
 }
 
+int
+fhandler_disk_file::mkdir (mode_t mode)
+{
+  int res = -1;
+  SECURITY_ATTRIBUTES sa = sec_none_nih;
+  security_descriptor sd;
+
+  if (allow_ntsec && has_acls ())
+    set_security_attribute (S_IFDIR | ((mode & 07777) & ~cygheap->umask),
+                           &sa, sd);
+
+  if (CreateDirectoryA (get_win32_name (), &sa))
+    {
+      if (!allow_ntsec && allow_ntea)
+       set_file_attribute (false, NULL, get_win32_name (),
+                           S_IFDIR | ((mode & 07777) & ~cygheap->umask));
+#ifdef HIDDEN_DOT_FILES
+      char *c = strrchr (real_dir.get_win32 (), '\\');
+      if ((c && c[1] == '.') || *get_win32_name () == '.')
+       SetFileAttributes (get_win32_name (), FILE_ATTRIBUTE_HIDDEN);
+#endif
+      res = 0;
+    }
+  else
+    __seterrno ();
+
+  return res;
+}
+
+int
+fhandler_disk_file::rmdir ()
+{
+  int res = -1;
+
+  /* Even own directories can't be removed if R/O attribute is set. */
+  if (pc.has_attribute (FILE_ATTRIBUTE_READONLY))
+    SetFileAttributes (get_win32_name (),
+                      (DWORD) pc & ~FILE_ATTRIBUTE_READONLY);
+
+  for (bool is_cwd = false; ; is_cwd = true)
+    {
+      DWORD err, att = 0;
+      int rc = RemoveDirectory (get_win32_name ());
+
+      if (isremote () && exists ())
+       att = GetFileAttributes (get_win32_name ());
+
+      /* Sometimes smb indicates failure when it really succeeds, so check for
+        this case specifically. */
+      if (rc || att == INVALID_FILE_ATTRIBUTES)
+       {
+         /* RemoveDirectory on a samba drive doesn't return an error if the
+            directory can't be removed because it's not empty. Checking for
+            existence afterwards keeps us informed about success. */
+         if (!isremote () || att == INVALID_FILE_ATTRIBUTES)
+           {
+             res = 0;
+             break;
+           }
+         err = ERROR_DIR_NOT_EMPTY;
+       }
+      else
+       err = GetLastError ();
+
+      /* This kludge detects if we are attempting to remove the current working
+        directory.  If so, we will move elsewhere to potentially allow the
+        rmdir to succeed.  This means that cygwin's concept of the current working
+        directory != Windows concept but, hey, whaddaregonnado?
+        Note that this will not cause something like the following to work:
+        $ cd foo
+        $ rmdir .
+        since the shell will have foo "open" in the above case and so Windows will
+        not allow the deletion. (Actually it does on 9X.)
+        FIXME: A potential workaround for this is for cygwin apps to *never* call
+        SetCurrentDirectory. */
+
+      extern char windows_system_directory[];
+      if (strcasematch (get_win32_name (), cygheap->cwd.win32)
+         && !strcasematch (windows_system_directory, cygheap->cwd.win32)
+         && !is_cwd
+         && SetCurrentDirectory (windows_system_directory))
+       continue;
+
+      /* On 9X ERROR_ACCESS_DENIED is returned
+        if you try to remove a non-empty directory. */
+      if (err == ERROR_ACCESS_DENIED
+         && wincap.access_denied_on_delete ())
+       err = ERROR_DIR_NOT_EMPTY;
+
+      __seterrno_from_win_error (err);
+
+      /* Directory still exists, restore its characteristics. */
+      if (pc.has_attribute (FILE_ATTRIBUTE_READONLY))
+       SetFileAttributes (get_win32_name (), (DWORD) pc);
+      if (is_cwd)
+       SetCurrentDirectory (get_win32_name ());
+      break;
+    }
+
+  return res;
+}
+
 DIR *
 fhandler_disk_file::opendir ()
 {
index 6de3baa..abca009 100644 (file)
@@ -168,4 +168,3 @@ fhandler_dev_random::dump ()
 {
   paranoid_printf ("here, fhandler_dev_random");
 }
-