3

I'm trying to mount a vfat disk image from DOS, using .C

if( mount( "/mypath/disk.img", "/mypath/img/", "vfat", MS_DIRSYNC | MS_SYNCHRONOUS, "utf8" ) ) { 
  printf( "Error mount %s errno=%d %s\n", dst.c_str(), errno, strerror( errno ) );
}

I get all the times the error "Block device required". Should i add some parameter or flag?

Note:I can mount from the bash the same file in the same target without any error.

UPDATE: I had some good result using the function to mount an ISO. When I run the program, it remains stacked on the call ioctl(loop_device_fd, LOOP_CLR_FD, 0);. When I exit from the program (ctrl-c), the image is mounted. Is LOOP_CLR_FD necessary to complete all the steps? In additional,it is mounted in read only and seems not possible to change it in read/write.

const auto loop_control = std::fopen( "/dev/loop-control", "r" );
const auto loop_control_fd = fileno(loop_control);
const auto devnr = ioctl(loop_control_fd, LOOP_CTL_GET_FREE);
std::stringstream loopname;
loopname << "/dev/loop" << devnr;
const auto loop_device_name = loopname.str();
const auto loop_device = std::fopen(loop_device_name.c_str(), "r");
const auto loop_device_fd = fileno(loop_device);
const auto image = std::fopen( dst.c_str(), "r" );
const auto image_fd = fileno(image);
//Associate the loop device with the open file whose file descriptor is passed as the (third) ioctl(2) argument.
ioctl(loop_device_fd, LOOP_SET_FD, image_fd);
const auto result = mount(loop_device_name.c_str(), dst_path_img.c_str(), "vfat", MS_RDONLY, NULL);
if( result ) {
printf( "Error mount %s errno=%d %s\n", dst.c_str(), errno, strerror( errno ) );
return;
}
ioctl(loop_device_fd, LOOP_CLR_FD, 0);
Cœur
  • 37,241
  • 25
  • 195
  • 267
kikkus
  • 31
  • 2
  • Does this answer your question? [Mounting an ISO with sys/mount.h](https://stackoverflow.com/questions/11378392/mounting-an-iso-with-sys-mount-h) – Alex Skalozub Feb 18 '20 at 20:41
  • I tried the examples, but no one seems to works. Maybe there vfat is not the same as iso. – kikkus Feb 18 '20 at 21:10
  • Does your vfat image contain multiple partitions? You may need to specify offset to a specific partition when configuring a loop device by sending additional `LOOP_SET_STATUS64` ioctl request: https://stackoverflow.com/questions/11295154/how-do-i-loop-mount-programmatically – Alex Skalozub Feb 18 '20 at 21:18
  • You may use `fdisk -lu disk.img` to check if the image contains partition table and determine correct offset. – Alex Skalozub Feb 18 '20 at 22:38
  • `xx@ubuntu:/mnt/hgfs/D# file /tmp/1582142378585/Dos3.3.img /tmp/1582142378585/Dos3.3.img: DOS/MBR boot sector, code offset 0x34+2, OEM-ID ")uyh+IHC" cached by Windows 9M, root entries 224, sectors 2880 (volumes <=32 MB), sectors/FAT 9, sectors/track 18, dos < 4.0 BootSector (0x0), FAT (12 bit by descriptor+sectors), followed by FAT` – kikkus Feb 19 '20 at 20:02
  • `xx@ubuntu:/mnt/hgfs/D# fdisk -lu /tmp/1582142378585/Dos3.3.img Disk /tmp/1582142378585/Dos3.3.img: 1.42 MiB, 1474560 bytes, 2880 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: dos Disk identifier: 0x6e612073` – kikkus Feb 19 '20 at 20:02
  • `Device Boot Start End Sectors Size Id Type /tmp/1582142378585/Dos3.3.img1 1634038304 1802693507 168655204 80.4G 77 unknown /tmp/1582142378585/Dos3.3.img2 1818845510 2043597754 224752245 107.2G 6f unknown /tmp/1582142378585/Dos3.3.img3 1498619936 2644929906 1146309971 546.6G 20 unknown /tmp/1582142378585/Dos3.3.img4 0 0 0 0B 20 unknown Partition table entries are not in disk order.` – kikkus Feb 19 '20 at 20:03
  • It seems like just calling `system("mount -o loop -t vfat /mypath/disk.img /mypath/img/")` would be a lot simpler and less error-prone, and would have a number of other benefits (updating mtab, can be done without root privileges if `user` set in fstab, and so on). Is there a reason you have to do it by hand? – Nate Eldredge Feb 19 '20 at 20:54
  • Like I said I can mount it from the bash and of course (already did) using the c system command. But I need to manage everything from c. – kikkus Feb 20 '20 at 06:23

3 Answers3

3

The example code from the link above seems to mount your image quite fine, with minor modifications to retrieve free loop device (I'm assuming it is Dos3.3 diskette image from allbootdisks.com):

#include <sys/mount.h>
#include <linux/loop.h>
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>

int main()
{
    int control_fd, file_fd, device_fd;
    char loop_device[16];

    control_fd = open("/dev/loop-control", O_RDWR);
    if (control_fd < 0) {
        perror("open loop control device failed");
        return 1;
    }

    int loop_id = ioctl(control_fd, LOOP_CTL_GET_FREE);
    sprintf(loop_device, "/dev/loop%d", loop_id);
    close(control_fd);

    printf("using loop device: %s\n", loop_device);

    file_fd = open("./Dos3.3.img", O_RDWR);
    if (file_fd < 0) {
        perror("open backing file failed");
        return 1;
    }

    device_fd = open(loop_device, O_RDWR);
    if (device_fd < 0) {
        perror("open loop device failed");
        close(file_fd);
        return 1;
    }

    if (ioctl(device_fd, LOOP_SET_FD, file_fd) < 0) {
        perror("ioctl LOOP_SET_FD failed");
        close(file_fd);
        close(device_fd);
        return 1;
    }

    close(file_fd);

    if (mount(loop_device, "./mnt/", "vfat", MS_DIRSYNC | MS_SYNCHRONOUS, "") < 0) {
        perror("mount failed");
    } else {
        printf("mount successful\n");
    }

    // always free loop device in the end
    ioctl(device_fd, LOOP_CLR_FD, 0);      
    close(device_fd);
}
Alex Skalozub
  • 2,511
  • 16
  • 15
1

The problem here is you're trying to mount an image as you you would do with a block device. A block device has more bindings to the operating system than an image file would, so you need to find a way around this.

Try a loopback device! A loopback device can give you the operating system reference to that image /mypath/disk.img as a block device. You can create a loopback device in bash like so:

# set up a block device
losetup -fP /mypath/disk.img
# now list the loopback devices 
losetup -a

Anyway, this solution is in bash, but certainly there is a library out there somewhere for c.

  • I can mount from the bash the same file in the same destination folder without any problem. But i need to do it in c. – kikkus Feb 18 '20 at 20:55
1

As the disk image is not really a device, it cannot be directly mounted. What you are trying to do, is to mount via a loop device. Command line equivalent is: mount /mypath/disk.img /mypath/img -t vfat -o loop

I'm not sure, but try whether adding the "loop, utf8" as your last parameter would fix the problem.

  • I tried to add the parameters, but nothing change. Same error. Error mount /tmp/1582059154724/Dos6.22.img errno=15 Block device required – kikkus Feb 18 '20 at 20:57
  • To be onest, I don't think it is vice to mount filesystems from C. The mount command does much more than just call mount(), so if you need, you may be better off by just calling the mount command from C. – Seppo Takalo Mar 04 '20 at 14:39