author | Alberto Bertogli
<albertito@gmail.com> 2004-10-10 23:58:55 UTC |
committer | Alberto Bertogli
<albertito@gmail.com> 2007-07-15 13:25:37 UTC |
parent | 2de82bf6f17c248aef6a51b3f9e441dce7d16d13 |
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;