Im trying to get the file permissions for a file or directory using the function stat(). I can get the correct information, such as; st_nlinks is for number of hard links and st_mode gives the mode of the file, which is what I am looking for. But the value stores in st_mode is an octal number. How do I now extract just the owner permissions.
For example the st_mode might store 42755 which means the owner has read write and execution permissions, but I don't know how to get extract the 7 from the number. If this is confusing maybe my code below will clarify things.
CODE:
DIR *dirp;
struct dirent *dp;
struct stat buf;
dirp = opendir(".");
while ((dp = readdir(dirp)) != NULL){
stat(dp->d_name, &buf);
//now here I have the octal number for the file permissions
//If I put a print statement here like so:
printf(">> %o %s\n", buf.st_mode, dp->d_name);
}
So some of you may see that I am trying to do what ls -l does on a Unix system. So instead of printing out the octal number for the mode I want to convert it to something like:
drwxr-xr-x for the value stored in st_mode: 42755
My professor recommended using a mask and perform a bitwise operation on it. I understand what he means but I tried something like:
mode_t owner = 0000100 & st_mode;
But when I print out owner I get the value of 100.
printf(">> owner permission: %o\n", owner);
OUTPUT:
owner permission: 100
So I am confused on how to do this. Does anyone know how to solve this problem?
By the way in case anyone is wondering I use mode_t as the type for owner because according to the man page for stat (man 2 stat) the member variable st_mode of the stat structure is of type mode_t. I figure this is just like a long int or something.
Use the macros defined in sys/stat.h to resolve the mode bits.
Refer to:
http://www.johnloomis.org/ece537/notes/Files/Examples/ls2.html
function mode_to_letters() for implementation details.
You should consider using defined macros rather than trying to "parse" permissions manually. Let's say you wish you get the write permission for the file owner user, that's could be checked like this:
int wpo = buff.st_mode & S_IWUSR;
if (wpo) {
printf("Ower has write permission");
} else {
printf("Ower doesn't have write permission");
}
You will find more useful macros in documentation: http://pubs.opengroup.org/onlinepubs/009695399/basedefs/sys/stat.h.html
The mask must be 0700:
111 000 000
To get owner rights rwx
Hi I have a similar question to this post How to get octal chmod format from stat() in c but I dont have any reputation so I cant comment on it. I was wondering what value would statchmod get if the file had permission drwxrw-r-- and is that value in decimal or octal?
struct stat buf;
stat(filename, &buf);
int statchmod = buf.st_mode;
I was also wondering what number
statchmod & 0777
outputs and again is it in decimal or octal? Should it output 0764?
EDIT: Thanks, I think I have a better understanding now. Still not clear on statchmod though. Is it in bits So would
statchmod & 511
output 500?
The function would be something like this.
int GetFilePermission(char* pcUsername, char* pcFilePath)
{
/*return TRUE if 'pcUsername' has read permission on file 'pcFilePath'.*/
}
I don't want to use stat(). Since it would be little bit long. I have to check file's permissions, it's owners and compare them in different combinations. Is there any short and simple way/trick of doing this?
Please help. Thanks in advance.
Using the access function we can get the user having a permission. See the man page of access.
int access(const char *pathname, int mode);
If you stat function, you getting all information about that file. In access we have these four only. R_OK, W_OK, X_OK and F_OK. Using this we can get easily. Return value is zero if success.
R_OK = read permission
W_OK = Write permission
X_OK = Execute permission
F_OK = file is existing.
You can use stat
Prototype for stat
#include <sys/stat.h>
int stat(const char *restrict path, struct stat *restrict buf);
Why won't the following code create a file with permissions read and write for user, group, and other?
char data[10] = "123456789";
int fh = open("test.txt", O_RDWR|O_CREAT, 0666);
write(fh, data, 10);
printf(strerror(errno));
close(fh);
Produces this file:
-rw-r--r-- 1 pc users 9 Nov 15 16:15 test.txt
What does that mean? I specifically asked for r+w in all categories.
Reset your user mask using the umask() system call before calling open().
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;
}
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 (---).
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.
This question recently 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 permissions you see aren't random; they're coming from the stack. Look at the following code snippet:
asm("push $0");
asm("push $0");
asm("push $0");
fd = open("base", O_RDWR|O_CREAT);
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
Hope this adds some clarity!
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.
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!
you can call umask(0); system call before using open(); system call to set your choices permissions to file correctly.
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.