Linux system call to discover the filesystem of a device - linux

My question is the following: I need to get the filesystem of a device (a pendrive in my case) to use this information. My application is running in a Linux embedded system and I want to accept only pendrives with FAT and FAT32 filesystem to perform a file exportation. I searched the internet, but I didn't find what is the system call that I need.
About the source code, my application is being written in C++.
I already used the struct statfs, however after a test I discover that the value of the field f_type is the same when I use a NTFS and a FAT32 formatted pendrive. The output of the test is the value 0x1021994.
I know that is possible to discover the filesystem, the "fdisk -l" command do the job, however I can't figure out in the fdisk code how.

You can use the statfs system call which includes uint32_t f_type; /* type of filesystem */ in the returned struct statfs
Note that, as JoshuaRLi points out, statfs is now deprecated in favor of statvfs — and struct statvfs does not include an f_type field.

The easiest way is:
1) Run the "mount" command to list one or more filesystems
2) Parse out the information you need
3) You can invoke "mount" from the "popen()" API
PS:
There's also a "mount()" API, which could eliminate steps 2) and 3), if you prefer.
Linux being Linux, there's also probably at least half a dozen other viable alternatives - your choice :)

Maybe you could parse /proc/mounts file?

Specify the filesystem type when mounting (do not use the default -t auto). If you need to support multiple types, consider trying them all.

Related

linux kernel driver debug log

I'm writing a Linux kernel driver for a device that has quite a bit going on and a bunch of interaction from user-space. In order to debug and troubleshoot these interactions I'm storing them in a data array in the driver and need to export this data to user-space via some sort of file node. It'd be great if I could just export the binary data and let user-space parse it into human-readable text but the requirement from other parties involved is to have this done in-driver so one can just cat the file node from the command line and get something readable.
Currently I'm just using a sysfs node but I'm pretty sure that's the wrong place for that sort of thing and I need to able to write out more than PAGE_SIZE of data. What is the proper filesystem object I should be using for this type of thing? I looked at debugfs but it seems to be for more specific things much like sysfs is.
I think the best way is to use the debugfs as its developed just for debugging purpose and only people with the necessary permission which you can decide will be able to access it.
So go ahead with using debugfs

Port Window Api---GetVolumeInformation to Linux

win Api
WINAPI GetVolumeInformation(
_In_opt_ LPCTSTR lpRootPathName,
_Out_opt_ LPTSTR lpVolumeNameBuffer,
_In_ DWORD nVolumeNameSize,
_Out_opt_ LPDWORD lpVolumeSerialNumber,
_Out_opt_ LPDWORD lpMaximumComponentLength,
_Out_opt_ LPDWORD lpFileSystemFlags,
_Out_opt_ LPTSTR lpFileSystemNameBuffer,
_In_ DWORD nFileSystemNameSize
);
Hello: I want to port windows api GetVolumeInformation to Linux.
Q1:Does Linux have the same function.
Q2:if not.
Q2.1 what is lpVolumeNameBuffer in linux(is /dev/sda1)? how can i get it in linux?
Q2.2 what is lpVolumeSerialNumber in linux(is )? i use ioctl get it.
struct hd_driveid id;ioctl(fd, HDIO_GET_IDENTITY, &id);
Q2.3 what is lpMaximumComponentLength in linux? how can i get it in linux?
Q2.4 what is lpFileSystemFlags in linux? how can i get it in linux?
Q2.5 what is lpFileSystemNameBuffer? how can i get it in linux?
If you have any good ideas I would really appreciate it.
Thanks!
Conceptually, linux doesn't have volumes in the same way that Windows does - linux has mount points, Windows has 'drive letters', for lack of a better term.
lpVolumeName is the friendly name of a mounted volume - for instance, my C: drive is labeled 'main_disk'. The point of this label is only to give a friendly name to the drive, and the label can change whenever the user decides to change it, and it does not affect the structure of the ultimate file system layout.
In linux, volumes are mounted as mount points, eg, the device referred to as /dev/sda2 might be mounted at the /var mount point. Here, /var is part of the file system, and thus, mount points determine the structure of the ultimate file system layout. This is not simply a friendly name for the user to give to their disk so that they can know what it is.
Linux and others do support something called disk labeling, but that's used to be able to refer to the disk using a stable name, instead of its device name, which could change if the hard drives are moved around in the computer. For instance, in FreeBSD, I could label my main hard drive root; when that hard drive is detected during boot up, i can instead refer to it as /dev/label/root and specify the mount point for it using that name. However, this is still being used to determine the ultimate structure of the file system - it's a functional dependency - and so the user can't change it willy-nilly without breaking something or having to change the fstab file that describes device-to-mount-point mappings.
lpVolumeSerialNumber has to do with the filesystem on the volume; that is, this field is specific to what filesystem is being used on the volume, and isn't something that all volumes will have.
In Windows, typically two filesystems are supported - Fat32 and NTFS - both of which can give a serial number to a file system. In Linux, FreeBSD, etc, there are many, many file systems - UFS/UFS2, EXT/EXT2/EXT3/EXT4, ReiserFS/Reiser4, BTRFS, ZFS, FFS, etc. Whether or not a volume has a serial number depends on what file system the volume is using, and not all filesystems support serial numbers. Each filesystem will have its own utility commands to query this sort of data - for instance, dumpfs on FreeBSD for UFS2 file systems.
The list goes on. Unfortunately, there are no direct analogs between Windows and Linux for the parts you're asking about, but as I've shown, sometimes it doesn't matter and when it does, you can usually find something to replace it with.
POSIX systems have statvfs()/fstatvfs() subroutines (which might be a library function or system call, depending on the OS). Perhaps they are what most closely resemble what the Windows' function you named does, but they have a very different interface.
I don't know if it matters to you, but a related problem is to enumerate mounted filesystems. To enumerate currently mounted filesystems on Linux, you can read the contents of /proc/mounts. Some other UNIX flavors (namely BSD-derived systems) have getvfsstat()/getfsstat() calls for the same purpose. Solaris has (or used to have) neither, and you best choice was to read /etc/mnttab. AIX has none of these, and your (only?) reliable (?) option to enumerate current mounts is to parse the output of the mount command, run without any argument.

Best POSIX way to determine if a filesystem is mounted read only

If I have a POSIX system like Linux or Mac OS X, what's the best and most portable way to determine if a path is on a read-only filesystem? I can think of 4 ways off the top of my head:
open(2) a file with O_WRONLY - You would need to come up with a unique filename and also pass in O_CREAT and O_EXCL. If it fails and you have an errno of EROFS then you know it's a read-only filesystem. This would have the annoying side effect of actually creating a file you didn't care about, but you could unlink(2) it immediately after creating it.
statvfs(3) - One of the fields of the returned struct statvfs is f_flag, and one of the flags is ST_RDONLY for a read-only filesystem. However, the spec for statvfs(3) makes it clear that applications cannot depend on any of the fields containing valid information. It would seem there's a decent possibility ST_RDONLY might not be set for a read-only filesystem.
access(2) - If you know the mount point, you can use access(2) with the W_OK flag as long as you are running as a user who would have write access to the mountpoint. Ie, either you are root or it was mounted with your UID as a mount parameter. You would get a return value of -1 and an errno of EROFS.
Parsing /etc/mtab or /proc/mounts - Doesn't seem portable. Mac OS X seems to have neither of these, for example. Even if the system did have /etc/mtab I'm not sure the fields are consistent between OSes or if the mount options for read-only (ro on Linux) are portable.
Are there other ways I'm missing? If you needed to know if a filesystem was mounted read-only, how would you do it?
You could also popen the command mount and examine the output looking for your file system and seeing if it held the text " (ro,".
But again, that's not necessarily portable.
My option would be to not worry about whether the file system was mounted read only at all. Just try and create your file and, if it fails, tell the user what the error was. And, of course, give them the option of saving it somewhere else.
You really have to do that sort of thing anyway since, in any scenario where there's even a small gap between testing and doing, you may find the situation changes (probably not to the extent of making an entire file system read only but, who knows, maybe there is (or will be in the future) a file system that allows this).
utime(path, NULL);
If you have write perms, then that will give you ROFS or -- if permitted -- simply update the mtime on the directory, which is basically harmless.

Hardware recognition in user space Linux

I want to be able to inspect my Linux machine hardware in C.
How do I get the information that appear in dmesg in C ?
For example, for keyboard the message is input: AT Translated Set 2 keyboard as /devices/platform/i8042/serio0/input/input0
I want to get in my program the label, AT Translated Set 2, and the path, /devices/platform/i8042/serio0/input/input0.
Any idea how to do so ?
amit
You can also look at the contents of files in /proc.
/proc/version, /proc/ioports, /proc/iomem, /proc/meminfo, and others have a lot of information in them.
The files under /proc/bus have additional information about the system's hardware devices.
I'd also recommend looking at the source code for usbutils and pciutils for example code to get the output from the lsusb and lspci commands respectively.
It uses the klogctl call.
Best thing is to read the source code yourself, it can be downloaded here: util-linux
You would want to use libhal, and connect to the hal daemon. If HAL isn't there, look for a mounted sysfs partition. Check out /sys/devices, or work backwards through /sys/bus.
If neither HAL nor sysfs is available, reconsider your approach or restrict your scope.

Efficient way to query or set the volume name of an ext3 partition under Linux?

Through a bit of digging, I've discovered how to set and get the volume name of an ext3 partition on my Linux box:
set the volume label
tune2fs -L MY-NEW-NAME /dev/disk/by-path/pci-0000:00:1f.2-scsi-2:0:0:0-part1
get the volume's current level
dumpe2fs -h /dev/disk/by-path/pci-0000:00:1f.2-scsi-2:0:0:0-part1 | grep 'volume name'
Those work fine, but I have several questions:
1) Are those commands the best way to set/get the volume name? Or is there an easier method that I don't know about?
2) How likely is changing a volume's label to break something? i.e. does a standard Linux system rely on volumes having certain names? Or can I rename volumes to any names I like, without causing problems?
3) At some point I would like to include in my program a GUI interface to the above functionality. One way to do that would be to have my program execute the above shell commands (via system() or whatever), but that seems a bit clunky and heavyweight... are there direct functions that I can call to do the same thing? If so, what are they?
Thanks,
Jeremy
1) What about e2label?
2) The 'mount' command can identify devices via their label, so changing a label could break something inside /etc/fstab.. Anyway normally they aren't used. (At least on Ubuntu and Fedora IIRC)
3) What language are you using? Anyway, it looks like e2label doesn't use any particular API.. It reads and writes to the device directly

Resources