Linux which device is this file on

Linux programming: which device a file is in

I would like to know which entry under /dev a file is in. For example, if /dev/sdc1 is mounted under /media/disk, and I ask for /media/disk/foo.txt, I would like to get /dev/sdc as response. Using stat system call on that file I will get its partition major and minor numbers (8 and 33, for sdc1). Now I need to get the «root» device (sdc) or its major/minor from that. Is there any syscall or library function I could use to link a partition to its main device? Or even better, to get that device directly from the file?

brw-rw---- 1 root floppy 8, 32 2011-04-01 20:00 /dev/sdc brw-rw---- 1 root floppy 8, 33 2011-04-01 20:00 /dev/sdc1 

5 Answers 5

The quick and dirty version: df $file | awk ‘NR == 2 ‘ .

Programmatically. well, there’s a reason I started with the quick and dirty version. There’s no portable way to programmatically get the list of mounted filesystems. ( getmntent() gets fstab entries, which is not the same thing.) Moreover, you can’t even parse the output of mount(8) reliably; on different Unixes, the mountpoint may be the first or the last item. The most portable way to do this ends up being. parsing df output (And even that is iffy, as you noticed with the partition number.). So you’re right back to the quick and dirty shell solution anyway, unless you want to traverse /dev and look for block devices with matching major(st_rdev) ( major() being from sys/types.h ).

If you restrict this to Linux, you can use /proc/mounts to get the list of mounted filesystems. Other specific Unixes can similarly be optimized: for example, on OS X and I think FreeBSD, you can use sysctl() on the vfs tree to get mountpoints. At worst you can find and use the appropriate header file to decipher whatever the mount table file is (and yes, even that varies: on Solaris it’s /etc/mnttab , on many other systems it’s /etc/mtab , some systems put it in /var/run instead of /etc , and on many Linuxes it’s either nonexistent or a symlink to /proc/mounts ). And its format is different on pretty much every Unix-like OS.

Источник

Linux programming: which device a file is in

I named my dongles ttyFTDI0 etc., and wrote the numbers on the dongles with a marker: Solution 3: This one-liner udev rule will give a fixed name (e.g. /dev/ttyUSB_A9YL5BJJ) based on serial number for any device with vendor/product ids as given. Put this into a udev rules file e.g. /etc/udev/rules.d/60-ftdi-serial-names.rules Solution 1: It may be that put_user() is defined as a macro so that the post increment operator in is screwing up — though I don’t see how it explains what you are seeing. Solution 1: Find more info using sysfs: Of course, the linked devices/. node contains a lot of information Adding information based on the OP’s comment: The device number keeps growing if devices are removed/inserted.

Читайте также:  Linux вывести все команды терминала

Linux programming: which device a file is in

The quick and dirty version: df $file | awk ‘NR == 2 ‘ .

Programmatically. well, there’s a reason I started with the quick and dirty version. There’s no portable way to programmatically get the list of mounted filesystems. ( getmntent() gets fstab entries, which is not the same thing.) Moreover, you can’t even parse the output of mount(8) reliably; on different Unixes, the mountpoint may be the first or the last item. The most portable way to do this ends up being. parsing df output (And even that is iffy, as you noticed with the partition number.). So you’re right back to the quick and dirty shell solution anyway, unless you want to traverse /dev and look for block devices with matching major(st_rdev) ( major() being from sys/types.h ).

If you restrict this to Linux, you can use /proc/mounts to get the list of mounted filesystems. Other specific Unixes can similarly be optimized: for example, on OS X and I think FreeBSD, you can use sysctl() on the vfs tree to get mountpoints. At worst you can find and use the appropriate header file to decipher whatever the mount table file is (and yes, even that varies: on Solaris it’s /etc/mnttab , on many other systems it’s /etc/mtab , some systems put it in /var/run instead of /etc , and on many Linuxes it’s either nonexistent or a symlink to /proc/mounts ). And its format is different on pretty much every Unix-like OS.

The information you want exists in sysfs which exposes the linux device tree. This models the relationships between the devices on the system and since you are trying to determine a parent disk device from a partition, this is the place to look. I don’t know if there are any hard and fast rules you can rely on to stop your code breaking with future versions of the kernel, but the kernel developers do try to maintain sysfs as a stable interface.

If you look at /sys/dev/block/: , you’ll see it is a symlink with the tail components being block// . If you were to perform a readlink(2) system call on that, you could parse the link destination to get the disk device name. In shell (since it’s easier to express this way, but doing it in C will be pretty easy):

$ echo $(basename $(dirname $(readlink /sys/dev/block/8:33))) sdc 

Alternatively, you could take advantage of the nesting of partition directories in the disk directories (again in shell, but from C, its an open(2) , read(2) , and close(2) ):

$ cat /sys/dev/block/8:33/../dev 8:32 

That assumes your starting major:minor is actually for a partition, not some other sort of non-nested device.

What you looking for is impossible — there is no 1:1 connection between a block device file and the partition it is describing.

  1. You can create multiple block device files with different names (but the same major and minor numbers) and they are indistinguishable (N:1)
  2. You can use a block device file as an argument to mount to mount a partition and then delete the block device file leaving the partition mounted. (0:1)
Читайте также:  How to add users and group in linux

So there is no way to do what you want except in a few specific and narrow cases.

Find out what device /dev/root represents in Linux?, Of course, you can look at the kernel command line and see on which initial root filesystem Linux was instructed to boot (root parameter): $ cat /proc/cmdline mem=512M console=ttyS2,115200n8 root=/dev/mmcblk0p2 rw rootwait However, this doesn’t mean that what you see is the current root device.

How to find out which USB-RS232 device is on which tty?

Find more info using sysfs:

$ ls /sys/bus/usb-serial/devices/ -ltrah lrwxrwxrwx 1 root root 0 2012-02-07 22:17 ttyUSB0 -> ../../../devices/pci0000:00/0000:00:0f.4/usb2/2-2/2-2:1.0/ttyUSB0 $ ls -ltrad /sys//devices/pci0000:00/0000:00:0f.4/usb2/2-2/2-2:1.0/ttyUSB0 drwxr-xr-x 4 root root 0 2012-02-07 22:17 /sys//devices/pci0000:00/0000:00:0f.4/usb2/2-2/2-2:1.0/ttyUSB0 $ ls -ltrad /dev/ttyUSB0 crw-rw---- 1 root dialout 188, 0 2012-02-01 00:17 /dev/ttyUSB0 

Of course, the linked devices/. node contains a lot of information

Adding information based on the OP’s comment:

The device number keeps growing if devices are removed/inserted. lsusb -t can be used to correlate the device numbers with usb bus/port.

Then, ‘lsusb -d devID’ can determine what device is on which port. Finally ‘ls /sys/bus/usb-serial/devices/ -ltrah’ will list (by bus/port) where it was mounted.

Not very convenient, but it ‘ works

You can use udev to assign a stable symbolic link to each FTDI dongle. Use device and vendor to match the type, and then the serial number for the specific device. Then use the symbolic link in the script.

I named my dongles ttyFTDI0 etc., and wrote the numbers on the dongles with a marker:

$ cat /etc/udev/ftdi.rules SUBSYSTEMS=="usb", KERNEL=="ttyUSB*", ATTRS=="0403", ATTRS=="6001", ATTRS=="FTDEN97D", SYMLINK+="ttyFTDI0" SUBSYSTEMS=="usb", KERNEL=="ttyUSB*", ATTRS=="0403", ATTRS=="6001", ATTRS=="A600b30P", SYMLINK+="ttyFTDI1" SUBSYSTEMS=="usb", KERNEL=="ttyUSB*", ATTRS=="0403", ATTRS=="6001", ATTRS=="A600bexU", SYMLINK+="ttyFTDI2" SUBSYSTEMS=="usb", KERNEL=="ttyUSB*", ATTRS=="0403", ATTRS=="6001", ATTRS=="FTFMSA54", SYMLINK+="ttyFTDI3" SUBSYSTEMS=="usb", KERNEL=="ttyUSB*", ATTRS=="0403", ATTRS=="6001", ATTRS=="FTFMUW4A", SYMLINK+="ttyFTDI4"

This one-liner udev rule will give a fixed name (e.g. /dev/ttyUSB_A9YL5BJJ) based on serial number for any device with vendor/product ids as given.

Put this into a udev rules file e.g. /etc/udev/rules.d/60-ftdi-serial-names.rules

SUBSYSTEM=="tty", ATTRS=="0403", ATTRS=="6001", ENV=="?*", SYMLINK+="ttyUSB_%E" 

C — Linux programming: which device a file is in, Major number will tell you which device it is: 3 — IDE on 1st controller, 22 — IDE on 2nd controller and 8 for SCSI. Minor number will tell you partition number and — for IDE devices — if it’s primary or secondary drive. This calculation is different for IDE and SCSI.

Linux Device Driver — what’s wrong with my device_read()?

It may be that put_user() is defined as a macro so that the post increment operator in

is screwing up — though I don’t see how it explains what you are seeing.

Anyway it would be more convenient and more efficient to use copy_to_user() to copy the whole msg.

Читайте также:  Add printer cups linux

The reason it only shows 1 byte is because you are incrementing the msg_ptr before setting it equal to c. It needs to be c = *msg_ptr++; or c = *msg_ptr; msg_ptr++; so that the increment happens after the assignment

Unix — What is special about /dev/tty?, /dev/tty is a synonym for the controlling terminal (if any) of the current process. As jtl999 says, it’s a character special file; that’s what the c in the ls -l output means. man 4 tty or man -s 4 tty should give you more information, or you can read the man page online here. Incidentally, pwd > /dev/tty doesn’t …

Device node access permissions in Linux

If your device registers itself using udev, which is the most likely case, then you can create a custom udev rule to manage the permissions on this device.

For example, this rule assigns rw-rw-rw- permissions to a device belonging to the USB vendor 0bb4:
SUBSYSTEM==»usb», ATTR==»0bb4″, MODE=»0666″, GROUP=»plugdev»

How to find out which USB-RS232 device is on which tty?, The device number keeps growing if devices are removed/inserted. lsusb -t can be used to correlate the device numbers with usb bus/port. Then, ‘lsusb -d devID’ can determine what device is on which port. Finally ‘ls /sys/bus/usb-serial/devices/ -ltrah’ will list (by bus/port) where it was mounted. Not very convenient, but it ‘ …

Источник

How to get device name on which a file is located from its path in c?

How do I do this with the C programming language? I know the terminal command to do it, but I need C functions that will do the job. EDIT: I have read this question before asking mine. It doesn’t concretly mention code in C, it’s more related to bash than to the C language. Thanks.

The duplicate has an answer regarding bash, while the answer posted here actually tells how to do this in C.

3 Answers 3

I just needed that inside a program I am writing.

So instead of running «df» and parsing the output, I wrote it from scratch.

You first find the device inode using stat() then iterate and parse /proc/self/mountinfo to find the inode and get the device name.

/* Get physical device from file or directory name. By Zibri https://github.com/Zibri/get_device */ #include #include #include #include #include #include #include #include #include int get_device(char *name) < struct stat fs; if (stat(name, &fs) < 0) < fprintf(stderr, "%s: No such file or directory\n", name); return -1; >FILE *f; char sline[256]; char minmaj[128]; sprintf(minmaj, "%d:%d ", (int) fs.st_dev >> 8, (int) fs.st_dev & 0xff); f = fopen("/proc/self/mountinfo", "r"); if (f == NULL) < fprintf(stderr, "Failed to open /proc/self/mountinfo\n"); exit(-1); >while (fgets(sline, 256, f)) < char *token; char *where; token = strtok(sline, "-"); where = strstr(token, minmaj); if (where) < token = strtok(NULL, " -:"); token = strtok(NULL, " -:"); printf("%s\n", token); break; >> fclose(f); return -1; > int main(int argc, char **argv) < if (argc != 2) < fprintf(stderr, "Usage:\n%s FILE OR DIRECTORY. \n", basename(argv[0])); return -1; >get_device(argv[1]); return 0; > 

output is just the device name.

$ gcc -O3 getdevice.c -o gd -Wall $ ./gd . /dev/sda4 $ ./gd /mnt/C /dev/sda3 $ ./gd /mnt/D /dev/sdb1 $ 

Источник

Оцените статью
Adblock
detector