open flags and file mode bits
When you open a door you decide two things in advance: are you going in to look, to change things, or both - and if the room does not exist yet, should one be built. open()'s flags answer exactly that. And when a brand-new file is created, you also stamp it with who is allowed to read, write, or run it later - that stamp is the file mode bits.
The second argument to open() is a set of flags combined with bitwise OR. The core three pick the access: O_RDONLY (read only), O_WRONLY (write only), or O_RDWR (both). On top of those you OR in optional behaviour: O_CREAT (create the file if it does not exist), O_TRUNC (if it exists, throw away its current contents), O_APPEND (every write goes to the end), O_EXCL (with O_CREAT, fail if the file already exists - useful to avoid clobbering). The third argument, the mode, only matters when O_CREAT actually creates a file. It is the permission bits, written in octal like 0644, read as three groups of three: owner, group, others, each granting read(4), write(2), execute(1). So 0644 means owner read+write (6), group read (4), others read (4).
Why it matters: getting flags right is how you say 'create but do not overwrite' or 'append, do not truncate' - subtle differences that decide whether you destroy existing data. And the mode you pass is masked by the process umask, so the file's real permissions can end up more restrictive than the number you wrote. Forgetting to pass a mode while using O_CREAT leaves the new file's permissions as garbage, a classic bug.
/* create only if it does not already exist; never clobber */ int fd = open("lock", O_WRONLY | O_CREAT | O_EXCL, 0644); if (fd < 0 && errno == EEXIST) { /* someone else already made it */ }
O_CREAT | O_EXCL is the atomic 'create-if-new' idiom; the mode 0644 stamps the new file's permissions.
The mode argument is advisory: the real permissions are mode AND NOT umask, so a umask of 022 turns 0666 into 0644. Pass a mode whenever O_CREAT is set; the kernel uses an indeterminate value otherwise.