3 * libjio - A library for Journaled I/O
4 * Alberto Bertogli (albertogli@telpin.com.ar)
12 #include <sys/types.h>
22 * To avoid completely useless code duplication, this functions rely on the
23 * UNIX wrappers from unix.c.
25 * The API is not nice, and you I wouldn't recommend it for any serious I/O;
26 * this wrappers are done more as code samples than anything else.
28 * TODO: it should be possible to implement something like this at some
29 * LD_PRELOAD level without too much harm for most apps.
30 * TODO: this is still experimental, it hasn't received too much testing
31 * (that's why it's not even documented), so use it at your own risk.
36 struct jfs
*jfopen(const char *path
, const char *mode
)
40 int pos_at_the_beginning
;
47 pos_at_the_beginning
= 1;
48 if (strlen(mode
) > 1 && strchr(mode
, '+'))
52 } else if (mode
[0] == 'a') {
53 /* in this case, make no distinction between "a" and "a+"
54 * because the file is _always_ open for reading anyways */
55 pos_at_the_beginning
= 0;
56 flags
= O_RDWR
| O_CREAT
;
57 } else if (mode
[0] == 'w') {
58 /* the same as before */
59 pos_at_the_beginning
= 1;
60 flags
= O_RDWR
| O_CREAT
| O_TRUNC
;
65 fs
= malloc(sizeof(struct jfs
));
67 fd
= jopen(fs
, path
, flags
, 0666, 0);
73 if (pos_at_the_beginning
)
74 lseek(fd
, 0, SEEK_SET
);
76 lseek(fd
, 0, SEEK_END
);
82 int jfclose(struct jfs
*stream
)
95 struct jfs
*jfreopen(const char *path
, const char *mode
, struct jfs
*stream
)
100 stream
= jfopen(path
, mode
);
105 size_t jfread(void *ptr
, size_t size
, size_t nmemb
, struct jfs
*stream
)
108 rv
= jread(stream
, ptr
, size
* nmemb
);
117 size_t jfwrite(const void *ptr
, size_t size
, size_t nmemb
, struct jfs
*stream
)
120 rv
= jwrite(stream
, ptr
, size
* nmemb
);
129 int jfileno(struct jfs
*stream
)
135 int jfeof(struct jfs
*stream
)
137 /* ANSI expects that when an EOF is reached in any operation (like
138 * fread() or fwrite()) some internal flag is set, and this function
139 * can be used to check if it is set or unset.
140 * As we don't do that (it's pointless for this kind of I/O), this
141 * just checks if the file pointer is at the end of the file */
143 off_t curpos
, endpos
;
145 pthread_mutex_lock(&(stream
->lock
));
147 curpos
= lseek(jfileno(stream
), 0, SEEK_CUR
);
148 endpos
= lseek(jfileno(stream
), 0, SEEK_END
);
150 lseek(jfileno(stream
), curpos
, SEEK_SET
);
152 pthread_mutex_unlock(&(stream
->lock
));
154 if (curpos
>= endpos
)
160 /* clearerr wrapper */
161 void jclearerr(struct jfs
*stream
)
163 /* As we do not carry any kind of error state (like explained in
164 * jfeof()), this function has no effect. */
168 int jferror(struct jfs
*stream
)
170 /* The same as the above; however not returning this might have some
171 * side effects on very subtle programs relying on this behaviour */
176 int jfseek(struct jfs
*stream
, long offset
, int whence
)
180 pthread_mutex_lock(&(stream
->lock
));
181 pos
= lseek(stream
->fd
, offset
, whence
);
182 pthread_mutex_unlock(&(stream
->lock
));
184 /* fseek returns 0 on success, -1 on error */
192 int jftell(struct jfs
*stream
)
194 return lseek(stream
->fd
, 0, SEEK_CUR
);
198 void jrewind(struct jfs
*stream
)
200 lseek(stream
->fd
, 0, SEEK_SET
);
203 /* convert a struct jfs to a FILE so you can use it with other functions that
204 * require a FILE pointer; be aware that you're bypassing the journaling layer
205 * and it can cause severe corruption if you're not extremely careful */
206 FILE *jfsopen(struct jfs
*stream
, const char *mode
)
208 return fdopen(stream
->fd
, mode
);