Here’s the problem: I called os.Chmod("test.txt", 777) in the code, hoping to make the read/write and execute permissions of the file available to all users.

After executing the code, I used the command ls to look at the list of files by hand. Here is the list.

$ ls -l test.txt
-r----x--x  1 cyhone  1085706827  0 Jun 20 13:27 test.txt

Surprisingly, the file permissions do not change to rwxrwxrwx as expected. Instead, after execution, the current user is left with read permissions, while other users have only executable permissions and no read/write permissions.

Because this is such a simple and silly mistake, let’s start with a straightforward conclusion:

  1. in C and Go, if you want to change the file permission form to rwxrwxrwx, you need to write 0777 instead of 777.
  2. 0777 is in octal format and 777 is in decimal format. When representing such permissions in Go, it is easier and more accurate to use octal representation if you want to align the chmod command.
  3. if you call chmod directly from the command line, not in code, then both 0777 and 777 are fine.

This is a very simple problem, but I embarrassingly fell into this trap, so I’ll share the problem and its cause.


Why does rwxrwxrwx correspond to the octal 0777 and not to 777?

The reason is that when the underlying layer translates the number into the corresponding authority, it actually uses the binary bit corresponding to that number and translates the last 9 bits bit by bit. For example, for octal 0777, the binary representation is as follows.


From the above diagram, 0777 represents rwxrwxrwx.

And for the decimal 777, its binary representation is as follows.


Looking at its bit-by-bit translation, it just so happens that the last 9 bits of 777 represent r----x--x , which agrees with our running result.

Then again, according to this theory, if we had to represent rwxrwxrwx in decimal, then it would be 511.

We can experiment with the code:

fileMode := os.FileMode(511)
fmt.Println(fileMode.String()) // -rwxrwxrwx