clinuxassembly

What are the binary representations for the flags used in the Linux open() syscall?


I am learning NASM and currently unsure what values should be used for the flags argument for open() as shown in the man page. I'm mainly asking this for clarification so I don't mess something up, and apologies if it's not appropriate for the site.

I read the man page, but couldn't find if the under-the-hood values listed, but since it and this SO answer said they are meant to be bitwise ORed together, I assumed they acted as bit flags (probably should have gathered that from the name). After looking here, I found them in "/usr/include/asm-generic/fcntl.h" on my computer (Ubuntu). This section with the flags looks like this, omitting some lines:

#define O_ACCMODE   00000003
#define O_RDONLY    00000000
#define O_WRONLY    00000001
#define O_RDWR      00000002
#define O_CREAT     00000100    /* not fcntl */
#define O_EXCL      00000200    /* not fcntl */
#define O_NOCTTY    00000400    /* not fcntl */
#define O_TRUNC     00001000    /* not fcntl */
#define O_APPEND    00002000
#define O_NONBLOCK  00004000
#define O_DSYNC     00010000    /* used to be O_SYNC, see below */
#define O_DIRECT    00040000    /* direct disk access hint */
#define O_LARGEFILE 00100000
#define O_DIRECTORY 00200000    /* must be a directory */
#define O_NOFOLLOW  00400000    /* don't follow links */
#define O_NOATIME   01000000
#define O_CLOEXEC   02000000    /* set close_on_exec */

#define __O_SYNC    04000000
#define O_SYNC      (__O_SYNC|O_DSYNC)
#define O_PATH      010000000
#define __O_TMPFILE 020000000
#define O_TMPFILE (__O_TMPFILE | O_DIRECTORY)

I saw that a leading zero means the values is in base-8, so I wrote them like this in binary (I'm not sure the standard way of writing in binary), in order of value:

O_RDONLY    = 0b                            0   /* was 0o0 */
O_WRONLY    = 0b                            1   /* was 0o1 */
O_RDWR      = 0b                           10   /* was 0o2 */
O_ACCMODE   = 0b                           11   /* was 0o3 */
O_CREAT     = 0b                     100 0000   /* was 0o100 */
O_EXCL      = 0b                    1000 0000   /* was 0o200 */
O_NOCTTY    = 0b                  1 0000 0000   /* was 0o400 */
O_TRUNC     = 0b                 10 0000 0000   /* was 0o1000 */
O_APPEND    = 0b                100 0000 0000   /* was 0o2000 */
O_NONBLOCK  = 0b               1000 0000 0000   /* was 0o4000 */
O_DSYNC     = 0b             1 0000 0000 0000   /* was 0o10000 */
O_DIRECT    = 0b           100 0000 0000 0000   /* was 0o40000 */
O_LARGEFILE = 0b          1000 0000 0000 0000   /* was 0o100000 */
O_DIRECTORY = 0b        1 0000 0000 0000 0000   /* was 0o200000 */
O_NOFOLLOW  = 0b       10 0000 0000 0000 0000   /* was 0o400000 */
O_NOATIME   = 0b      100 0000 0000 0000 0000   /* was 0o1000000 */
O_CLOEXEC   = 0b     1000 0000 0000 0000 0000   /* was 0o2000000 */
O_SYNC      = 0b  10 0000 0000 0000 0000 0000   /* was 0o10000000 */
O_TMPFILE   = 0b 100 0000 0000 0000 0000 0000   /* was 0o20000000 */

I assume some have denoting values on the same bits so they aren't used at the same time. Did I do something wrong in this process, or are these the correct values for using them as flags for the open() syscall?


Solution

  • These are the correct values on your system. There is no guarantee that they'll be the same on another system. That's why you use headers that provide the correct numbers for your system.

    As a side-note, this assumption is wrong:

    I assume some have denoting values on the same bits so they aren't used at the same time.

    They're ensuring that they are passed at the same time, it can't do a thing to ensure they're not passed the same time (e.g. no one actually passes __O_SYNC, they pass O_SYNC, and there is no way for the library to distinguish passing O_SYNC | O_DSYNC from O_SYNC in the first place).

    For the specific overlapping flags: