Reputation: 81
#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
int main(int argc, char **argv)
{
int fd1, fd2;
fd1 = open("dup1.txt", O_RDWR | O_CREAT| S_IREAD | S_IWRITE);
printf("\nOriginal fd = %d", fd1);
if(fd1 == -1){
printf("\nFATAL Error\n");
exit(1);
}
}
#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
int main(int argc, char **argv)
{
int fd1, fd2;
fd1 = open("dup1.txt", O_RDWR | O_CREAT, S_IREAD | S_IWRITE);
printf("\nOriginal fd = %d", fd1);
if(fd1 == -1){
printf("\nFATAL Error\n");
exit(1);
}
}
The program1 returns -1 for fd, if the file already exists (works fine when it doesn't), but the program2 below the first one works fine. The difference is placement of option flags.
Upvotes: 0
Views: 2610
Reputation: 755026
When you use O_CREAT
, open()
takes three arguments and the third argument is the permissions on the file to be created:
fd1 = open("dup1.txt", O_RDWR | O_CREAT, 0644);
The permissions (S_I*
flags) are never specified in the options (second) argument (which uses O_*
flags) or vice versa. Theoretically the symbolic names are more portable than the octal literals, but IMNSHO octal literals are easier to interpret. You can use whatever permissions you like, but unless you're creating executable programs, you probably should not be setting the x
bit for anyone, and for security reasons, you should consider not granting group or public write access (allowing group and public read access to be overridden by umask()
as the user sees fit. Classically (in the days of yore when security was less of a concern), permissions were habitually 0666 by default for files.
Upvotes: 1
Reputation: 2038
On my machine, S_IWRITE
has the same value as O_EXCL
. The program:
int main() {
printf("%x %x\n", S_IREAD, S_IWRITE);
printf("%x\n", O_EXCL);
return 0;
}
gives:
100 80
80
So I guess, specifying the flag S_IWRITE
together with O_CREAT
now has the same effect as O_CREAT | O_EXCL
, which causes open
to fail if the file already exists.
However, I think you should invoke the system calls with the proper use of their arguments.
Upvotes: 4
Reputation: 263627
The open
system call may be called with either 2 or 3 arguments.
These two calls:
fd1 = open("dup1.txt", O_RDWR | O_CREAT| S_IREAD | S_IWRITE);
and
fd1 = open("dup1.txt", O_RDWR | O_CREAT, S_IREAD | S_IWRITE);
are quite different; the first passes a second argument equal to O_RDWR | O_CREAT| S_IREAD | S_IWRITE
, and the second passes a second argument equal to O_RDWR | O_CREAT
and a third argument equal to S_IREAD | S_IWRITE
.
The second argument should always be a bitwise "or" of one or more flags whose names start with O_
.
If and only if the second argument includes the O_CREAT
flag, you need to pass a second argument, which should be either a bitwise "or" of one or more flags whose names start with S_
, or an octal number such as 0640
specifying permissions.
Your first call is incorrect; you shouldn't pass S_*
flags in the second argument, and if the second argument includes O_CREAT
, you need a third argument.
This ability to pass either two or three arguments is a bit odd. The Linux man page documents open
like this:
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
which is arguably incorrect (C doesn't have function overloading like that). POSIX describes it like this:
int open(const char *path, int oflag, ...);
making it a variadic function, similar to printf
.
Upvotes: 2