In order to have stats on a hardrive one can use the sys/statvfs
It takes either a path or a fd.
int statvfs(const char *path, struct statvfs *buf);
int fstatvfs(int fd, struct statvfs *buf);
In my application I am parsing /proc/diskstats which provide me with the device name (ex: sda1, sda2).
I don't know how to use that device name in order to get the same stats as the statvfs functions.
What functions can be used?
Read /etc/mtab and map device names to mount paths.
To connect a device with where its mounted, look at mount. The source for mount should tell you how to find the path each device is mounted on. Then you can open the path and call statvfs
Related
I want to create a file on /dev/mmcblk0, if it doesn't exist already, and then write to it. My question is how to check if there is already such file on the sdcard and then access it, does it show up like /dev/mmcblk0/somefile?
/dev/mmcblk0 points to a drive, so you will need to mount the drive first before you can see what files are available on it or create new files.
You should use the command mount(8) to mount the device first. That will cause the device's filesystem to be attached to your system's file-system, and therefore, makes you able to access files on it just like you normally do. For example:
mount /dev/mmcblk0 /home/yooo123/sdcard
If all goes well, you can read and write files to it using fopen, fwrite, etc.
FILE *fp = fopen("/home/yooo123/sdcard/file.txt", "w");
...
fprintf(fp, "Hello, SD Card!\n");
However, if you want to do all of that from a C program, look up the mount(2) system call.
int mount(const char *source, const char *target,
const char *filesystemtype, unsigned long mountflags,
const void *data);
Im reading the fcntl manual page and came across thw dnotify:
File and directory change notification (dnotify)
It is suggested that new application should use inotify instead, but I think they are not the same since inotify works with char * paths making it suffering from file renaming (or cathing MOVED_FROM/MOVED_TO events) but dnotify works with file descriptors which is different:
int fcntl(int fd, int cmd, ... /* arg */ );
So as far as I can tell dnotify is not a subset of inotify neither vice versa.
Is it discouraged to use dnotify in newer kernel even if I want to subscribe on events by file descriptor, not by a file path as inotify allows?
If you read the manual page for inotify_add_watch closer, then yes it takes a path but it returns a "watch descriptor"
for the filesystem object (inode) that corresponds to pathname
So the path is only used to locate the inode. Once that's done you have a reference to the inode and the name of the file can be changed without problems.
I want to check the content of a file from Linux Kernel v3.0.8 knowing only struct inode *. I only need to read the beginning of a file pointed by this inode, then close and return. I don't care about additional information like filename/mountpoint etc.. In fact, the file may not have the name (like deleted but still open). Is it possible?
I finally did it like this:
This is needed.
struct path root;
struct file *filerd;
Get the init task fs root.
task_lock(&init_task);
get_fs_root(init_task.fs, &root);
task_unlock(&init_task);
Change dentry to this file:
root.dentry = d_find_alias(inode);
Open file:
filerd = file_open_root(root.dentry->d_parent, root.mnt,
root.dentry->d_name.name, O_RDONLY);
It worked for every process I tested and for different mount points, which surprised me.
First, a little background information to provide some motivation for this question: I've got a program that runs on a headless Linux server and reads/writes files on several removable external hard drives, each of which is formatted with ext4 filesystem. Very occasionally, the filesystem metadata on one of these drives gets corrupted for whatever reason (ext4 journalling notwithstanding), which can cause the ext4 filesystem drive to detect a problem and remount the partition as read-only, presumably as a precaution against cascading errors corrupting the drive further.
Okay, fair enough; but what I'd like to do now is add a function to my program that can detect when the drive is in this remounted-read-only state, so that it can pro-actively notify the user that his drive is in trouble.
My question is, what is an elegant/supported way to query a filesystem to find out if it is mounted read-only?
Attempting to write a file to the filesystem isn't good enough, because that could fail for other reasons, and also because I don't want to write to the filesystem if I don't have to.
My program could fopen("/proc/mounts", "r") and parse the lines of text that it generates (grepping for the "rw," token on the line corresponding to my partition), and I will if I have to, but that solution seems a bit hacky (too much like screen-scraping, liable to break if the text format ever changes).
So, is there some lightweight/purpose-built Linux system call that I could use that would tell me whether a given filesystem mount point (e.g. "/dev/sda1") is currently mounted read-only? It seems like stat() might be able to do it, but I can't see how.
The getmntent() family should meet your needs.
NAME
getmntent, setmntent, addmntent, endmntent, hasmntopt, getmntent_r -
get filesystem descriptor file entry
SYNOPSIS
#include <stdio.h>
#include <mntent.h>
FILE *setmntent(const char *filename, const char *type);
struct mntent *getmntent(FILE *stream);
int addmntent(FILE *stream, const struct mntent *mnt);
int endmntent(FILE *streamp);
char *hasmntopt(const struct mntent *mnt, const char *opt);
/* GNU extension */
#include <mntent.h>
struct mntent *getmntent_r(FILE *streamp, struct mntent *mntbuf,
char *buf, int buflen);
DESCRIPTION
These routines are used to access the filesystem description file
/etc/fstab and the mounted filesystem description file /etc/mtab.
The setmntent() function opens the filesystem description file
filename and returns a file pointer which can be used by getmntent().
The argument type is the type of access required and can take the same
values as the mode argument of fopen(3).
The getmntent() function reads the next line of the filesystem
description file from stream and returns a pointer to a structure
containing the broken out fields from a line in the file. The pointer
points to a static area of memory which is overwritten by subsequent
calls to getmntent().
The addmntent() function adds the mntent structure mnt to the end of
the open stream.
The endmntent() function closes the stream associated with the
filesystem description file.
The hasmntopt() function scans the mnt_opts field (see below) of the
mntent structure mnt for a substring that matches opt. See
and mount(8) for valid mount options.
The reentrant getmntent_r() function is similar to getmntent(), but
stores the struct mount in the provided *mntbuf and stores the strings
pointed to by the entries in that struct in the provided array buf of
size buflen.
The mntent structure is defined in as follows:
struct mntent {
char *mnt_fsname; /* name of mounted filesystem */
char *mnt_dir; /* filesystem path prefix */
char *mnt_type; /* mount type (see mntent.h) */
char *mnt_opts; /* mount options (see mntent.h) */
int mnt_freq; /* dump frequency in days */
int mnt_passno; /* pass number on parallel fsck */
};
...
The easiest way to check that the filesystem of an open file for writing has become mounted read-only is to check the errno variable for EROFS error.
If you don't have the possibility of having a writable directory or file in that filesystem, you cannot get a portable way of checking if the filesystem has become read only (more if it has become so due to device errors)
Another way is to ask the administrator to check, or try to read the /proc/mounts file yourself. But this is linux specific only.
I'm using Linux (Ubuntu 11.10).
Well, when I call the system call open, for example in a C program:
size_t filedesc = open("testfile.txt",O_CREAT | O_WRONLY,0640);
How can I access the partition, I mean is there a way to return the partition used?
The system call open is the defined above:
SYSCALL_DEFINE3(open, const char __user *, filename, int, flags, int, mode)
If I want, I can put a printk("%s",filename) and see the path. But how I can access the partition?
An example: I have two archives example.txt in two different partitions (for example /dev/sda1 and /dev/sda2).
Then I call the system call open: Lets suppose I called the example.txt in the partition /dev/sda2.
Is there a way to acess the partition (for example, printk(KERN_ALERT "%s",partition)) using the open system call?
There's nothing as simple as you might hope.
Within the do_sys_open() function, immediately before return fd;, the struct file *f points to a legitimate, opened, struct file.
The struct file contains a struct path f_path.
The struct path contains a struct vfsmount *mnt. struct vfsmount represents every mounted filesystem on the system.
The struct vfsmount contains a struct super_block *mnt_sb.
The struct super_block contains a struct block_device *s_bdev.
The struct block_device contains a struct hd_struct *bd_part.
The struct hd_struct contains a struct device __dev and an int partno. Together, these two define which partition your file is located on.
Update
I had originally stopped looking when I found the device and partition number references, since I assumed that was all that was required to put together the human-friendly string. But when looking again with fresh eyes, I see there is more:
The struct hd_struct contains a struct partition_meta_info *info.
The struct partition_meta_info contains a field:
u8 volname[PARTITION_META_INFO_VOLNAMELTH];
This field is name of the device you're after.
Thru a shell, df /some/dir gives you the file-system involved. Programmatically, with stat system call, you get the st_dev field.
(added:) I don't guess what you want to do exactly, but perhaps doing that using FUSE could be simpler.