Как найти файл для подключенного устройства?
Вопрос:
если я зациклить файл, как это
mount /volumes/jfs.dsk /mnt/jfs -t jfs -o loop
то, что происходит за кулисами
losetup /dev/loop1 /volumes/jfs.dsk
mount /dev/loop1 /mnt/jfs -t jfs -o loop
Мой вопрос сейчас:
Если у меня есть /dev/loop1, как я могу найти файл, к которому принадлежит это устройство?
например, учитывая "/dev/loop1" в качестве входных данных, как я могу получить обратно /volumes/jfs.dsk?
3 ответа
Поскольку никто не знал конкретного ответа, я отвечаю здесь как ссылка для других:
public static string loopfile_from_sysfs(string device)
{
string res = null;
Mono.Unix.Native.Stat st;
System.IntPtr f;
//if (stat(device, &st) || !S_ISBLK(st.st_mode))
//if (System.Convert.ToBoolean(Mono.Unix.Native.Syscall.stat(device, out st)) || !S_ISBLK((int) st.st_mode))
// return null;
Mono.Unix.Native.Syscall.stat(device, out st);
const string _PATH_SYS_DEVBLOCK = "/sys/dev/block";
string strPath = string.Format("{0}/{1}:{2}/loop/backing_file", _PATH_SYS_DEVBLOCK, gnu_dev_major(st.st_rdev), gnu_dev_minor(st.st_rdev));
f = Mono.Unix.Native.Syscall.fopen(strPath, "r");
if (f == IntPtr.Zero)
return null;
Mono.Unix.Native.Syscall.fclose(f);
res = System.IO.File.ReadAllText(strPath);
strPath = null;
return res;
} // End Function loopfile_from_sysfs
public static string loopdev_get_loopfile(string device)
{
string res = loopfile_from_sysfs(device);
if (res == null)
{
loop_info lo = new loop_info();
loop_info64 lo64 = new loop_info64();
int fd;
if ((fd = Mono.Unix.Native.Syscall.open(device, Mono.Unix.Native.OpenFlags.O_RDONLY)) < 0)
return null;
if (UnsafeNativeMethods.ioctl(fd, LOOP_GET_STATUS64, ref lo64) == 0)
{
//lo64.lo_file_name[LO_NAME_SIZE-2] = '*';
//lo64.lo_file_name[LO_NAME_SIZE-1] = 0;
//res = strdup((char *) lo64.lo_file_name);
res = lo64.lo_file_name;
Console.WriteLine("LOOP_GET_STATUS64");
}
else if (UnsafeNativeMethods.ioctl(fd, LOOP_GET_STATUS, ref lo) == 0)
{
//lo.lo_name[LO_NAME_SIZE-2] = '*';
//lo.lo_name[LO_NAME_SIZE-1] = 0;
//res = strdup((char *) lo.lo_name);
res = lo.lo_name;
Console.WriteLine("LOOP_GET_STATUS");
}
Mono.Unix.Native.Syscall.close(fd);
} // End if (res == null)
return res;
} // End Function loopdev_get_loopfile
И это версия C:
static char *loopfile_from_sysfs(const char *device)
{
FILE *f;
struct stat st;
char buf[PATH_MAX], *res = NULL;
// PATH_MAX: 4096
if (stat(device, &st) || !S_ISBLK(st.st_mode))
return NULL;
#define _PATH_SYS_DEVBLOCK "/sys/dev/block"
snprintf(buf, sizeof(buf), _PATH_SYS_DEVBLOCK "/%d:%d/loop/backing_file",
major(st.st_rdev), minor(st.st_rdev));
f = fopen(buf, "r");
if (!f)
return NULL;
if (fgets(buf, sizeof(buf), f)) {
size_t sz = strlen(buf);
if (sz) {
buf[sz - 1] = '\0';
res = strdup(buf);
}
}
fclose(f);
printf("loopfile_from_sysfs Result: %s\n", res);
return res;
}
char *loopdev_get_loopfile(const char *device)
{
char *res = loopfile_from_sysfs(device);
if (!res) {
struct loop_info lo;
struct loop_info64 lo64;
int fd;
if ((fd = open(device, O_RDONLY)) < 0)
return NULL;
if (ioctl(fd, LOOP_GET_STATUS64, &lo64) == 0) {
lo64.lo_file_name[LO_NAME_SIZE-2] = '*';
lo64.lo_file_name[LO_NAME_SIZE-1] = 0;
res = strdup((char *) lo64.lo_file_name);
printf("LOOP_GET_STATUS64\n");
} else if (ioctl(fd, LOOP_GET_STATUS, &lo) == 0) {
lo.lo_name[LO_NAME_SIZE-2] = '*';
lo.lo_name[LO_NAME_SIZE-1] = 0;
res = strdup((char *) lo.lo_name);
printf("LOOP_GET_STATUS\n");
}
close(fd);
}
return res;
}
Из страницы руководства проигрыша (8)
Если указан только аргумент loopdev, отображается состояние соответствующего устройства цикла.
Так что вам нужно только использовать
$ losetup /dev/loop1
/dev/loop1: [0802]:4751362 (/volumes/jfs.dsk)
Если у вас последнее ядро (2.6.37 или выше), вы также можете получить целевой файл в /sys/block/loopX/loop/backing_file
,
$ cat /sys/block/loop1/loop/backing_file
/volumes/jfs.dsk
Если вы хотите сделать это проблематично (вы не четко указали это, но вы добавили c
тега), вы должны использовать вызов ioctl LOOP_GET_STATUS или LOOP_GET_STATUS64.
Думаю звоню
strace losetup /dev/loop1
и тогда поиск в Google даст вам ответ.
Из того, что я видел на своем ПК, для получения статуса устройства обратной петли вызывается ioctl 0x4c05.