git » libjio » commit 46aed9e

Reintroduce dup() and dup2() in the preloader.

author Alberto Bertogli
2005-03-10 07:34:35 UTC
committer Alberto Bertogli
2007-07-15 13:49:04 UTC
parent f7982307ba785c713f9a2613ca35a20ff325545c

Reintroduce dup() and dup2() in the preloader.

Signed-off-by: Alberto Bertogli <albertito@gmail.com>

bindings/preload/libjio_preload.c +126 -8

diff --git a/bindings/preload/libjio_preload.c b/bindings/preload/libjio_preload.c
index fb9c7dd..1924d4f 100644
--- a/bindings/preload/libjio_preload.c
+++ b/bindings/preload/libjio_preload.c
@@ -58,11 +58,14 @@ 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;
 	struct jfs *fs;
 	pthread_mutex_t lock;
 };
@@ -96,6 +99,7 @@ static struct fd_entry fd_table[MAXFD];
 			if (called)			\
 				fprintf(stderr, "\t");	\
 			called++;			\
+			fprintf(stderr, "%5.5d ", getpid()); \
 			fprintf(stderr, "%s(): ", __FUNCTION__ ); \
 			fprintf(stderr, __VA_ARGS__);	\
 			fflush(stderr);			\
@@ -182,6 +186,8 @@ static int __attribute__((constructor)) init(void)
 	libc_load(lseek);
 	libc_load(lseek64);
 	libc_load(fsync);
+	libc_load(dup);
+	libc_load(dup2);
 
 	printd("done\n");
 	return 1;
@@ -255,6 +261,8 @@ int open(const char *pathname, int flags, ...)
 
 	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);
 
@@ -327,6 +335,8 @@ int open64(const char *pathname, int flags, ...)
 
 	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);
 
@@ -334,6 +344,38 @@ int open64(const char *pathname, int flags, ...)
 	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();
+
+	if (fd_table[fd].fs != NULL) {
+		fd_table[fd].fd = -1;
+		free(fd_table[fd].refcount);
+		fd_table[fd].refcount = NULL;
+		free(fd_table[fd].fs);
+		fd_table[fd].fs = NULL;
+	}
+
+	return r;
+}
 
 int close(int fd)
 {
@@ -357,14 +399,7 @@ int close(int fd)
 	}
 	printd("libjio\n");
 
-	rec_inc();
-	r = jclose(fs);
-	if (fd_table[fd].fs != NULL) {
-		free(fd_table[fd].fs);
-		fd_table[fd].fd = -1;
-		fd_table[fd].fs = NULL;
-	}
-	rec_dec();
+	r = unlocked_close(fd);
 	fd_unlock(fd);
 
 	printd("return %d\n", r);
@@ -393,6 +428,89 @@ int unlink(const char *pathname)
 	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. */