Skip to content

Instantly share code, notes, and snippets.

@bboozzoo
Created October 26, 2021 10:00
Show Gist options
  • Save bboozzoo/7520a4d8f157e4bb83606fe8d483b9c5 to your computer and use it in GitHub Desktop.
Save bboozzoo/7520a4d8f157e4bb83606fe8d483b9c5 to your computer and use it in GitHub Desktop.
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <fcntl.h>
#include <limits.h>
#include <linux/loop.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <unistd.h>
void fd_cleanup(int *fd) {
if (fd != NULL && *fd >= 0) {
close(*fd);
*fd = -1;
}
}
#define CLEANUP(__f) __attribute__((__cleanup__(__f)))
int main(int argc, char *argv[]) {
const char *fname = NULL;
if (argc < 2) {
fprintf(stderr, "usage: %s <snap-file-name>\n", argv[0]);
return 1;
}
fname = argv[1];
int f CLEANUP(fd_cleanup) = open(fname, O_RDONLY | O_CLOEXEC | O_DIRECT);
if (f < 0) {
perror("open snap failed");
return 1;
}
int lc CLEANUP(fd_cleanup) = open("/dev/loop-control", O_RDWR | O_CLOEXEC);
if (lc < 0) {
perror("opening loop-control failed");
return 1;
}
int loop_free = ioctl(lc, LOOP_CTL_GET_FREE);
if (loop_free < 0) {
perror("get free failed");
return 1;
}
fprintf(stderr, "got device %d\n", loop_free);
char loop_dev_path[PATH_MAX] = {0};
snprintf(loop_dev_path, sizeof(loop_dev_path), "/dev/loop%d", loop_free);
int ldev CLEANUP(fd_cleanup) = open(loop_dev_path, O_RDWR | O_CLOEXEC);
if (ldev < 0) {
perror("cannot open loop device");
return 1;
}
struct loop_config config = {
.fd = f,
.block_size = 0,
.info =
{
.lo_flags = LO_FLAGS_DIRECT_IO | LO_FLAGS_READ_ONLY,
},
};
strncpy(config.info.lo_file_name, fname, sizeof(config.info.lo_file_name));
if (ioctl(ldev, LOOP_CONFIGURE, &config)) {
perror("loop configure failed");
return 1;
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment