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