Reputation: 771
I am trying to read some text from a file and write it to another using open()
, read()
and write()
.
This is my open()
for the file-to-write-to (I want to create a new file and write into it):
fOut = open ("test-1", O_RDWR | O_CREAT | O_SYNC);
This is setting file-permissions to something I don't understand at all. This is the output of ls -l
:
---------T 1 chaitanya chaitanya 0 2010-02-11 09:38 test-1
Even the read permission is locked. I tried searching for this, but could not find ANYTHING.
Strangely, write()
still successfully writes data to the file.
Also, if I do a 'chmod 777 test-1', things start working properly again.
Could someone please let me know where I am going wrong in my open call?
Thanks!
For your reference, I have pasted the complete program below:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
int main () {
char buffer[512], ch;
int fIn, fOut, i;
ssize_t bytes;
FILE *fp = NULL;
//open a file
fIn = open ("test", O_RDONLY);
if (fIn == -1) {
printf("\nfailed to open file.");
return 1;
}
//read from file
bytes = read (fIn, buffer, sizeof(buffer));
//and close it
close (fIn);
printf("\nSuccessfully read %d bytes.\n", bytes);
//Create a new file
fOut = open ("test-1", O_RDWR | O_CREAT | O_SYNC);
printf("\nThese are the permissions for test-1\n");
fflush(stdout);
system("ls -l test-1");
//write to it and close it.
write (fOut, buffer, bytes);
close (fOut);
//write is somehow locking even the read permission to the file. Change it.
system("chmod 777 test-1");
fp = fopen ("test-1", "r");
if (fp == NULL) {
printf("\nCan't open test-1");
return 1;
}
while (1)
{
ch = fgetc(fp);
if (ch == EOF)
break;
printf("\n%c", ch);
}
fclose (fp);
return 0;
}
Upvotes: 75
Views: 122613
Reputation: 607
This question helped me out, so I wanted to do my part to add a bit more depth as to what's going on. Like it was stated before, you were missing the third argument to open()
.
However, the story doesn't end there: the permissions you see aren't random!
If you're on an x86 system, you'll see they're coming from the stack. A debugger is always helpful, but we can also look at the following code snippet:
#include<stdlib.h>
#include<fcntl.h>
int main(){
asm("push $0");
asm("push $0");
asm("push $0");
fd = open("base", O_RDWR|O_CREAT);
}
You can see we're using inline assembly to manually set up parts of the stack. Note the following result:
----------. 1 user user 4 Feb 26 08:21 base
Let's change the first push to 1, i.e. execute permission:
asm("push $1;push $0;push $0");
fd = open("base", O_RDWR|O_CREAT);
and we get:
---------x. 1 user user 4 Feb 26 08:25 base
Change the push to 4, i.e. read permission, and mess with the other two values:
asm("push $4;push $5;push $6");
fd = open("base", O_RDWR|O_CREAT);
and we get:
-------r--. 1 user user 4 Feb 26 08:27 base
Thus we can see the third value popped off the stack (first pushed) is what really matters. Finally for fun we can try 5 and then 50, which respectively result in:
-------r-x. 1 user user 4 Feb 26 08:27 base
----rw----. 1 user user 4 Feb 26 08:28 base
Note that if you're on an x86-64 system, arguments are first stored in registers and not the stack. In particular, on a Linux system the first six arguments are passed in RDI, RSI, RDX, RCX, R8, R9. You're still targeting what would be the third argument, so in particular:
asm("mov $1, %rdx");
fd = open("base", O_RDWR|O_CREAT);
Hope this adds some clarity!
Upvotes: 10
Reputation: 25522
open() takes a third argument which is the set of permissions, i.e.
open(filename, O_RDWR|O_CREAT, 0666)
0666 is an octal number, i.e. every one of the 6's corresponds to three permission bits
6 = rw
7 = rwx
first three bits for owner permission, next three bits for group permission and next is for the world the first digit - represents that is file or directory. (0 - file, d - directory) here we used 0 means file
It's a typical pitfall. The compiler allows you to leave the permission argument away because when you open an existing file the permission bits don't make sense. But when you forget the argument when you create a file, you get a random set of permissions, e.g. 0000 in your case (---).
Upvotes: 112
Reputation: 31
This is kind of an old thread, but I think people should be aware of the "sys/stat.h" library. This includes a bunch of symbolic constants for setting permission bits.
For example: To open a file with Read/Write permissions enabled for the user
#include <fcntl.h>
#include <sys/stat.h>
open("Your/File/Path", O_RDWR | O_CREAT, S_IWUSR | S_IRUSR);
where:
S_IWUSR // Sets the Users Write bit
S_IRUSR // Sets the Users Read bit
This library includes a bunch of others, I won't list them all here but you can read up on it all here.
Of course you can put in the octal values to set these bits, however some may argue that it is poor coding practice.
Upvotes: 2
Reputation: 479
Not strictly relevant to the question, but the accepted answer could use this clarifying point:
There is a relationship between rwx and its numerical representation that can be seen by treating the presence of a letter as a binary 1, and its absence as a binary 0.
e.g.
rwx <--> 111 (binary) <--> 7 (octal)
r-- <--> 100 (binary) <--> 4 (octal)
-wx <--> 011 (binary) <--> 3 (octal)
As a further addendum, you may now consider the chmod command:
chmod 777 filename.extension --> rwxrwxrwx permissions
777 <--> 111 111 111 <--> rwx rwx rwx
or: chmod 654 filename.extension --> rw-r-x-r--
654 <--> 110 101 100 <--> rw- r-x r--
Hope this is informative!
Upvotes: 4
Reputation: 51
Actually umask()
only filters permissions and does not set them. The typical umask()
value is 0002
("don't give away write permission to the world") and if your mode value in the open( "file", O_CREAT, 0777)
gave all permissions, the resulting file would have 775
as its permssions.
Upvotes: 5
Reputation: 610
you can call umask(0);
system call before using open();
system call to set your choices permissions to file correctly.
Upvotes: 2
Reputation: 12135
Reading http://linux.die.net/man/2/open it seems you missed the mode
parameter for open:
mode must be specified when O_CREAT is in the flags, and is ignored otherwise. The argument mode specifies the permissions to use in case a new file is created.
Upvotes: 12