Hi Bram,

2016/1/17 Sun 23:57:02 UTC+9 Bram Moolenaar:
> Patch 7.4.1114 (after 7.4.1107)
> Problem:    delete() does not work well with symbolic links.
> Solution:   Recognize symbolik links.
> Files:      src/eval.c, src/fileio.c, src/os_unix.c, src/proto/os_unix.pro,
>             src/testdir/test_delete.vim, runtime/doc/eval.txt

This patch still has some problems on Windows.

* Doesn't handle junctions properly. They should be handled as same as symlinks.
* A symlink or junction to a directory should removed by RemoveDirectory()
  not DeleteFile().

Attached patch fixes them.
I also think os_win32.c should have mch_isrealdir().

Regards,
Ken Takata

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.
# HG changeset patch
# Parent  4ab7ebda8ab1cd75e8f65432ed1be2f14fc58a6c

diff --git a/src/fileio.c b/src/fileio.c
--- a/src/fileio.c
+++ b/src/fileio.c
@@ -7298,14 +7298,10 @@ delete_recursive(char_u *name)
     /* A symbolic link to a directory itself is deleted, not the directory it
      * points to. */
     if (
-# if defined(WIN32)
-	 mch_isdir(name) && !mch_is_symbolic_link(name)
+# if defined(UNIX) || defined(WIN32)
+	 mch_isrealdir(name)
 # else
-#  ifdef UNIX
-	 mch_isrealdir(name)
-#  else
 	 mch_isdir(name)
-#  endif
 # endif
 	    )
     {
diff --git a/src/os_win32.c b/src/os_win32.c
--- a/src/os_win32.c
+++ b/src/os_win32.c
@@ -3133,6 +3133,17 @@ mch_isdir(char_u *name)
 }
 
 /*
+ * return TRUE if "name" is a directory, NOT a symlink to a directory
+ * return FALSE if "name" is not a directory
+ * return FALSE for error
+ */
+    int
+mch_isrealdir(char_u *name)
+{
+    return mch_isdir(name) && !mch_is_symbolic_link(name);
+}
+
+/*
  * Create directory "name".
  * Return 0 on success, -1 on error.
  */
@@ -3193,10 +3204,10 @@ mch_is_hard_link(char_u *fname)
 }
 
 /*
- * Return TRUE if file "fname" is a symbolic link.
+ * Return TRUE if "name" is a symbolic link (or a junction).
  */
     int
-mch_is_symbolic_link(char_u *fname)
+mch_is_symbolic_link(char_u *name)
 {
     HANDLE		hFind;
     int			res = FALSE;
@@ -3207,7 +3218,7 @@ mch_is_symbolic_link(char_u *fname)
     WIN32_FIND_DATAW	findDataW;
 
     if (enc_codepage >= 0 && (int)GetACP() != enc_codepage)
-	wn = enc_to_utf16(fname, NULL);
+	wn = enc_to_utf16(name, NULL);
     if (wn != NULL)
     {
 	hFind = FindFirstFileW(wn, &findDataW);
@@ -3216,7 +3227,7 @@ mch_is_symbolic_link(char_u *fname)
 		&& GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
 	{
 	    /* Retry with non-wide function (for Windows 98). */
-	    hFind = FindFirstFile(fname, &findDataA);
+	    hFind = FindFirstFile(name, &findDataA);
 	    if (hFind != INVALID_HANDLE_VALUE)
 	    {
 		fileFlags = findDataA.dwFileAttributes;
@@ -3232,7 +3243,7 @@ mch_is_symbolic_link(char_u *fname)
     else
 #endif
     {
-	hFind = FindFirstFile(fname, &findDataA);
+	hFind = FindFirstFile(name, &findDataA);
 	if (hFind != INVALID_HANDLE_VALUE)
 	{
 	    fileFlags = findDataA.dwFileAttributes;
@@ -3244,7 +3255,8 @@ mch_is_symbolic_link(char_u *fname)
 	FindClose(hFind);
 
     if ((fileFlags & FILE_ATTRIBUTE_REPARSE_POINT)
-	    && reparseTag == IO_REPARSE_TAG_SYMLINK)
+	    && (reparseTag == IO_REPARSE_TAG_SYMLINK
+		|| reparseTag == IO_REPARSE_TAG_MOUNT_POINT))
 	res = TRUE;
 
     return res;
@@ -5849,7 +5861,8 @@ mch_delay(
 
 
 /*
- * this version of remove is not scared by a readonly (backup) file
+ * This version of remove is not scared by a readonly (backup) file.
+ * This can also remove a symbolic link like Unix.
  * Return 0 for success, -1 for failure.
  */
     int
@@ -5860,6 +5873,13 @@ mch_remove(char_u *name)
     int		n;
 #endif
 
+    /*
+     * On Windows, deleting a directory's symbolic link is done by
+     * RemoveDirectory(): mch_rmdir.  It seems unnatural, but it is fact.
+     */
+    if (mch_isdir(name) && mch_is_symbolic_link(name))
+	return mch_rmdir(name);
+
     win32_setattrs(name, FILE_ATTRIBUTE_NORMAL);
 
 #ifdef FEAT_MBYTE
diff --git a/src/proto/os_win32.pro b/src/proto/os_win32.pro
--- a/src/proto/os_win32.pro
+++ b/src/proto/os_win32.pro
@@ -21,6 +21,7 @@ int mch_setperm __ARGS((char_u *name, lo
 void mch_hide __ARGS((char_u *name));
 int mch_ishidden __ARGS((char_u *name));
 int mch_isdir __ARGS((char_u *name));
+int mch_isrealdir __ARGS((char_u *name));
 int mch_mkdir __ARGS((char_u *name));
 int mch_rmdir __ARGS((char_u *name));
 int mch_is_hard_link __ARGS((char_u *fname));

Raspunde prin e-mail lui