2

I want to access a device (opening it) with the only information about the device being an st_dev field in a file stat struct.

int fd;
char *path;
struct stat buf;
stat("/path/to/my/file", &buf);
// do some things with buf.st_dev
// then either path contains a path to the device refered by st_dev or fd contains a file descriptor refering to it.

I want to find a way to do this either in a POSIX portable way, or with distincts specific ways for at least Linux and MacOS systems

Gilles 'SO- stop being evil'
  • 104,111
  • 38
  • 209
  • 254
Blumer
  • 75
  • 7
  • I don't think there's any way to do this in POSIX. You may be able to do it using Linux-specific operations. – Barmar Nov 08 '21 at 17:01
  • I am also keen to find a way to do in using Linux-specific operations – Blumer Nov 08 '21 at 17:04
  • @Barmar https://stackoverflow.com/questions/57642729/how-do-i-convert-s-st-dev-to-sys-block-name is not a duplicate. Not only because it's for Linux, but also because it's only about locating a place with metadata about the device, not a place that allows reaching the content of the block device. – Gilles 'SO- stop being evil' Nov 08 '21 at 17:21
  • I assumed (incorrectly) that metadata would include the device path or mount info. @Gilles'SO-stopbeingevil' – Barmar Nov 08 '21 at 17:28

1 Answers1

3

Direct interaction with a block device requires a device node. The device node controls permissions (who can access the device directly).

Theoretical solution: call mknod or mknodat to create a block device (S_IFBLK) with the given dev_t value. It needs to be on a filesystem that supports device files.

mknod("/var/run/myprogram/mydevice", S_IFBLK | S_IRUSR | S_IWUSR, buf.st_dev);

This requires elevated privileges: classically root permissions. On Linux, the CAP_MKNOD capability is sufficient, but some security frameworks may prevent even root from creating device nodes in random places. I don't know whether this requires more than root permissions on macOS.

Make sure not to give unprivileged programs access to the device.

Practical solution: look under /dev for a suitable device, i.e. a block device ((found_stat.st_mode & S_IFBLK) != 0) such that found_stat.st_rdev == buf.st_dev. There's no POSIX C function that does the recursive search, so you'll have to code it manually.

While find can do the recursive traversal, it has no option to match a device file by its device number, which makes it inconvenient to locate the desired device.

Gilles 'SO- stop being evil'
  • 104,111
  • 38
  • 209
  • 254