jseek.patch
  Implement jlseek, a lseek wrapper.

rollback_fixes.patch
  Fix several things in jtrans_rollback()

commit_exit_paths.patch
  Fix commit exit paths.

fix_tid_handling.patch
  Make sure all references to transaction IDs are properly handled

malloc_checks.patch
  Check malloc() return value properly in jtrans_add().

rmdir_in_cleanup.patch
  Remove the journal directory in jfsck_cleanup().

close_jdirfd.patch
  Close jdirfd on jclose() and several places inside checkers.

jmap_signedness.patch
  Fix jmap signedness in jopen() and jfsck().

version-0.18.patch
  Version 0.18.

initialize_pdata.patch
  Initialize op->pdata to NULL inside fill_trans().

destroy_mutex.patch
  Destroy jfs' mutex on jclose().

jfsck_munmap.patch
  Fix several memory leaks inside jfsck().



 Make.conf |    2 -
 check.c   |  113 ++++++++++++++++++++++++++++++++++++++++++++++----------------
 libjio.h  |    4 +-
 trans.c   |   54 ++++++++++++++---------------
 unix.c    |   12 ++++++
 5 files changed, 127 insertions(+), 58 deletions(-)


unchanged:
--- cur/unix.c~jseek	2004-07-21 00:34:53.000000000 -0300
+++ cur-root/unix.c	2004-07-22 09:49:50.701861336 -0300
@@ -169,3 +169,15 @@ int jtruncate(struct jfs *fs, off_t leng
 	return rv;
 }
 
+/* lseek wrapper */
+off_t jlseek(struct jfs *fs, off_t offset, int whence)
+{
+	int rv;
+
+	pthread_mutex_lock(&(fs->lock));
+	rv = lseek(fs->fd, offset, whence);
+	pthread_mutex_unlock(&(fs->lock));
+
+	return rv;
+}
+
unchanged:
--- cur-root/libjio.h	2004-07-22 09:56:26.119748680 -0300
+++ cur-root/libjio.h	2004-07-22 10:59:56.945415120 -0300
@@ -26,7 +26,7 @@
 	char *name;		/* and its name */
 	int jdirfd;		/* journal directory file descriptor */
 	int jfd;		/* journal's lock file descriptor */
-	int *jmap;		/* journal's lock file mmap area */
+	unsigned int *jmap;	/* journal's lock file mmap area */
 	int flags;		/* journal flags */
 	struct jlinger *ltrans;	/* lingered transactions */
 	pthread_mutex_t lock;	/* a soft lock used in some operations */
@@ -114,6 +114,7 @@
 ssize_t jpwrite(struct jfs *fs, const void *buf, size_t count, off_t offset);
 ssize_t jwritev(struct jfs *fs, const struct iovec *vector, int count);
 int jtruncate(struct jfs *fs, off_t length);
+off_t jlseek(struct jfs *fs, off_t offset, int whence);
 
 /* ANSI C stdio wrappers */
 struct jfs *jfopen(const char *path, const char *mode);
@@ -139,6 +140,7 @@
 /* jtrans constants */
 #define J_COMMITED	1	/* mark a transaction as commited */
 #define J_ROLLBACKED	2	/* mark a transaction as rollbacked */
+#define J_ROLLBACKING	3	/* mark a transaction as rollbacking */
 
 /* disk constants */
 #define J_DISKHEADSIZE	 12	/* length of disk_header */
unchanged:
--- cur-root/trans.c	2004-07-24 21:46:36.404664984 -0300
+++ cur-root/trans.c	2004-07-24 22:59:10.354674952 -0300
@@ -127,6 +127,7 @@
 
 		ts->op = tmpop;
 	}
+	pthread_mutex_destroy(&(ts->lock));
 }
 
 
@@ -139,22 +140,21 @@
 	pthread_mutex_lock(&(ts->lock));
 	if (ts->op == NULL) {
 		ts->op = malloc(sizeof(struct joper));
+		if (ts->op == NULL)
+			return 0;
 		jop = ts->op;
 		jop->prev = NULL;
 	} else {
 		for (tmpop = ts->op; tmpop->next != NULL; tmpop = tmpop->next)
 			;
 		tmpop->next = malloc(sizeof(struct joper));
+		if (tmpop->next == NULL)
+			return 0;
 		tmpop->next->prev = tmpop;
 		jop = tmpop->next;
 	}
 	pthread_mutex_unlock(&(ts->lock));
 
-	if (jop == NULL) {
-		/* malloc() failed */
-		return 0;
-	}
-
 	jop->buf = malloc(count);
 	if (jop->buf == NULL) {
 		free(jop);
@@ -213,7 +213,7 @@
 	/* save the header */
 	buf_init = malloc(J_DISKHEADSIZE);
 	if (buf_init == NULL)
-		goto exit;
+		goto unlink_exit;
 
 	bufp = buf_init;
 
@@ -229,7 +229,7 @@
 	rv = spwrite(fd, buf_init, J_DISKHEADSIZE, 0);
 	if (rv != J_DISKHEADSIZE) {
 		free(buf_init);
-		goto exit;
+		goto unlink_exit;
 	}
 
 	free(buf_init);
@@ -245,7 +245,7 @@
 			rv = plockf(ts->fs->fd, F_LOCKW, op->offset, op->len);
 			if (rv == -1)
 				/* note it can fail with EDEADLK */
-				goto exit;
+				goto unlink_exit;
 			op->locked = 1;
 		}
 	}
@@ -259,14 +259,14 @@
 		if (!(ts->flags & J_NOROLLBACK) && (op->pdata == NULL)) {
 			op->pdata = malloc(op->len);
 			if (op->pdata == NULL)
-				goto exit;
+				goto unlink_exit;
 
 			op->plen = op->len;
 
 			rv = spread(ts->fs->fd, op->pdata, op->len,
 					op->offset);
 			if (rv < 0)
-				goto exit;
+				goto unlink_exit;
 			if (rv < op->len) {
 				/* we are extending the file! */
 				/* ftruncate(ts->fs->fd, op->offset + op->len); */
@@ -277,7 +277,7 @@
 		/* save the operation's header */
 		buf_init = malloc(J_DISKOPHEADSIZE);
 		if (buf_init == NULL)
-			goto exit;
+			goto unlink_exit;
 
 		bufp = buf_init;
 
@@ -293,7 +293,7 @@
 		rv = spwrite(fd, buf_init, J_DISKOPHEADSIZE, curpos);
 		if (rv != J_DISKOPHEADSIZE) {
 			free(buf_init);
-			goto exit;
+			goto unlink_exit;
 		}
 
 		free(buf_init);
@@ -303,18 +303,18 @@
 		/* and save it to the disk */
 		rv = spwrite(fd, op->buf, op->len, curpos);
 		if (rv != op->len)
-			goto exit;
+			goto unlink_exit;
 
 		curpos += op->len;
 	}
 
 	/* compute and save the checksum */
 	if (!checksum(fd, curpos, &csum))
-		goto exit;
+		goto unlink_exit;
 
 	rv = spwrite(fd, &csum, sizeof(uint32_t), curpos);
 	if (rv != sizeof(uint32_t))
-		goto exit;
+		goto unlink_exit;
 	curpos += sizeof(uint32_t);
 
 	/* this is a simple but efficient optimization: instead of doing
@@ -323,7 +323,7 @@
 	 * transaction file is only useful if it's complete (ie. after this
 	 * point) so we only flush here (both data and metadata) */
 	if (fsync(fd) != 0)
-		goto exit;
+		goto unlink_exit;
 	if (fsync(ts->fs->jdirfd) != 0) {
 		/* it seems to be legal that fsync() on directories is not
 		 * implemented, so if this fails with EINVAL or EBADF, just
@@ -333,7 +333,7 @@
 		if (errno == EINVAL || errno == EBADF) {
 			sync();
 		} else {
-			goto exit;
+			goto unlink_exit;
 		}
 	}
 
@@ -346,7 +346,7 @@
 		op->locked = 0;
 
 		if (rv != op->len)
-			goto exit;
+			goto rollback_exit;
 
 		written += rv;
 	}
@@ -354,7 +354,7 @@
 	if (ts->flags & J_LINGER) {
 		linger = malloc(sizeof(struct jlinger));
 		if (linger == NULL)
-			goto exit;
+			goto rollback_exit;
 
 		linger->id = id;
 		linger->name = strdup(name);
@@ -372,7 +372,7 @@
 	ts->flags = ts->flags | J_COMMITED;
 
 
-exit:
+rollback_exit:
 	/* If the transaction failed we try to recover by rollbacking it
 	 * NOTE: on extreme conditions (ENOSPC/disk failure) this can fail
 	 * too! There's nothing much we can do in that case, the caller should
@@ -384,12 +384,9 @@
 	 * Transactions that were successfuly recovered by rollbacking them
 	 * will have J_ROLLBACKED in their flags, so the caller can verify if
 	 * the failure was recovered or not. */
-	if (!(ts->flags & J_COMMITED)) {
-		unlink(name);
-		free_tid(ts->fs, ts->id);
-
+	if (!(ts->flags & J_COMMITED) && !(ts->flags & J_ROLLBACKING)) {
 		rv = ts->flags;
-		ts->flags = ts->flags | J_NOLOCK;
+		ts->flags = ts->flags | J_NOLOCK | J_ROLLBACKING;
 		if (jtrans_rollback(ts) >= 0) {
 			ts->flags = rv | J_ROLLBACKED;
 		} else {
@@ -558,7 +555,7 @@
 	plockf(jfd, F_LOCKW, 0, 0);
 	lstat(jlockfile, &sinfo);
 	if (sinfo.st_size != sizeof(unsigned int)) {
-		t = 1;
+		t = 0;
 		rv = spwrite(jfd, &t, sizeof(t), 0);
 		if (rv != sizeof(t)) {
 			plockf(jfd, F_UNLOCK, 0, 0);
@@ -569,7 +566,7 @@
 
 	fs->jfd = jfd;
 
-	fs->jmap = (int *) mmap(NULL, sizeof(unsigned int),
+	fs->jmap = (unsigned int *) mmap(NULL, sizeof(unsigned int),
 			PROT_READ | PROT_WRITE, MAP_SHARED, jfd, 0);
 	if (fs->jmap == MAP_FAILED)
 		return -1;
@@ -615,10 +612,13 @@
 		return -1;
 	if (close(fs->jfd))
 		return -1;
+	if (close(fs->jdirfd))
+		return -1;
 	if (fs->name)
 		/* allocated by strdup() in jopen() */
 		free(fs->name);
 	munmap(fs->jmap, sizeof(unsigned int));
+	pthread_mutex_destroy(&(fs->lock));
 
 	return 0;
 }
diff -u cur-root/check.c cur-root/check.c
--- cur-root/check.c	2004-07-24 22:00:07.343383560 -0300
+++ cur-root/check.c	2004-07-24 23:02:56.589282064 -0300
@@ -66,6 +66,8 @@
 		op->buf = (void *) p;
 		p += op->len;
 
+		op->pdata = NULL;
+
 		if (ts->op == NULL) {
 			ts->op = op;
 			op->prev = NULL;
@@ -93,52 +95,74 @@
 /* check the journal and rollback incomplete transactions */
 int jfsck(const char *name, struct jfsck_result *res)
 {
-	int fd, tfd, rv, i;
+	int fd, tfd, rv, i, ret;
 	unsigned int maxtid;
 	uint32_t csum1, csum2;
 	char jdir[PATH_MAX], jlockfile[PATH_MAX], tname[PATH_MAX];
 	struct stat sinfo;
 	struct jfs fs;
 	struct jtrans *curts;
+	struct joper *tmpop;
 	DIR *dir;
 	struct dirent *dent;
 	unsigned char *map;
 	off_t filelen;
 
+	fd = tfd = -1;
+	filelen = 0;
+	dir = NULL;
+	fs.jmap = NULL;
+	map = NULL;
+	ret = 0;
 
 	fd = open(name, O_RDWR | O_SYNC | O_LARGEFILE);
-	if (fd < 0)
-		return J_ENOENT;
+	if (fd < 0) {
+		ret = J_ENOENT;
+		goto exit;
+	}
 
 	fs.fd = fd;
 	fs.name = (char *) name;
 
-	if (!get_jdir(name, jdir))
-		return J_ENOMEM;
+	if (!get_jdir(name, jdir)) {
+		ret = J_ENOMEM;
+		goto exit;
+	}
 	rv = lstat(jdir, &sinfo);
-	if (rv < 0 || !S_ISDIR(sinfo.st_mode))
-		return J_ENOJOURNAL;
+	if (rv < 0 || !S_ISDIR(sinfo.st_mode)) {
+		ret = J_ENOJOURNAL;
+		goto exit;
+	}
 
 	fs.jdirfd = open(jdir, O_RDONLY);
-	if (fs.jdirfd < 0)
-		return J_ENOJOURNAL;
+	if (fs.jdirfd < 0) {
+		ret = J_ENOJOURNAL;
+		goto exit;
+	}
 
 	/* open the lock file, which is only used to complete the jfs
 	 * structure */
 	snprintf(jlockfile, PATH_MAX, "%s/%s", jdir, "lock");
 	rv = open(jlockfile, O_RDWR | O_CREAT, 0600);
-	if (rv < 0)
-		return J_ENOJOURNAL;
+	if (rv < 0) {
+		ret = J_ENOJOURNAL;
+		goto exit;
+	}
 	fs.jfd = rv;
 
-	fs.jmap = (int *) mmap(NULL, sizeof(unsigned int),
+	fs.jmap = (unsigned int *) mmap(NULL, sizeof(unsigned int),
 			PROT_READ | PROT_WRITE, MAP_SHARED, fs.jfd, 0);
-	if (fs.jmap == MAP_FAILED)
-		return J_ENOJOURNAL;
+	if (fs.jmap == MAP_FAILED) {
+		ret = J_ENOJOURNAL;
+		fs.jmap = NULL;
+		goto exit;
+	}
 
 	dir = opendir(jdir);
-	if (dir == NULL)
-		return J_ENOJOURNAL;
+	if (dir == NULL) {
+		ret = J_ENOJOURNAL;
+		goto exit;
+	}
 
 	/* loop for each file in the journal directory to find out the greater
 	 * transaction number */
@@ -153,20 +177,22 @@
 		if (rv > maxtid)
 			maxtid = rv;
 	}
-	closedir(dir);
 
 	/* rewrite the lockfile, writing the new maxtid on it, so that when we
 	 * rollback a transaction it doesn't step over existing ones */
 	rv = spwrite(fs.jfd, &maxtid, sizeof(maxtid), 0);
 	if (rv != sizeof(maxtid)) {
-		return J_ENOMEM;
+		ret = J_ENOMEM;
+		goto exit;
 	}
 
 	/* we loop all the way up to the max transaction id */
 	for (i = 1; i <= maxtid; i++) {
 		curts = malloc(sizeof(struct jtrans));
-		if (curts == NULL)
-			return J_ENOMEM;
+		if (curts == NULL) {
+			ret = J_ENOMEM;
+			goto exit;
+		}
 
 		jtrans_init(&fs, curts);
 		curts->id = i;
@@ -175,8 +201,10 @@
 		 * really looping in order (recovering transaction in a
 		 * different order as they were applied means instant
 		 * corruption) */
-		if (!get_jtfile(name, i, tname))
-			return J_ENOMEM;
+		if (!get_jtfile(name, i, tname)) {
+			ret = J_ENOMEM;
+			goto exit;
+		}
 		tfd = open(tname, O_RDWR | O_SYNC | O_LARGEFILE, 0600);
 		if (tfd < 0) {
 			res->invalid++;
@@ -193,6 +221,11 @@
 
 		filelen = lseek(tfd, 0, SEEK_END);
 		map = mmap(0, filelen, PROT_READ, MAP_SHARED, tfd, 0);
+		if (map == MAP_FAILED) {
+			res->broken++;
+			map = NULL;
+			goto loop;
+		}
 		rv = fill_trans(map, filelen, curts);
 		if (rv != 1) {
 			res->broken++;
@@ -212,30 +245,48 @@
 
 		rv = jtrans_commit(curts);
 
-		munmap(map, filelen);
-
 		if (rv < 0) {
 			res->apply_error++;
 			goto loop;
 		}
 		res->reapplied++;
 
-
 loop:
 		if (tfd >= 0) {
 			close(tfd);
 			tfd = -1;
 		}
+		if (map != NULL)
+			munmap(map, filelen);
 
+		if (curts->name)
+			free(curts->name);
+		while (curts->op != NULL) {
+			tmpop = curts->op->next;
+			if (curts->op->pdata)
+				free(curts->op->pdata);
+			free(curts->op);
+			curts->op = tmpop;
+		}
+		pthread_mutex_destroy(&(curts->lock));
 		free(curts);
 
 		res->total++;
 	}
 
-	close(fs.fd);
-	close(fs.jfd);
+exit:
+	if (fs.fd >= 0)
+		close(fs.fd);
+	if (fs.jfd >= 0)
+		close(fs.jfd);
+	if (fs.jdirfd >= 0)
+		close(fs.jdirfd);
+	if (dir != NULL)
+		closedir(dir);
+	if (fs.jmap != NULL)
+		munmap(fs.jmap, sizeof(unsigned int));
 
-	return 0;
+	return ret;
 
 }
 
@@ -269,14 +320,18 @@
 		strcat(tfile, dent->d_name);
 
 		/* the full filename is too large */
-		if (strlen(tfile) > PATH_MAX)
+		if (strlen(tfile) > PATH_MAX) {
+			closedir(dir);
 			return 0;
+		}
 
 		/* and remove it */
 		unlink(tfile);
 	}
 	closedir(dir);
 
+	rmdir(jdir);
+
 	return 1;
 }
 
unchanged:
--- cur/Make.conf~version-0.18	2004-07-24 21:50:40.050625168 -0300
+++ cur-root/Make.conf	2004-07-24 21:50:44.524944968 -0300
@@ -1,5 +1,5 @@
 
-VERSION="0.17"
+VERSION="0.18"
 
 CC = gcc
 CFLAGS += -Wall -O6 \
