git » libjio » commit 82c3aef

Allow to open files read-only.

author Alberto Bertogli
2004-10-10 23:58:55 UTC
committer Alberto Bertogli
2007-07-15 13:25:37 UTC
parent 2de82bf6f17c248aef6a51b3f9e441dce7d16d13

Allow to open files read-only.

Allow to open files read-only.

libjio.h +1 -0
trans.c +40 -16

diff --git a/libjio.h b/libjio.h
index 816f3ee..7e2e43e 100644
--- a/libjio.h
+++ b/libjio.h
@@ -150,6 +150,7 @@ FILE *jfsopen(struct jfs *stream, const char *mode);
 #define J_COMMITTED	8	/* mark a transaction as committed */
 #define J_ROLLBACKED	16	/* mark a transaction as rollbacked */
 #define J_ROLLBACKING	32	/* mark a transaction as rollbacking */
+#define J_RDONLY	64	/* mark a file as read-only */
 
 /* disk constants */
 #define J_DISKHEADSIZE	 12	/* length of disk_header */
diff --git a/trans.c b/trans.c
index 3af6287..bb1daff 100644
--- a/trans.c
+++ b/trans.c
@@ -138,9 +138,16 @@ int jtrans_add(struct jtrans *ts, const void *buf, size_t count, off_t offset)
 {
 	struct joper *jop, *tmpop;
 
+	pthread_mutex_lock(&(ts->lock));
+
+	/* fail for read-only accesses */
+	if (ts->flags & J_RDONLY) {
+		pthread_mutex_unlock(&(ts->lock));
+		return 0;
+	}
+
 	/* find the last operation in the transaction and create a new one at
 	 * the end */
-	pthread_mutex_lock(&(ts->lock));
 	if (ts->op == NULL) {
 		ts->op = malloc(sizeof(struct joper));
 		if (ts->op == NULL) {
@@ -201,6 +208,10 @@ ssize_t jtrans_commit(struct jtrans *ts)
 	ts->flags = ts->flags & ~J_COMMITTED;
 	ts->flags = ts->flags & ~J_ROLLBACKED;
 
+	/* fail for read-only accesses */
+	if (ts->flags & J_RDONLY)
+		goto exit;
+
 	name = (char *) malloc(PATH_MAX);
 	if (name == NULL)
 		goto exit;
@@ -525,12 +536,18 @@ int jopen(struct jfs *fs, const char *name, int flags, int mode, int jflags)
 	fs->jdirfd = -1;
 	fs->jmap = MAP_FAILED;
 
-	/* we always need read and write access, because when we commit a
-	 * transaction we read the current contents before applying, and write
-	 * access is needed for locking with fcntl */
-	flags = flags & ~O_WRONLY;
-	flags = flags & ~O_RDONLY;
-	flags = flags | O_RDWR;
+	/* we provide either read-only or read-write access, because when we
+	 * commit a transaction we read the current contents before applying,
+	 * and write access is needed for locking with fcntl; the test is done
+	 * this way because O_RDONLY is usually 0, so "if (flags & O_RDONLY)"
+	 * will fail. */
+	if ((flags & O_WRONLY) || (flags & O_RDWR)) {
+		flags = flags & ~O_WRONLY;
+		flags = flags & ~O_RDONLY;
+		flags = flags | O_RDWR;
+	} else {
+		jflags = jflags | J_RDONLY;
+	}
 
 	fs->name = strdup(name);
 	fs->flags = jflags;
@@ -559,6 +576,11 @@ int jopen(struct jfs *fs, const char *name, int flags, int mode, int jflags)
 	if (fs->fd < 0)
 		goto error_exit;
 
+	/* nothing else to do for read-only access */
+	if (flags & O_RDONLY) {
+		return fs->fd;
+	}
+
 	if (!get_jdir(name, jdir))
 		goto error_exit;
 	rv = mkdir(jdir, 0750);
@@ -645,20 +667,22 @@ int jclose(struct jfs *fs)
 
 	ret = 0;
 
-	if (jsync(fs))
-		ret = -1;
+	if (! (fs->flags & J_RDONLY)) {
+		if (jsync(fs))
+			ret = -1;
+		if (fs->jfd < 0 || close(fs->jfd))
+			ret = -1;
+		if (fs->jdirfd < 0 || close(fs->jdirfd))
+			ret = -1;
+		if (fs->jmap != MAP_FAILED)
+			munmap(fs->jmap, sizeof(unsigned int));
+	}
+
 	if (fs->fd < 0 || close(fs->fd))
 		ret = -1;
-	if (fs->jfd < 0 || close(fs->jfd))
-		ret = -1;
-	if (fs->jdirfd < 0 || close(fs->jdirfd))
-		ret = -1;
 	if (fs->name)
 		/* allocated by strdup() in jopen() */
 		free(fs->name);
-	if (fs->jmap != MAP_FAILED)
-		munmap(fs->jmap, sizeof(unsigned int));
-
 	pthread_mutex_destroy(&(fs->lock));
 
 	return ret;