Alien-Libjio

 view release on metacpan or  search on metacpan

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

	libc = dlopen("libc.so.6", RTLD_NOW);
	if (libc == NULL) {
		printd("Error loading libc: %s\n", dlerror());
		return 0;
	}

	/* load symbols from the C library */
	#define libc_load(F) c_##F = dlsym(libc, #F)
	libc_load(open);
	libc_load(open64);
	libc_load(close);
	libc_load(unlink);
	libc_load(read);
	libc_load(pread);
	libc_load(pread64);
	libc_load(readv);
	libc_load(write);
	libc_load(pwrite);
	libc_load(pwrite64);
	libc_load(writev);
	libc_load(ftruncate);
	libc_load(ftruncate64);
	libc_load(lseek);
	libc_load(lseek64);
	libc_load(fsync);
	libc_load(dup);
	libc_load(dup2);

	printd("done\n");
	return 1;
}

/*
 * wrappers
 */

int open(const char *pathname, int flags, ...)
{
	int r, fd;
	jfs_t *fs;
	mode_t mode;
	struct stat st;
	va_list l;

	if (flags & O_CREAT) {
		va_start(l, flags);
		mode = va_arg(l, mode_t);
		va_end(l);
	} else {
		/* set it to 0, it's ignored anyway */
		mode = 0;
	}

	if (called) {
		printd("orig (r)\n");
		return (*c_open)(pathname, flags, mode);
	}
	printd("libjio\n");

	/* skip special files */
	r = stat(pathname, &st);
	if (r == 0 && ( S_ISDIR(st.st_mode) \
			|| S_ISCHR(st.st_mode) \
			|| S_ISFIFO(st.st_mode) ) ) {
		printd("orig (s)\n");
		return (*c_open)(pathname, flags, mode);
	}

	/* skip /proc and /sys (not /dev, the problematic files are taken care
	 * of with the stat test above */
	/* FIXME: this breaks with relative paths */
	if ( (strncmp("/proc", pathname, 5) == 0) ||
			(strncmp("/sys", pathname, 4) == 0) ) {
		printd("orig (f)\n");
		return (*c_open)(pathname, flags, mode);
	}

	rec_inc();
	fs = jopen(pathname, flags, mode, 0);
	if (fs == NULL) {
		rec_dec();
		return -1;
	}
	rec_dec();

	fd = jfileno(fs);

	fd_lock(fd);
	fd_table[fd].fd = fd;
	fd_table[fd].refcount = malloc(sizeof(unsigned int));
	*fd_table[fd].refcount = 1;
	fd_table[fd].fs = fs;
	fd_unlock(fd);

	printd("return %d\n", fd);
	return fd;
}

/* exact copy of open(), but call c_open64 instead of c_open */
int open64(const char *pathname, int flags, ...)
{
	int r, fd;
	jfs_t *fs;
	mode_t mode;
	struct stat st;
	va_list l;

	if (flags & O_CREAT) {
		va_start(l, flags);
		mode = va_arg(l, mode_t);
		va_end(l);
	} else {
		/* set it to 0, it's ignored anyway */
		mode = 0;
	}

	if (called) {
		printd("orig (r)\n");
		return (*c_open64)(pathname, flags, mode);
	}
	printd("libjio\n");

	/* skip special files */
	r = stat(pathname, &st);
	if (r == 0 && ( S_ISDIR(st.st_mode) \
			|| S_ISCHR(st.st_mode) \
			|| S_ISFIFO(st.st_mode) ) ) {
		printd("orig (s)\n");
		return (*c_open64)(pathname, flags, mode);
	}

	/* skip /proc and /sys (not /dev, the problematic files are taken care
	 * of with the stat test above */
	/* FIXME: this breaks with relative paths */
	if ( (strncmp("/proc", pathname, 5) == 0) ||
			(strncmp("/sys", pathname, 4) == 0) ) {
		printd("orig (f)\n");
		return (*c_open64)(pathname, flags, mode);
	}

	rec_inc();
	fs = jopen(pathname, flags, mode, 0);
	if (fs == NULL) {
		rec_dec();
		return -1;
	}
	rec_dec();

	fd = jfileno(fs);

	fd_lock(fd);
	fd_table[fd].fd = fd;
	fd_table[fd].refcount = malloc(sizeof(unsigned int));
	*fd_table[fd].refcount = 1;
	fd_table[fd].fs = fs;
	fd_unlock(fd);

	printd("return %d\n", fd);
	return fd;
}

/* close() is split in two functions: unlocked_close() that performs the real
 * actual close and cleanup, and close() which takes care of the locking and
 * calls unlocked_close(); this is because in dup*() we need to close with
 * locks already held to avoid races. */
int unlocked_close(int fd)
{
	int r;

	if (*fd_table[fd].refcount > 1) {
		/* we still have references, don't really close */
		printd("not closing, refcount: %d\n", *fd_table[fd].refcount);
		(*fd_table[fd].refcount)--;
		fd_table[fd].fd = -1;
		fd_table[fd].refcount = NULL;
		fd_table[fd].fs = NULL;
		return 0;
	}

	rec_inc();
	r = jclose(fd_table[fd].fs);
	rec_dec();

	fd_table[fd].fd = -1;



( run in 2.498 seconds using v1.01-cache-2.11-cpan-63c85eba8c4 )