如何以编程方式进行循环挂载?

14
我最近写了一篇关于如何在树莓派上从镜像文件中挂载分区的指南。这些说明相当复杂,因此我想用一个C程序来替换它们。我已经成功列出了图像的分区并计算了适当的偏移量。
在原始说明中,我们需要运行:
$ sudo mount -o loop,offset=80740352 debian6-19-04-2012.img /mnt

我现在需要用代码实现这个。我已经找到了mount函数和util-linux中的libmount
我现在在util-linux中找到了loopdev.c。有没有一种简单的方法来创建loop设备,还是我必须从这段代码中学习并使用ioctl呢?

1
最简单的方法是从您的代码中调用mount(使用systemexec*变体)。 - Mat
5
为什么不编写Shell脚本? - iblue
1
@iblue 我手头有点时间...我对C语言比Bash更有信心。Git最初是用shell脚本编写的,然后进行了移植,我猜我(愚蠢地?)跳过了一个步骤。 - Alex Chamberlain
1
你可以在C中跳过shell分支,fork和执行mount命令。看起来很容易。你的argv将有一些固定字符串,一个由用户提供的镜像文件名和一个sprintf(...,"loop,offset=%llu", offset) - Alan Curry
1
@FaheemMitha 不是这样的,如果你看一下我在 Github 上的进展,你就会看到我正在计算偏移量。创建循环设备是一个问题。 - Alex Chamberlain
显示剩余6条评论
1个回答

15

下面的函数将循环设备device绑定到fileoffset处。成功返回0,否则返回1。

int loopdev_setup_device(const char * file, uint64_t offset, const char * device) {
  int file_fd = open(file, O_RDWR);
  int device_fd = -1; 

  struct loop_info64 info;

  if(file_fd < 0) {
    fprintf(stderr, "Failed to open backing file (%s).\n", file);
    goto error;
  }

  if((device_fd = open(device, O_RDWR)) < 0) {
    fprintf(stderr, "Failed to open device (%s).\n", device);
    goto error;
  }

  if(ioctl(device_fd, LOOP_SET_FD, file_fd) < 0) {
    fprintf(stderr, "Failed to set fd.\n");
    goto error;
  }

  close(file_fd);
  file_fd = -1; 

  memset(&info, 0, sizeof(struct loop_info64)); /* Is this necessary? */
  info.lo_offset = offset;
  /* info.lo_sizelimit = 0 => max avilable */
  /* info.lo_encrypt_type = 0 => none */

  if(ioctl(device_fd, LOOP_SET_STATUS64, &info)) {
    fprintf(stderr, "Failed to set info.\n");
    goto error;
  }

  close(device_fd);
  device_fd = -1; 

  return 0;

  error:
    if(file_fd >= 0) {
      close(file_fd);
    }   
    if(device_fd >= 0) {
      ioctl(device_fd, LOOP_CLR_FD, 0); 
      close(device_fd);
    }   
    return 1;
}

参考资料

  1. linux/loop.h
  2. piimg

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接