Alien-Libjio

 view release on metacpan or  search on metacpan

libjio/bindings/preload/libjio_preload.c  view on Meta::CPAN

#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) {
		printd("locking out of bounds fd %d\n", fd);
		return 0;
	}
	//printd("L %d\n", fd);
	r = pthread_mutex_lock(&(fd_table[fd].lock));
	//printd("OK %d\n", fd);
	return !r;
}

static inline int fd_unlock(int fd)
{
	int r;

	if (fd < 0 || fd >= MAXFD) {
		printd("unlocking out of bounds fd %d\n", fd);
		return 0;
	}
	//printd("U %d\n", fd);
	r = pthread_mutex_unlock(&(fd_table[fd].lock));
	//printd("OK %d\n", fd);
	return !r;
}




( run in 1.626 second using v1.01-cache-2.11-cpan-02777c243ea )