Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C system calls open / read / write / close and O_CREAT|O_EXCL

Tags:

c

system-calls

Given the following code (it's supposed to write "helloworld" in a "helloworld" file, and then read the text):

#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>

#define FNAME "helloworld"

int main(){ 
    int filedes, nbytes;
    char buf[128];

    /* Creates a file */
    if((filedes=open(FNAME, O_CREAT | O_EXCL | O_WRONLY | O_APPEND, 
        S_IRUSR | S_IWUSR)) == -1){
            write(2, "Error1\n", 7);
    }

    /* Writes hello world to file */
    if(write(filedes, FNAME, 10) != 10)
        write(2, "Error2\n", 7);

    /* Close file */
    close(filedes);

    if((filedes = open(FNAME, O_RDONLY))==-1)
        write(2, "Error3\n", 7);

    /* Prints file contents on screen */    
    if((nbytes=read(filedes, buf, 128)) == -1)
        write(2, "Error4\n", 7);

    if(write(1, buf, nbytes) != nbytes)
        write(2, "Error5\n", 7);

    /* Close file after read */
    close(filedes); 

    return (0);
}

The first time I run the program, the output is:

helloworld

After that every time I to run the program, the output is:

Error1
Error2
helloworld

I don't understand why the text isn't appended, as I've specified the O_APPEND file. Is it because I've included O_CREAT? It the file is already created, shouldn't O_CREAT be ignored?

like image 635
Andrei Ciobanu Avatar asked Apr 03 '10 19:04

Andrei Ciobanu


People also ask

What are system calls in C?

A system call is a request for service that a program makes of the kernel. The service is generally something that only the kernel has the privilege to do, such as doing I/O.

What is open () system call in C?

open (C System Call) open is a system call that is used to open a new file and obtain its file descriptor.

What does open () system call returns?

DESCRIPTION. Given a pathname for a file, open() returns a file descriptor, a small, non-negative integer for use in subsequent system calls (read(2), write(2), lseek(2), fcntl(2), etc.). The file descriptor returned by a successful call will be the lowest-numbered file descriptor not currently open for the process.

What is the syntax for open system call?

The open() system call has two syntax. We discuss the first one here: int open(const char *pathname, int flags); The first parameter is the name of the file that you want to open for reading/writing.


1 Answers

O_EXCL forces the file to be created. If the file already exists, the call fails.

It is used to ensure that the file has to be created, with the given permissions passed in the third parameter. In short, you have these options:

  • O_CREAT: Create the file with the given permissions if the file doesn't already exist. If the file exists, it is opened and permissions are ignored.
  • O_CREAT | O_EXCL: Create the file with the given permissions if the file doesn't already exist. If the file exists, it fails. This is useful in order to create lockfiles and guarantee exclusive access to the file (as long as all programs which use that file follow the same protocol).
  • O_CREAT | O_TRUNC: Create the file with the given permissions if the file doesn't already exist. Otherwise, truncate the file to zero bytes. This has more of the effect we expect when we think "create a new blank file". Still, it keeps the permissions already present in the existing file.

More information from the manual page:

O_EXCL

When used with O_CREAT, if the file already exists it is an error and the open() will fail. In this context, a symbolic link exists, regardless of where it points to. O_EXCL is broken on NFS file systems; programs which rely on it for performing locking tasks will contain a race condition. The solution for performing atomic file locking using a lockfile is to create a unique file on the same file system (e.g., incorporating hostname and pid), use link(2) to make a link to the lockfile. If link() returns 0, the lock is successful. Otherwise, use stat(2) on the unique file to check if its link count has increased to 2, in which case the lock is also successful.

like image 55
Juliano Avatar answered Sep 29 '22 07:09

Juliano