Alien-Libjio

 view release on metacpan or  search on metacpan

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

	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;
	free(fd_table[fd].refcount);
	fd_table[fd].refcount = NULL;
	fd_table[fd].fs = NULL;

	return r;
}

int close(int fd)
{
	int r;
	jfs_t *fs;

	if (called) {
		printd("orig\n");
		return (*c_close)(fd);
	}

	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_close)(fd);
	}
	printd("libjio\n");

	r = unlocked_close(fd);
	fd_unlock(fd);

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


int unlink(const char *pathname)
{
	int r;
	struct jfsck_result res;

	if (called) {
		printd("orig\n");
		return (*c_unlink)(pathname);
	}

	printd("libjio\n");

	rec_inc();
	r = jfsck(pathname, NULL, &res, 0);
	rec_dec();

	r = (*c_unlink)(pathname);
	printd("return %d\n", r);

	return r;
}

int dup(int oldfd)
{
	int r;

	if (called) {
		printd("orig\n");
		return (*c_dup)(oldfd);
	}

	if (fd_table[oldfd].fs == NULL) {
		printd("NULL fs, fd %d\n", oldfd);
		fd_unlock(oldfd);
		return (*c_dup)(oldfd);
	}

	if (!fd_lock(oldfd)) {
		printd("out of bounds fd: %d\n", oldfd);
		return -1;
	}

	printd("libjio\n");

	rec_inc();
	r = (*c_dup)(oldfd);
	rec_dec();

	if (r >= 0) {
		fd_lock(r);
		fd_table[r].fd = r;
		fd_table[r].refcount = fd_table[oldfd].refcount;
		(*fd_table[r].refcount)++;
		fd_table[r].fs = fd_table[oldfd].fs;
		fd_unlock(r);
	}

	fd_unlock(oldfd);
	printd("return %d\n", r);
	return r;
}

int dup2(int oldfd, int newfd)
{
	int r;

	if (called) {
		printd("orig\n");
		return (*c_dup2)(oldfd, newfd);
	}

	if (!fd_lock(oldfd)) {
		printd("out of bounds fd: %d\n", oldfd);
		return -1;
	}

	if (fd_table[oldfd].fs == NULL) {
		printd("NULL fs, fd %d\n", oldfd);
		fd_unlock(oldfd);
		return (*c_dup2)(oldfd, newfd);
	}

	printd("libjio\n");

	rec_inc();
	r = (*c_dup2)(oldfd, newfd);
	rec_dec();

	if (r >= 0) {
		fd_lock(newfd);
		if (fd_table[newfd].fs != NULL) {
			unlocked_close(newfd);
		}
		fd_table[newfd].fd = newfd;
		fd_table[newfd].refcount = fd_table[oldfd].refcount;
		(*fd_table[newfd].refcount)++;
		fd_table[newfd].fs = fd_table[oldfd].fs;
		fd_unlock(newfd);
	}

	fd_unlock(oldfd);
	printd("return %d\n", r);
	return r;
}


/* the rest of the functions are automagically generated from the following
 * macro. The ugliest. I'm so proud. */

#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) );



( run in 0.486 second using v1.01-cache-2.11-cpan-524268b4103 )