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

Created on 12 Aug 2019  路  6Comments  路  Source: golang/go

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.

FrozenDueToAge NeedsInvestigation

Most helpful comment

Closing as per https://github.com/golang/go/issues/33605#issuecomment-520672726 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

All 6 comments

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?

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

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

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.

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 :+1:

Closing as per https://github.com/golang/go/issues/33605#issuecomment-520672726 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
Was this page helpful?
0 / 5 - 0 ratings