root/src/jlog/jlog_io.c

Revision 647ef348e1bcdee83786760f7616926b52a6bac1, 6.3 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 9 months ago)

Various code cleanliness fixes.

  • Property mode set to 100644
Line 
1 /*
2  * Copyright (c) 2005-2008, Message Systems, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  *    * Redistributions of source code must retain the above copyright
10  *      notice, this list of conditions and the following disclaimer.
11  *    * Redistributions in binary form must reproduce the above
12  *      copyright notice, this list of conditions and the following
13  *      disclaimer in the documentation and/or other materials provided
14  *      with the distribution.
15  *    * Neither the name Message Systems, Inc. nor the names
16  *      of its contributors may be used to endorse or promote products
17  *      derived from this software without specific prior written
18  *      permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32
33 /*
34  * We want the single unix spec, so this define is needed on
35  * the identity crisis that is Linux. pread()/pwrite()
36  */
37 #include "jlog_config.h"
38 #include "jlog_hash.h"
39 #include "jlog_io.h"
40 #include <assert.h>
41 #include <errno.h>
42 #include <fcntl.h>
43 #include <pthread.h>
44 #include <sys/mman.h>
45 #include <sys/stat.h>
46 #include <unistd.h>
47
48 static pthread_mutex_t jlog_files_lock = PTHREAD_MUTEX_INITIALIZER;
49 static jlog_hash_table jlog_files = JLOG_HASH_EMPTY;
50
51 typedef struct {
52   dev_t st_dev;
53   ino_t st_ino;
54 } jlog_file_id;
55
56 struct _jlog_file {
57   jlog_file_id id;
58   int fd;
59   int refcnt;
60   int locked;
61   pthread_mutex_t lock;
62 };
63
64 jlog_file *jlog_file_open(const char *path, int flags, int mode)
65 {
66   struct stat sb;
67   jlog_file_id id;
68   jlog_file *f = NULL;
69   union {
70     jlog_file *f;
71     void *vptr;
72   } pun;
73   int fd, realflags = O_RDWR;
74
75   if (flags & O_CREAT) realflags |= O_CREAT;
76   if (flags & O_EXCL) realflags |= O_EXCL;
77
78   if (pthread_mutex_lock(&jlog_files_lock) != 0) return NULL;
79
80   /* coverity[fs_check_call] */
81   if (stat(path, &sb) == 0) {
82     if (!S_ISREG(sb.st_mode)) goto out;
83     memset(&id, 0, sizeof(id));
84     id.st_dev = sb.st_dev;
85     id.st_ino = sb.st_ino;
86     if (jlog_hash_retrieve(&jlog_files, (void *)&id, sizeof(jlog_file_id),
87                            &pun.vptr))
88     {
89       if (!(flags & O_EXCL)) {
90         f = pun.f;
91         f->refcnt++;
92       }
93       goto out;
94     }
95   }
96
97   /* coverity[toctou] */
98   if ((fd = open(path, realflags, mode)) == -1) goto out;
99   if (fstat(fd, &sb) != 0) {
100     while (close(fd) == -1 && errno == EINTR) ;
101     goto out;
102   }
103   id.st_dev = sb.st_dev;
104   id.st_ino = sb.st_ino;
105   if (!(f = malloc(sizeof(jlog_file)))) {
106     while (close(fd) == -1 && errno == EINTR) ;
107     goto out;
108   }
109   memset(f, 0, sizeof(jlog_file));
110   f->id = id;
111   f->fd = fd;
112   f->refcnt = 1;
113   f->locked = 0;
114   pthread_mutex_init(&(f->lock), NULL);
115   if (!jlog_hash_store(&jlog_files, (void *)&f->id, sizeof(jlog_file_id), f)) {
116     while (close(f->fd) == -1 && errno == EINTR) ;
117     free(f);
118     f = NULL;
119   }
120 out:
121   pthread_mutex_unlock(&jlog_files_lock);
122   return f;
123 }
124
125 int jlog_file_close(jlog_file *f)
126 {
127   if (pthread_mutex_lock(&jlog_files_lock) != 0) return 0;
128   if (--f->refcnt == 0) {
129     assert(jlog_hash_delete(&jlog_files, (void *)&f->id, sizeof(jlog_file_id),
130                             NULL, NULL));
131     while (close(f->fd) == -1 && errno == EINTR) ;
132     free(f);
133   }
134   pthread_mutex_unlock(&jlog_files_lock); 
135   return 1;
136 }
137
138 int jlog_file_lock(jlog_file *f)
139 {
140   struct flock fl;
141   int frv;
142
143   memset(&fl, 0, sizeof(fl));
144   fl.l_type = F_WRLCK;
145   fl.l_whence = SEEK_SET;
146   fl.l_start = 0;
147   fl.l_len = 0;
148
149   if (pthread_mutex_lock(&(f->lock)) != 0) return 0;
150   while ((frv = fcntl(f->fd, F_SETLKW, &fl)) == -1 && (errno == EINTR || errno == EAGAIN)) ;
151   if (frv != 0) {
152     int save = errno;
153     pthread_mutex_unlock(&(f->lock));
154     errno = save;
155     return 0;
156   }
157   f->locked = 1;
158   return 1;
159 }
160
161 int jlog_file_unlock(jlog_file *f)
162 {
163   struct flock fl;
164   int frv;
165
166   if (!f->locked) return 0;
167
168   memset(&fl, 0, sizeof(fl));
169   fl.l_type = F_UNLCK;
170   fl.l_whence = SEEK_SET;
171   fl.l_start = 0;
172   fl.l_len = 0;
173
174   while ((frv = fcntl(f->fd, F_SETLKW, &fl)) == -1 && (errno == EINTR || errno == EAGAIN)) ;
175   if (frv != 0) return 0;
176   f->locked = 0;
177   pthread_mutex_unlock(&(f->lock));
178   return 1;
179 }
180
181 int jlog_file_pread(jlog_file *f, void *buf, size_t nbyte, off_t offset)
182 {
183   while (nbyte > 0) {
184     ssize_t rv = pread(f->fd, buf, nbyte, offset);
185     if (rv == -1 && errno == EINTR) continue;
186     if (rv <= 0) return 0;
187     nbyte -= rv;
188     offset += rv;
189   }
190   return 1;
191 }
192
193 int jlog_file_pwrite(jlog_file *f, const void *buf, size_t nbyte, off_t offset)
194 {
195   while (nbyte > 0) {
196     ssize_t rv = pwrite(f->fd, buf, nbyte, offset);
197     if (rv == -1 && errno == EINTR) continue;
198     if (rv <= 0) return 0;
199     nbyte -= rv;
200     offset += rv;
201   }
202   return 1;
203 }
204
205 int jlog_file_sync(jlog_file *f)
206 {
207   int rv;
208
209 #ifdef HAVE_FDATASYNC
210   while((rv = fdatasync(f->fd)) == -1 && errno == EINTR) ;
211 #else
212   while((rv = fsync(f->fd)) == -1 && errno == EINTR) ;
213 #endif
214   if (rv == 0) return 1;
215   return 0;
216 }
217
218 int jlog_file_map_read(jlog_file *f, void **base, size_t *len)
219 {
220   struct stat sb;
221   void *my_map;
222   int flags = 0;
223
224 #ifdef MAP_SHARED
225   flags = MAP_SHARED;
226 #endif
227   if (fstat(f->fd, &sb) != 0) return 0;
228   my_map = mmap(NULL, sb.st_size, PROT_READ, flags, f->fd, 0);
229   if (my_map == MAP_FAILED) return 0;
230   *base = my_map;
231   *len = sb.st_size;
232   return 1;
233 }
234
235 off_t jlog_file_size(jlog_file *f)
236 {
237   struct stat sb;
238   int rv;
239   while ((rv = fstat(f->fd, &sb)) == -1 && errno == EINTR) ;
240   if (rv != 0) return -1;
241   return sb.st_size;
242 }
243
244 int jlog_file_truncate(jlog_file *f, off_t len)
245 {
246   int rv;
247   while ((rv = ftruncate(f->fd, len)) == -1 && errno == EINTR) ;
248   if (rv == 0) return 1;
249   return 0;
250 }
251
252 /* vim:se ts=2 sw=2 et: */
Note: See TracBrowser for help on using the browser.