git » libjio » commit f318eae

Fix opening files using O_APPEND

author Alberto Bertogli
2009-04-16 16:16:15 UTC
committer Alberto Bertogli
2009-04-16 16:16:15 UTC
parent 6f3c37f159f317673a6929125a329d082bdb10f1

Fix opening files using O_APPEND

When opening a file in O_APPEND mode, each write must behave just as if a
lseek(fs->fd, 0, SEEK_END) was performed before it.

We used not to honour that behaviour, but this patch fixes that.

Thanks to Jonathan Yu for the bug report.

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

libjio/ansi.c +5 -5
libjio/common.h +1 -0
libjio/trans.c +1 -0
libjio/unix.c +11 -2

diff --git a/libjio/ansi.c b/libjio/ansi.c
index 64c9eb8..c23f3c4 100644
--- a/libjio/ansi.c
+++ b/libjio/ansi.c
@@ -48,12 +48,12 @@ struct jfs *jfopen(const char *path, const char *mode)
 		else
 			flags = O_RDONLY;
 	} else if (mode[0] == 'a') {
-		/* in this case, make no distinction between "a" and "a+"
-		 * because the file is _always_ open for reading anyways */
-		pos_at_the_beginning = 0;
-		flags = O_RDWR | O_CREAT;
+		if (strlen(mode) > 1 && strchr(mode, '+'))
+			pos_at_the_beginning = 1;
+		else
+			pos_at_the_beginning = 0;
+		flags = O_RDWR | O_CREAT | O_APPEND;
 	} else if (mode[0] == 'w') {
-		/* the same as before */
 		pos_at_the_beginning = 1;
 		flags = O_RDWR | O_CREAT | O_TRUNC;
 	} else {
diff --git a/libjio/common.h b/libjio/common.h
index f5ff8f0..56837d6 100644
--- a/libjio/common.h
+++ b/libjio/common.h
@@ -35,6 +35,7 @@ struct jfs {
 	int jfd;		/* journal's lock file descriptor */
 	unsigned int *jmap;	/* journal's lock file mmap area */
 	uint32_t flags;		/* journal flags */
+	uint32_t open_flags;	/* open() flags */
 	struct jlinger *ltrans;	/* lingered transactions */
 	size_t ltrans_len;	/* length of all the lingered transactions */
 	pthread_mutex_t ltlock;	/* lingered transactions' lock */
diff --git a/libjio/trans.c b/libjio/trans.c
index 0053aea..d7ac3a4 100644
--- a/libjio/trans.c
+++ b/libjio/trans.c
@@ -424,6 +424,7 @@ struct jfs *jopen(const char *name, int flags, int mode, int jflags)
 
 	fs->name = strdup(name);
 	fs->flags = jflags;
+	fs->open_flags = flags;
 	fs->ltrans = NULL;
 	fs->ltrans_len = 0;
 
diff --git a/libjio/unix.c b/libjio/unix.c
index 3182124..9d6b685 100644
--- a/libjio/unix.c
+++ b/libjio/unix.c
@@ -9,6 +9,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <sys/types.h>
+#include <fcntl.h>
 #include <unistd.h>
 
 #include "libjio.h"
@@ -91,7 +92,11 @@ ssize_t jwrite(struct jfs *fs, const void *buf, size_t count)
 
 	pthread_mutex_lock(&(fs->lock));
 
-	pos = lseek(fs->fd, 0, SEEK_CUR);
+	if (fs->open_flags & O_APPEND)
+		pos = lseek(fs->fd, 0, SEEK_END);
+	else
+		pos = lseek(fs->fd, 0, SEEK_CUR);
+
 	jtrans_add(ts, buf, count, pos);
 
 	rv = jtrans_commit(ts);
@@ -141,7 +146,11 @@ ssize_t jwritev(struct jfs *fs, const struct iovec *vector, int count)
 
 	pthread_mutex_lock(&(fs->lock));
 
-	ipos = lseek(fs->fd, 0, SEEK_CUR);
+	if (fs->open_flags & O_APPEND)
+		ipos = lseek(fs->fd, 0, SEEK_END);
+	else
+		ipos = lseek(fs->fd, 0, SEEK_CUR);
+
 	t = ipos;
 
 	sum = 0;