protection mask question, bash vs. open() - Unix

This is a discussion on protection mask question, bash vs. open() - Unix ; As root in bash on Mandriva 2007.1, using gcc 4.1.2: % touch /tmp/foo % stat -c %a /tmp/foo 644 As root running a program in bash: fd = open("/tmp/foo", O_WRONLY | O_CREAT | O_NONBLOCK | O_TRUNC ); % stat -c ...

+ Reply to Thread
Results 1 to 4 of 4

Thread: protection mask question, bash vs. open()

  1. protection mask question, bash vs. open()

    As root in bash on Mandriva 2007.1, using gcc 4.1.2:

    % touch /tmp/foo
    % stat -c %a /tmp/foo
    644

    As root running a program in bash:

    fd = open("/tmp/foo", O_WRONLY | O_CREAT | O_NONBLOCK | O_TRUNC );

    % stat -c %a /tmp/foo
    7644

    I expected 644.

    % stat -c %a /tmp
    1777

    I don't get it. /usr/include/bits/fcntl.h shows

    #define O_TRUNC 01000 /* not fcntl */
    #define O_APPEND 02000
    #define O_NONBLOCK 04000

    It looked like the "flags" setting is being reused in the
    "mode" field, which is not supplied. So I tried it this way:

    fd = open("/tmp/foo", O_WRONLY | O_CREAT | O_NONBLOCK|O_TRUNC, 0611);

    and the file was created with a 611 protection mask, whereas this:

    fd = open("/tmp/foo", O_WRONLY | O_CREAT | O_NONBLOCK);

    made the file with a 1204 mask, which makes even less sense.

    What is going on with the 2 argument form of open and the protection
    mask on the created file???

    Thanks,

    David Mathog


  2. Re: protection mask question, bash vs. open()

    David Mathog writes:

    > As root in bash on Mandriva 2007.1, using gcc 4.1.2:
    >
    > % touch /tmp/foo
    > % stat -c %a /tmp/foo
    > 644
    >
    > As root running a program in bash:
    >
    > fd = open("/tmp/foo", O_WRONLY | O_CREAT | O_NONBLOCK | O_TRUNC );
    >
    > % stat -c %a /tmp/foo
    > 7644
    >
    > I expected 644.
    >
    > % stat -c %a /tmp
    > 1777
    >
    > I don't get it. /usr/include/bits/fcntl.h shows
    >
    > #define O_TRUNC 01000 /* not fcntl */
    > #define O_APPEND 02000
    > #define O_NONBLOCK 04000
    >
    > It looked like the "flags" setting is being reused in the
    > "mode" field, which is not supplied. So I tried it this way:
    >
    > fd = open("/tmp/foo", O_WRONLY | O_CREAT | O_NONBLOCK|O_TRUNC, 0611);
    >
    > and the file was created with a 611 protection mask, whereas this:
    >
    > fd = open("/tmp/foo", O_WRONLY | O_CREAT | O_NONBLOCK);
    >
    > made the file with a 1204 mask, which makes even less sense.
    >
    > What is going on with the 2 argument form of open and the protection
    > mask on the created file???


    If the second argument to open() includes O_CREAT, a third argument
    must be supplied. Otherwise results are more or less random, as
    you've seen. The situation is similar to calling printf() with too
    few arguments for the format string.

    --
    Måns Rullgård
    mans@mansr.com

  3. Re: protection mask question, bash vs. open()

    Måns Rullgård wrote:
    > David Mathog writes:


    >> What is going on with the 2 argument form of open and the protection
    >> mask on the created file???

    >
    > If the second argument to open() includes O_CREAT, a third argument
    > must be supplied. Otherwise results are more or less random, as
    > you've seen. The situation is similar to calling printf() with too
    > few arguments for the format string.
    >


    Ah, I see it now way down at the bottom of the man page for open at the
    bottom of the section on mode:

    mode must be specified when O_CREAT is in the flags, and
    is ignored otherwise.

    This key point isn't mentioned in the section which describes O_CREAT.

    So it seems the only, way to have the file set with the current umask is
    to first call getumask(), then to use that value as the third argument
    in the open() call.

    As for the randomness, let me guess: since mode MUST be supplied if
    O_CREAT is used open() sees O_CREAT and assumes mode WAS supplied and
    reads this "third parameter" when called, even if there wasn't one.
    This results in it pulling in some arbitrary value from memory and
    voila, random protection mask.

    Thanks,

    David Mathog

  4. Re: protection mask question, bash vs. open()

    On Dec 7, 8:46 am, David Mathog wrote:
    > Måns Rullgård wrote:
    > > David Mathog writes:
    > >> What is going on with the 2 argument form of open and the protection
    > >> mask on the created file???

    >
    > > If the second argument to open() includes O_CREAT, a third argument
    > > must be supplied. Otherwise results are more or less random, as
    > > you've seen. The situation is similar to calling printf() with too
    > > few arguments for the format string.

    >
    > Ah, I see it now way down at the bottom of the man page for open at the
    > bottom of the section on mode:
    >
    > mode must be specified when O_CREAT is in the flags, and
    > is ignored otherwise.
    >
    > This key point isn't mentioned in the section which describes O_CREAT.
    >
    > So it seems the only, way to have the file set with the current umask is
    > to first call getumask(), then to use that value as the third argument
    > in the open() call.


    No. Actually, what you probably want to do is

    open(file, O_WRONLY | O_CREAT | O_TRUNC | O_NONBLOCK, 0666);

    If `mode' is the mode you pass to open(), the file's mode is set to
    (mode & ~umask). You don't want to use the umask itself as the mode
    because it's complemented. You could set the mode to ~umask but using
    0666 has the same effect and is easier.

    > As for the randomness, let me guess: since mode MUST be supplied if
    > O_CREAT is used open() sees O_CREAT and assumes mode WAS supplied and
    > reads this "third parameter" when called, even if there wasn't one.
    > This results in it pulling in some arbitrary value from memory and
    > voila, random protection mask.


    Exactly. It's a limitation of the C language that a function which
    takes variable arguments can't know how many were actually passed, and
    must get this information from other arguments. If they weren't
    actually passed, it'll use whatever happened to be at the
    corresponding place on the stack.

+ Reply to Thread