Skip to content

Instantly share code, notes, and snippets.

@brauner
Created April 22, 2020 12:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save brauner/dcaf15e6977cc1bfadfb3965f126c02f to your computer and use it in GitHub Desktop.
Save brauner/dcaf15e6977cc1bfadfb3965f126c02f to your computer and use it in GitHub Desktop.
#ifndef _GNU_SOURCE
#define _GNU_SOURCE 1
#endif
#include <linux/loop.h>
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <limits.h>
#include <linux/bpf.h>
#include <linux/magic.h>
#include <linux/sched.h>
#include <malloc.h>
#include <poll.h>
#include <pthread.h>
#include <sched.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/fsuid.h>
#include <sys/mman.h>
#include <sys/mount.h>
#include <sys/param.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <linux/types.h>
#include <sys/un.h>
#include <sys/wait.h>
#include <unistd.h>
int attach_image_to_loop(const char *source, int loop_fd)
{
int ret, fret = -1;
struct loop_info64 lo64;
int fd_img = -1;
fd_img = open(source, O_RDWR | O_CLOEXEC);
if (fd_img < 0) {
fprintf(stderr, "Failed to open %s\n", source);
goto on_error;
}
ret = ioctl(loop_fd, LOOP_SET_FD, fd_img);
if (ret < 0) {
fprintf(stderr, "%m - Failed to set loop device to %s\n", source);
goto on_error;
}
memset(&lo64, 0, sizeof(lo64));
snprintf((char *)lo64.lo_file_name, LO_NAME_SIZE, "%s", source);
ret = ioctl(loop_fd, LOOP_SET_STATUS64, &lo64);
if (ret < 0) {
fprintf(stderr, "%m - Failed to set loop device status for %s\n", source);
goto on_error;
}
fret = 0;
on_error:
if (fd_img >= 0)
close(fd_img);
return fret;
}
int main(int argc, char *argv[])
{
int ret, mntfd, loop_ctl_fd, loopidx, loop_fd;
char *image, *mntpt, *target, *fstype;
char path[4096];
int n = 1;
if (argc < 5)
exit(EXIT_FAILURE);
mntpt = argv[1];
image = argv[2];
target = argv[3];
fstype = argv[4];
ret = mount("none", mntpt, "loop", 0, 0);
if (ret) {
fprintf(stderr, "%m - Failed to mount loopfs at %s\n", mntpt);
exit(EXIT_FAILURE);
}
mntfd = open(mntpt, O_DIRECTORY | O_CLOEXEC);
if (mntfd < 0) {
fprintf(stderr, "%m - Failed to open loopfs mount %s\n", mntpt);
exit(EXIT_FAILURE);
}
(void)snprintf(path, sizeof(path), "%s/loop-control", mntpt);
loop_ctl_fd = open(path, O_RDWR | O_CLOEXEC);
if (loop_ctl_fd < 0) {
fprintf(stderr,
"%m - Failed to open loopfs loop-control device %s\n",
path);
exit(EXIT_FAILURE);
}
ret = umount2(mntpt, MNT_DETACH);
if (ret) {
fprintf(stderr, "%m - Failed to unmount loopfs at %s\n", mntpt);
exit(EXIT_FAILURE);
}
loopidx = ioctl(loop_ctl_fd, LOOP_CTL_GET_FREE);
if (loopidx < 0) {
fprintf(stderr, "%m - Failed to get new loopfs loop device\n");
exit(EXIT_FAILURE);
}
(void)snprintf(path, sizeof(path), "loop%d", loopidx);
loop_fd = openat(mntfd, path, O_RDWR | O_CLOEXEC);
if (loop_fd < 0) {
fprintf(stderr, "%m - Failed to open loop device %s\n", path);
exit(EXIT_FAILURE);
}
printf("Opened loop device %s\n", path);
ret = attach_image_to_loop(image, loop_fd);
if (ret) {
fprintf(stderr,
"%m - Failed to attach image %s to loop device %s\n",
image, path);
exit(EXIT_FAILURE);
}
printf("Attached image %s to loop device %s\n", image, path);
snprintf(path, sizeof(path), "/proc/self/fd/%d", loop_fd);
ret = mount(path, tardetachedget, fstype, 0, 0);
if (ret) {
fprintf(stderr, "%m - Failed to mount %s to %s\n", path, target);
exit(EXIT_FAILURE);
}
printf("Mounted %s to %s\n", path, target);
exit(EXIT_SUCCESS);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment