]> git.ipfire.org Git - thirdparty/squid.git/blame - src/fs/ufs/UFSSwapLogParser.cc
Bug 3610: peername_regex ACL
[thirdparty/squid.git] / src / fs / ufs / UFSSwapLogParser.cc
CommitLineData
58373ff8
FC
1/*
2 * SQUID Web Proxy Cache http://www.squid-cache.org/
3 * ----------------------------------------------------------
4 *
5 * Squid is the result of efforts by numerous individuals from
6 * the Internet community; see the CONTRIBUTORS file for full
7 * details. Many organizations have provided support for Squid's
8 * development; see the SPONSORS file for full details. Squid is
9 * Copyrighted (C) 2001 by the Regents of the University of
10 * California; see the COPYRIGHT file for full details. Squid
11 * incorporates software developed and/or copyrighted by other
12 * sources; see the CREDITS file for full details.
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
187642d0 27 *
58373ff8
FC
28 */
29
30#include "squid.h"
31#include "md5.h"
32#include "StoreSwapLogData.h"
33#include "swap_log_op.h"
34#include "UFSSwapLogParser.h"
35
36/// Parse a swap header entry created on a system with 32-bit size_t and sfileno
37/// this is typical of 32-bit systems without large file support
38/// NP: SQUID_MD5_DIGEST_LENGTH is very risky still.
39class UFSSwapLogParser_v1_32bs:public Fs::Ufs::UFSSwapLogParser
40{
41public:
42 /// version 1 cache swap.state entry with 32-bit size_t (swap_file_sz)
43 /// time_t an sfileno have no variation from the v1 baseline format
44 struct StoreSwapLogDataOld {
45 char op;
46 sfileno swap_filen;
47 time_t timestamp;
48 time_t lastref;
49 time_t expires;
50 time_t lastmod;
51 uint32_t swap_file_sz;
52 uint16_t refcount;
53 uint16_t flags;
54 unsigned char key[SQUID_MD5_DIGEST_LENGTH];
55 };
56 UFSSwapLogParser_v1_32bs(FILE *fp):Fs::Ufs::UFSSwapLogParser(fp) {
57 record_size = sizeof(UFSSwapLogParser_v1_32bs::StoreSwapLogDataOld);
58 }
59 /// Convert the on-disk 32-bit format to our current format while reading
60 bool ReadRecord(StoreSwapLogData &swapData) {
61 UFSSwapLogParser_v1_32bs::StoreSwapLogDataOld readData;
62 int bytes = sizeof(UFSSwapLogParser_v1_32bs::StoreSwapLogDataOld);
63
64 assert(log);
65
66 if (fread(&readData, bytes, 1, log) != 1) {
67 return false;
68 }
69 swapData.op = readData.op;
70 swapData.swap_filen = readData.swap_filen;
71 swapData.timestamp = readData.timestamp;
72 swapData.lastref = readData.lastref;
73 swapData.expires = readData.expires;
74 swapData.lastmod = readData.lastmod;
75 swapData.swap_file_sz = readData.swap_file_sz;
76 swapData.refcount = readData.refcount;
77 swapData.flags = readData.flags;
78 memcpy(swapData.key, readData.key, SQUID_MD5_DIGEST_LENGTH);
79 return true;
80 }
81};
82
83/// swap.state v2 log parser
84class UFSSwapLogParser_v2: public Fs::Ufs::UFSSwapLogParser
85{
86public:
87 UFSSwapLogParser_v2(FILE *fp): Fs::Ufs::UFSSwapLogParser(fp) {
88 record_size = sizeof(StoreSwapLogData);
89 }
90 bool ReadRecord(StoreSwapLogData &swapData) {
91 assert(log);
92 return fread(&swapData, sizeof(StoreSwapLogData), 1, log) == 1;
93 }
94};
95
96Fs::Ufs::UFSSwapLogParser *
97Fs::Ufs::UFSSwapLogParser::GetUFSSwapLogParser(FILE *fp)
98{
99 StoreSwapLogHeader header;
100
101 assert(fp);
102
103 if (fread(&header, sizeof(StoreSwapLogHeader), 1, fp) != 1)
104 return NULL;
105
106 if (header.op != SWAP_LOG_VERSION) {
107 debugs(47, DBG_IMPORTANT, "Old swap file detected...");
108 fseek(fp, 0, SEEK_SET);
109 return new UFSSwapLogParser_v1_32bs(fp); // Um. 32-bits except time_t, and can't determine that.
110 }
111
112 debugs(47, 2, "Swap file version: " << header.version);
113
114 if (header.version == 1) {
115 if (fseek(fp, header.record_size, SEEK_SET) != 0)
116 return NULL;
117
118 debugs(47, DBG_IMPORTANT, "Rejecting swap file v1 to avoid cache " <<
119 "index corruption. Forcing a full cache index rebuild. " <<
120 "See Squid bug #3441.");
121 return NULL;
122
123#if UNUSED_CODE
124 // baseline
125 // 32-bit sfileno
126 // native time_t (hopefully 64-bit)
127 // 64-bit file size
128 if (header.record_size == sizeof(StoreSwapLogData)) {
129 debugs(47, DBG_IMPORTANT, "Version 1 of swap file with LFS support detected... ");
130 return new UFSSwapLogParser_v1(fp);
131 }
132
133 // which means we have a 3-way grid of permutations to import (yuck!)
134 // 1) sfileno 32-bit / 64-bit (64-bit was broken)
135 // 2) time_t 32-bit / 64-bit
136 // 3) size_t 32-bit / 64-bit (32-bit was pre-LFS)
137
138 // 32-bit systems...
139 // only LFS (size_t) differs from baseline
140 if (header.record_size == sizeof(struct UFSSwapLogParser_v1_32bs::StoreSwapLogDataOld)) {
141 debugs(47, DBG_IMPORTANT, "Version 1 (32-bit) swap file without LFS support detected... ");
142 return new UFSSwapLogParser_v1_32bs(fp);
143 }
144 // LFS (size_t) and timestamps (time_t) differs from baseline
145 if (header.record_size == sizeof(struct UFSSwapLogParser_v1_32bst::StoreSwapLogDataOld)) {
146 debugs(47, DBG_IMPORTANT, "Version 1 (32-bit) swap file with short timestamps and without LFS support detected... ");
147 return new UFSSwapLogParser_v1_32bst(fp);
148 }
149 // No downgrade for 64-bit timestamps to 32-bit.
150
151 // 64-bit systems
152 // sfileno was 64-bit for a some builds
153 if (header.record_size == sizeof(struct UFSSwapLogParser_v1_64bfn::StoreSwapLogDataOld)) {
154 debugs(47, DBG_IMPORTANT, "Version 1 (64-bit) swap file with broken sfileno detected... ");
155 return new UFSSwapLogParser_v1_64bfn(fp);
156 }
157 // NP: 64-bit system with 32-bit size_t/time_t are not handled.
158
159 debugs(47, DBG_IMPORTANT, "WARNING: The swap file has wrong format!... ");
160 debugs(47, DBG_IMPORTANT, "NOTE: Cannot safely downgrade caches to short (32-bit) timestamps.");
161 return NULL;
162#endif
163 }
164
165 if (header.version >= 2) {
166 if (!header.sane()) {
167 debugs(47, DBG_IMPORTANT, "ERROR: Corrupted v" << header.version <<
168 " swap file header.");
169 return NULL;
170 }
171
172 if (fseek(fp, header.record_size, SEEK_SET) != 0)
173 return NULL;
174
175 if (header.version == 2)
176 return new UFSSwapLogParser_v2(fp);
177 }
178
179 // TODO: v3: write to disk in network-order bytes for the larger fields?
180
181 debugs(47, DBG_IMPORTANT, "Unknown swap file version: " << header.version);
182 return NULL;
183}
184
185int
186Fs::Ufs::UFSSwapLogParser::SwapLogEntries()
187{
188 struct stat sb;
189
190 if (log_entries >= 0)
191 return log_entries;
192
193 if (log && record_size && 0 == fstat(fileno(log), &sb)) {
194 log_entries = sb.st_size/record_size;
195 return log_entries;
196 }
197
198 return 0;
199}