]>
Commit | Line | Data |
---|---|---|
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. | |
39 | class UFSSwapLogParser_v1_32bs:public Fs::Ufs::UFSSwapLogParser | |
40 | { | |
41 | public: | |
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 | |
84 | class UFSSwapLogParser_v2: public Fs::Ufs::UFSSwapLogParser | |
85 | { | |
86 | public: | |
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 | ||
96 | Fs::Ufs::UFSSwapLogParser * | |
97 | Fs::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 | ||
185 | int | |
186 | Fs::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 | } |