0

My intention was to open two files, where the second one would be brand new, with the same permissions as the first file. So to test my code I changed the first file permissions to "777". Then I proceeded to run my program. And to my surprise, the permission of the newborn file2 were wrong! They where set to 755. Even weirder is when I set the first file to "111" and tried again, the result now was "1204". Can someone explain to me this weird behavior?

Here's my code

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

int main(int argc, char *args[]) {
    struct stat stats;
    int fd1, fd2;
    fd1 = open("testfile.txt", O_RDONLY);
        /* Error check*/
        if (fd1 == -1) {
            /* Error handling */
            perror("Opening");
            printf("Unable to open file: %s\n", "testfile.txt");
            printf("ERROR: %s\n", strerror(errno));
            return 1;
        }
    if(fstat(fd1, &stats) == -1)
    {
        printf("Error while getting stats: %s\n", strerror(errno));
        exit(-1);
    }

    //Receives the output file as a main argument . . .
    if (argc > 1)
    {
        //(stats.st_mode = Gets the mask of the first file)
        fd2 = open(args[1], O_WRONLY|O_CREAT, stats.st_mode);
        /* Error check*/
        if (fd2 == -1) {
            /* Error handling */
            perror("Opening");
            printf("Unable to open file: %s\n",args[1]);
            printf("ERROR: %s\n", strerror(errno));
            return 1;
        }
    }
    //. . . if it doesn't it creates a standard one warning you about it
    else
    {
        fd2 = open("Nope.txt", O_WRONLY|O_CREAT, stats.st_mode);
        /* Error check*/
        if (fd2 == -1) {
            /* Error handling */
            perror("Opening");
            printf("Unable to open file: %s\n",args[1]);
            printf("ERROR: %s\n", strerror(errno));
            return 1;
        }
        printf("Standard file created\n");
    }
    close(fd1);
    close(fd2);
    return 0;
}

I tried to make it as tidy as I could :)

B.Castarunza
  • 135
  • 12
  • Are you converting between different bases correctly in all the right places? oct1204 is the same as dec644, which is rw- r-- r--, a fairly typical permission. – Thomas Jager May 07 '20 at 15:51
  • Are you allowed to override the `group` and `other` permissions for a volume? – Weather Vane May 07 '20 at 15:54
  • Hi interesting, the `st_mode` field contains other flags as well. To convert this to a file mode that can be used by `open`, perhaps this would be of interest: https://stackoverflow.com/questions/11669504/store-st-mode-from-stat-in-a-file-and-reuse-it-in-chmod – IronMan May 07 '20 at 15:57
  • @Thomas Jager Yeah Octal; – B.Castarunza May 07 '20 at 17:37
  • @Weather Vane Sorry, I don't even know what volume means in this contest; – B.Castarunza May 07 '20 at 17:40
  • @IronMan Thank you, I'll definitely look into it! – B.Castarunza May 07 '20 at 17:40
  • By 'volume' I meant 'folder' or 'directory' etc. If the 'group' does not have permissions for a folder, are you allowed to give them further along the folder tree? – Weather Vane May 07 '20 at 17:41

1 Answers1

0

From open(2) man page on the part about O_CREATE:

The effective mode is modified by the process's umask in the usual way: in the absence of a default ACL, the mode of the created file is (mode & ~umask).

If you type umask in bash you can see what value is used and which bits get cleared from the mode you provide.

Julien Thierry
  • 651
  • 4
  • 11
  • Now it all makes sense! (The squigly line is equal to the NOT operator right?) – B.Castarunza May 07 '20 at 23:32
  • wierdly enough the same problem happened again with the mkdir() instruction. My default umask is set to *022*.My program creates the directory *hello* with this instruction: mkdir("hello", 644), but after I ran it I find out that the permission are *1204*. How come? – B.Castarunza May 08 '20 at 22:57
  • `uname` is more or less a way to configure the "default max permission" when a user creates files. This way, a program can just create files with permissions `777` to say "I want this file as accessible as is allowed by the user". The the user configuration will adapt the permissions adequately. You can modify your umask setting, to allow programs you run to create files with more permissive accesses. – Julien Thierry May 09 '20 at 06:41
  • And yes the "squigly line" (tilde :) ), is the BITWISE NOT (so all bits from umask are inverted). – Julien Thierry May 09 '20 at 06:45
  • Okay, but if my umask is 0022 ( ~umask = 7755) if then followed with a BITWISE AND with 644, shouldn't the result remain 644 instead of 1204 ( which is the final permission that my new directory ultimately gets )? – B.Castarunza May 09 '20 at 10:01
  • It sounds like there is some conversion to octal involved. Where are you seeing the 1204? Because basically 1204 is 644 in base 8. – Julien Thierry May 09 '20 at 11:37
  • wait it's 644 not octal? – B.Castarunza May 10 '20 at 12:56
  • What is likely happening is that you need to convert 644 from octal to decimal before passing it to `mkdir`. – Julien Thierry May 10 '20 at 15:25
  • ok thanks, I find it weird though, how in open it accepts it as octal and in others as decimal, is there a special character that put next to the number tells the function that that's an octal? – B.Castarunza May 11 '20 at 07:57