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 520
WS_Id(const struct ws *ws, char *id)
41
{
42
43 520
        WS_Assert(ws);
44 520
        AN(id);
45 520
        memcpy(id, ws->id, WS_ID_SIZE);
46 520
        id[0] |= 0x20;                  // cheesy tolower()
47 520
}
48
49
void
50 5260
WS_MarkOverflow(struct ws *ws)
51
{
52 5260
        CHECK_OBJ_NOTNULL(ws, WS_MAGIC);
53
54 5260
        ws->id[0] &= ~0x20;             // cheesy toupper()
55 5260
}
56
57
static void
58 217083
ws_ClearOverflow(struct ws *ws)
59
{
60 217083
        CHECK_OBJ_NOTNULL(ws, WS_MAGIC);
61
62 217083
        ws->id[0] |= 0x20;              // cheesy tolower()
63 217083
}
64
65
int
66 682063
WS_Overflowed(const struct ws *ws)
67
{
68 682063
        CHECK_OBJ_NOTNULL(ws, WS_MAGIC);
69 682063
        AN(ws->id[0]);
70
71 682063
        if (ws->id[0] & 0x20)           // cheesy islower()
72 679733
                return (0);
73 2330
        return (1);
74 682063
}
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 217119
WS_Rollback(struct ws *ws, uintptr_t pp)
84
{
85
86 217119
        WS_Assert(ws);
87
88 217119
        if (pp == 0)
89 172030
                pp = (uintptr_t)ws->s;
90 217119
        ws_ClearOverflow(ws);
91 217119
        WS_Reset(ws, pp);
92 217119
}
93
94
/*--------------------------------------------------------------------*/
95
96
const char *
97 16185
WS_Printf(struct ws *ws, const char *fmt, ...)
98
{
99
        unsigned u, v;
100
        va_list ap;
101
        char *p;
102
103 16185
        u = WS_ReserveAll(ws);
104 16185
        p = ws->f;
105 16185
        va_start(ap, fmt);
106 16185
        v = vsnprintf(p, u, fmt, ap);
107 16185
        va_end(ap);
108 16185
        if (v >= u) {
109 1475
                WS_Release(ws, 0);
110 1475
                WS_MarkOverflow(ws);
111 1475
                p = NULL;
112 1475
        } else {
113 14710
                WS_Release(ws, v + 1);
114
        }
115 16185
        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 149515
WS_VSB_new(struct vsb *vsb, struct ws *ws)
134
{
135
        unsigned u;
136
        static char bogus[2];   // Smallest possible vsb
137
138 149515
        AN(vsb);
139 149515
        WS_Assert(ws);
140 149515
        u = WS_ReserveAll(ws);
141 149515
        if (WS_Overflowed(ws) || u < 2)
142 220
                AN(VSB_init(vsb, bogus, sizeof bogus));
143
        else
144 149295
                AN(VSB_init(vsb, WS_Reservation(ws), u));
145 149515
}
146
147
char *
148 149530
WS_VSB_finish(struct vsb *vsb, struct ws *ws, size_t *szp)
149
{
150
        char *p;
151
152 149530
        AN(vsb);
153 149530
        WS_Assert(ws);
154 149530
        if (!VSB_finish(vsb)) {
155 149364
                p = VSB_data(vsb);
156 149364
                if (p == ws->f) {
157 149269
                        WS_Release(ws, VSB_len(vsb) + 1);
158 149269
                        if (szp != NULL)
159 122463
                                *szp = VSB_len(vsb);
160 149269
                        VSB_fini(vsb);
161 149269
                        return (p);
162
                }
163 95
        }
164 261
        WS_MarkOverflow(ws);
165 261
        VSB_fini(vsb);
166 261
        WS_Release(ws, 0);
167 261
        if (szp)
168 130
                *szp = 0;
169 261
        return (NULL);
170 149530
}