Go and file perms on Windows

Michal Pristas
3 min readNov 14, 2018

--

Every now and then you need to play with files, create, read, write and check permissions. Today I will focus on the last part. While permissions on Unix are easy and works as expected, the statement is not so true for Windows.

According to https://golang.org/pkg/os/#Chmod

On Windows, the mode must be non-zero but otherwise only the 0200 bit (owner writable) of mode is used; it controls whether the file’s read-only attribute is set or cleared. attribute. The other bits are currently unused. Use mode 0400 for a read-only file and 0600 for a readable+writable file.

Maybe it’s only me but from this few sentences, I do not know what to expect when getting fileInfo.Mode(). So let’s run few experiments and understand a bit better how this behaves.

Maybe you already know that and it’s clear to you. Following experiments will be simple, nothing you wouldn’t do yourself. But my memory gets corrupted over time so here I am backing them up into the cloud.

The Code

For each experiment, I will use this simple application:

package mainimport (
"log"
"os"
)
func main() {
fileName := "file.txt"
fileInfo, err := os.Stat(fileName)
if err != nil {
log.Fatalln(err)
}
log.Println(fileInfo.Mode())
}

Experiment 1: Basic file

By basic file, I understand a file which I create with a normal user running application. Simple mkfile. Nothing fancy.

2018/11/14 15:43:00 -rw-rw-rw-

Basic file is readable and writable to the world at least in Unix world (0666).

Experiment 2: Remove perms for user keep Administrators group

The change here is that we’re trying to access a file which is not accessible for my user just an Administrator.

The output is as follows:

2018/11/14 16:43:00 chmod file.txt: Access is denied.
exit status 1

What would result in 0200 returns error on Windows.

Experiment 3: Attribute — hidden

Windows UI gives me options to change 2 attributes Hidden and Read-only. I do not expect the first one to have any effect but let’s take a look.

The output is as follows:

2018/11/14 15:43:00 -rw-rw-rw-

No change, in Explorer hidden files are not visible but are accessible without changes in permissions.

Experiment 4: Attribute — read-only

With read-only attribute, I would, in fact, expect a change in Mode and my expectation turned out right:

2018/11/14 15:43:00 -r--r--r--

Fun with Chmod

Now let's see how Chmods changes the result (and if it does)

I changed the code to look like this

package mainimport (
"log"
"os"
)
func main() {
fileName := "file.txt"
if err := os.Chmod(fileName, 0600); err != nil {
log.Fatalln(err)
}

fileInfo, err := os.Stat(fileName)
if err != nil {
log.Fatalln(err)
}
log.Println(fileInfo.Mode())
}

and will change mode value before each Experiment for simplicity.

Experiment 5: chmod 0600

By changing to 0600 nothing changes, according to docs 0600 means read+write and it’s true.

2018/11/14 15:43:00 -rw-rw-rw-

Experiment 6: chmod 0400

Change to 0400 should result in setting the read-only attribute.

After the run, I checked the properties of the file and it is in fact changed:

Changed attribute to read-only

fileInfo.Mode() returns 0444 as we saw in Experiment 4

2018/11/14 15:43:00 -r--r--r--

Groups and permissions stayed intact.

Experiment 7: chmod 0200

Now changing from 0444 to 0200.

I was wondering whether it will remove perms or reset it to 0666.

2018/11/14 15:43:00 -rw-rw-rw-

Former is the case here. Read-only attribute got cleared and perms were set to 0666. I guess the “0200 bit (owner writable)” means that it sets 0666 for the owner and the owner is me.

Summary

So it looks like with windows you can sum up modes into 3 cases:

  • writable (0666)
  • read-only (0444)
  • not accessible (returns error)

--

--