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