Alien-Libjio
view release on metacpan or search on metacpan
libjio/bindings/preload/libjio_preload.c view on Meta::CPAN
/*
* libjio C preloader
* Alberto Bertogli (albertito@blitiri.com.ar)
*
* This generates a shared object that, when prelinked, can be used to make an
* existing application to use libjio for UNIX I/O.
* It's not nice or pretty, and does some nasty tricks to work both with and
* without LFS. I don't think it builds or works without glibc.
*/
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/uio.h>
#include <dlfcn.h>
/* we don't build this with LFS, however, it's essential that the proper
* environment is set for libjio's loading; otherwise we would mess the ABI
* up */
typedef long long off64_t;
#define _FILE_OFFSET_BITS 64
#define off_t off64_t
#include <libjio.h>
#undef off_t
#undef _FILE_OFFSET_BITS
/* maximum number of simultaneous open file descriptors we support */
#define MAXFD (4096 * 2)
/* recursion counter, per-thread */
static int __thread called = 0;
/* C library functions, filled via the dynamic loader */
static void *libc;
static int (*c_open)(const char *pathname, int flags, mode_t mode);
static int (*c_open64)(const char *pathname, int flags, mode_t mode);
static int (*c_close)(int fd);
static int (*c_unlink)(const char *pathname);
static ssize_t (*c_read)(int fd, void *buf, size_t count);
static ssize_t (*c_pread)(int fd, void *buf, size_t count, off_t offset);
static ssize_t (*c_pread64)(int fd, void *buf, size_t count, off64_t offset);
static ssize_t (*c_readv)(int fd, const struct iovec *vector, int count);
static ssize_t (*c_write)(int fd, const void *buf, size_t count);
static ssize_t (*c_pwrite)(int fd, const void *buf, size_t count, off_t offset);
static ssize_t (*c_pwrite64)(int fd, const void *buf, size_t count, off64_t offset);
static ssize_t (*c_writev)(int fd, const struct iovec *vector, int count);
static int (*c_ftruncate)(int fd, off_t length);
static int (*c_ftruncate64)(int fd, off64_t length);
static off_t (*c_lseek)(int fd, off_t offset, int whence);
static off64_t (*c_lseek64)(int fd, off64_t offset, int whence);
static int (*c_fsync)(int fd);
static int (*c_dup)(int oldfd);
static int (*c_dup2)(int oldfd, int newfd);
/* file descriptor table, to translate fds to jfs */
struct fd_entry {
int fd;
unsigned int *refcount;
jfs_t *fs;
pthread_mutex_t lock;
};
static struct fd_entry fd_table[MAXFD];
/* useful macros, mostly for debugging purposes */
#if 1
#define rec_inc() do { called++; } while(0)
#define rec_dec() do { called--; } while(0)
#define printd(...) do { } while(0)
#else
/* debug variants */
#define rec_inc() \
do { \
called++; \
fprintf(stderr, "I: %d\n", called); \
fflush(stderr); \
} while (0)
#define rec_dec() \
do { \
called--; \
fprintf(stderr, "D: %d\n", called); \
fflush(stderr); \
} while (0)
#define printd(...) \
do { \
if (called) \
fprintf(stderr, "\t"); \
called++; \
fprintf(stderr, "%5.5d ", getpid()); \
fprintf(stderr, "%s(): ", __FUNCTION__ ); \
fprintf(stderr, __VA_ARGS__); \
fflush(stderr); \
called--; \
} while(0)
#endif
/* functions used to lock fds from the table; they do boundary checks so we
* catch out of bounds accesses */
static inline int fd_lock(int fd)
{
int r;
if (fd < 0 || fd >= MAXFD) {
libjio/bindings/preload/libjio_preload.c view on Meta::CPAN
#define mkwrapper(rtype, name, DEF, INVR, INVM) \
rtype name DEF \
{ \
rtype r; \
jfs_t *fs; \
\
if (called) { \
printd("orig\n"); \
return (*c_##name) INVR; \
} \
\
if (!fd_lock(fd)) { \
printd("out of bounds fd: %d\n", fd); \
return -1; \
} \
fs = fd_table[fd].fs; \
if (fs == NULL) { \
printd("(): NULL fs, fd %d\n", fd); \
fd_unlock(fd); \
return (*c_##name) INVR; \
} \
printd("libjio\n"); \
\
rec_inc(); \
r = j##name INVM; \
rec_dec(); \
fd_unlock(fd); \
\
printd("return %lld\n", (long long) r); \
return r; \
}
/* 32-bit versions */
mkwrapper(ssize_t, read, (int fd, void *buf, size_t count),
(fd, buf, count), (fs, buf, count) );
mkwrapper(ssize_t, pread, (int fd, void *buf, size_t count, off_t offset),
(fd, buf, count, offset), (fs, buf, count, offset) );
mkwrapper(ssize_t, readv, (int fd, const struct iovec *vector, int count),
(fd, vector, count), (fs, vector, count) );
mkwrapper(ssize_t, write, (int fd, const void *buf, size_t count),
(fd, buf, count), (fs, buf, count) );
mkwrapper(ssize_t, pwrite,
(int fd, const void *buf, size_t count, off_t offset),
(fd, buf, count, offset), (fs, buf, count, offset) );
mkwrapper(ssize_t, writev, (int fd, const struct iovec *vector, int count),
(fd, vector, count), (fs, vector, count) );
mkwrapper(off_t, lseek, (int fd, off_t offset, int whence),
(fd, offset, whence), (fs, offset, whence) );
/* libjio defines jtruncate and jsync, not jftruncate and jfsync, which breaks
* the macro; so we add a nice #define to unbreak it */
#define jftruncate jtruncate
mkwrapper(int, ftruncate, (int fd, off_t length),
(fd, length), (fs, length) );
#define jfsync jsync
mkwrapper(int, fsync, (int fd), (fd), (fs) );
/* 64-bit versions */
#define jpread64 jpread
mkwrapper(ssize_t, pread64, (int fd, void *buf, size_t count, off64_t offset),
(fd, buf, count, offset), (fs, buf, count, offset) );
#define jpwrite64 jpwrite
mkwrapper(ssize_t, pwrite64,
(int fd, const void *buf, size_t count, off64_t offset),
(fd, buf, count, offset), (fs, buf, count, offset) );
#define jlseek64 jlseek
mkwrapper(off64_t, lseek64, (int fd, off64_t offset, int whence),
(fd, offset, whence), (fs, offset, whence) );
#define jftruncate64 jtruncate
mkwrapper(int, ftruncate64, (int fd, off64_t length),
(fd, length), (fs, length) );
( run in 1.430 second using v1.01-cache-2.11-cpan-140bd7fdf52 )