Where the file status info actually store when we using stat() in to get?
I'am learning Unix Programing, But i am confused when i using stat() function to get file status. There are no any information about where the file info actually store.
void do_stat(char *filename) {
struct stat info;
if (stat(filename, &info) == -1) {
perror(filename);
} else {
show_file_info(filename, &info);
}
}
To answer this question, you should complete the basic knowledge about UNIX-like file system. You can get a basic impression in here.
For your question: The files status info are store in inode list, file's inode number are record in directory file.
When you call system method stat() to get the status info about a file, the kernel will get the inode number from the directory file, then calculate the real disk address of the inode, then get the status info.
You can use ls -i1a dirname to get the inode info of a directory's files, here are output after i exec this command, the first column are the inode number:
$ ls -i1a .
8627654638 .
633334 ..
8627654639 gitlab
Related
I am writing a small shell in C that runs on Linux. Because there are a lot of dups involved, I would like to ask if there is a way to print what is inside position 0. For example if I call dup2(file_name,0) is there a way to print the file_name so I can use it for debugging?
If you are using linux operating system,you can show your file description table easily
every process on linux stored /proc/ directory by their process id, fd folder show file description table of process
e.g.
ls -l /proc/1405/fd
You can't get the filename from dup2. As you can read here it only returns a int value:
int dup2(int fildes, int fildes2);
What you can do in Linux is:
You can use readlink on /proc/self/fd/NNN where NNN is the file
descriptor. This will give you the name of the file as it was when it
was opened [here]
Or something more creative is creating a struct where you can assosiate the fildes to a filename.
Something like this:
struct Files{
int fildes;
char filename[50];
} files;
If you have more then one just create an array and take the one you need every time; in such a way you can always map it with a filename.
I need to get all files/directories owned by current user in a program. In fact i'm trying to read /proc filesystem in solaris(11) . Need to get output similar to ps -u but just the pids and needs to get it done from a program. What i tried is just did readdir and for each entry/dirname, try to read /pos/name/psinfo and if it fails skip else if it opens list the pid. Is there more efficient way of doing it ? I checked how ps -u is working through truss and it only opened the /proc/pid/psinfo file for the user pids.Not sure how it figured out that this is current user pid .
I'm thinking popen("ps -u") is more efficient than what i'm doing and is there any better way to do this ?
I'm trying to do this Solaris 11.
Here is sample code
do
{
errno = 0;
pDirEnt= readdir(dptr);
if(pDirEnt){
sprintf(fileToOpen, "/proc/%s/psinfo", pDirEnt->d_name);
sprintf(asfileToOpen, "/proc/%s/as", pDirEnt->d_name);
count++;
fd = open(fileToOpen, O_RDONLY);
if(fd >= 0) {
read(fd, &psInfo, sizeof(struct psinfo));
close(fd);
..
..
}
}
} while( haveMore );
Have you read proc(4)? That provides you with the documentation that you need for use of /proc on Solaris.
The pfiles(1) utility should help as well. However, if you want to see all files open by a specific user then you'll need to either run your program as that user, or run the program with suitably elevated privileges in order to read the process table.
I didn't find your problem description very clear, perhaps you could clarify exactly what it is that you are trying to achieve.
How do I check if a file(input) is in the program's directory in C?
First I think I can just open the file, but I don't want user to see my other files by input something like ../important_dir/important_file, but maybe it's OK if the user do things like ./dir1/../file1. Which means, as long as the file is in current dir(no child dir), it's OK to open that.
Then I search around and found readdir, which can be used to lookup everything in current directory, but still, if current directory has a lot of files, it will be way too slow to lookup a filename every time getting a user input.
Is there any fast and secure way to do that?
I think realpath should do the work.
I'll post solution tomorrow if possible.
You can just use stat() to check for a file's status. It would return -1 if the file in question does not exist and set errno to ENOENT.
char filename[] = "myfile";
struct stat s = {0};
if (!(stat(filename, &s)
{
if (ENOENT == errno)
perror("file does not exist.");
}
I have program, say name giverootAccess. This program can receive a file name in the current directory (where giverootAccess resides) as a command-line argument. Then the file will get the root access. The file can be an executable or a shell script.
Now the problem is that, A hacker can get root access by redirecting the request to bash. I want to restrict a user to give root access only on those files inside the directory where giverootAccess resides. hacker can redirect file name to unwanted programs and hence get the root permission.
So I need a mechanism to uniquely identify a file, not by its name (as it can be mimicked and hacked). Is inode can be used for this purpose?
My plan is, when the application installs, I will store the inodes of all the files in the directory and whenever somebody runs the giverootAccess with a file name, I will check the file name and its inodes are matching with stored one. If matching, then only giverootAccess program actually give root access to the file.
Do you have any other simple mechanism to do this job ?
You can use file descriptor to get the inode number, use this code :
int fd, inode;
fd = open("/path/to/your/file", YOUR_DESIRED_OPEN_MODE);
if (fd < 0) {
// some error occurred while opening the file
// use [perror("Error opening the file");] to get error description
}
struct stat file_stat;
int ret;
ret = fstat (fd, &file_stat);
if (ret < 0) {
// error getting file stat
}
inode = file_stat.st_ino; // inode now contains inode number of the file with descriptor fd
// Use your inode number
// ...
fstat is a system call that is used to determine information about a file based on its file descriptor.
It is described here
stat is a structure that contains meta information of a file and is described here
to use stat structure and fstat system call you should add #include <sys/stat.h> to your code.
You can find the inode number of a file using stat: http://linux.die.net/man/2/stat
You can find the inode number using the stat() system call. However, if you are using a non ext system like FAT32 and NTFS, the inode table will dynamically generated. Which means that the inode numbers may change and the application should not rely on it.
I have a process using C on Linux OS that writes data to a file. It uses open()/write() functions and I've been wondering if another process rm'd or mv'd the file. How can my process find out and recreate the file?
You can use fstat() to get the information about the open file. If the st_nlink field is zero, the file has been removed from the file system (possibly by being moved to a different file system, but there's no real way for you to determine that). There's a decent chance you have the only remaining reference to that file - though there might be other processes also holding it open. The disk space won't be released until the last process with an open file descriptor for the file finally closes the file.
If the st_nlink field is still positive, then your file still has a name somewhere out in the file system. You then need to use stat() to determine whether the st_dev and st_ino fields for the given file name match the same fields from the file descriptor. If the name still exists and has the same device and inode number, then it is 'the same' file (though the contents may have changed). If there's a difference, then the open file is different from the file specified by name.
Note that if you want to be sure that the given name is not a symbolic link to a moved copy of the file, then you would have to use lstat() on the file when you open it (to ensure it isn't a symlink at that point), and again when you check the file (instead of using stat()).
You can use the stat call to do this.
struct stat st;
if(stat("/tmp",&st) == 0)
printf(" /tmp is present\n");
else
/* Write code to create the file */