Fairport
v1.0.38
|
00001 00002 00003 00004 00005 00006 00007 00008 00009 00010 #ifndef FAIRPORT_DISK_DISK_H 00011 #define FAIRPORT_DISK_DISK_H 00012 00013 #include <cstddef> 00014 00015 #include "fairport/util/primitives.h" 00016 00018 namespace fairport 00019 { 00021 namespace disk 00022 { 00023 00028 template<typename T> 00029 struct block_reference 00030 { 00031 typedef T block_id_disk; 00032 typedef T location; 00033 00034 block_id_disk bid; 00035 location ib; 00036 } FAIRPORT_MS_STRUCT; 00038 static_assert(sizeof(block_reference<ulong>) == 8, "block_reference<ulong> incorrect size"); 00039 static_assert(sizeof(block_reference<ulonglong>) == 16, "block_reference<ulonglong> incorrect size"); 00041 00042 // 00043 // header 00044 // 00045 00048 00052 const size_t header_fmap_entries = 128; 00053 00057 const size_t header_fpmap_size = 128; 00058 00062 const size_t header_lock_entries = 32; 00063 00067 enum database_format 00068 { 00069 database_format_ansi_min = 14, 00070 database_format_ansi = 15, 00071 database_format_unicode_min = 20, 00072 database_format_unicode = 23 00073 }; 00074 00078 enum database_type 00079 { 00080 database_ost = 12, 00081 database_pst = 19 00082 }; 00083 00086 const ushort pst_magic = 0x4D53; 00089 const ushort ost_magic = 0x4F53; 00090 00096 enum crypt_method 00097 { 00098 crypt_method_none = 0, 00099 crypt_method_permute = 1, 00100 crypt_method_cyclic = 2 00101 }; 00102 00111 template<typename T> 00112 struct root 00113 { 00114 typedef T location; 00115 typedef T count; 00116 00117 ulong cOrphans; 00118 location ibFileEof; 00119 location ibAMapLast; 00120 count cbAMapFree; 00121 count cbPMapFree; 00122 block_reference<T> brefNBT; 00123 block_reference<T> brefBBT; 00124 byte fAMapValid; 00125 byte bARVec; 00126 ushort cARVec; 00127 } FAIRPORT_MS_STRUCT; 00129 static_assert(sizeof(root<ulong>) == 40, "root<ulong> incorrect size"); 00130 static_assert(sizeof(root<ulonglong>) == 80, "root<ulonglong> incorrect size"); 00131 static_assert(offsetof(root<ulonglong>, cOrphans) == 0, "root<ulonglong> cOrphans at incorrect offset"); 00132 static_assert(offsetof(root<ulonglong>, ibFileEof) == 8, "root<ulonglong> ibFileEof at incorrect offset"); 00133 static_assert(offsetof(root<ulonglong>, ibAMapLast) == 16, "root<ulonglong> ibAMapLast at incorrect offset"); 00134 static_assert(offsetof(root<ulonglong>, cbAMapFree) == 24, "root<ulonglong> cbAMapFree at incorrect offset"); 00135 static_assert(offsetof(root<ulonglong>, cbPMapFree) == 32, "root<ulonglong> cbPMapFree at incorrect offset"); 00136 static_assert(offsetof(root<ulonglong>, brefNBT) == 40, "root<ulonglong> brefNBT at incorrect offset"); 00137 static_assert(offsetof(root<ulonglong>, brefBBT) == 56, "root<ulonglong> brefBBT at incorrect offset"); 00138 static_assert(offsetof(root<ulonglong>, fAMapValid) == 72, "root<ulonglong> fAMapValid at incorrect offset"); 00139 static_assert(offsetof(root<ulonglong>, bARVec) == 73, "root<ulonglong> bARVec at incorrect offset"); 00140 static_assert(offsetof(root<ulonglong>, cARVec) == 74, "root<ulonglong> cARVec at incorrect offset"); 00142 00148 const uint hlmagic = 0x4e444221; 00149 00151 template<typename T> 00152 struct header 00153 { 00154 } FAIRPORT_MS_STRUCT; 00156 00164 template<> 00165 struct header<ulonglong> 00166 { 00167 typedef ulonglong block_id_disk; 00168 typedef ulonglong location; 00169 typedef ulonglong count; 00170 00171 ulong dwMagic; 00172 ulong dwCRCPartial; 00173 ushort wMagicClient; 00174 ushort wVer; 00175 ushort wVerClient; 00176 byte bPlatformCreate; 00177 byte bPlatformAccess; 00178 ulong dwOpenDBID; 00179 ulong dwOpenClaimID; 00180 block_id_disk bidUnused; 00181 block_id_disk bidNextP; 00182 ulong dwUnique; 00183 node_id rgnid[nid_type_max]; 00184 root<ulonglong> root_info; 00185 byte rgbFM[header_fmap_entries]; 00186 byte rgbFP[header_fpmap_size]; 00187 byte bSentinel; 00188 byte bCryptMethod; 00189 byte rgbReserved[2]; 00190 #ifdef __GNUC__ 00191 // GCC refuses to pack this next to rgbReserved 00192 byte bidNextB[8]; 00193 #else 00194 #pragma pack(4) 00195 block_id_disk bidNextB; 00196 #pragma pack() 00197 #endif 00198 ulong dwCRCFull; 00199 byte rgbVersionEncoded[3]; 00200 byte bLockSemaphore; 00201 byte rgbLock[header_lock_entries]; 00202 } FAIRPORT_MS_STRUCT; 00204 static_assert(sizeof(header<ulonglong>) == 568, "header<ulonglong> incorrect size"); 00205 static_assert(offsetof(header<ulonglong>, rgnid) == 44, "header<ulonglong> rgnid at incorrect offset"); 00206 static_assert(offsetof(header<ulonglong>, root_info) == 176, "header<ulonglong> root_info at incorrect offset"); 00207 static_assert(offsetof(header<ulonglong>, rgbFM) == 256, "header<ulonglong> rgbFM at incorrect offset"); 00208 static_assert(offsetof(header<ulonglong>, dwCRCFull) == 524, "header<ulonglong> dwCRCFull at incorrect offset"); 00210 00217 template<> 00218 struct header<ulong> 00219 { 00220 typedef ulong block_id_disk; 00221 typedef ulong location; 00222 typedef ulong count; 00223 00224 ulong dwMagic; 00225 ulong dwCRCPartial; 00226 ushort wMagicClient; 00227 ushort wVer; 00228 ushort wVerClient; 00229 byte bPlatformCreate; 00230 byte bPlatformAccess; 00231 ulong dwOpenDBID; 00232 ulong dwOpenClaimID; 00233 #ifdef __GNUC__ 00234 byte bidNextB[4]; 00235 #else 00236 block_id_disk bidNextB; 00237 #endif 00238 block_id_disk bidNextP; 00239 ulong dwUnique; 00240 node_id rgnid[nid_type_max]; 00241 root<ulong> root_info; 00242 byte rgbFM[header_fmap_entries]; 00243 byte rgbFP[header_fpmap_size]; 00244 byte bSentinel; 00245 byte bCryptMethod; 00246 byte rgbReserved[2]; 00247 ulonglong ullReserved; 00248 ulong dwReserved; 00249 byte rgbVersionEncoded[3]; 00250 byte bLockSemaphore; 00251 byte rgbLock[header_lock_entries]; 00252 } FAIRPORT_MS_STRUCT; 00254 static_assert(sizeof(header<ulong>) == 512, "header<ulong> incorrect size"); 00255 static_assert(offsetof(header<ulong>, rgnid) == 36, "header<ulong> rgnid at incorrect offset"); 00256 static_assert(offsetof(header<ulong>, rgbFM) == 204, "header<ulong> rgbFM at incorrect offset"); 00258 00260 template<typename T> 00261 struct header_crc_locations 00262 { 00263 } FAIRPORT_MS_STRUCT; 00265 00269 template<> 00270 struct header_crc_locations<ulong> 00271 { 00272 static const size_t start = offsetof(header<ulong>, wMagicClient); 00273 static const size_t end = offsetof(header<ulong>, bLockSemaphore); 00274 static const size_t length = end - start; 00275 } FAIRPORT_MS_STRUCT; 00276 00281 template<> 00282 struct header_crc_locations<ulonglong> 00283 { 00284 static const size_t partial_start = header_crc_locations<ulong>::start; 00285 static const size_t partial_end = header_crc_locations<ulong>::end; 00286 static const size_t partial_length = header_crc_locations<ulong>::length; 00287 static const size_t full_start = offsetof(header<ulonglong>, wMagicClient); 00288 static const size_t full_end = offsetof(header<ulonglong>, dwCRCFull); 00289 static const size_t full_length = full_end - full_start; 00290 } FAIRPORT_MS_STRUCT; 00291 00292 // 00293 // utility functions 00294 // 00295 00298 00301 const ulong crc_table[] = { 00302 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F, 00303 0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, 00304 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2, 00305 0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, 00306 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9, 00307 0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, 00308 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C, 00309 0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, 00310 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423, 00311 0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, 00312 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106, 00313 0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, 00314 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D, 00315 0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, 00316 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950, 00317 0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, 00318 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7, 00319 0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, 00320 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA, 00321 0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, 00322 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81, 00323 0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, 00324 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84, 00325 0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, 00326 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB, 00327 0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, 00328 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E, 00329 0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, 00330 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55, 00331 0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, 00332 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28, 00333 0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, 00334 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F, 00335 0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, 00336 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242, 00337 0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, 00338 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69, 00339 0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, 00340 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC, 00341 0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, 00342 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693, 00343 0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, 00344 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D 00345 }; 00346 00350 const byte table1[] = 00351 { 00352 65, 54, 19, 98, 168, 33, 110, 187, 00353 244, 22, 204, 4, 127, 100, 232, 93, 00354 30, 242, 203, 42, 116, 197, 94, 53, 00355 210, 149, 71, 158, 150, 45, 154, 136, 00356 76, 125, 132, 63, 219, 172, 49, 182, 00357 72, 95, 246, 196, 216, 57, 139, 231, 00358 35, 59, 56, 142, 200, 193, 223, 37, 00359 177, 32, 165, 70, 96, 78, 156, 251, 00360 170, 211, 86, 81, 69, 124, 85, 0, 00361 7, 201, 43, 157, 133, 155, 9, 160, 00362 143, 173, 179, 15, 99, 171, 137, 75, 00363 215, 167, 21, 90, 113, 102, 66, 191, 00364 38, 74, 107, 152, 250, 234, 119, 83, 00365 178, 112, 5, 44, 253, 89, 58, 134, 00366 126, 206, 6, 235, 130, 120, 87, 199, 00367 141, 67, 175, 180, 28, 212, 91, 205, 00368 226, 233, 39, 79, 195, 8, 114, 128, 00369 207, 176, 239, 245, 40, 109, 190, 48, 00370 77, 52, 146, 213, 14, 60, 34, 50, 00371 229, 228, 249, 159, 194, 209, 10, 129, 00372 18, 225, 238, 145, 131, 118, 227, 151, 00373 230, 97, 138, 23, 121, 164, 183, 220, 00374 144, 122, 92, 140, 2, 166, 202, 105, 00375 222, 80, 26, 17, 147, 185, 82, 135, 00376 88, 252, 237, 29, 55, 73, 27, 106, 00377 224, 41, 51, 153, 189, 108, 217, 148, 00378 243, 64, 84, 111, 240, 198, 115, 184, 00379 214, 62, 101, 24, 68, 31, 221, 103, 00380 16, 241, 12, 25, 236, 174, 3, 161, 00381 20, 123, 169, 11, 255, 248, 163, 192, 00382 162, 1, 247, 46, 188, 36, 104, 117, 00383 13, 254, 186, 47, 181, 208, 218, 61, 00384 }; 00385 00389 const byte table2[] = 00390 { 00391 20, 83, 15, 86, 179, 200, 122, 156, 00392 235, 101, 72, 23, 22, 21, 159, 2, 00393 204, 84, 124, 131, 0, 13, 12, 11, 00394 162, 98, 168, 118, 219, 217, 237, 199, 00395 197, 164, 220, 172, 133, 116, 214, 208, 00396 167, 155, 174, 154, 150, 113, 102, 195, 00397 99, 153, 184, 221, 115, 146, 142, 132, 00398 125, 165, 94, 209, 93, 147, 177, 87, 00399 81, 80, 128, 137, 82, 148, 79, 78, 00400 10, 107, 188, 141, 127, 110, 71, 70, 00401 65, 64, 68, 1, 17, 203, 3, 63, 00402 247, 244, 225, 169, 143, 60, 58, 249, 00403 251, 240, 25, 48, 130, 9, 46, 201, 00404 157, 160, 134, 73, 238, 111, 77, 109, 00405 196, 45, 129, 52, 37, 135, 27, 136, 00406 170, 252, 6, 161, 18, 56, 253, 76, 00407 66, 114, 100, 19, 55, 36, 106, 117, 00408 119, 67, 255, 230, 180, 75, 54, 92, 00409 228, 216, 53, 61, 69, 185, 44, 236, 00410 183, 49, 43, 41, 7, 104, 163, 14, 00411 105, 123, 24, 158, 33, 57, 190, 40, 00412 26, 91, 120, 245, 35, 202, 42, 176, 00413 175, 62, 254, 4, 140, 231, 229, 152, 00414 50, 149, 211, 246, 74, 232, 166, 234, 00415 233, 243, 213, 47, 112, 32, 242, 31, 00416 5, 103, 173, 85, 16, 206, 205, 227, 00417 39, 59, 218, 186, 215, 194, 38, 212, 00418 145, 29, 210, 28, 34, 51, 248, 250, 00419 241, 90, 239, 207, 144, 182, 139, 181, 00420 189, 192, 191, 8, 151, 30, 108, 226, 00421 97, 224, 198, 193, 89, 171, 187, 88, 00422 222, 95, 223, 96, 121, 126, 178, 138, 00423 }; 00424 00428 const byte table3[] = 00429 { 00430 71, 241, 180, 230, 11, 106, 114, 72, 00431 133, 78, 158, 235, 226, 248, 148, 83, 00432 224, 187, 160, 2, 232, 90, 9, 171, 00433 219, 227, 186, 198, 124, 195, 16, 221, 00434 57, 5, 150, 48, 245, 55, 96, 130, 00435 140, 201, 19, 74, 107, 29, 243, 251, 00436 143, 38, 151, 202, 145, 23, 1, 196, 00437 50, 45, 110, 49, 149, 255, 217, 35, 00438 209, 0, 94, 121, 220, 68, 59, 26, 00439 40, 197, 97, 87, 32, 144, 61, 131, 00440 185, 67, 190, 103, 210, 70, 66, 118, 00441 192, 109, 91, 126, 178, 15, 22, 41, 00442 60, 169, 3, 84, 13, 218, 93, 223, 00443 246, 183, 199, 98, 205, 141, 6, 211, 00444 105, 92, 134, 214, 20, 247, 165, 102, 00445 117, 172, 177, 233, 69, 33, 112, 12, 00446 135, 159, 116, 164, 34, 76, 111, 191, 00447 31, 86, 170, 46, 179, 120, 51, 80, 00448 176, 163, 146, 188, 207, 25, 28, 167, 00449 99, 203, 30, 77, 62, 75, 27, 155, 00450 79, 231, 240, 238, 173, 58, 181, 89, 00451 4, 234, 64, 85, 37, 81, 229, 122, 00452 137, 56, 104, 82, 123, 252, 39, 174, 00453 215, 189, 250, 7, 244, 204, 142, 95, 00454 239, 53, 156, 132, 43, 21, 213, 119, 00455 52, 73, 182, 18, 10, 127, 113, 136, 00456 253, 157, 24, 65, 125, 147, 216, 88, 00457 44, 206, 254, 36, 175, 222, 184, 54, 00458 200, 161, 128, 166, 153, 152, 168, 47, 00459 14, 129, 101, 115, 228, 194, 162, 138, 00460 212, 225, 17, 208, 8, 139, 42, 242, 00461 237, 154, 100, 63, 193, 108, 249, 236 00462 }; 00463 00471 template<typename T> 00472 ushort compute_signature(T id, T address); 00473 00480 template<typename T> 00481 ushort compute_signature(const block_reference<T>& reference) { return compute_signature(reference.bid, reference.ib); } 00482 00489 ulong compute_crc(const void * pdata, ulong cb); 00490 00500 void permute(void * pdata, ulong cb, bool encrypt); 00501 00511 void cyclic(void * pdata, ulong cb, ulong key); 00512 00513 00514 // 00515 // page structures 00516 // 00517 00520 00521 00525 const size_t page_size = 512; 00526 00532 enum page_type 00533 { 00534 page_type_bbt = 0x80, 00535 page_type_nbt = 0x81, 00536 page_type_fmap = 0x82, 00537 page_type_pmap = 0x83, 00538 page_type_amap = 0x84, 00539 page_type_fpmap = 0x85, 00540 page_type_dlist = 0x86 00541 }; 00542 00544 template<typename T> 00545 struct page_trailer 00546 { 00547 } FAIRPORT_MS_STRUCT; 00549 00555 template<> 00556 struct page_trailer<ulonglong> 00557 { 00558 typedef ulonglong block_id_disk; 00559 00560 byte page_type; 00561 byte page_type_repeat; 00562 ushort signature; 00563 ulong crc; 00564 block_id_disk bid; 00565 } FAIRPORT_MS_STRUCT; 00567 static_assert(sizeof(page_trailer<ulonglong>) == 16, "page_trailer<ulonglong> incorrect size"); 00569 00576 template<> 00577 struct page_trailer<ulong> 00578 { 00579 typedef ulong block_id_disk; 00580 00581 byte page_type; 00582 byte page_type_repeat; 00583 ushort signature; 00584 block_id_disk bid; 00585 ulong crc; 00586 } FAIRPORT_MS_STRUCT; 00588 static_assert(sizeof(page_trailer<ulong>) == 12, "page_trailer<ulong> incorrect size"); 00590 00595 template<typename T> 00596 struct page 00597 { 00598 static const size_t page_data_size = page_size - sizeof(page_trailer<T>); 00599 00600 byte data[page_data_size]; 00601 page_trailer<T> trailer; 00602 } FAIRPORT_MS_STRUCT; 00604 static_assert(sizeof(page<ulong>) == page_size, "page<ulong> incorrect size"); 00605 static_assert(sizeof(page<ulonglong>) == page_size, "page<ulonglong> incorrect size"); 00607 00611 const size_t bytes_per_slot = 64; 00612 00616 const size_t first_amap_page_location = 0x4400; 00617 00629 template<typename T> 00630 struct amap_page : public page<T> 00631 { 00632 } FAIRPORT_MS_STRUCT; 00634 static_assert(sizeof(amap_page<ulong>) == page_size, "amap_page<ulong> incorrect size"); 00635 static_assert(sizeof(amap_page<ulonglong>) == page_size, "amap_page<ulonglong> incorrect size"); 00637 00648 template<typename T> 00649 struct pmap_page : public page<T> 00650 { 00651 } FAIRPORT_MS_STRUCT; 00653 static_assert(sizeof(pmap_page<ulong>) == page_size, "pmap_page<ulong> incorrect size"); 00654 static_assert(sizeof(pmap_page<ulonglong>) == page_size, "pmap_page<ulonglong> incorrect size"); 00656 00666 template<typename T> 00667 struct fmap_page : public page<T> 00668 { 00669 } FAIRPORT_MS_STRUCT; 00671 static_assert(sizeof(fmap_page<ulong>) == page_size, "fmap_page<ulong> incorrect size"); 00672 static_assert(sizeof(fmap_page<ulonglong>) == page_size, "fmap_page<ulonglong> incorrect size"); 00674 00688 template<typename T> 00689 struct fpmap_page : public page<T> 00690 { 00691 } FAIRPORT_MS_STRUCT; 00693 static_assert(sizeof(fpmap_page<ulong>) == page_size, "fpmap_page<ulong> incorrect size"); 00694 static_assert(sizeof(fpmap_page<ulonglong>) == page_size, "fpmap_page<ulonglong> incorrect size"); 00696 00700 const size_t dlist_page_location = 0x4200; 00701 00711 template<typename T> 00712 struct dlist_page 00713 { 00714 static const size_t extra_space = page<T>::page_data_size - 8; 00715 static const size_t max_entries = extra_space / sizeof(ulong); 00716 00717 byte flags; 00718 byte num_entries; 00719 union 00720 { 00721 ulong current_page; 00722 ulong backfill_location; 00723 }; 00724 union 00725 { 00726 ulong entries[max_entries]; 00727 byte _ignore[extra_space]; 00728 }; 00729 page_trailer<T> trailer; 00730 } FAIRPORT_MS_STRUCT; 00732 static_assert(sizeof(dlist_page<ulong>) == page_size, "dlist_page<ulong> incorrect size"); 00733 static_assert(sizeof(dlist_page<ulonglong>) == page_size, "dlist_page<ulonglong> incorrect size"); 00735 00739 const ulong dlist_page_num_mask = 0x0000FFFF; 00740 00744 const ulong dlist_slots_shift = 20; 00745 00750 inline ulong dlist_get_page_num(ulong entry) { return entry & dlist_page_num_mask; } 00751 00756 inline ulong dlist_get_slots(ulong entry) { return entry >> dlist_slots_shift; } 00757 00764 template<typename T> 00765 struct bt_entry 00766 { 00767 typedef T bt_key; 00768 00769 bt_key key; 00770 block_reference<T> ref; 00771 } FAIRPORT_MS_STRUCT; 00773 static_assert(sizeof(bt_entry<ulong>) == 12, "bt_entry<ulong> incorrect size"); 00774 static_assert(sizeof(bt_entry<ulonglong>) == 24, "bt_entry<ulonglong> incorrect size"); 00776 00783 template<typename T> 00784 struct nbt_leaf_entry 00785 { 00786 typedef T nid_index; 00787 typedef T block_id_disk; 00788 00789 nid_index nid; 00790 block_id_disk data; 00791 block_id_disk sub; 00792 node_id parent_nid; 00793 } FAIRPORT_MS_STRUCT; 00795 static_assert(sizeof(nbt_leaf_entry<ulong>) == 16, "nbt_leaf_entry<ulong> incorrect size"); 00796 static_assert(sizeof(nbt_leaf_entry<ulonglong>) == 32, "nbt_leaf_entry<ulonglong> incorrect size"); 00798 00805 template<typename T> 00806 struct bbt_leaf_entry 00807 { 00808 block_reference<T> ref; 00809 ushort size; 00810 ushort ref_count; 00811 } FAIRPORT_MS_STRUCT; 00813 static_assert(sizeof(bbt_leaf_entry<ulong>) == 12, "bbt_leaf_entry<ulong> incorrect size"); 00814 static_assert(sizeof(bbt_leaf_entry<ulonglong>) == 24, "bbt_leaf_entry<ulonglong> incorrect size"); 00816 00827 template<typename T, typename EntryType> 00828 struct bt_page 00829 { 00830 static const size_t extra_space = page<T>::page_data_size - sizeof(T); 00831 static const size_t max_entries = extra_space / sizeof(EntryType); 00832 union 00833 { 00834 EntryType entries[max_entries]; 00835 byte _ignore[extra_space]; 00836 }; 00837 00838 byte num_entries; 00839 byte num_entries_max; 00840 byte entry_size; 00841 byte level; 00842 00843 page_trailer<T> trailer; 00844 } FAIRPORT_MS_STRUCT; 00846 namespace detail { 00847 // We can't pass types containing "," to offsetof, because it's a 00848 // preprocessor macro, and it doesn't really understand how to parse an 00849 // argument list. So we declare some aliases in a "detail" namespace 00850 // where they won't pollute the header. 00851 typedef bt_page<ulong, bt_entry<ulong> > bt_page_ulong; 00852 typedef bt_page<ulonglong, bt_entry<ulonglong> > bt_page_ulonglong; 00853 } 00854 static_assert(offsetof(detail::bt_page_ulong, num_entries) == 496, "bt_page<ulong, bt_entry<ulong> > num_entries at incorrect offset"); 00855 static_assert(offsetof(detail::bt_page_ulonglong, num_entries) == 488, "bt_page<ulonglong, bt_entry<ulonglong> > num_entries at incorrect offset"); 00856 static_assert(offsetof(detail::bt_page_ulong, trailer) == 500, "bt_page<ulong, bt_entry<ulong> > trailer at incorrect offset"); 00857 static_assert(offsetof(detail::bt_page_ulonglong, trailer) == 496, "bt_page<ulonglong, bt_entry<ulonglong> > trailer at incorrect offset"); 00859 00866 template<typename T> 00867 struct nbt_nonleaf_page : public bt_page<T, bt_entry<T> > 00868 { 00869 } FAIRPORT_MS_STRUCT; 00871 static_assert(sizeof(nbt_nonleaf_page<ulong>) == page_size, "nbt_nonleaf_page<ulong> incorrect size"); 00872 static_assert(sizeof(nbt_nonleaf_page<ulonglong>) == page_size, "nbt_nonleaf_page<ulonglong> incorrect size"); 00874 00882 template<typename T> 00883 struct bbt_nonleaf_page : public bt_page<T, bt_entry<T> > 00884 { 00885 } FAIRPORT_MS_STRUCT; 00887 static_assert(sizeof(bbt_nonleaf_page<ulong>) == page_size, "bbt_nonleaf_page<ulong> incorrect size"); 00888 static_assert(sizeof(bbt_nonleaf_page<ulonglong>) == page_size, "bbt_nonleaf_page<ulonglong> incorrect size"); 00890 00898 template<typename T> 00899 struct nbt_leaf_page : public bt_page<T, nbt_leaf_entry<T> > 00900 { 00901 } FAIRPORT_MS_STRUCT; 00903 static_assert(sizeof(nbt_leaf_page<ulong>) == page_size, "nbt_leaf_page<ulong> incorrect size"); 00904 static_assert(sizeof(nbt_leaf_page<ulonglong>) == page_size, "nbt_leaf_page<ulonglong> incorrect size"); 00906 00914 template<typename T> 00915 struct bbt_leaf_page : public bt_page<T, bbt_leaf_entry<T> > 00916 { 00917 } FAIRPORT_MS_STRUCT; 00919 static_assert(sizeof(bbt_leaf_page<ulong>) == page_size, "bbt_leaf_page<ulong> incorrect size"); 00920 static_assert(sizeof(bbt_leaf_page<ulonglong>) == page_size, "bbt_leaf_page<ulonglong> incorrect size"); 00922 00923 // 00924 // block structures 00925 // 00926 00929 00933 const size_t max_block_disk_size = 8 * 1024; 00934 00938 enum block_types 00939 { 00940 block_type_external = 0x00, 00941 block_type_extended = 0x01, 00942 block_type_sub = 0x02 00943 }; 00944 00953 template<typename T> 00954 size_t align_disk(size_t size); 00955 00963 size_t align_slot(size_t size); 00964 00968 const uint block_id_attached_bit = 0x1; 00969 00973 const uint block_id_internal_bit = 0x2; 00974 00978 const uint block_id_increment = 0x4; 00979 00986 template<typename T> 00987 bool bid_is_external(T bid) { return ((bid & block_id_internal_bit) == 0); } 00988 00995 template<typename T> 00996 bool bid_is_internal(T bid) { return !bid_is_external(bid); } 00997 00999 template<typename T> 01000 struct block_trailer 01001 { 01002 } FAIRPORT_MS_STRUCT; 01004 01014 template<> 01015 struct block_trailer<ulonglong> 01016 { 01017 typedef ulonglong block_id_disk; 01018 01019 ushort cb; 01020 ushort signature; 01021 ulong crc; 01022 block_id_disk bid; 01023 } FAIRPORT_MS_STRUCT; 01025 static_assert(sizeof(block_trailer<ulonglong>) == 16, "block_trailer<ulonglong> incorrect size"); 01027 01035 template<> 01036 struct block_trailer<ulong> 01037 { 01038 typedef ulong block_id_disk; 01039 01040 ushort cb; 01041 ushort signature; 01042 block_id_disk bid; 01043 ulong crc; 01044 } FAIRPORT_MS_STRUCT; 01046 static_assert(sizeof(block_trailer<ulong>) == 12, "block_trailer<ulong> incorrect size"); 01048 01057 template<typename T> 01058 struct external_block 01059 { 01060 static const size_t max_size = max_block_disk_size - sizeof(block_trailer<T>); 01061 byte data[1]; 01062 } FAIRPORT_MS_STRUCT; 01063 01065 template<typename T> 01066 struct extended_block 01067 { 01068 } FAIRPORT_MS_STRUCT; 01070 01082 template<> 01083 struct extended_block<ulonglong> 01084 { 01085 typedef ulonglong block_id_disk; 01086 01087 static const size_t max_count = (external_block<ulonglong>::max_size - 8) / sizeof(extended_block<ulonglong>::block_id_disk); 01088 static const size_t max_size = external_block<ulonglong>::max_size * extended_block<ulonglong>::max_count; 01089 01090 byte block_type; 01091 byte level; 01092 ushort count; 01093 ulong total_size; 01094 block_id_disk bid[1]; 01095 } FAIRPORT_MS_STRUCT; 01096 01104 template<> 01105 struct extended_block<ulong> 01106 { 01107 typedef ulong block_id_disk; 01108 01109 static const size_t max_count = ((4096L) - sizeof(block_trailer<ulong>) - 8) / sizeof(extended_block<ulong>::block_id_disk); 01110 static const size_t max_size = external_block<ulong>::max_size * extended_block<ulong>::max_count; 01111 01112 byte block_type; 01113 byte level; 01114 ushort count; 01115 ulong total_size; 01116 block_id_disk bid[1]; 01117 } FAIRPORT_MS_STRUCT; 01118 01126 template<typename T> 01127 struct sub_leaf_entry 01128 { 01129 typedef T block_id_disk; 01130 01131 node_id nid; 01132 block_id_disk data; 01133 block_id_disk sub; 01134 } FAIRPORT_MS_STRUCT; 01136 static_assert(sizeof(sub_leaf_entry<ulong>) == 12, "sub_leaf_entry<ulong> incorrect size"); 01137 static_assert(sizeof(sub_leaf_entry<ulonglong>) == 24, "sub_leaf_entry<ulonglong> incorrect size"); 01139 01147 template<typename T> 01148 struct sub_nonleaf_entry 01149 { 01150 typedef T block_id_disk; 01151 01152 node_id nid_key; 01153 block_id_disk sub_block_bid; 01154 } FAIRPORT_MS_STRUCT; 01156 static_assert(sizeof(sub_nonleaf_entry<ulong>) == 8, "sub_nonleaf_entry<ulong> incorrect size"); 01157 static_assert(sizeof(sub_nonleaf_entry<ulonglong>) == 16, "sub_nonleaf_entry<ulonglong> incorrect size"); 01159 01169 template<typename T, typename EntryType> 01170 struct sub_block 01171 { 01172 byte block_type; 01173 byte level; 01174 ushort count; 01175 EntryType entry[1]; 01176 } FAIRPORT_MS_STRUCT; 01177 01185 template<typename T> 01186 struct sub_nonleaf_block : public sub_block<T, sub_nonleaf_entry<T> > 01187 { 01188 } FAIRPORT_MS_STRUCT; 01189 01197 template<typename T> 01198 struct sub_leaf_block : public sub_block<T, sub_leaf_entry<T> > 01199 { 01200 } FAIRPORT_MS_STRUCT; 01201 01202 // 01203 // heap structures 01204 // 01205 01208 01212 const byte heap_signature = 0xEC; 01213 01216 const uint heap_max_alloc_size = 3580; 01217 01220 const uint heap_max_alloc_size_wver_14 = 3068; 01221 01225 enum heap_client_signature 01226 { 01227 heap_sig_gmp = 0x6C, //< Internal 01228 heap_sig_tc = 0x7C, //< Table context 01229 heap_sig_smp = 0x8C, //< Internal 01230 heap_sig_hmp = 0x9C, //< Internal 01231 heap_sig_ch = 0xA5, //< \deprecated Internal 01232 heap_sig_chtc = 0xAC, //< \deprecated Internal 01233 heap_sig_bth = 0xB5, //< BTree on Heap 01234 heap_sig_pc = 0xBC //< Property Context 01235 }; 01236 01239 enum heap_fill_level 01240 { 01241 heap_fill_empty, //< >= 3584 bytes free 01242 heap_fill_1, //< 2560 - 3583 bytes free 01243 heap_fill_2, //< 2048 - 2559 bytes free 01244 heap_fill_3, //< 1792 - 2047 bytes free 01245 heap_fill_4, //< 1536 - 1791 bytes free 01246 heap_fill_5, //< 1280 - 1535 bytes free 01247 heap_fill_6, //< 1024 - 1279 bytes free 01248 heap_fill_7, //< 768 - 1023 bytes free 01249 heap_fill_8, //< 512 - 767 bytes free 01250 heap_fill_9, //< 256 - 511 bytes free 01251 heap_fill_10, //< 128 - 255 bytes free 01252 heap_fill_11, //< 64 - 127 bytes free 01253 heap_fill_12, //< 32 - 63 bytes free 01254 heap_fill_13, //< 16 - 31 bytes free 01255 heap_fill_14, //< 8 - 15 bytes free 01256 heap_fill_full //< < 8 bytes free 01257 }; 01258 01262 struct heap_first_header 01263 { 01264 static const uint fill_level_size = 4; 01265 01266 ushort page_map_offset; 01267 byte signature; 01268 byte client_signature; 01269 heap_id root_id; 01270 byte page_fill_levels[fill_level_size]; 01271 } FAIRPORT_MS_STRUCT; 01272 01276 struct heap_page_header 01277 { 01278 ushort page_map_offset; 01279 } FAIRPORT_MS_STRUCT; 01280 01284 struct heap_page_fill_header 01285 { 01286 static const uint fill_level_size = 64; 01287 01288 ushort page_map_offset; 01289 byte page_fill_levels[fill_level_size]; 01290 } FAIRPORT_MS_STRUCT; 01291 01305 struct heap_page_map 01306 { 01307 ushort num_allocs; 01308 ushort num_frees; 01309 ushort allocs[1]; 01310 } FAIRPORT_MS_STRUCT; 01311 01312 // 01313 // bth structures 01314 // 01315 01318 01323 struct bth_header 01324 { 01325 byte bth_signature; 01326 byte key_size; 01327 byte entry_size; 01328 byte num_levels; 01329 heap_id root; 01330 } FAIRPORT_MS_STRUCT; 01331 01340 #pragma pack(2) 01341 template<typename K> 01342 struct bth_nonleaf_entry 01343 { 01344 K key; 01345 heap_id page FAIRPORT_PACK_2; 01346 }; 01347 #pragma pack() 01348 01349 static_assert(sizeof(bth_nonleaf_entry<ushort>) == 6, "bth_nonleaf_entry<ushort> incorrect size"); 01350 static_assert(offsetof(bth_nonleaf_entry<ushort>, key) == 0, "bth_nonleaf_entry<ushort> key at incorrect offset"); 01351 static_assert(offsetof(bth_nonleaf_entry<ushort>, page) == 2, "bth_nonleaf_entry<ushort> page at incorrect offset"); 01353 01361 template<typename K, typename V> 01362 struct bth_leaf_entry 01363 { 01364 K key; 01365 V value; 01366 } FAIRPORT_MS_STRUCT; 01367 01380 template<typename EntryType> 01381 struct bth_node 01382 { 01383 EntryType entries[1]; 01384 } FAIRPORT_MS_STRUCT; 01385 01393 template<typename K, typename V> 01394 struct bth_leaf_node : bth_node<bth_leaf_entry<K,V> > 01395 { 01396 } FAIRPORT_MS_STRUCT; 01397 01405 template<typename K> 01406 struct bth_nonleaf_node : bth_node<bth_nonleaf_entry<K> > 01407 { 01408 } FAIRPORT_MS_STRUCT; 01409 01410 // 01411 // pc structures 01412 // 01413 01416 01424 #pragma pack(2) 01425 struct prop_entry 01426 { 01427 ushort type; //$< Property type 01428 heapnode_id id; //$< Heapnode id for variable length properties, or the value directly for fixed size property types 01429 }; 01430 #pragma pack() 01431 01432 static_assert(sizeof(bth_leaf_entry<ushort, prop_entry>) == 8, "bth_leaf_entry<ushort, prop_entry> incorrect size"); 01434 01440 struct sub_object 01441 { 01442 node_id nid; //$< The subnode id containing the data for the object 01443 ulong size; //$< The size of the object 01444 } FAIRPORT_MS_STRUCT; 01445 01453 struct mv_toc 01454 { 01455 ulong count; //$< Number of entries in the TOC 01456 ulong offsets[1]; //$< Array of offsets for the start of each entry 01457 } FAIRPORT_MS_STRUCT; 01458 01459 // 01460 // tc structures 01461 // 01462 01465 01469 enum tc_offsets 01470 { 01471 tc_offsets_four, //$< Offset of the end of the four and eight byte columns 01472 tc_offsets_two, //$< Offset of the end of the two byte columns 01473 tc_offsets_one, //$< Offset of the end of the one byte columns 01474 tc_offsets_bitmap, //$< Offset of the end of the existance bitmap 01475 tc_offsets_max //$< Number of entries in the offset array 01476 }; 01477 01481 #pragma pack(2) 01482 struct column_description 01483 { 01484 ushort type; //$< Column property type 01485 prop_id id; //$< Column property id 01486 ushort offset; //$< Offset into the row 01487 byte size; //$< Width of the column 01488 byte bit_offset; //$< Bit offset into the existance bitmap 01489 }; 01490 01497 struct gust_column_description 01498 { 01499 ushort type; 01500 prop_id id; 01501 ushort offset; 01502 byte size; 01503 byte unused1; 01504 ushort bit_offset; 01505 ushort unused2; 01506 node_id data_subnode; 01507 }; 01508 01512 struct tc_header 01513 { 01514 byte signature; //$< TC signature, \ref heap_sig_tc 01515 byte num_columns; //$< Number of columns in this table 01516 ushort size_offsets[tc_offsets_max]; // Row offset array, see \ref tc_offsets 01517 heap_id row_btree_id; //$< The bth_header allocation for the row mapping btree 01518 heapnode_id row_matrix_id; //$< The heapnode_id allocation for the row matrix 01519 byte unused[4]; 01520 column_description columns[1]; //$< Column description array, of length num_columns 01521 }; 01522 01526 struct gust_header 01527 { 01528 byte signature; 01529 byte unused1; 01530 ushort size_offsets[tc_offsets_max]; 01531 heap_id row_btree_id; 01532 heapnode_id row_matrix_id; 01533 byte unused2[4]; 01534 ushort num_columns; 01535 node_id column_subnode; 01536 ulong unused3; 01537 ulong unused4; 01538 }; 01539 #pragma pack() 01540 01541 // 01542 // nameid structures 01543 // 01544 01547 01554 struct nameid 01555 { 01556 union 01557 { 01558 ulong id; 01559 ulong string_offset; 01560 }; 01561 ulong index; 01562 } FAIRPORT_MS_STRUCT; 01563 01572 struct nameid_hash_entry 01573 { 01574 ulong hash_base; 01575 ulong index; 01576 } FAIRPORT_MS_STRUCT; 01578 static_assert(sizeof(nameid) == 8, "nameid incorrect size"); 01579 static_assert(sizeof(nameid_hash_entry) == 8, "nameid incorrect size"); 01581 01587 inline ushort nameid_get_prop_index(const nameid& n) { return (ushort)(n.index >> 16); } 01588 01594 inline ushort nameid_get_guid_index(const nameid& n) { return (ushort)((ushort)n.index >> 1); } 01595 01601 inline bool nameid_is_string(const nameid& n) { return n.index & 0x1; } 01602 01608 inline ushort nameid_get_prop_index(const nameid_hash_entry& n) { return (ushort)(n.index >> 16); } 01609 01615 inline ushort nameid_get_guid_index(const nameid_hash_entry& n) { return (ushort)((ushort)n.index >> 1); } 01616 01622 inline bool nameid_is_string(const nameid_hash_entry& n) { return n.index & 0x1; } 01623 01624 } // end disk namespace 01625 } // end fairport namespace 01626 01627 01628 template<typename T> 01629 inline fairport::ushort fairport::disk::compute_signature(T id, T address) 01630 { 01631 T value = address ^ id; 01632 01633 return (ushort(ushort(value >> 16) ^ ushort(value))); 01634 } 01635 01636 inline fairport::ulong fairport::disk::compute_crc(const void * pdata, ulong cb) 01637 { 01638 ulong crc = 0; 01639 const byte * pb = reinterpret_cast<const byte*>(pdata); 01640 01641 while(cb-- > 0) 01642 crc = crc_table[(int)(byte)crc ^ *pb++] ^ (crc >> 8); 01643 01644 return crc; 01645 } 01646 01647 inline void fairport::disk::permute(void * pdata, ulong cb, bool encrypt) 01648 { 01649 byte * pb = reinterpret_cast<byte*>(pdata); 01650 const byte * ptable = encrypt ? table1 : table3; 01651 byte b; 01652 01653 while(cb-- > 0) 01654 { 01655 b = *pb; 01656 *pb++ = ptable[b]; 01657 } 01658 } 01659 01660 inline void fairport::disk::cyclic(void * pdata, ulong cb, ulong key) 01661 { 01662 byte * pb = reinterpret_cast<byte*>(pdata); 01663 byte b; 01664 ushort w; 01665 01666 w = (ushort)(key ^ (key >> 16)); 01667 01668 while (cb-- > 0) 01669 { 01670 b = *pb; 01671 b = (byte)(b + (byte)w); 01672 b = table1[b]; 01673 b = (byte)(b + (byte)(w >> 8)); 01674 b = table2[b]; 01675 b = (byte)(b - (byte)(w >> 8)); 01676 b = table3[b]; 01677 b = (byte)(b - (byte)w); 01678 *pb++ = b; 01679 01680 w = (ushort)(w + 1); 01681 } 01682 } 01683 01684 template<typename T> 01685 inline size_t fairport::disk::align_disk(size_t size) 01686 { 01687 return align_slot(size + sizeof(block_trailer<T>)); 01688 } 01689 01690 inline size_t fairport::disk::align_slot(size_t size) 01691 { 01692 return ((size + bytes_per_slot - 1) & ~(bytes_per_slot - 1)); 01693 } 01694 01695 #endif