On Thu, Mar 15, 2012 at 5:02 PM, Benjamin Fritz <[email protected]>wrote:

> On Thu, Mar 15, 2012 at 2:28 PM, Bram Moolenaar <[email protected]>
> wrote:
> >
> > David Pope wrote:
> >
> >> On Wednesday, July 20, 2011 3:54:09 PM UTC-4, Craig Barkhouse wrote:
> >>
> >> > The mch_is_linked() function in os_win32.c only checks if there is
> >> > more than one hard link (i.e. name) for the file.  It doesn't check
> >> > if the file is a symbolic link.  By contrast the Unix code does
> >> > check if the file is a symbolic link.
> >> >
> >> > Sounds like a TODO item.
> >>
> >> Hello all, did this ever get turned into a TODO item?  I've
> >> encountered this myself (I'm syncing all my vim configuration across
> >> machines using Dropbox, with symbolic links for .vim/, .vimrc, and
> >> .gvimrc).
> >>
> >> I see in the latest Mercurial code that mch_is_linked() still only
> >> checks for hard links.  If it's not already in someone's TODO bucket I
> >> can work on a fix.  The APIs are straightforward in the versions of
> >> Windows that support symlinks; I suspect more of the work will be in
> >> figuring out how to get that support into vim without breaking binary
> >> compatibility on older systems.  Would the maintainers be interested
> >> in seeing a patch for this?
> >
> > A patch definitely helps.  And a way to reproduce the problem.
> >
>
> Reproduction is easy.
>
> 1. Create a symbolic link on Windows. (e.g. mklink link_path target_path)
> 2. open the file in Vim
> 3. write the file from Vim
>
> The symbolic link has been destroyed, now it's a "real" file separate
> from the file it was originally linked to.


Here's my first shot at a patch that fixes the "can't save to symlinks" bug
on Windows.  It augments the Windows version of mch_is_linked() to also
return TRUE if the file is a symbolic link, so the delete-then-move pattern
is avoided and the symlink is preserved.

The patch also addresses a separate bug I encountered while fixing the
above.  If you set nowritebackup on Windows, and then save a file that you
opened via a symbolic link, the readonly attribute gets set.

The cause was that the Windows version of mch_getperm() was returning
Windows FILE_ATTRIBUTE_* flags instead of the Unix-style flags in mode_t,
which was then later passed unchanged to the CRT open() function (which
expects mode_t flags).

For a normal (non-symlink, non-whatever) file, this just happened to be
FILE_ATTRIBUTE_NORMAL (0200, 0x80), which maps to the Unix S_IWUSR.  By
sheer chance, this meant that normal files correctly received write
permission, i.e. no readonly flag.

For a symlink, FILE_ATTRIBUTE_NORMAL is not set; for example, the symlink I
was testing against returned FILE_ATTRIBUTE_ARCHIVE (040, 0x20) and
FILE_ATTRIBUTE_REPARSE_POINT (02000, 0x400).  By the time these made it
back to create(), it appeared as though we wanted no write permissions,
i.e. set the readonly flag.

The patch changes os_win32.c so that all code outside of the file deals
with mode_t flags, while os_win32.c itself deals with FILE_ATTRIBUTE_*
flags.  There are a couple of new internal helper functions for this.

This is my first patch, so I'm sure I messed up somewhere; feedback is
welcome.  Sorry if the above is too wordy, this was a fun one to diagnose.
 ;)

Caveats:
  * I have no way to test Win98, can someone help?  There is lots of Win98
fallback code in os_win32.c (to use non-Unicode functions when FEAT_MBYTE
is defined).
  * I added win32_* signatures to os_win32.pro for the new internal
functions; I'm not sure if the *.pro files are intended mainly for function
exports, or just to avoid having to make forward declarations (as I've done
here).
  * I'm using a couple of CRT functions that weren't in use before; I don't
know if it's reasonable to assume that they work as expected on all the old
platforms that are required.

----
David Pope

-- 
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

Attachment: symlinkfix.diff
Description: Binary data

Raspunde prin e-mail lui