I created a file called my_file and verfied the inode value. I opened he file again and re-write some more contents. When I viewed the inode size. It varied from the previous inode size. Why isnt the inode same for the file my_file after re-writing on it ?
Related
I am studying operating systems from the book OSTEP. In the file-systems implementation chapter, there is a file creation timeline, which displays what operations are done on what type of file-system elements(inodes, data blocks, inode/data bitmaps etc) when you create a file. Following image displays the timeline.
File Creation Timeline
Suppose we want to create a file bar in /foo/, so the file will be /foo/bar. what data elements will be accessed?
I understood following steps
(1) Start reading from root, to go to location where we want to create a file, so first we read the inode of root so that we can access its data block to find what is the inode number of foo directory.
(2) Read from root data block the inode number of foo.
(3) Now read from inode of foo to find location of its data block.
(4) In the data block of foo, we check whether there is any file with name bar. We can only proceed with creation if there is not, because Linux does not allow same filenames in same directory.
(5) Assuming we can proceed, we read from inode bitmap to find which inode is available for allocation.
(6) Then we allocate that inode by writing to corresponding bitmap location of the above discovered inode.
(7) Then we make an entry in foo for the file of bar. The entry will be a pair ('bar', <inode no of bar>). So a write in foo.
(8) Now I'm stuck from this read done in the inode of bar. Why do we need to read from this inode?
I think we should write straight away in the inode of bar. We have to write metadata of bar to this inode right? Then why de we read hear?
In c, how would I find a directory in a virtual disk? I can easily recurse the absolute path and tun that into just the name of the directory I am looking for (i.e. turning /x/y/z into just z). I know that the root is inode 2, and I know how to get to some parts of the file system (superblock, block descriptor, inode table, bg_block/inode bitmap) but I have no clue how to traverse all the data in the image.
This image only has one block group, for what it's worth. Inode size and block size are set to their own predefined variables in the header (EXT2_BLOCK_SIZE and s_inode_size in superblock).
You have to implement the namei algorithm for ext[234] filesystem to get to the correct place. Just follow the kernel source code for the implementation of the ext[234] filesystem and look for the namei routine.
I understand file descriptors are kernel handle to identify the file , while inode number of a file is pointer to a structure which has other details about file(Correct me if I am wrong). But I am unable to get the difference between them.
An inode is an artifact of a particular file-system and how it manages indirection. A "traditional *ix" file-system uses this to link together files into directories, and even multiple parts of a file together. That is, an inode represents a physical manifestation of the file-system implementation.
On the other hand, a file descriptor is an opaque identifier to an open file by the Kernel. As long as the file remains open that identifier can be used to perform operations such as reading and writing. The usage of "file" here is not to be confused with a general "file on a disk" - rather a file in this context represents a stream and operations which can be performed upon it, regardless of the source.
A file descriptor is not related to an inode, except as such may be used internally by particular [file-system] driver.
The difference is not substantial, both are related to the abstract term called "file". An inode is a filesystem structure that represents files. Whereas, a file descriptor is an integer returned by open syscall. By definition:
Files are represented by inodes. The inode of a file is a structure kept by the filesystem which holds information about a file, like its type, owner, permissions, inode links count and so on.
On other the hand, a file descriptor
File Descriptors:
The value returned by an open call is termed a file descriptor and is essentially an index into an array of open files kept by the kernel.
The kernel doesn't represent open files by their names, instead it uses an array of entries for open files for every process, so a file descriptor in effect is an index into an array of open files. For example, let's assume you're doing the following operation in a process:
read(0, 10)
0 denotes the file descriptor number, and 10 to read 10 bytes. In this case, the process requests 10 bytes from the file/stream in index 0, this is stdin. The kernel automatically grants each process three open streams:
Descriptor No.
0 ---> stdin
1 ---> stdout
2 ---> stderr
These descriptors are given to you for free by the kernel.
Now, when you open a file, in the process via open("/home/myname/file.txt") syscall, you'll have index 3 for the newly opened file, you open another file, you get index 4 and so forth. These are the descriptors of the opened files in the process:
Descriptor No.
0 ---> stdin
1 ---> stdout
2 ---> stderr
3 ---> /home/user100/out.txt
4 ---> /home/user100/file.txt
See OPEN(2) it explains what goes underneath the surface when you call open.
The fundamental difference is that an inode represents a file while a file descriptor (fd) represents a ticket to access the file, with limited permission and time window. You can think an inode as kind of complex ID of the file. Each file object has a unique inode. On the other hand, a file descriptor is an "opened" file by a particular user. The user program is not aware of the file's inode. It uses the fd to access the file. Depending on the user's permissions and the mode the user program choses to open the file (read-only for example) a fd is allowed a certain set of operations on the file. Once the fd is "closed" the user program can't access the file unless it opens another fd. At any given time, there can be multiple fds accessing a file in the same or different user programs.
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 */