CBDATA_CLASS_INIT(RebuildState);
-
-class UFSSwapLogParser_old:public UFSSwapLogParser
+/// Parse a swap header entry created on a system with 32-bit size_t and sfileno
+/// this is typical of 32-bit systems without large file support
+/// NP: SQUID_MD5_DIGEST_LENGTH is very risky still.
+class UFSSwapLogParser_v1_32bs:public UFSSwapLogParser
{
public:
+ /// version 1 cache swap.state entry with 32-bit size_t (swap_file_sz)
+ /// time_t an sfileno have no variation from the v1 baseline format
struct StoreSwapLogDataOld {
char op;
sfileno swap_filen;
time_t lastref;
time_t expires;
time_t lastmod;
- size_t swap_file_sz;
+ uint32_t swap_file_sz;
u_short refcount;
u_short flags;
unsigned char key[SQUID_MD5_DIGEST_LENGTH];
};
- UFSSwapLogParser_old(FILE *fp):UFSSwapLogParser(fp) {
- record_size = sizeof(UFSSwapLogParser_old::StoreSwapLogDataOld);
+ UFSSwapLogParser_v1_32bs(FILE *fp):UFSSwapLogParser(fp) {
+ record_size = sizeof(UFSSwapLogParser_v1_32bs::StoreSwapLogDataOld);
}
- bool ReadRecord(StoreSwapLogData &swapData);
-};
+ /// Convert the on-disk 32-bit format to our current format while reading
+ bool ReadRecord(StoreSwapLogData &swapData) {
+ UFSSwapLogParser_v1_32bs::StoreSwapLogDataOld readData;
+ int bytes = sizeof(UFSSwapLogParser_v1_32bs::StoreSwapLogDataOld);
+
+ assert(log);
+ if (fread(&readData, bytes, 1, log) != 1) {
+ return false;
+ }
+ swapData.op = readData.op;
+ swapData.swap_filen = readData.swap_filen;
+ swapData.timestamp = readData.timestamp;
+ swapData.lastref = readData.lastref;
+ swapData.expires = readData.expires;
+ swapData.lastmod = readData.lastmod;
+ swapData.swap_file_sz = readData.swap_file_sz;
+ swapData.refcount = readData.refcount;
+ swapData.flags = readData.flags;
+ xmemcpy(swapData.key, readData.key, SQUID_MD5_DIGEST_LENGTH);
+ return true;
+ }
+};
-bool UFSSwapLogParser_old::ReadRecord(StoreSwapLogData &swapData)
+/// Parse a swap header entry created on a system with 32-bit size_t, time_t and sfileno
+/// this is typical of 32-bit systems without large file support and with old kernels
+/// NP: SQUID_MD5_DIGEST_LENGTH is very risky still.
+class UFSSwapLogParser_v1_32bst:public UFSSwapLogParser
{
- UFSSwapLogParser_old::StoreSwapLogDataOld readData;
- int bytes = sizeof(UFSSwapLogParser_old::StoreSwapLogDataOld);
+public:
+ /// version 1 cache swap.state entry with 32-bit size_t (swap_file_sz)
+ /// time_t also differs
+ /// sfileno has no variation from the v1 baseline format
+ struct StoreSwapLogDataOld {
+ char op;
+ sfileno swap_filen;
+ int32_t timestamp;
+ int32_t lastref;
+ int32_t expires;
+ int32_t lastmod;
+ uint32_t swap_file_sz;
+ u_short refcount;
+ u_short flags;
+ unsigned char key[SQUID_MD5_DIGEST_LENGTH];
+ };
+ UFSSwapLogParser_v1_32bst(FILE *fp):UFSSwapLogParser(fp) {
+ record_size = sizeof(UFSSwapLogParser_v1_32bst::StoreSwapLogDataOld);
+ }
+ /// Convert the on-disk 32-bit format to our current format while reading
+ bool ReadRecord(StoreSwapLogData &swapData) {
+ UFSSwapLogParser_v1_32bst::StoreSwapLogDataOld readData;
+ int bytes = sizeof(UFSSwapLogParser_v1_32bst::StoreSwapLogDataOld);
- assert(log);
+ assert(log);
- if (fread(&readData, bytes, 1, log) != 1) {
- return false;
+ if (fread(&readData, bytes, 1, log) != 1) {
+ return false;
+ }
+ swapData.op = readData.op;
+ swapData.swap_filen = readData.swap_filen;
+ swapData.timestamp = readData.timestamp;
+ swapData.lastref = readData.lastref;
+ swapData.expires = readData.expires;
+ swapData.lastmod = readData.lastmod;
+ swapData.swap_file_sz = readData.swap_file_sz;
+ swapData.refcount = readData.refcount;
+ swapData.flags = readData.flags;
+ xmemcpy(swapData.key, readData.key, SQUID_MD5_DIGEST_LENGTH);
+ return true;
}
- swapData.op = readData.op;
- swapData.swap_filen = readData.swap_filen;
- swapData.timestamp = readData.timestamp;
- swapData.lastref = readData.lastref;
- swapData.expires = readData.expires;
- swapData.lastmod = readData.lastmod;
- swapData.swap_file_sz = readData.swap_file_sz;
- swapData.refcount = readData.refcount;
- swapData.flags = readData.flags;
- xmemcpy(swapData.key, readData.key, SQUID_MD5_DIGEST_LENGTH);
- return true;
-}
+};
+
+/// Parse a swap header entry created on a system with 64-bit size_t and sfileno
+/// this is typical of 64-bit systems prior to this patch fixing sfileno to 32-bits
+/// NP: SQUID_MD5_DIGEST_LENGTH is very risky still.
+class UFSSwapLogParser_v1_64bfn:public UFSSwapLogParser
+{
+public:
+ /// version 1 cache swap.state entry with 64-bit sfileno
+ struct StoreSwapLogDataOld {
+ char op;
+ int64_t swap_filen;
+ time_t timestamp;
+ time_t lastref;
+ time_t expires;
+ time_t lastmod;
+ uint64_t swap_file_sz;
+ u_short refcount;
+ u_short flags;
+ unsigned char key[SQUID_MD5_DIGEST_LENGTH];
+ };
+ UFSSwapLogParser_v1_64bfn(FILE *fp):UFSSwapLogParser(fp) {
+ record_size = sizeof(UFSSwapLogParser_v1_64bfn::StoreSwapLogDataOld);
+ }
+ /// Convert the on-disk 64-bit format to our current format while reading
+ bool ReadRecord(StoreSwapLogData &swapData) {
+ UFSSwapLogParser_v1_64bfn::StoreSwapLogDataOld readData;
+ int bytes = sizeof(UFSSwapLogParser_v1_64bfn::StoreSwapLogDataOld);
+ assert(log);
+
+ if (fread(&readData, bytes, 1, log) != 1) {
+ return false;
+ }
+ swapData.op = readData.op;
+ if ((readData.swap_filen>>32) != 0) {
+ fatalf("File ID on record is greater than maximum cache file ID.");
+ }
+ swapData.swap_filen = (int32_t)readData.swap_filen;
+ swapData.timestamp = readData.timestamp;
+ swapData.lastref = readData.lastref;
+ swapData.expires = readData.expires;
+ swapData.lastmod = readData.lastmod;
+ swapData.swap_file_sz = readData.swap_file_sz;
+ swapData.refcount = readData.refcount;
+ swapData.flags = readData.flags;
+ xmemcpy(swapData.key, readData.key, SQUID_MD5_DIGEST_LENGTH);
+ return true;
+ }
+};
class UFSSwapLogParser_v1:public UFSSwapLogParser
{
return NULL;
if (header.op != SWAP_LOG_VERSION) {
- debugs(47, 1, "Old swap file detected... ");
+ debugs(47, 1, "Old swap file detected...");
fseek(fp, 0, SEEK_SET);
- return new UFSSwapLogParser_old(fp);
+ return new UFSSwapLogParser_v1_32bs(fp); // Um. 32-bits except time_t, and can't determine that.
}
if (header.version == 1) {
if (fseek(fp, header.record_size, SEEK_SET) != 0)
return NULL;
- if (header.record_size == sizeof(struct UFSSwapLogParser_old::StoreSwapLogDataOld)) {
- debugs(47, 1, "Version 1 of swap file without LFS support detected... ");
- return new UFSSwapLogParser_old(fp);
- }
-
+ // baseline
+ // 32-bit sfileno
+ // native time_t (hopefully 64-bit)
+ // 64-bit file size
if (header.record_size == sizeof(StoreSwapLogData)) {
debugs(47, 1, "Version 1 of swap file with LFS support detected... ");
return new UFSSwapLogParser_v1(fp);
}
- debugs(47, 1, "The swap file has wrong format!... ");
+ // which means we have a 3-way grid of permutations to import (yuck!)
+ // 1) sfileno 32-bit / 64-bit (64-bit was broken)
+ // 2) time_t 32-bit / 64-bit
+ // 3) size_t 32-bit / 64-bit (32-bit was pre-LFS)
+
+ // 32-bit systems...
+ // only LFS (size_t) differs from baseline
+ if (header.record_size == sizeof(struct UFSSwapLogParser_v1_32bs::StoreSwapLogDataOld)) {
+ debugs(47, 1, "Version 1 (32-bit) swap file without LFS support detected... ");
+ return new UFSSwapLogParser_v1_32bs(fp);
+ }
+ // LFS (size_t) and timestamps (time_t) differs from baseline
+ if (header.record_size == sizeof(struct UFSSwapLogParser_v1_32bst::StoreSwapLogDataOld)) {
+ debugs(47, 1, "Version 1 (32-bit) swap file with short timestamps and without LFS support detected... ");
+ return new UFSSwapLogParser_v1_32bst(fp);
+ }
+ // No downgrade for 64-bit timestamps to 32-bit.
+
+ // 64-bit systems
+ // sfileno was 64-bit for a some builds
+ if (header.record_size == sizeof(struct UFSSwapLogParser_v1_64bfn::StoreSwapLogDataOld)) {
+ debugs(47, 1, "Version 1 (64-bit) swap file with broken sfileno detected... ");
+ return new UFSSwapLogParser_v1_64bfn(fp);
+ }
+ // NP: 64-bit system with 32-bit size_t/time_t are not handled.
+
+ debugs(47, 1, "WARNING: The swap file has wrong format!... ");
+ debugs(47, 1, "NOTE: Cannot safely downgrade caches to short (32-bit) timestamps.");
return NULL;
}
+ // XXX: version 2 of swapfile. This time use fixed-bit sizes for everything!!
+ // and preferrably write to disk in network-order bytes for the larger fields.
+
return NULL;
}