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 )