Subject: bug#22795: 25.0.91; Can't write read only file on w32

From: "Ota, Takaaki" <[email-masked]>
Date: Mon, 29 Feb 2016 08:40:35 -0800

Fri, 26 Feb 2016 23:53:33 +0200: Eli Zaretskii <[email-masked]> wrote:

> > Date: Fri, 26 Feb 2016 11:26:05 -0800
> > CC: <[email-masked]>
> > From: "Ota, Takaaki" <[email-masked]>
> > 
> > I think this is something to do with my mingw.  I cannot remember when
> > I updated mingw last time.  Here is the comparison between trace in
> > emacs-24.5 and emacs-25.0.91.  The difference is in the open system
> > call.  Both pass the same set of parameters to open but emacs-24.5
> > gets 3 and emacs-25.0.91 gets -1.  Both emacs were built using mingw
> > but I cannot guarantee they are the same version of mingw.
> 
> I very much doubt this has something to do with MinGW, because MinGW
> uses the Windows runtime library, so running the two executables on
> the same box will use the same library.
> 
> > Can you think of any other reason than they were built with
> > different mingw to explain the difference of the open() behavior?
> 
> Step into the 'open' call -- it's shadowed by 'sys_open' defined on
> w32.c.  What flags are passed to _wopen in each case?  Your trace from
> GDB seems to indicate that in the case of 25.0.91 we pass O_BINARY,
> while in 24.5 we don't.  If this is really the case, maybe that's the
> reason, although I don't currently see why it would lead to a failure
> (and it certainly doesn't fail for me).  Is there any other difference
> in flags and modes with which we call _wopen in each case?
> 
> Also, I think by the time this code is run, the original file should
> have been renamed to the backup-file name, so the file you are saving
> should not exist on disk by the time we open it.  If that is not the
> case with 25.0.91, then perhaps what fails is not the open call, but
> the rename call before that.
> 
> Thanks.
> 

I am now very much puzzled.  Here is the trace up to _wopen().  I
printed parameters to _wopen() and they are identical yet one succeeds
and the other fails.

================================ emacs-24.5 =====================================

4819      open_flags |= EQ (mustbenew, Qexcl) ? O_EXCL : !NILP (append) ? 0 : O_TRUNC;
(gdb) 
4820      if (NUMBERP (append))
(gdb) 
4823        open_flags |= O_APPEND;
(gdb) 
4830      if (open_and_close_file)
(gdb) 
4832          desc = emacs_open (fn, open_flags, mode);
(gdb) s
emacs_open (file=file@entry=0x5bf6ec8 "c:/d/ota/memo", 
    oflags=oflags@entry=33537, mode=mode@entry=384) at sysdep.c:2143
2143    {
(gdb) n
2145      oflags |= O_CLOEXEC;
(gdb) 
2146      while ((fd = open (file, oflags, mode)) < 0 && errno == EINTR)
(gdb) s
sys_open (path=path@entry=0x5bf6ec8 "c:/d/ota/memo", oflag=oflag@entry=33665, 
    mode=mode@entry=384) at w32.c:4172
4172    {
(gdb) n
4173      const char* mpath = map_w32_filename (path, NULL);
(gdb) 
4180          filename_to_utf16 (mpath, mpath_w);
(gdb) 
4176      if (w32_unicode_filenames)
(gdb) 
4180          filename_to_utf16 (mpath, mpath_w);
(gdb) 
4176      if (w32_unicode_filenames)
(gdb) 
4180          filename_to_utf16 (mpath, mpath_w);
(gdb) 
4184          if ((oflag & (_O_CREAT | _O_EXCL)) != (_O_CREAT | _O_EXCL))
(gdb) 
4185            res = _wopen (mpath_w, (oflag & ~_O_CREAT) | _O_NOINHERIT, mode);
(gdb) p mpath_w
$1 = L"c:\\d\\ota\\memo\000\340\074\311\003\000\000\300\235\017\001\001\000\xe558\210\364\141\073\005\xf822\255\003\116\137\x5c9\xf822\255\003\325\245\334\003\xe554\210\b\000\xe550\210\xe648\210\375\226\022\001\030\000\xf822\255\003\xf822\255\003\000\000\n\000\102\225\312\003\142\372\256\003\102\225\312\003\xf822\255\003\xf822\255\003\xf822\255\003\000\000\272\374\075\167@\000\065\302\057\001\320\224\022\001\000\000\000\000\000\000\000\000\xe5a4\210\000\000\340\245\077\001\350\245\077\001\000\000\000\000\334\136\325\120\352\013\000ä\000\003\001\000\xed4b\320\126\154\153\030\001\000\000\000\000\xe60c\210\324\134\027\001\003\000\xe60c\210\000\000\xe600\210\000\255\x1fb5\000\255\x1fb5\xe6e8\210\330\162\023\001\003\000\xe60c\210\000\000\000\255\x1fb5\030\000\030\000\002\000\000\100\000\342\374\312\003\340\374\312\003\344\267\042\001\300\235\017\001\121\305\057\001\321\267\042\001\220\141\073\005\xf822\255\003\000\255\x1fb5\000\255\x1fb5\xed4b\320\126\220\267\042\001\005\000\005\000\350\265\034\001\071\212\017\001\023\000\102\225\312\003$\000\xf822\255\003\000\000\000\000\xf822\255\003\xe70c\210\xed4b\000\001\225\267\042\001"...
(gdb) p oflag
$2 = 33665
(gdb) p mode
$3 = 384
(gdb) s
4186          if (res < 0)
(gdb) p res
$4 = 3

================================ emacs-25.0.91 =====================================

4810      open_flags |= EQ (mustbenew, Qexcl) ? O_EXCL : !NILP (append) ? 0 : O_TRUNC;
(gdb) 
4811      if (NUMBERP (append))
(gdb) 
4810      open_flags |= EQ (mustbenew, Qexcl) ? O_EXCL : !NILP (append) ? 0 : O_TRUNC;
(gdb) 
4821      if (open_and_close_file)
(gdb) 
4823          desc = emacs_open (fn, open_flags, mode);
(gdb) s
emacs_open (file=file@entry=0x883a4ac "c:/d/ota/memo", 
    oflags=oflags@entry=33537, mode=mode@entry=384) at sysdep.c:2260
2260    {
(gdb) n
2263        oflags |= O_BINARY;
(gdb) 
2264      oflags |= O_CLOEXEC;
(gdb) 
2265      while ((fd = open (file, oflags, mode)) < 0 && errno == EINTR)
(gdb) s
sys_open (path=path@entry=0x883a4ac "c:/d/ota/memo", oflag=oflag@entry=33665, 
    mode=mode@entry=384) at w32.c:4290
4290    {
(gdb) n
4291      const char* mpath = map_w32_filename (path, NULL);
(gdb) 
4298          filename_to_utf16 (mpath, mpath_w);
(gdb) 
4294      if (w32_unicode_filenames)
(gdb) 
4298          filename_to_utf16 (mpath, mpath_w);
(gdb) 
4294      if (w32_unicode_filenames)
(gdb) 
4298          filename_to_utf16 (mpath, mpath_w);
(gdb) 
4302          if ((oflag & (_O_CREAT | _O_EXCL)) != (_O_CREAT | _O_EXCL))
(gdb) 
4303            res = _wopen (mpath_w, (oflag & ~_O_CREAT) | _O_NOINHERIT, mode);
(gdb) p mpath_w
$2 = L"c:\\d\\ota\\memo\000\006\000\002\145\021\133\321\x889\000\000\324\302\x82d\300\170\000\310\317\123\377\310\317\123\377\310\317\123\377^\000\063\317\x889\000\000\000\000\310\317\123\377\040\201\000\310\317\123\377\002\000ä\000\000\000\xe3dc\210p\000\062\117\061\001\073\255\022\001\000\160\375\176\154\041\000\074\030\000ÿ\000\n\000\000\000\xe488\210\xa69a\027\001ä\000\xe454\210\100\102\017\000\000'\000\110\121·\xe51c\210\045\143\103\167\000\000\000\000\000\000\000\000\xe444\210\000\000\x29e0\001\002\x29e8\001\002\000\000\000\000\xddf1\327\120\352\013\000\xe380\210\005\000\002\000\120\213\030\002\005\000\xd868\042\001\000\000\000\000\023\000\023\000\xd86c\042\001\xe4a0\210\021\122\061\001\xd85c\042\001\062\117\061\001\xee70\210\000\000\xe4a0\210\xedef\320\126\xd840\042\001\022\000\012\024\000\xe58c\210\164\261\017\001\xd85c\042\001\xd86d\042\001R\000\012\024\000\005\000\xe58c\210\005\000\xe58c\210\000\000\xd845\042\001\xf658\x805\xf4dc\x805\022\000\000\000\002\145\021\xd840\042\001\022\000\160\214\135\377"...
(gdb) p oflag
$3 = 33665
(gdb) p mode
$4 = 384
(gdb) s
[New Thread 8556.0x2230]
[New Thread 8556.0x12c4]
4304          if (res < 0)
(gdb) p res
$5 = -1