Reputation: 31
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);
Upvotes: 3
Views: 1311
Reputation: 2576
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);
}
Upvotes: 3
Reputation: 66
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.
Upvotes: 1
Reputation: 101
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.
Upvotes: 1