varnish-cache/lib/libvarnish/vfil.c
1
/*-
2
 * Copyright (c) 2006 Verdens Gang AS
3
 * Copyright (c) 2006-2011 Varnish Software AS
4
 * All rights reserved.
5
 *
6
 * Author: Dag-Erling Smørgrav <des@des.no>
7
 *
8
 * Redistribution and use in source and binary forms, with or without
9
 * modification, are permitted provided that the following conditions
10
 * are met:
11
 * 1. Redistributions of source code must retain the above copyright
12
 *    notice, this list of conditions and the following disclaimer.
13
 * 2. Redistributions in binary form must reproduce the above copyright
14
 *    notice, this list of conditions and the following disclaimer in the
15
 *    documentation and/or other materials provided with the distribution.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
21
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
 * SUCH DAMAGE.
28
 */
29
30
#include "config.h"
31
32
#include <time.h>
33
#include <sys/types.h>
34
#include <sys/stat.h>
35
#include <errno.h>
36
#include <fcntl.h>
37
#include <limits.h>
38
#include <stdio.h>
39
#include <stdlib.h>
40
#include <unistd.h>
41
#include <stdint.h>
42
#include <string.h>
43
#ifdef HAVE_SYS_MOUNT_H
44
#  include <sys/param.h>
45
#  include <sys/mount.h>
46
#endif
47
#ifdef HAVE_SYS_STATVFS_H
48
#  include <sys/statvfs.h>
49
#endif
50
#ifdef HAVE_SYS_VFS_H
51
#  include <sys/vfs.h>
52
#endif
53
#if defined(__linux__) && defined(HAVE_FALLOCATE)
54
#  include <linux/magic.h>
55
#endif
56
57
#include "vdef.h"
58
59
#include "miniobj.h"
60
#include "vas.h"
61
#include "vsb.h"
62
#include "vfil.h"
63
#include "vqueue.h"
64
65
void
66 33399
VFIL_null_fd(int target)
67
{
68
        int fd;
69
70 33399
        assert(target >= 0);
71 33399
        fd = open("/dev/null", O_RDWR);
72 33399
        assert(fd >= 0);
73 33399
        assert(dup2(fd, target) == target);
74 33399
        closefd(&fd);
75 33399
}
76
77
static char *
78 4629
vfil_readfd(int fd, ssize_t *sz)
79
{
80
        struct stat st;
81
        char *f;
82
        int i;
83
84 4629
        AZ(fstat(fd, &st));
85 4629
        if (!S_ISREG(st.st_mode))
86 0
                return (NULL);
87 4629
        f = malloc(st.st_size + 1);
88 4629
        assert(f != NULL);
89 4629
        i = read(fd, f, st.st_size + 1);
90 4629
        if (i != st.st_size) {
91 0
                free(f);
92 0
                return (NULL);
93
        }
94 4629
        f[i] = '\0';
95 4629
        if (sz != NULL)
96 0
                *sz = st.st_size;
97 4629
        return (f);
98
}
99
100
static int
101 30
vfil_writefd(int fd, const char *buf, size_t sz)
102
{
103
        ssize_t len;
104
105 90
        while (sz > 0) {
106 30
                len = write(fd, buf, sz);
107 30
                if (len < 0)
108 0
                        return (len);
109 30
                if (len == 0)
110 0
                        break;
111 30
                buf += len;
112 30
                sz -= len;
113
        }
114
115 30
        return (sz == 0 ? 0 : -1);
116
}
117
118
static int
119 4665
vfil_openfile(const char *pfx, const char *fn, int flags, int mode)
120
{
121
        char fnb[PATH_MAX + 1];
122
123 4665
        if (fn[0] != '/' && pfx != NULL) {
124
                /* XXX: graceful length check */
125 0
                bprintf(fnb, "/%s/%s", pfx, fn);
126 0
                fn = fnb;
127
        }
128
129 4665
        if (flags & O_CREAT)
130 30
                return (open(fn, flags, mode));
131
        else
132 4635
                return (open(fn, flags));
133
}
134
135
char *
136 4635
VFIL_readfile(const char *pfx, const char *fn, ssize_t *sz)
137
{
138
        int fd, err;
139
        char *r;
140
141 4635
        fd = vfil_openfile(pfx, fn, O_RDONLY, 0);
142 4635
        if (fd < 0)
143 6
                return (NULL);
144 4629
        r = vfil_readfd(fd, sz);
145 4629
        err = errno;
146 4629
        closefd(&fd);
147 4629
        errno = err;
148 4629
        return (r);
149
}
150
151
int
152 30
VFIL_writefile(const char *pfx, const char *fn, const char *buf, size_t sz)
153
{
154
        int fd, err;
155
        int r;
156
157 30
        fd = vfil_openfile(pfx, fn, O_WRONLY|O_CREAT|O_TRUNC, 0660);
158 30
        if (fd < 0)
159 0
                return (fd);
160 30
        r = vfil_writefd(fd, buf, sz);
161 30
        err = errno;
162 30
        closefd(&fd);
163 30
        errno = err;
164 30
        return (r);
165
}
166
167
int
168 0
VFIL_nonblocking(int fd)
169
{
170
        int i;
171
172 0
        i = fcntl(fd, F_GETFL);
173 0
        assert(i != -1);
174 0
        i |= O_NONBLOCK;
175 0
        i = fcntl(fd, F_SETFL, i);
176 0
        assert(i != -1);
177 0
        return (i);
178
}
179
180
/*
181
 * Get file system information from an fd
182
 * Returns block size, total size and space available in the passed pointers
183
 * Returns 0 on success, or -1 on failure with errno set
184
 */
185
int
186 87453
VFIL_fsinfo(int fd, unsigned *pbs, uintmax_t *psize, uintmax_t *pspace)
187
{
188
        unsigned bs;
189
        uintmax_t size, space;
190
#if defined(HAVE_SYS_STATVFS_H)
191
        struct statvfs fsst;
192
193 87453
        if (fstatvfs(fd, &fsst))
194 0
                return (-1);
195 87453
        bs = fsst.f_frsize;
196 87453
        size = fsst.f_blocks * fsst.f_frsize;
197 87453
        space = fsst.f_bavail * fsst.f_frsize;
198
#elif defined(HAVE_SYS_MOUNT_H) || defined(HAVE_SYS_VFS_H)
199
        struct statfs fsst;
200
201
        if (fstatfs(fd, &fsst))
202
                return (-1);
203
        bs = fsst.f_bsize;
204
        size = fsst.f_blocks * fsst.f_bsize;
205
        space = fsst.f_bavail * fsst.f_bsize;
206
#else
207
#error no struct statfs / struct statvfs
208
#endif
209
210 87453
        if (pbs)
211 81
                *pbs = bs;
212 87453
        if (psize)
213 81
                *psize = size;
214 87453
        if (pspace)
215 87372
                *pspace = space;
216 87453
        return (0);
217
}
218
219
/*
220
 * Make sure that the file system can accommodate the file of the given
221
 * size. Will use fallocate if available. If fallocate is not available
222
 * and insist is true, it will write size zero bytes.
223
 *
224
 * Returns 0 on success, -1 on failure with errno set.
225
 */
226
227
int
228 87372
VFIL_allocate(int fd, off_t size, int insist)
229
{
230
        struct stat st;
231
        uintmax_t fsspace;
232
        size_t l;
233
        ssize_t l2, l3;
234
        char *buf;
235
        ssize_t bufsiz;
236 87372
        int retval = 0;
237
238 87372
        if (ftruncate(fd, size))
239 0
                return (-1);
240 87372
        if (fstat(fd, &st))
241 0
                return (-1);
242 87372
        if (VFIL_fsinfo(fd, NULL, NULL, &fsspace))
243 0
                return (-1);
244 87372
        if ((st.st_blocks * 512) + fsspace < size) {
245
                /* Sum of currently allocated blocks and available space
246
                   is less than requested size */
247 0
                errno = ENOSPC;
248 0
                return (-1);
249
        }
250
#if defined(__linux__) && defined(HAVE_FALLOCATE)
251
        {
252
                /* fallocate will for some filesystems (e.g. xfs) not take
253
                   the already allocated blocks of the file into
254
                   account. This will cause fallocate to report ENOSPC
255
                   when called on an existing fully allocated file unless
256
                   the filesystem has enough free space to accommodate the
257
                   complete new file size. Because of this we enable
258
                   fallocate only on filesystems that are known to work as
259
                   we expect. */
260
                struct statfs stfs;
261
                if (!fstatfs(fd, &stfs) && stfs.f_type == EXT4_SUPER_MAGIC) {
262
                        if (!fallocate(fd, 0, 0, size))
263
                                return (0);
264
                        if (errno == ENOSPC)
265
                                return (-1);
266
                }
267
        }
268
#endif
269 87372
        if (!insist)
270 12
                return (0);
271
272
        /* Write size zero bytes to make sure the entire file is allocated
273
           in the file system */
274 87360
        if (size > 65536)
275 2055
                bufsiz = 64 * 1024;
276
        else
277 85305
                bufsiz = size;
278 87360
        buf = calloc(1, bufsiz);
279 87360
        AN(buf);
280 87360
        assert(lseek(fd, 0, SEEK_SET) == 0);
281 238425
        for (l = 0; l < size; l += l2) {
282 151065
                l2 = bufsiz;
283 151065
                if (l + l2 > size)
284 0
                        l2 = size - l;
285 151065
                l3 = write(fd, buf, l2);
286 151065
                if (l3 != l2) {
287 0
                        retval = -1;
288 0
                        break;
289
                }
290
        }
291 87360
        assert(lseek(fd, 0, SEEK_SET) == 0);
292 87360
        free(buf);
293 87360
        return (retval);
294
}
295
296
struct vfil_dir {
297
        unsigned                magic;
298
#define VFIL_DIR_MAGIC          0x3e214967
299
        char                    *dir;
300
        VTAILQ_ENTRY(vfil_dir)  list;
301
};
302
303
struct vfil_path {
304
        unsigned                magic;
305
#define VFIL_PATH_MAGIC         0x92dbcc31
306
        char                    *str;
307
        VTAILQ_HEAD(,vfil_dir)  paths;
308
};
309
310
/*
311
 * Path searching functions
312
 */
313
314
void
315 6420
VFIL_setpath(struct vfil_path **pp, const char *path)
316
{
317
        struct vfil_path *vp;
318
        struct vfil_dir *vd;
319
        char *p, *q;
320
321 6420
        AN(pp);
322 6420
        AN(path);
323
324 6420
        vp = *pp;
325 6420
        if (vp == NULL) {
326 6408
                ALLOC_OBJ(vp, VFIL_PATH_MAGIC);
327 6408
                AN(vp);
328 6408
                VTAILQ_INIT(&vp->paths);
329 6408
                *pp = vp;
330
        }
331 6420
        REPLACE(vp->str, path);
332 12864
        while (!VTAILQ_EMPTY(&vp->paths)) {
333 24
                vd = VTAILQ_FIRST(&vp->paths);
334 24
                VTAILQ_REMOVE(&vp->paths, vd, list);
335 24
                FREE_OBJ(vd);
336
        }
337 38151
        for (p = vp->str; p != NULL; p = q) {
338 31731
                q = strchr(p, ':');
339 31731
                if (q != NULL)
340 25311
                        *q++ = '\0';
341 31731
                ALLOC_OBJ(vd, VFIL_DIR_MAGIC);
342 31731
                AN(vd);
343 31731
                vd->dir = p;
344 31731
                VTAILQ_INSERT_TAIL(&vp->paths, vd, list);
345
        }
346 6420
}
347
348
static int
349 108
vfil_path_openfile(void *priv, const char *fn)
350
{
351
        char *p, **pp;
352
353 108
        AN(priv);
354 108
        AN(fn);
355 108
        p = VFIL_readfile(NULL, fn, NULL);
356 108
        if (p == NULL)
357 6
                return (1);
358
359 102
        pp = priv;
360 102
        *pp = p;
361 102
        return (0);
362
}
363
364
int
365 1155
VFIL_searchpath(const struct vfil_path *vp, vfil_path_func_f *func, void *priv,
366
    const char *fni, char **fno)
367
{
368
        struct vsb *vsb;
369
        struct vfil_dir *vd;
370
        int i, e;
371
372 1155
        CHECK_OBJ_NOTNULL(vp, VFIL_PATH_MAGIC);
373 1155
        AN(fno);
374 1155
        *fno = NULL;
375
376 1155
        if (func == NULL) {
377 114
                func = vfil_path_openfile;
378 114
                AN(priv);
379
        }
380
381 1155
        if (*fni == '/') {
382 84
                i = func(priv, fni);
383 84
                if (i <= 0)
384 78
                        REPLACE(*fno, fni);
385 84
                return (i);
386
        }
387 1071
        vsb = VSB_new_auto();
388 1071
        AN(vsb);
389 3267
        VTAILQ_FOREACH(vd, &vp->paths, list) {
390 3258
                VSB_clear(vsb);
391 3258
                VSB_printf(vsb, "%s/%s", vd->dir, fni);
392 3258
                AZ(VSB_finish(vsb));
393 3258
                if (access(VSB_data(vsb), F_OK))
394 2196
                        continue;
395 1062
                i = func(priv, VSB_data(vsb));
396 1062
                if (i <= 0) {
397 1062
                        e = errno;
398 1062
                        *fno = strdup(VSB_data(vsb));
399 1062
                        AN(*fno);
400 1062
                        VSB_destroy(&vsb);
401 1062
                        errno = e;
402 1062
                        return (i);
403
                }
404
        }
405 9
        VSB_destroy(&vsb);
406 9
        return (-1);
407
}