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