I have recently written a guide on how to mount partitions from image files on Raspberry Pi.SE. The instructions are rather complicated and I have a bit of time, so want to replace them by a C program. I have successfully listed the partitions of the image and calculated to appropriate offsets.
In the original instructions, we needed to run
$ sudo mount -o loop,offset=80740352 debian6-19-04-2012.img /mnt
I now need to do this in code. I have found the mount function and libmount in util-linux.
I have now found loopdev.c in util-linux. Is there an easy way to create loop devices or do I have to learn from this code and use ioctl?
A "loop" device in Linux is an abstraction that lets you treat a file like a block device. It's specifically meant for a use like your example, where you can mount a file containing a CD image and interact with the filesystem in it as if it were burned to a CD and placed in your drive.
The loop device is a block device that maps its data blocks not to a physical device such as a hard disk or optical disk drive, but to the blocks of a regular file in a filesystem or to another block device.
The special /dev/loop-control file can be used to create and destroy loop devices or to find the first available loop device. Associating a file with a specific device, or setting other parameters like offsets or block sizes, is done with ioctl() calls on the device itself.
The following function binds the loop device device
to file
at offset
. It returns 0 on success, 1 otherwise.
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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With