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