3

I m opening a file with open() function.

I want that open() function discard the file content if it already exists, and then the file is treated as a new empty file.

I tried with the following code:

int open_file(char *filename)
{
    int fd = -1;
    fd = open(filename, O_RDWR | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
    if (fd < 0) {
        printf("Couldn't create new file %s: %s\n",
            filename, strerror(errno));
        return -1;
    }
    close(fd);
    return 0;
}

but I got the following error:

Couldn't create new file kallel333: File exists

What am I missing?

alk
  • 69,737
  • 10
  • 105
  • 255
MOHAMED
  • 41,599
  • 58
  • 163
  • 268
  • Do you want to remove or truncate the file – µtex Jun 21 '16 at 14:13
  • 5
    Have you tried with adding O_TRUNC flag. – µtex Jun 21 '16 at 14:15
  • @sas watever, the goal is to have a new empty opened file. I do not want to get this error – MOHAMED Jun 21 '16 at 14:15
  • 1
    You could [open with the truncate option](http://stackoverflow.com/a/17033060/1460794). – wally Jun 21 '16 at 14:18
  • 2
    Add `O_TRUNC` and remove `O_EXCL`. `O_EXCL` says the file may not exist — the `open()` will fail if it does. The `O_TRUNC` says to truncate the file if it does already exist. – Jonathan Leffler Jun 21 '16 at 14:18
  • using `O_RDWR` is telling the OS to open the file with a mode similar to "w+" (if using `fopen()`) what you actually want is O_WRONLY. However, it would be easier to call `unlink()` or `delete()` or `truncate()` on the file, then call open with the desired parameters. – user3629249 Jun 22 '16 at 16:58

5 Answers5

9

Please add O_TRUNC flag and remove O_EXCL.

open(filename, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);

From open man page -

O_EXCL Ensure that this call creates the file: if this flag is specified in conjunction with O_CREAT, and pathname already exists, then open() will fail.

O_TRUNC If the file already exists and is a regular file and the access mode allows writing (i.e., is O_RDWR or O_WRONLY) it will be truncated to length

µtex
  • 900
  • 5
  • 12
3

The problem is the O_EXCL flag. From the man page for open(2):

O_EXCL Ensure that this call creates the file: if this flag is specified in conjunction with O_CREAT, and pathname already exists, then open() will fail.

I suggest removing O_EXCL, adding O_TRUNC, and trying again.

Tom Karzes
  • 22,815
  • 2
  • 22
  • 41
2

The manual page for open() says this about the O_TRUNC flag:

O_TRUNC If the file already exists and is a regular file and the open mode allows writing (i.e., is O_RDWR or O_WRONLY) it will be truncated to length 0. If the file is a FIFO or terminal device file, the O_TRUNC flag is ignored. Otherwise the effect of O_TRUNC is unspecified.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
TZof
  • 150
  • 1
  • 7
  • That's part of it — but only part of it. You have to remove the `O_EXCL` too, because if it is present, the system call will fail to open the file if it already exists, before the truncation has a chance to happen. Note that it is a good idea to provide a link to the online version of the manual page you consulted if at all possible. For Linux, you can often use http://linux.die.net/ as a source of manual pages — though there are many alternatives. – Jonathan Leffler Jun 21 '16 at 14:31
0

As everyone has stated, it's due to using the O_EXCL flag, when it should be the O_TRUNC flag instead. I just had this same issue. My best advice to anyone trying to use these syscalls that involve macros is to read the man page of your syscall. Understand what your macros mean before you try to use them and confuse yourself.

man 2 open

Bionic_Beadle
  • 195
  • 1
  • 1
  • 9
-1

I will tell you what this error is all about ! Open function will have a return type i.e some value will be returned after the execution of this system call (which in your case will be stored in fd). This value will indicate whether the execution of the system call is a success or not. When open system call fails, it automatically returns -1 (to fd) which you are already initializing in the first statement of your function int fd = -1;. Therefore, the statement if (fd < 0) is being validated as correct and hence you are getting that error. Please note that you should not set the return values of the system calls, they are to be returned automatically when the program executes. What you need to do is just make sure you capture that value and validate it. So please change your first statement of the function int fd = -1 to simply int fd.

Bottom line: You are setting the return value of the open system call to -1 thereby telling the compiler that its creation should fail at any cost !! As far as the permissions are concerned, please refer to the other comments !! :)

Coding Ninja
  • 114
  • 12
  • `int fd = -1` does not set the return value of the open call. It's unnecessary to set this variable before calling open, but it doesn't have any effect. – Dan Stahlke May 29 '20 at 00:25