How to get octal chmod from st_mode - c

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?

Related

extracting digits from octal number in C

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

File permission as a four digit number in c

I am trying to get the permission of a file as a four digit number.
I have created a file lol with permission 0777
struct stat st;
stat("lol", &st);
printf("%d",st.st_mode);
When I test this, the result is not 0777. Why?

Reproducing Linux stat command in C

I'm writing my own version of the stat command and I am having difficulty getting the correct output for the Device field.
When I run the Linux stat command on an empty file in the working directory I get:
Device: 801h/2049d
To replicate this I tried to extract from the stat structure, the st_dev field.
But printing st_dev gives me
Device: 801
I am missing the h at the end and I am not sure where the 2049d comes from.
Is the first part just a formatting problem? I am printing in hex format. And how can I extract 2049d?
Since (hexadecimal) 0x801 == 2049 (decimal), you can get the output you're after from:
printf("Device: %xh/%dd\n", st.st_dev, st.st_dev);
The h in the format is the h that appears at the end of 801h; the %x means 'print number in hex'. Similarly, the %d means print in decimal, and the trailing d is the d in 2049d.
Incidentally, on Linux and other POSIX platforms, you can also avoid repeating the st.st_dev argument. For example:
#include <stdio.h>
int main(void)
{
printf("Device: %1$xh/%1$dd\n", 0x801);
return 0;
}
This also produces:
Device: 801h/2049d
To see why, read the printf()
specification very carefully. Note that if you use one of the 1$ modifiers, you must (should) use it with every conversion specification.

Linux & C: 'write()' does not write anything to file

I have a simple task to accomplish with this routine where, all it has to do is, open the file, append data from a buffer & close.
I am using 'open' & 'write' for that purpose on a linux machine. Although the return code after 'write()' is positive, the file size does not increase and it is always empty. I ma pulling my hair to figure out what the issue with the below code. Thought some fresh eyes can shed some light.
#define BIT_Q_FILE ".\\bitq.dat"
int BQWrite(void *p)
{
int fd ;
int rc = -1 ;
fd = open(BIT_Q_FILE, O_RDWR | O_APPEND ) ;
if (fd < 0)
return -1;
memset(&BITQBuff,0,sizeof(typeBITQFile));
memcpy(&BITQBuff.pBitQueue,p,sizeof(typeBITQueue));
rc = write(fd, &BITQBuff,sizeof(typeBITQFile)) ;
close(fd) ;
if(rc!=sizeof(typeBITQFile))
{
return -1;
}
rc = sizeof(typeBITQueue);
return rc ;
}
I got your problem right here:
#define BIT_Q_FILE ".\\bitq.dat"
You've hit a trifecta of Windows-to-Unix porting gotchas:
The directory separator on Unix is /, not \.
But Unix is perfectly happy to let you put \ in the middle of a file name. (The only bytes — and I really mean bytes, not characters — that cannot appear in a pathname component are those with the values 0x2F and 0x00.)
Unix is also perfectly happy to let a file name begin with a dot; however, by default ls does not print any file names that begin with a dot.
So you are expecting data to be written to a file named bitq.dat in the current directory, but it is actually being written to a file named .\bitq.dat, still in the current directory. That file is hidden by default, so it looks like the data is disappearing into thin air. ls -a will reveal the hidden file, and rm .\\bitq.dat will delete it. To fix your code, just change the define to
#define BIT_Q_FILE "bitq.dat"
It is not necessary to put a leading ./ on the path passed to open.
This may not be the only problem with your code, but I don't see anything else obviously wrong. If you need more help, please post a new question with a complete, minimal test program that people can compile and run for themselves.
Try change
#define BIT_Q_FILE ".\\\bitq.dat"
to
#define BIT_Q_FILE "./bitq.dat"

How to get file information similar to "ls -la" using C?

I am using ar.h for the defining the struct. I was wondering on how I would go about getting information about a file and putting it into those specified variables in the struct.
struct ar_hdr {
char ar_name[16]; /* name of this member */
char ar_date[12]; /* file mtime */
char ar_uid[6]; /* owner uid; printed as decimal */
char ar_gid[6]; /* owner gid; printed as decimal */
char ar_mode[8]; /* file mode, printed as octal */
char ar_size[10]; /* file size, printed as decimal */
char ar_fmag[2]; /* should contain ARFMAG */
};
Using the struct defined above, how would I put get the information from the file from ls -la
-rw-rw----. 1 clean-unix upg40883 368 Oct 29 15:17 testar
?
You're looking for stat(2,3p).
In order to emulate the behavior of ls -la you need a combination of readdir and stat. Do a man 3 readdir and a man 2 stat to get information on how to use them.
Capturing the output of ls -la is possible, but not such a good idea. People might expect that of a shell script, but not a C or C++ program. It's even sort of the wrong thing to do in Python or perl if you can help it.
You will have to construct your structure yourself from the data available to you. strftime can be used for formatting the time in a manner you like.
For collecting data about a single file into an archive header entry, the primary answer is stat(); in other contexts (such as ls -la), you might also need to use lstat() and readlink(). (Beware: readlink() does not null terminate its return string!)
With ls -la, you would probably use the opendir() family of functions (readdir() and closedir() too) to read the contents of a directory.
If you needed to handle a recursive search, then you'd be looking at nftw(). (There's also a less capable ftw(), but you'd probably be better off using nftw().)

Resources