Skip to content
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

os: os.OpenFile() ignores FileMode when truncating a existing file #33605

Closed
WestleyK opened this issue Aug 12, 2019 · 6 comments

Comments

@WestleyK
Copy link

commented Aug 12, 2019

What version of Go are you using (go version)?

$ go version
go version go1.12.7 linux/amd64

Does this issue reproduce with the latest release?

Yes

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/westleyk/.cache/go-build"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/westleyk/go"
GOPROXY=""
GORACE=""
GOROOT="/usr/local/go"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build074655655=/tmp/go-build -gno-record-gcc-switches"

What did you do?

Here is a test code, that will use os.OpenFile() to open a test file with 0777:

package main

import (
	"log"
	"os"
)

func main() {
	f, err := os.OpenFile("foo.txt", os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0777)
	if err != nil {
		log.Fatalf("failed opening file: %s", err)
	}

	f.Close()
}

What did you expect to see?

When I run the code with go run test.go, and foo.txt does not exist, I get the expected results:

$ ls -l foo.txt
ls: cannot access 'foo.txt': No such file or directory

$ go run test.go 

$ ls -l foo.txt
-rwxr-xr-x 1 westleyk westleyk 0 Aug 12 12:16 foo.txt

But, when foo.txt already exist (with the "default" permission), the specified 777 file permission is ignored and not applied to foo.txt...

$ touch foo.txt
$ ls -l foo.txt 
-rw-r--r-- 1 westleyk westleyk 0 Aug 12 12:17 foo.txt

$ go run test.go 

$ ls -l foo.txt 
-rw-r--r-- 1 westleyk westleyk 0 Aug 12 12:17 foo.txt

I expected when truncating the already-existing file, os.OpenFile will truncated it, and apply the specified file permission.


What did you see instead?

os.OpenFile() ignored the 0777 permission, and continued without an error.

@dmitshur dmitshur added this to the Go1.14 milestone Aug 13, 2019

@dmitshur

This comment has been minimized.

Copy link
Member

commented Aug 13, 2019

Thanks for reporting.

Do you know (or can you check) what was the behavior in Go 1.11 or older versions? In other words, is this a recent regression, or has it always behaved like that?

@WestleyK

This comment has been minimized.

Copy link
Author

commented Aug 13, 2019

@dmitshur, I got the same behavior as above with go1.11, all the way down to go1.2.2. So all the go versions are like this.

@networkimprov

This comment has been minimized.

Copy link

commented Aug 13, 2019

I believe you'll see the same behavior from a C program; i.e. that's POSIX.

@dmitshur

This comment has been minimized.

Copy link
Member

commented Aug 13, 2019

Thank you for confirming this is not a recent regression, that's very helpful.

This issue is under the Go1.14 milestone, so we can investigate it during the upcoming development cycle.

@WestleyK

This comment has been minimized.

Copy link
Author

commented Aug 13, 2019

Yeah, a similar c program does this same behavior, which seems a little weird... I guess this is not a issue with Go. Thanks for the help! Close when ready 👍

@odeke-em

This comment has been minimized.

Copy link
Member

commented Aug 13, 2019

Closing as per #33605 (comment) and thanks @WestleyK for the report, @dmitshur for the triage and @networkimprov for catching that an equivalent C program produces the same result.

For the record here is the equivalent C program

#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/errno.h>
#include <stdio.h>

int main() {
    int fd = open("foo.txt", O_CREAT|O_TRUNC|O_WRONLY, 0777);
    if (fd < 0) {
        fprintf(stderr, "opening file: %s\n", strerror(errno));
        return -1;
    }
    close(fd);
    return 0;
}

and when run, here are the results:

$ gcc main.c -o main
$ ls -lrth
total 32
-rw-r--r--  1 emmanuelodeke  staff   315B 13 Aug 00:18 main.c
-rwxr-xr-x  1 emmanuelodeke  staff   8.5K 13 Aug 00:19 main
$ ./main 
$ ls -lrth
total 32
-rw-r--r--  1 emmanuelodeke  staff   315B 13 Aug 00:18 main.c
-rwxr-xr-x  1 emmanuelodeke  staff   8.5K 13 Aug 00:19 main
-rwxr-xr-x  1 emmanuelodeke  staff     0B 13 Aug 00:19 foo.txt
$ ./main 
$ ls -lrth
total 32
-rw-r--r--  1 emmanuelodeke  staff   315B 13 Aug 00:18 main.c
-rwxr-xr-x  1 emmanuelodeke  staff   8.5K 13 Aug 00:19 main
-rwxr-xr-x  1 emmanuelodeke  staff     0B 13 Aug 00:20 foo.txt
$ chmod 0777 foo.txt # Now trying with chmod and this should change the permissions
$ ls -lrth
total 32
-rw-r--r--  1 emmanuelodeke  staff   315B 13 Aug 00:18 main.c
-rwxr-xr-x  1 emmanuelodeke  staff   8.5K 13 Aug 00:19 main
-rwxrwxrwx  1 emmanuelodeke  staff     0B 13 Aug 00:20 foo.txt

@odeke-em odeke-em closed this Aug 13, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
4 participants
You can’t perform that action at this time.