Issue #12307 has been updated by Benoit Daloze.


Usaku NAKAMURA wrote:
> To my understanding, POSIX doesn't say so.
> It only says that the mode is not changed when specified O_TRUNC for an existing file.
> ( http://pubs.opengroup.org/onlinepubs/9699919799/ )
> 
> This behavior is derived from the implementation of MSVCRT.
> Changing this is a little difficult because of the limitation of the Windows API.
> So, to persuade me, please show more strong example, such as a standard like POSIX, or more samples from UNIX-like platforms (BSDs, Solaris, AIX, HP-UX and so on).

My understanding is that the 3rd argument to open(2) only makes sense with O_CREAT.
In fact, most man pages don't even show the 3rd argument, and only explain it in the context of O_CREAT, so it is clearly an unexpected behavioral extension to interpret it in other cases.

OS X and Open BSD man pages seem to explain that clearly:
http://man.openbsd.org/?query=open&apropos=0&sec=0&arch=default&manpath=OpenBSD-current:
"The flags argument may indicate the file is to be created if it does not exist (by specifying the O_CREAT flag), in which case the file is created with a mode specified by an additional argument of type mode_t as described in chmod(2) and modified by the process' umask value (see umask(2))."

And I believe the POSIX page you linked as well, in slightly less clear terms:
"If the file exists, this flag has no effect except as noted under O_EXCL below.
Otherwise, the file shall be created; the user ID of the file shall be set ...; the group ID of the file shall be set ...; and the access permission bits (see sys/stat.h) of the file mode shall be set to *the value of the argument following the oflag argument* taken as type mode_t modified as follows: a bitwise AND is performed on the file-mode bits and the corresponding bits in the complement of the process' file mode creation mask."

This is the only time the 3rd argument is mentioned and says that O_CREAT does set the permission bits.
It is also said that if O_CREAT is passed and the file exists it has no effect (and so the 3rd argument is not interpreted).

The document does not explicitly forbids to change file permissions (except for O_TRUNC but the motivation seems to be to have well-defined semantics with concurrent access and change nothing but the file size), but I believe that to be an unexpected and unreasonable side-effect. If such a thing happens, then one could argue any random function taking extra arguments is allowed to change file permissions.

----------------------------------------
Bug #12307: File.new and File.open change permissions even if the file exists on Windows
https://bugs.ruby-lang.org/issues/12307#change-58200

* Author: Benoit Daloze
* Status: Open
* Priority: Normal
* Assignee: 
* ruby -v: ruby 2.2.4p230 (2015-12-16 revision 53155) [i386-mingw32]
* Backport: 2.1: UNKNOWN, 2.2: UNKNOWN, 2.3: UNKNOWN
----------------------------------------
For instance:

~~~
# New file
File.open("abc", "w", 0666) { |f|
  puts f.stat.mode.to_s(8) # => 100666, OK
}

# File exists
File.open("abc", "w", 0466) { |f|
  puts f.stat.mode.to_s(8) # => 100444, BUG
}
~~~

So the mode of the file was changed even though the file already exists.
This is inconsistent with the behavior on other platforms such as UNIX which only consider mode for new files.
open(2) is fairly clear about this on Linux and OS X: "if neither O_CREAT nor O_TMPFILE is specified, then mode is ignored".



-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>