Statistics
| Branch: | Revision:

root / drivers / tapdisk-logfile.c @ master

History | View | Annotate | Download (5.4 kB)

1 abdb293f Chrysostomos Nanakos
/*
2 abdb293f Chrysostomos Nanakos
 * Copyright (c) 2009, XenSource Inc.
3 abdb293f Chrysostomos Nanakos
 * All rights reserved.
4 abdb293f Chrysostomos Nanakos
 *
5 abdb293f Chrysostomos Nanakos
 * Redistribution and use in source and binary forms, with or without
6 abdb293f Chrysostomos Nanakos
 * modification, are permitted provided that the following conditions are met:
7 abdb293f Chrysostomos Nanakos
 *     * Redistributions of source code must retain the above copyright
8 abdb293f Chrysostomos Nanakos
 *       notice, this list of conditions and the following disclaimer.
9 abdb293f Chrysostomos Nanakos
 *     * Redistributions in binary form must reproduce the above copyright
10 abdb293f Chrysostomos Nanakos
 *       notice, this list of conditions and the following disclaimer in the
11 abdb293f Chrysostomos Nanakos
 *       documentation and/or other materials provided with the distribution.
12 abdb293f Chrysostomos Nanakos
 *     * Neither the name of XenSource Inc. nor the names of its contributors
13 abdb293f Chrysostomos Nanakos
 *       may be used to endorse or promote products derived from this software
14 abdb293f Chrysostomos Nanakos
 *       without specific prior written permission.
15 abdb293f Chrysostomos Nanakos
 *
16 abdb293f Chrysostomos Nanakos
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 abdb293f Chrysostomos Nanakos
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 abdb293f Chrysostomos Nanakos
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 abdb293f Chrysostomos Nanakos
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
20 abdb293f Chrysostomos Nanakos
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 abdb293f Chrysostomos Nanakos
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 abdb293f Chrysostomos Nanakos
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23 abdb293f Chrysostomos Nanakos
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24 abdb293f Chrysostomos Nanakos
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25 abdb293f Chrysostomos Nanakos
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 abdb293f Chrysostomos Nanakos
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 abdb293f Chrysostomos Nanakos
 */
28 abdb293f Chrysostomos Nanakos
29 abdb293f Chrysostomos Nanakos
#ifdef HAVE_CONFIG_H
30 abdb293f Chrysostomos Nanakos
#include "config.h"
31 abdb293f Chrysostomos Nanakos
#endif
32 abdb293f Chrysostomos Nanakos
33 abdb293f Chrysostomos Nanakos
#include <stdlib.h>
34 abdb293f Chrysostomos Nanakos
#include <string.h>
35 abdb293f Chrysostomos Nanakos
#include <unistd.h>
36 abdb293f Chrysostomos Nanakos
#include <errno.h>
37 abdb293f Chrysostomos Nanakos
#include <time.h>
38 abdb293f Chrysostomos Nanakos
#include <stdarg.h>
39 abdb293f Chrysostomos Nanakos
#include <sys/time.h>
40 abdb293f Chrysostomos Nanakos
#include <sys/mman.h>
41 abdb293f Chrysostomos Nanakos
42 abdb293f Chrysostomos Nanakos
#include "tapdisk-logfile.h"
43 abdb293f Chrysostomos Nanakos
#include "tapdisk-utils.h"
44 abdb293f Chrysostomos Nanakos
45 abdb293f Chrysostomos Nanakos
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
46 abdb293f Chrysostomos Nanakos
47 abdb293f Chrysostomos Nanakos
static inline size_t
48 abdb293f Chrysostomos Nanakos
page_align(size_t size)
49 abdb293f Chrysostomos Nanakos
{
50 abdb293f Chrysostomos Nanakos
        size_t page_size = sysconf(_SC_PAGE_SIZE);
51 abdb293f Chrysostomos Nanakos
        return (size + page_size - 1) & ~(page_size - 1);
52 abdb293f Chrysostomos Nanakos
}
53 abdb293f Chrysostomos Nanakos
54 abdb293f Chrysostomos Nanakos
static void
55 abdb293f Chrysostomos Nanakos
tapdisk_logfile_free_buffer(td_logfile_t *log)
56 abdb293f Chrysostomos Nanakos
{
57 abdb293f Chrysostomos Nanakos
        if (log->vbuf) {
58 abdb293f Chrysostomos Nanakos
                munmap(log->vbuf, page_align(log->vbufsz));
59 abdb293f Chrysostomos Nanakos
                log->vbuf = NULL;
60 abdb293f Chrysostomos Nanakos
        }
61 abdb293f Chrysostomos Nanakos
}
62 abdb293f Chrysostomos Nanakos
63 abdb293f Chrysostomos Nanakos
static int
64 abdb293f Chrysostomos Nanakos
tapdisk_logfile_init_buffer(td_logfile_t *log, size_t size)
65 abdb293f Chrysostomos Nanakos
{
66 abdb293f Chrysostomos Nanakos
        int prot, flags, err;
67 abdb293f Chrysostomos Nanakos
68 abdb293f Chrysostomos Nanakos
        if (!size)
69 abdb293f Chrysostomos Nanakos
                return -EINVAL;
70 abdb293f Chrysostomos Nanakos
71 abdb293f Chrysostomos Nanakos
        prot  = PROT_READ|PROT_WRITE;
72 abdb293f Chrysostomos Nanakos
        flags = MAP_ANONYMOUS|MAP_PRIVATE;
73 abdb293f Chrysostomos Nanakos
74 abdb293f Chrysostomos Nanakos
        log->vbuf = mmap(NULL, page_align(size), prot, flags, -1, 0);
75 abdb293f Chrysostomos Nanakos
        if (log->vbuf == MAP_FAILED) {
76 abdb293f Chrysostomos Nanakos
                log->vbuf = NULL;
77 abdb293f Chrysostomos Nanakos
                goto fail;
78 abdb293f Chrysostomos Nanakos
        }
79 abdb293f Chrysostomos Nanakos
80 abdb293f Chrysostomos Nanakos
        err = mlock(log->vbuf, page_align(size));
81 abdb293f Chrysostomos Nanakos
        if (err)
82 abdb293f Chrysostomos Nanakos
                goto fail;
83 abdb293f Chrysostomos Nanakos
84 abdb293f Chrysostomos Nanakos
        log->vbufsz = size;
85 abdb293f Chrysostomos Nanakos
86 abdb293f Chrysostomos Nanakos
        return 0;
87 abdb293f Chrysostomos Nanakos
88 abdb293f Chrysostomos Nanakos
fail:
89 abdb293f Chrysostomos Nanakos
        tapdisk_logfile_free_buffer(log);
90 abdb293f Chrysostomos Nanakos
        err = -errno;
91 abdb293f Chrysostomos Nanakos
        return err;
92 abdb293f Chrysostomos Nanakos
}
93 abdb293f Chrysostomos Nanakos
94 abdb293f Chrysostomos Nanakos
int
95 abdb293f Chrysostomos Nanakos
tapdisk_logfile_unlink(td_logfile_t *log)
96 abdb293f Chrysostomos Nanakos
{
97 abdb293f Chrysostomos Nanakos
        int err;
98 abdb293f Chrysostomos Nanakos
99 abdb293f Chrysostomos Nanakos
        err = unlink(log->path);
100 abdb293f Chrysostomos Nanakos
        if (err)
101 abdb293f Chrysostomos Nanakos
                err = -errno;
102 abdb293f Chrysostomos Nanakos
103 abdb293f Chrysostomos Nanakos
        return err;
104 abdb293f Chrysostomos Nanakos
}
105 abdb293f Chrysostomos Nanakos
106 abdb293f Chrysostomos Nanakos
static int
107 abdb293f Chrysostomos Nanakos
__tapdisk_logfile_rename(td_logfile_t *log, const char *newpath)
108 abdb293f Chrysostomos Nanakos
{
109 abdb293f Chrysostomos Nanakos
        const size_t max = sizeof(log->path);
110 abdb293f Chrysostomos Nanakos
        int err;
111 abdb293f Chrysostomos Nanakos
112 abdb293f Chrysostomos Nanakos
        if (!strcmp(log->path, newpath))
113 abdb293f Chrysostomos Nanakos
                return 0;
114 abdb293f Chrysostomos Nanakos
115 abdb293f Chrysostomos Nanakos
        if (strlen(newpath) > max)
116 abdb293f Chrysostomos Nanakos
                return -ENAMETOOLONG;
117 abdb293f Chrysostomos Nanakos
118 abdb293f Chrysostomos Nanakos
        err = rename(log->path, newpath);
119 abdb293f Chrysostomos Nanakos
        if (err) {
120 abdb293f Chrysostomos Nanakos
                err = -errno;
121 abdb293f Chrysostomos Nanakos
                return err;
122 abdb293f Chrysostomos Nanakos
        }
123 abdb293f Chrysostomos Nanakos
124 abdb293f Chrysostomos Nanakos
        strncpy(log->path, newpath, max);
125 abdb293f Chrysostomos Nanakos
126 abdb293f Chrysostomos Nanakos
        return 0;
127 abdb293f Chrysostomos Nanakos
}
128 abdb293f Chrysostomos Nanakos
129 abdb293f Chrysostomos Nanakos
static int
130 abdb293f Chrysostomos Nanakos
tapdisk_logfile_name(char *path, size_t size,
131 abdb293f Chrysostomos Nanakos
                     const char *dir, const char *ident, const char *suffix)
132 abdb293f Chrysostomos Nanakos
{
133 abdb293f Chrysostomos Nanakos
        const size_t max = MIN(size, TD_LOGFILE_PATH_MAX);
134 abdb293f Chrysostomos Nanakos
        return snprintf(path, max, "%s/%s.%d%s", dir, ident, getpid(), suffix);
135 abdb293f Chrysostomos Nanakos
}
136 abdb293f Chrysostomos Nanakos
137 abdb293f Chrysostomos Nanakos
int
138 abdb293f Chrysostomos Nanakos
tapdisk_logfile_rename(td_logfile_t *log,
139 abdb293f Chrysostomos Nanakos
                       const char *dir, const char *ident, const char *suffix)
140 abdb293f Chrysostomos Nanakos
{
141 abdb293f Chrysostomos Nanakos
        char newpath[TD_LOGFILE_PATH_MAX+1];
142 abdb293f Chrysostomos Nanakos
143 abdb293f Chrysostomos Nanakos
        tapdisk_logfile_name(newpath, sizeof(newpath), dir, ident, suffix);
144 abdb293f Chrysostomos Nanakos
145 abdb293f Chrysostomos Nanakos
        return __tapdisk_logfile_rename(log, newpath);
146 abdb293f Chrysostomos Nanakos
}
147 abdb293f Chrysostomos Nanakos
148 abdb293f Chrysostomos Nanakos
void
149 abdb293f Chrysostomos Nanakos
tapdisk_logfile_close(td_logfile_t *log)
150 abdb293f Chrysostomos Nanakos
{
151 abdb293f Chrysostomos Nanakos
        if (log->file) {
152 abdb293f Chrysostomos Nanakos
                fclose(log->file);
153 abdb293f Chrysostomos Nanakos
                log->file = NULL;
154 abdb293f Chrysostomos Nanakos
        }
155 abdb293f Chrysostomos Nanakos
156 abdb293f Chrysostomos Nanakos
        tapdisk_logfile_free_buffer(log);
157 abdb293f Chrysostomos Nanakos
}
158 abdb293f Chrysostomos Nanakos
159 abdb293f Chrysostomos Nanakos
int
160 abdb293f Chrysostomos Nanakos
tapdisk_logfile_open(td_logfile_t *log,
161 abdb293f Chrysostomos Nanakos
                     const char *dir, const char *ident, const char *ext,
162 abdb293f Chrysostomos Nanakos
                     size_t bufsz)
163 abdb293f Chrysostomos Nanakos
{
164 abdb293f Chrysostomos Nanakos
        int err;
165 abdb293f Chrysostomos Nanakos
166 abdb293f Chrysostomos Nanakos
        memset(log, 0, sizeof(log));
167 abdb293f Chrysostomos Nanakos
168 abdb293f Chrysostomos Nanakos
        tapdisk_logfile_name(log->path, sizeof(log->path), dir, ident, ext);
169 abdb293f Chrysostomos Nanakos
170 abdb293f Chrysostomos Nanakos
        log->file = fopen(log->path, "w");
171 abdb293f Chrysostomos Nanakos
        if (!log->file) {
172 abdb293f Chrysostomos Nanakos
                err = -errno;
173 abdb293f Chrysostomos Nanakos
                goto fail;
174 abdb293f Chrysostomos Nanakos
        }
175 abdb293f Chrysostomos Nanakos
176 abdb293f Chrysostomos Nanakos
        err = tapdisk_logfile_init_buffer(log, bufsz);
177 abdb293f Chrysostomos Nanakos
        if (err)
178 abdb293f Chrysostomos Nanakos
                goto fail;
179 abdb293f Chrysostomos Nanakos
180 abdb293f Chrysostomos Nanakos
        return 0;
181 abdb293f Chrysostomos Nanakos
182 abdb293f Chrysostomos Nanakos
fail:
183 abdb293f Chrysostomos Nanakos
        tapdisk_logfile_unlink(log);
184 abdb293f Chrysostomos Nanakos
        tapdisk_logfile_close(log);
185 abdb293f Chrysostomos Nanakos
        return err;
186 abdb293f Chrysostomos Nanakos
}
187 abdb293f Chrysostomos Nanakos
188 abdb293f Chrysostomos Nanakos
int
189 abdb293f Chrysostomos Nanakos
tapdisk_logfile_setvbuf(td_logfile_t *log, int mode)
190 abdb293f Chrysostomos Nanakos
{
191 abdb293f Chrysostomos Nanakos
        int err = 0;
192 abdb293f Chrysostomos Nanakos
193 abdb293f Chrysostomos Nanakos
        if (log->file) {
194 abdb293f Chrysostomos Nanakos
                err = setvbuf(log->file, log->vbuf, mode, log->vbufsz);
195 abdb293f Chrysostomos Nanakos
                if (err)
196 abdb293f Chrysostomos Nanakos
                        err = -errno;
197 abdb293f Chrysostomos Nanakos
        }
198 abdb293f Chrysostomos Nanakos
199 abdb293f Chrysostomos Nanakos
        return err;
200 abdb293f Chrysostomos Nanakos
}
201 abdb293f Chrysostomos Nanakos
202 abdb293f Chrysostomos Nanakos
ssize_t
203 abdb293f Chrysostomos Nanakos
tapdisk_logfile_vprintf(td_logfile_t *log, const char *fmt, va_list ap)
204 abdb293f Chrysostomos Nanakos
{
205 abdb293f Chrysostomos Nanakos
        char buf[1024];
206 abdb293f Chrysostomos Nanakos
        size_t size, n;
207 abdb293f Chrysostomos Nanakos
        ssize_t len;
208 abdb293f Chrysostomos Nanakos
        struct timeval tv;
209 abdb293f Chrysostomos Nanakos
210 abdb293f Chrysostomos Nanakos
        if (!log->file)
211 abdb293f Chrysostomos Nanakos
                return -EBADF;
212 abdb293f Chrysostomos Nanakos
213 abdb293f Chrysostomos Nanakos
        gettimeofday(&tv, NULL);
214 abdb293f Chrysostomos Nanakos
215 abdb293f Chrysostomos Nanakos
        size = sizeof(buf);
216 abdb293f Chrysostomos Nanakos
        len  = 0;
217 abdb293f Chrysostomos Nanakos
218 abdb293f Chrysostomos Nanakos
        len += tapdisk_syslog_strftime(buf, size, &tv);
219 abdb293f Chrysostomos Nanakos
        len += snprintf(buf + len, size - len, ": ");
220 abdb293f Chrysostomos Nanakos
        len += tapdisk_syslog_strftv(buf + len, size - len, &tv);
221 abdb293f Chrysostomos Nanakos
        len += snprintf(buf + len, size - len, " ");
222 abdb293f Chrysostomos Nanakos
        len += vsnprintf(buf + len, size - len, fmt, ap);
223 abdb293f Chrysostomos Nanakos
224 abdb293f Chrysostomos Nanakos
        if (buf[len-1] != '\n')
225 abdb293f Chrysostomos Nanakos
                len += snprintf(buf + len, size - len, "\n");
226 abdb293f Chrysostomos Nanakos
227 abdb293f Chrysostomos Nanakos
        n = fwrite(buf, len, 1, log->file);
228 abdb293f Chrysostomos Nanakos
        if (n != len)
229 abdb293f Chrysostomos Nanakos
                len = -ferror(log->file);
230 abdb293f Chrysostomos Nanakos
231 abdb293f Chrysostomos Nanakos
        return len;
232 abdb293f Chrysostomos Nanakos
}
233 abdb293f Chrysostomos Nanakos
234 abdb293f Chrysostomos Nanakos
ssize_t
235 abdb293f Chrysostomos Nanakos
tapdisk_logfile_printf(td_logfile_t *log, const char *fmt, ...)
236 abdb293f Chrysostomos Nanakos
{
237 abdb293f Chrysostomos Nanakos
        va_list ap;
238 abdb293f Chrysostomos Nanakos
        int rv;
239 abdb293f Chrysostomos Nanakos
240 abdb293f Chrysostomos Nanakos
        va_start(ap, fmt);
241 abdb293f Chrysostomos Nanakos
        rv = tapdisk_logfile_vprintf(log, fmt, ap);
242 abdb293f Chrysostomos Nanakos
        va_end(ap);
243 abdb293f Chrysostomos Nanakos
244 abdb293f Chrysostomos Nanakos
        return rv;
245 abdb293f Chrysostomos Nanakos
}
246 abdb293f Chrysostomos Nanakos
247 abdb293f Chrysostomos Nanakos
int
248 abdb293f Chrysostomos Nanakos
tapdisk_logfile_flush(td_logfile_t *log)
249 abdb293f Chrysostomos Nanakos
{
250 abdb293f Chrysostomos Nanakos
        int rv = EOF;
251 abdb293f Chrysostomos Nanakos
252 abdb293f Chrysostomos Nanakos
        if (log->file)
253 abdb293f Chrysostomos Nanakos
                rv = fflush(log->file);
254 abdb293f Chrysostomos Nanakos
255 abdb293f Chrysostomos Nanakos
        return rv;
256 abdb293f Chrysostomos Nanakos
}