Created
May 30, 2023 14:37
-
-
Save giuseppe/1351cc2e391b9d3d3cf61ea82f974648 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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