There were several memory leaks inside jfsck(), they've probably been there for a...
[libjio.git] / ansi.c
blob8ded68644833be97248b5892d9a851b6be755d5f
2 /*
3 * libjio - A library for Journaled I/O
4 * Alberto Bertogli (albertogli@telpin.com.ar)
6 * ANSI C API wrappers
7 */
9 #include <stdio.h>
10 #include <string.h>
11 #include <stdlib.h>
12 #include <sys/types.h>
13 #include <sys/stat.h>
14 #include <fcntl.h>
15 #include <unistd.h>
16 #include <pthread.h>
18 #include "libjio.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.
35 /* fopen wrapper */
36 struct jfs *jfopen(const char *path, const char *mode)
38 int fd;
39 int flags;
40 int pos_at_the_beginning;
41 struct jfs *fs;
43 if (strlen(mode) < 1)
44 return NULL;
46 if (mode[0] == 'r') {
47 pos_at_the_beginning = 1;
48 if (strlen(mode) > 1 && strchr(mode, '+'))
49 flags = O_RDWR;
50 else
51 flags = O_RDONLY;
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;
61 } else {
62 return NULL;
65 fs = malloc(sizeof(struct jfs));
67 fd = jopen(fs, path, flags, 0666, 0);
68 if (fd < 0) {
69 free(fs);
70 return NULL;
73 if (pos_at_the_beginning)
74 lseek(fd, 0, SEEK_SET);
75 else
76 lseek(fd, 0, SEEK_END);
78 return fs;
81 /* fclose wrapper */
82 int jfclose(struct jfs *stream)
84 int rv;
85 rv = jclose(stream);
86 free(stream);
88 if (rv == 0)
89 return 0;
90 else
91 return EOF;
94 /* freopen wrapper */
95 struct jfs *jfreopen(const char *path, const char *mode, struct jfs *stream)
97 if (stream)
98 jfclose(stream);
100 stream = jfopen(path, mode);
101 return stream;
104 /* fread wrapper */
105 size_t jfread(void *ptr, size_t size, size_t nmemb, struct jfs *stream)
107 int rv;
108 rv = jread(stream, ptr, size * nmemb);
110 if (rv <= 0)
111 return 0;
113 return rv / size;
116 /* fwrite wrapper */
117 size_t jfwrite(const void *ptr, size_t size, size_t nmemb, struct jfs *stream)
119 int rv;
120 rv = jwrite(stream, ptr, size * nmemb);
122 if (rv <= 0)
123 return 0;
125 return rv / size;
128 /* fileno wrapper */
129 int jfileno(struct jfs *stream)
131 return stream->fd;
134 /* feof wrapper */
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)
155 return 1;
156 else
157 return 0;
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. */
167 /* ferror wrapper */
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 */
172 return 0;
175 /* fseek wrapper */
176 int jfseek(struct jfs *stream, long offset, int whence)
178 long pos;
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 */
185 if (pos == -1)
186 return 1;
188 return 0;
191 /* ftell wrapper */
192 int jftell(struct jfs *stream)
194 return lseek(stream->fd, 0, SEEK_CUR);
197 /* rewind wrapper */
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);