Skip to content

[Windows] O_EXCL should override O_TRUNC #2505

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 13, 2019

Conversation

gmittert
Copy link
Contributor

@gmittert gmittert commented Sep 9, 2019

Setting O_CREAT and O_EXCL together should always force the creation
of a new file and fail otherwise, regardless of if O_TRUNC is set.

In addition, O_EXCL should only take effect if O_CREAT is set,
otherwise, the result is undefined behavior per the specification (in
our case, setting to OPEN_EXISTING).

@gmittert gmittert requested a review from compnerd September 9, 2019 20:01
@gmittert
Copy link
Contributor Author

gmittert commented Sep 9, 2019

@swift-ci please test linux

@@ -906,15 +906,16 @@ CF_EXPORT int _NS_open(const char *name, int oflag, int pmode) {

DWORD dwCreationDisposition;
switch (oflag & (O_CREAT | O_EXCL | O_TRUNC)) {
case O_CREAT | O_EXCL | O_TRUNC:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that O_TRUNC is interesting, the behaviour between these two is different I believe.

Copy link
Contributor Author

@gmittert gmittert Sep 9, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it is different, referencing https://pubs.opengroup.org/onlinepubs/9699919799/:

O_EXCL
If O_CREAT and O_EXCL are set, open() shall fail if the file exists. The check for the existence of the file and the creation of the file if it does not exist shall be atomic with respect to other threads executing open() naming the same filename in the same directory with O_EXCL and O_CREAT set. If O_EXCL and O_CREAT are set, and path names a symbolic link, open() shall fail and set errno to [EEXIST], regardless of the contents of the symbolic link. If O_EXCL is set and O_CREAT is not set, the result is undefined.

and

O_TRUNC
If the file exists and is a regular file, and the file is successfully opened O_RDWR or O_WRONLY, its length shall be truncated to 0, and the mode and owner shall be unchanged. It shall have no effect on FIFO special files or terminal device files. Its effect on other file types is implementation-defined. The result of using O_TRUNC without either O_RDWR or O_WRONLY is undefined.

In the case of O_CREAT | O_EXCL | O_TRUNC, if a file exists, then O_EXCL causes open to fail regardless of O_TRUNC. If the file doesn't exist, then O_TRUNC doesn't do anything and is the same as O_CREAT | O_EXCL.

Setting `O_CREAT` and `O_EXCL` together should always force the creation
of a new file and fail otherwise, regardless of if O_TRUNC is set.

In addition, `O_EXCL` should only take effect if `O_CREAT` is set,
otherwise, the result is undefined behavior per the specification (in
our case, setting to OPEN_EXISTING).
@gmittert
Copy link
Contributor Author

@swift-ci please test

@compnerd compnerd merged commit 46435a1 into swiftlang:master Nov 13, 2019
@gmittert gmittert deleted the ExclusiveBehavior branch November 13, 2019 03:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants