varnish-cache/bin/varnishd/cache/cache_ws_common.c
0
/*-
1
 * Copyright (c) 2006 Verdens Gang AS
2
 * Copyright (c) 2006-2021 Varnish Software AS
3
 * All rights reserved.
4
 *
5
 * Author: Poul-Henning Kamp <phk@phk.freebsd.dk>
6
 * Author: Dridi Boukelmoune <dridi.boukelmoune@gmail.com>
7
 *
8
 * SPDX-License-Identifier: BSD-2-Clause
9
 *
10
 * Redistribution and use in source and binary forms, with or without
11
 * modification, are permitted provided that the following conditions
12
 * are met:
13
 * 1. Redistributions of source code must retain the above copyright
14
 *    notice, this list of conditions and the following disclaimer.
15
 * 2. Redistributions in binary form must reproduce the above copyright
16
 *    notice, this list of conditions and the following disclaimer in the
17
 *    documentation and/or other materials provided with the distribution.
18
 *
19
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22
 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
23
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29
 * SUCH DAMAGE.
30
 *
31
 */
32
33
#include "config.h"
34
35
#include <stdio.h>
36
37
#include "cache_varnishd.h"
38
39
void
40 104
WS_Id(const struct ws *ws, char *id)
41
{
42
43 104
        WS_Assert(ws);
44 104
        AN(id);
45 104
        memcpy(id, ws->id, WS_ID_SIZE);
46 104
        id[0] |= 0x20;                  // cheesy tolower()
47 104
}
48
49
void
50 1051
WS_MarkOverflow(struct ws *ws)
51
{
52 1051
        CHECK_OBJ_NOTNULL(ws, WS_MAGIC);
53
54 1051
        ws->id[0] &= ~0x20;             // cheesy toupper()
55 1051
}
56
57
static void
58 44033
ws_ClearOverflow(struct ws *ws)
59
{
60 44033
        CHECK_OBJ_NOTNULL(ws, WS_MAGIC);
61
62 44033
        ws->id[0] |= 0x20;              // cheesy tolower()
63 44033
}
64
65
int
66 138948
WS_Overflowed(const struct ws *ws)
67
{
68 138948
        CHECK_OBJ_NOTNULL(ws, WS_MAGIC);
69 138948
        AN(ws->id[0]);
70
71 138948
        if (ws->id[0] & 0x20)           // cheesy islower()
72 138483
                return (0);
73 465
        return (1);
74 138948
}
75
76
/*
77
 * Reset the WS to a cookie or its start and clears any overflow
78
 *
79
 * for varnishd internal use only
80
 */
81
82
void
83 44039
WS_Rollback(struct ws *ws, uintptr_t pp)
84
{
85
86 44039
        WS_Assert(ws);
87
88 44039
        if (pp == 0)
89 34903
                pp = (uintptr_t)ws->s;
90 44039
        ws_ClearOverflow(ws);
91 44039
        WS_Reset(ws, pp);
92 44039
}
93
94
/*--------------------------------------------------------------------*/
95
96
const char *
97 3314
WS_Printf(struct ws *ws, const char *fmt, ...)
98
{
99
        unsigned u, v;
100
        va_list ap;
101
        char *p;
102
103 3314
        u = WS_ReserveAll(ws);
104 3314
        p = ws->f;
105 3314
        va_start(ap, fmt);
106 3314
        v = vsnprintf(p, u, fmt, ap);
107 3314
        va_end(ap);
108 3314
        if (v >= u) {
109 295
                WS_Release(ws, 0);
110 295
                WS_MarkOverflow(ws);
111 295
                p = NULL;
112 295
        } else {
113 3019
                WS_Release(ws, v + 1);
114
        }
115 3314
        return (p);
116
}
117
118
/*---------------------------------------------------------------------
119
 * Build a VSB on a workspace.
120
 * Usage pattern:
121
 *
122
 *      struct vsb vsb[1];
123
 *      char *p;
124
 *
125
 *      WS_VSB_new(vsb, ctx->ws);
126
 *      VSB_printf(vsb, "blablabla");
127
 *      p = WS_VSB_finish(vsb, ctx->ws, NULL);
128
 *      if (p == NULL)
129
 *              return (FAILURE);
130
 */
131
132
void
133 30474
WS_VSB_new(struct vsb *vsb, struct ws *ws)
134
{
135
        unsigned u;
136
        static char bogus[2];   // Smallest possible vsb
137
138 30474
        AN(vsb);
139 30474
        WS_Assert(ws);
140 30474
        u = WS_ReserveAll(ws);
141 30474
        if (WS_Overflowed(ws) || u < 2)
142 44
                AN(VSB_init(vsb, bogus, sizeof bogus));
143
        else
144 30430
                AN(VSB_init(vsb, WS_Reservation(ws), u));
145 30474
}
146
147
char *
148 30477
WS_VSB_finish(struct vsb *vsb, struct ws *ws, size_t *szp)
149
{
150
        char *p;
151
152 30477
        AN(vsb);
153 30477
        WS_Assert(ws);
154 30477
        if (!VSB_finish(vsb)) {
155 30440
                p = VSB_data(vsb);
156 30440
                if (p == ws->f) {
157 30421
                        WS_Release(ws, VSB_len(vsb) + 1);
158 30421
                        if (szp != NULL)
159 24985
                                *szp = VSB_len(vsb);
160 30421
                        VSB_fini(vsb);
161 30421
                        return (p);
162
                }
163 19
        }
164 56
        WS_MarkOverflow(ws);
165 56
        VSB_fini(vsb);
166 56
        WS_Release(ws, 0);
167 56
        if (szp)
168 26
                *szp = 0;
169 56
        return (NULL);
170 30477
}