Skip to content

Instantly share code, notes, and snippets.

@giuseppe
Created May 30, 2023 14:37
Show Gist options
  • Save giuseppe/1351cc2e391b9d3d3cf61ea82f974648 to your computer and use it in GitHub Desktop.
Save giuseppe/1351cc2e391b9d3d3cf61ea82f974648 to your computer and use it in GitHub Desktop.
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/syscall.h>
#include <sys/sysmacros.h>
#include <sys/xattr.h>
#include <unistd.h>
# define cleanup_free __attribute__((cleanup (cleanup_freep)))
# define cleanup_close __attribute__((cleanup (cleanup_closep)))
struct file_handle
{
unsigned int handle_bytes; /* Size of f_handle [in, out] */
int handle_type; /* Handle type [out] */
unsigned char f_handle[0]; /* File identifier (sized by
caller) [out] */
};
typedef unsigned char u8;
typedef unsigned char uuid_t[16];
/* On-disk and in-memory format for redirect by file handle */
struct ovl_fh
{
u8 version; /* 0 */
u8 magic; /* 0xfb */
u8 len; /* size of this header + size of fid */
u8 flags; /* OVL_FH_FLAG_* */
u8 type; /* fid_type of fid */
uuid_t uuid; /* uuid of filesystem */
u8 fid[0]; /* file identifier */
} __packed;
void
cleanup_closep (void *p)
{
int *pp = p;
if (*pp >= 0)
close (*pp);
}
void
cleanup_freep (void *p)
{
void **pp = (void **) p;
free (*pp);
}
int
open_by_handle_at (int mount_fd, struct file_handle *handle, int flags)
{
return syscall (SYS_open_by_handle_at, mount_fd, handle, flags);
}
static ssize_t
safe_read_xattr (char **ret, int sfd, const char *name, size_t initial_size)
{
cleanup_free char *buffer = NULL;
size_t current_size;
ssize_t s;
current_size = initial_size;
buffer = malloc (current_size + 1);
if (buffer == NULL)
return -1;
while (1)
{
char *tmp;
s = fgetxattr (sfd, name, buffer, current_size);
if (s >= 0 && s < current_size)
break;
if (s < 0 && errno != ERANGE)
break;
current_size *= 2;
tmp = realloc (buffer, current_size + 1);
if (tmp == NULL)
return -1;
buffer = tmp;
}
if (s <= 0)
return s;
buffer[s] = '\0';
/* Change owner. */
*ret = buffer;
buffer = NULL;
return s;
}
int main(int argc, char *argv[])
{
cleanup_free struct file_handle *fh = NULL;
cleanup_free char *xattr_content = NULL;
cleanup_close int originfd = -1;
cleanup_close int fd = -1;
struct ovl_fh *ofh;
size_t s;
if (argc < 2)
{
fprintf (stderr, "Usage: %s FILE\n", argv[0]);
return 1;
}
fd = open(argv[1], O_RDONLY);
if (fd < 0)
{
fprintf (stderr, "open: %m\n");
return 1;
}
if (safe_read_xattr (&xattr_content, fd, "trusted.overlay.origin", 128) < 0)
{
fprintf (stderr, "safe_read_xattr: %m\n");
return 1;
}
ofh = (struct ovl_fh *) xattr_content;
s = ofh->len - sizeof (*ofh);
fh = malloc (sizeof (struct file_handle) + s);
if (fh == NULL)
{
fprintf (stderr, "malloc: %m\n");
return 1;
}
fh->handle_bytes = s;
fh->handle_type = ofh->type;
memcpy (fh->f_handle, ofh->fid, s);
originfd = open_by_handle_at (AT_FDCWD, fh, O_RDONLY);
if (originfd < 0)
{
fprintf (stderr, "open_by_handle_at: %m\n");
return 1;
}
/* originfd now points to the original FILE that was copied up. */
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment