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 23596
VFIL_null_fd(int target)
67
{
68
        int fd;
69
70 23596
        assert(target >= 0);
71 23596
        fd = open("/dev/null", O_RDWR);
72 23596
        assert(fd >= 0);
73 23596
        assert(dup2(fd, target) == target);
74 23596
        closefd(&fd);
75 23596
}
76
77
static char *
78 2746
vfil_readfd(int fd, ssize_t *sz)
79
{
80
        struct stat st;
81
        char *f;
82
        int i;
83
84 2746
        AZ(fstat(fd, &st));
85 2746
        if (!S_ISREG(st.st_mode))
86 0
                return (NULL);
87 2746
        f = malloc(st.st_size + 1);
88 2746
        assert(f != NULL);
89 2746
        i = read(fd, f, st.st_size + 1);
90 2746
        if (i != st.st_size) {
91 0
                free(f);
92 0
                return (NULL);
93
        }
94 2746
        f[i] = '\0';
95 2746
        if (sz != NULL)
96 0
                *sz = st.st_size;
97 2746
        return (f);
98
}
99
100
static int
101 8
vfil_writefd(int fd, const char *buf, size_t sz)
102
{
103
        ssize_t len;
104
105 24
        while (sz > 0) {
106 8
                len = write(fd, buf, sz);
107 8
                if (len < 0)
108 0
                        return (len);
109 8
                if (len == 0)
110 0
                        break;
111 8
                buf += len;
112 8
                sz -= len;
113
        }
114
115 8
        return (sz == 0 ? 0 : -1);
116
}
117
118
static int
119 2758
vfil_openfile(const char *pfx, const char *fn, int flags, int mode)
120
{
121
        char fnb[PATH_MAX + 1];
122
123 2758
        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 2758
        if (flags & O_CREAT)
130 8
                return (open(fn, flags, mode));
131
        else
132 2750
                return (open(fn, flags));
133
}
134
135
char *
136 2750
VFIL_readfile(const char *pfx, const char *fn, ssize_t *sz)
137
{
138
        int fd, err;
139
        char *r;
140
141 2750
        fd = vfil_openfile(pfx, fn, O_RDONLY, 0);
142 2750
        if (fd < 0)
143 4
                return (NULL);
144 2746
        r = vfil_readfd(fd, sz);
145 2746
        err = errno;
146 2746
        closefd(&fd);
147 2746
        errno = err;
148 2746
        return (r);
149
}
150
151
int
152 8
VFIL_writefile(const char *pfx, const char *fn, const char *buf, size_t sz)
153
{
154
        int fd, err;
155
        int r;
156
157 8
        fd = vfil_openfile(pfx, fn, O_WRONLY|O_CREAT|O_TRUNC, 0660);
158 8
        if (fd < 0)
159 0
                return (fd);
160 8
        r = vfil_writefd(fd, buf, sz);
161 8
        err = errno;
162 8
        closefd(&fd);
163 8
        errno = err;
164 8
        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 44740
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 44740
        if (fstatvfs(fd, &fsst))
194 0
                return (-1);
195 44740
        bs = fsst.f_frsize;
196 44740
        size = fsst.f_blocks * fsst.f_frsize;
197 44740
        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 44740
        if (pbs)
211 54
                *pbs = bs;
212 44740
        if (psize)
213 54
                *psize = size;
214 44740
        if (pspace)
215 44686
                *pspace = space;
216 44740
        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 44686
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 44686
        int retval = 0;
237
238 44686
        if (ftruncate(fd, size))
239 0
                return (-1);
240 44686
        if (fstat(fd, &st))
241 0
                return (-1);
242 44686
        if (VFIL_fsinfo(fd, NULL, NULL, &fsspace))
243 0
                return (-1);
244 44686
        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 44686
        if (!insist)
270 8
                return (0);
271
272
        /* Write size zero bytes to make sure the entire file is allocated
273
           in the file system */
274 44678
        if (size > 65536)
275 1228
                bufsiz = 64 * 1024;
276
        else
277 43450
                bufsiz = size;
278 44678
        buf = calloc(1, bufsiz);
279 44678
        AN(buf);
280 44678
        assert(lseek(fd, 0, SEEK_SET) == 0);
281 127424
        for (l = 0; l < size; l += l2) {
282 82746
                l2 = bufsiz;
283 82746
                if (l + l2 > size)
284 0
                        l2 = size - l;
285 82746
                l3 = write(fd, buf, l2);
286 82746
                if (l3 != l2) {
287 0
                        retval = -1;
288 0
                        break;
289
                }
290
        }
291 44678
        assert(lseek(fd, 0, SEEK_SET) == 0);
292 44678
        free(buf);
293 44678
        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 3648
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 3648
        AN(pp);
322 3648
        AN(path);
323
324 3648
        vp = *pp;
325 3648
        if (vp == NULL) {
326 3640
                ALLOC_OBJ(vp, VFIL_PATH_MAGIC);
327 3640
                AN(vp);
328 3640
                VTAILQ_INIT(&vp->paths);
329 3640
                *pp = vp;
330
        }
331 3648
        REPLACE(vp->str, path);
332 7312
        while (!VTAILQ_EMPTY(&vp->paths)) {
333 16
                vd = VTAILQ_FIRST(&vp->paths);
334 16
                VTAILQ_REMOVE(&vp->paths, vd, list);
335 16
                FREE_OBJ(vd);
336
        }
337 18062
        for (p = vp->str; p != NULL; p = q) {
338 14414
                q = strchr(p, ':');
339 14414
                if (q != NULL)
340 10766
                        *q++ = '\0';
341 14414
                ALLOC_OBJ(vd, VFIL_DIR_MAGIC);
342 14414
                AN(vd);
343 14414
                vd->dir = p;
344 14414
                VTAILQ_INSERT_TAIL(&vp->paths, vd, list);
345
        }
346 3648
}
347
348
static int
349 72
vfil_path_openfile(void *priv, const char *fn)
350
{
351
        char *p, **pp;
352
353 72
        AN(priv);
354 72
        AN(fn);
355 72
        p = VFIL_readfile(NULL, fn, NULL);
356 72
        if (p == NULL)
357 4
                return (1);
358
359 68
        pp = priv;
360 68
        *pp = p;
361 68
        return (0);
362
}
363
364
int
365 578
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 578
        CHECK_OBJ_NOTNULL(vp, VFIL_PATH_MAGIC);
373 578
        AN(fno);
374 578
        *fno = NULL;
375
376 578
        if (func == NULL) {
377 76
                func = vfil_path_openfile;
378 76
                AN(priv);
379
        }
380
381 578
        if (*fni == '/') {
382 56
                i = func(priv, fni);
383 56
                if (i <= 0)
384 52
                        REPLACE(*fno, fni);
385 56
                return (i);
386
        }
387 522
        vsb = VSB_new_auto();
388 522
        AN(vsb);
389 1486
        VTAILQ_FOREACH(vd, &vp->paths, list) {
390 1480
                VSB_clear(vsb);
391 1480
                VSB_printf(vsb, "%s/%s", vd->dir, fni);
392 1480
                AZ(VSB_finish(vsb));
393 1480
                if (access(VSB_data(vsb), F_OK))
394 964
                        continue;
395 516
                i = func(priv, VSB_data(vsb));
396 516
                if (i <= 0) {
397 516
                        e = errno;
398 516
                        *fno = strdup(VSB_data(vsb));
399 516
                        AN(*fno);
400 516
                        VSB_destroy(&vsb);
401 516
                        errno = e;
402 516
                        return (i);
403
                }
404
        }
405 6
        VSB_destroy(&vsb);
406 6
        return (-1);
407
}