drgn/vmtest/onoatimehack.c
Omar Sandoval 87b7292aa5 Relicense drgn from GPLv3+ to LGPLv2.1+
drgn is currently licensed as GPLv3+. Part of the long term vision for
drgn is that other projects can use it as a library providing
programmatic interfaces for debugger functionality. A more permissive
license is better suited to this goal. We decided on LGPLv2.1+ as a good
balance between software freedom and permissiveness.

All contributors not employed by Meta were contacted via email and
consented to the license change. The only exception was the author of
commit c4fbf7e589 ("libdrgn: fix for compilation error"), who did not
respond. That commit reverted a single line of code to one originally
written by me in commit 640b1c011d ("libdrgn: embed DWARF index in
DWARF info cache").

Signed-off-by: Omar Sandoval <osandov@osandov.com>
2022-11-01 17:05:16 -07:00

109 lines
2.5 KiB
C

// Copyright (c) Meta Platforms, Inc. and affiliates.
// SPDX-License-Identifier: LGPL-2.1-or-later
/*
* QEMU's 9pfs server passes through O_NOATIME from the client. If the server
* process doesn't have permission to use O_NOATIME (e.g., because it's being
* run without privileges and it doesn't own the file), then the open will fail.
* Overlayfs uses O_NOATIME, so overlayfs on top of 9pfs doesn't work. We work
* around this with this LD_PRELOAD hack to remove O_NOATIME from open() and
* fcntl() calls.
*
* As of QEMU 5.1.0, the 9pfs server falls back to removing O_NOATIME, so this
* isn't necessary on newer versions.
*/
#include <dlfcn.h>
#include <fcntl.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#define ORIG(name) ({ \
static typeof(&name) orig; \
\
if (!orig) { \
void *tmp; \
\
tmp = dlsym(RTLD_NEXT, #name); \
if (!tmp) { \
fprintf(stderr, "%s\n", dlerror()); \
abort(); \
} \
orig = tmp; \
} \
orig; \
})
#ifndef __OPEN_NEEDS_MODE
/* From glibc fnctl.h. */
#ifdef __O_TMPFILE
# define __OPEN_NEEDS_MODE(oflag) \
(((oflag) & O_CREAT) != 0 || ((oflag) & __O_TMPFILE) == __O_TMPFILE)
#else
# define __OPEN_NEEDS_MODE(oflag) (((oflag) & O_CREAT) != 0)
#endif
#endif
#define OPEN_MODE(flags) ({ \
mode_t mode = 0; \
\
if (__OPEN_NEEDS_MODE(flags)) { \
va_list ap; \
\
va_start(ap, flags); \
mode = va_arg(ap, mode_t); \
va_end(ap); \
} \
mode; \
})
int open(const char *pathname, int flags, ...)
{
flags &= ~O_NOATIME;
return ORIG(open)(pathname, flags, OPEN_MODE(flags));
}
int open64(const char *pathname, int flags, ...)
{
flags &= ~O_NOATIME;
return ORIG(open64)(pathname, flags, OPEN_MODE(flags));
}
int openat(int dirfd, const char *pathname, int flags, ...)
{
flags &= ~O_NOATIME;
return ORIG(openat)(dirfd, pathname, flags, OPEN_MODE(flags));
}
int openat64(int dirfd, const char *pathname, int flags, ...)
{
flags &= ~O_NOATIME;
return ORIG(openat64)(dirfd, pathname, flags, OPEN_MODE(flags));
}
#define FCNTL_ARG(cmd) ({ \
va_list ap; \
void *arg; \
\
va_start(ap, cmd); \
arg = va_arg(ap, void *); \
va_end(ap); \
if (cmd == F_SETFL) \
arg = (void *)((uintptr_t)arg & ~O_NOATIME); \
arg; \
})
int fcntl(int fd, int cmd, ...)
{
return ORIG(fcntl)(fd, cmd, FCNTL_ARG(cmd));
}
int fcntl64(int fd, int cmd, ...)
{
return ORIG(fcntl64)(fd, cmd, FCNTL_ARG(cmd));
}