1 /*
2  * Copyright (C) 1996-2021 The Squid Software Foundation and contributors
3  *
4  * Squid software is distributed under GPLv2+ license and includes
5  * contributions from numerous individuals and organizations.
6  * Please see the COPYING and CONTRIBUTORS files for details.
7  */
8 
9 /* DEBUG: section 20    Storage Manager Swapfile Metadata */
10 
11 #include "squid.h"
12 #include "md5.h"
13 #include "MemObject.h"
14 #include "Store.h"
15 #include "StoreMeta.h"
16 #include "StoreMetaUnpacker.h"
17 
18 #if HAVE_SYS_WAIT_H
19 #include <sys/wait.h>
20 #endif
21 
22 void
storeSwapTLVFree(tlv * n)23 storeSwapTLVFree(tlv * n)
24 {
25     tlv *t;
26 
27     while ((t = n) != NULL) {
28         n = t->next;
29         xfree(t->value);
30         delete t;
31     }
32 }
33 
34 /*
35  * Build a TLV list for a StoreEntry
36  */
37 tlv *
storeSwapMetaBuild(StoreEntry * e)38 storeSwapMetaBuild(StoreEntry * e)
39 {
40     tlv *TLV = NULL;        /* we'll return this */
41     tlv **T = &TLV;
42     assert(e->mem_obj != NULL);
43     const int64_t objsize = e->mem_obj->expectedReplySize();
44 
45     // e->mem_obj->request may be nil in this context
46     SBuf url;
47     if (e->mem_obj->request)
48         url = e->mem_obj->request->storeId();
49     else
50         url = e->url();
51 
52     debugs(20, 3, "storeSwapMetaBuild URL: " << url);
53 
54     tlv *t = StoreMeta::Factory (STORE_META_KEY,SQUID_MD5_DIGEST_LENGTH, e->key);
55 
56     if (!t) {
57         storeSwapTLVFree(TLV);
58         return NULL;
59     }
60 
61     T = StoreMeta::Add(T, t);
62     t = StoreMeta::Factory(STORE_META_STD_LFS,STORE_HDR_METASIZE,&e->timestamp);
63 
64     if (!t) {
65         storeSwapTLVFree(TLV);
66         return NULL;
67     }
68 
69     // XXX: do TLV without the c_str() termination. check readers first though
70     T = StoreMeta::Add(T, t);
71     t = StoreMeta::Factory(STORE_META_URL, url.length()+1, url.c_str());
72 
73     if (!t) {
74         storeSwapTLVFree(TLV);
75         return NULL;
76     }
77 
78     if (objsize >= 0) {
79         T = StoreMeta::Add(T, t);
80         t = StoreMeta::Factory(STORE_META_OBJSIZE, sizeof(objsize), &objsize);
81 
82         if (!t) {
83             storeSwapTLVFree(TLV);
84             return NULL;
85         }
86     }
87 
88     T = StoreMeta::Add(T, t);
89     SBuf vary(e->mem_obj->vary_headers);
90 
91     if (!vary.isEmpty()) {
92         t = StoreMeta::Factory(STORE_META_VARY_HEADERS, vary.length(), vary.c_str());
93 
94         if (!t) {
95             storeSwapTLVFree(TLV);
96             return NULL;
97         }
98 
99         StoreMeta::Add (T, t);
100     }
101 
102     return TLV;
103 }
104 
105 char *
storeSwapMetaPack(tlv * tlv_list,int * length)106 storeSwapMetaPack(tlv * tlv_list, int *length)
107 {
108     int buflen = 0;
109     tlv *t;
110     int j = 0;
111     char *buf;
112     assert(length != NULL);
113     ++buflen;           /* STORE_META_OK */
114     buflen += sizeof(int);  /* size of header to follow */
115 
116     for (t = tlv_list; t; t = t->next)
117         buflen += sizeof(char) + sizeof(int) + t->length;
118 
119     buf = (char *)xmalloc(buflen);
120 
121     buf[j] = (char) STORE_META_OK;
122     ++j;
123 
124     memcpy(&buf[j], &buflen, sizeof(int));
125 
126     j += sizeof(int);
127 
128     for (t = tlv_list; t; t = t->next) {
129         buf[j] = t->getType();
130         ++j;
131         memcpy(&buf[j], &t->length, sizeof(int));
132         j += sizeof(int);
133         memcpy(&buf[j], t->value, t->length);
134         j += t->length;
135     }
136 
137     assert((int) j == buflen);
138     *length = buflen;
139     return buf;
140 }
141 
142