00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <Basics.H>
00025 #include <FS.H>
00026 #include <VestaLog.H>
00027 #include <Recovery.H>
00028 #include "FP.H"
00029 #include "Poly.H"
00030 #include "ByteModTable.H"
00031
00032 using std::istream;
00033 using std::ostream;
00034 using std::ios;
00035
00036
00037
00038 #define INLINE_POLYINC
00039
00040
00041
00042 #define UNROLL_LOOP
00043
00044 const int WordSize = sizeof(Word);
00045 const int WordBits = WordSize * 8;
00046
00047
00048
00049
00050
00051 #if BYTE_ORDER == BIG_ENDIAN
00052 #define ORDER_WORD_BYTES(p_x) Basics::swab64(p_x)
00053 #elif BYTE_ORDER == LITTLE_ENDIAN
00054 #define ORDER_WORD_BYTES(p_x) (p_x)
00055 #else
00056 #error Unknown byte order
00057 #endif
00058
00059
00060
00061 #ifdef UNROLL_LOOP
00062 static Poly *ByteModTable0 = ByteModTable[0];
00063 static Poly *ByteModTable1 = ByteModTable[1];
00064 static Poly *ByteModTable2 = ByteModTable[2];
00065 static Poly *ByteModTable3 = ByteModTable[3];
00066 static Poly *ByteModTable4 = ByteModTable[4];
00067 static Poly *ByteModTable5 = ByteModTable[5];
00068 static Poly *ByteModTable6 = ByteModTable[6];
00069 #endif
00070 static Poly *ByteModTable7 = ByteModTable[7];
00071
00072 static void ExtendByChar( Poly& p, const unsigned char c) throw ()
00073
00074
00075
00076 {
00077 Poly temp = POLY_ZERO;
00078 unsigned char c0 = (unsigned char)(p.w[0]);
00079 #ifdef INLINE_POLYINC
00080 Poly *tblPoly = &(ByteModTable7[c0]);
00081 temp.w[0] ^= tblPoly->w[0];
00082 temp.w[1] ^= tblPoly->w[1];
00083 #else
00084 PolyInc( temp, ByteModTable7[c0]);
00085 #endif
00086 p.w[0] = (p.w[0] >> 8) | (p.w[1] << (WordBits - 8));
00087 p.w[1] = (p.w[1] >> 8) | (((Word)c) << (WordBits - 8));
00088 #ifdef INLINE_POLYINC
00089 p.w[0] ^= temp.w[0];
00090 p.w[1] ^= temp.w[1];
00091 #else
00092 PolyInc( p, temp);
00093 #endif
00094 }
00095
00096 static void ExtendByBytes( Poly& p,
00097 const unsigned char *source, int n) throw ()
00098
00099
00100
00101 {
00102 assert(0 < n && n < 8);
00103
00104 const int bits = 8 * n;
00105 Poly temp = POLY_ZERO;
00106 Word mask = p.w[0];
00107 for (int i = 0; i < n; i++) {
00108 unsigned char c0 = (unsigned char)mask;
00109 #ifdef INLINE_POLYINC
00110 Poly *tblPoly = &(ByteModTable[i+8-n][c0]);
00111 temp.w[0] ^= tblPoly->w[0];
00112 temp.w[1] ^= tblPoly->w[1];
00113 #else
00114 PolyInc( temp, ByteModTable[i+8-n][c0]);
00115 #endif
00116 mask >>= 8;
00117 }
00118 #if defined(VALGRIND_SUPPORT)
00119
00120
00121 mask = 0;
00122 char *mask_c = (char *) &mask;
00123 for(int i = 0; i < n; i++)
00124 {
00125 mask_c[i] = source[i];
00126 }
00127 mask = ORDER_WORD_BYTES(mask);
00128 #else
00129 unsigned int align_mask = sizeof(Word) - 1;
00130 int align = ((PointerInt) source) & align_mask;
00131 if (align == 0) {
00132 mask = ORDER_WORD_BYTES(*(Word *)source);
00133 } else {
00134
00135
00136 Word *w1 = (Word *)(source - align);
00137
00138
00139
00140 Word *w2 = ((WordSize - align) < n)
00141 ? (Word *)(source + (WordSize - align))
00142 : (Word *)0;
00143 align <<= 3;
00144 mask = (ORDER_WORD_BYTES(*w1) >> align);
00145
00146 if(w2 != 0)
00147 {
00148 mask |= (ORDER_WORD_BYTES(*w2) << (WordBits - align));
00149 }
00150 }
00151 #endif
00152 p.w[0] = (p.w[0] >> bits) | (p.w[1] << (WordBits-bits));
00153 p.w[1] = (p.w[1] >> bits) | (mask << (WordBits-bits));
00154 #ifdef INLINE_POLYINC
00155 p.w[0] ^= temp.w[0];
00156 p.w[1] ^= temp.w[1];
00157 #else
00158 PolyInc( p, temp);
00159 #endif
00160 }
00161
00162 static void ExtendByWords( Poly& p, const Word *source, int n)
00163 throw ()
00164
00165
00166 {
00167 Poly temp;
00168
00169 for (int i = 0; i < n; i++) {
00170 temp = POLY_ZERO;
00171 #ifdef UNROLL_LOOP
00172 {
00173 unsigned char *ptr = (unsigned char *) &(p.w[0]);
00174 #if BYTE_ORDER == BIG_ENDIAN
00175 Poly p7 = ByteModTable7[*ptr++];
00176 Poly p6 = ByteModTable6[*ptr++];
00177 Poly p5 = ByteModTable5[*ptr++];
00178 Poly p4 = ByteModTable4[*ptr++];
00179 Poly p3 = ByteModTable3[*ptr++];
00180 Poly p2 = ByteModTable2[*ptr++];
00181 Poly p1 = ByteModTable1[*ptr++];
00182 Poly p0 = ByteModTable0[*ptr];
00183 #elif BYTE_ORDER == LITTLE_ENDIAN
00184 Poly p0 = ByteModTable0[*ptr++];
00185 Poly p1 = ByteModTable1[*ptr++];
00186 Poly p2 = ByteModTable2[*ptr++];
00187 Poly p3 = ByteModTable3[*ptr++];
00188 Poly p4 = ByteModTable4[*ptr++];
00189 Poly p5 = ByteModTable5[*ptr++];
00190 Poly p6 = ByteModTable6[*ptr++];
00191 Poly p7 = ByteModTable7[*ptr];
00192 #else
00193 #error Unknown byte order
00194 #endif
00195 temp.w[0] ^= p0.w[0]; temp.w[1] ^= p0.w[1];
00196 temp.w[0] ^= p1.w[0]; temp.w[1] ^= p1.w[1];
00197 temp.w[0] ^= p2.w[0]; temp.w[1] ^= p2.w[1];
00198 temp.w[0] ^= p3.w[0]; temp.w[1] ^= p3.w[1];
00199 temp.w[0] ^= p4.w[0]; temp.w[1] ^= p4.w[1];
00200 temp.w[0] ^= p5.w[0]; temp.w[1] ^= p5.w[1];
00201 temp.w[0] ^= p6.w[0]; temp.w[1] ^= p6.w[1];
00202 temp.w[0] ^= p7.w[0]; temp.w[1] ^= p7.w[1];
00203 }
00204 #else
00205 Word mask = p.w[0];
00206 for (int j = 0; j < 8; j++) {
00207 unsigned char c0 = (unsigned char)mask;
00208 #ifdef INLINE_POLYINC
00209 Poly *tblPoly = &(ByteModTable[j][c0]);
00210 temp.w[0] ^= tblPoly->w[0];
00211 temp.w[1] ^= tblPoly->w[1];
00212 #else
00213 PolyInc( temp, ByteModTable[j][c0]);
00214 #endif // USE_POLY_INC
00215 mask >>= 8;
00216 }
00217 #endif
00218 p.w[0] = p.w[1];
00219 p.w[1] = ORDER_WORD_BYTES(source[i]);
00220 #ifdef INLINE_POLYINC
00221 p.w[0] ^= temp.w[0];
00222 p.w[1] ^= temp.w[1];
00223 #else
00224 PolyInc( p, temp);
00225 #endif
00226 }
00227 }
00228
00229
00230
00231 static void RawFPExtend( RawFP& fp,
00232 const char *addr, int len) throw ()
00233
00234
00235 {
00236 unsigned char *p = (unsigned char *) addr;
00237 int residue;
00238
00239
00240 if (len >= WordSize) {
00241 residue = WordSize - (((PointerInt) p) % WordSize);
00242 if (residue != WordSize) {
00243 ExtendByBytes( fp, p, residue);
00244 p += residue;
00245 len -= residue;
00246 }
00247 }
00248
00249
00250 if (len >= WordSize) {
00251 ExtendByWords( fp, (Word *) p, len / WordSize);
00252 p += (len / WordSize) * WordSize;
00253 len %= WordSize;
00254 }
00255
00256
00257 if (len != 0) {
00258 ExtendByBytes( fp, p, len);
00259 }
00260 }
00261
00262
00263
00264 void FP::Tag::Init(const char *s, int len) throw ()
00265 {
00266 RawFP fp = POLY_ONE;
00267 RawFPExtend( fp, s, len);
00268 Permute(fp);
00269 }
00270
00271 FP::Tag& FP::Tag::Extend(const char *s, int len) throw ()
00272 {
00273 if (len < 0) len = strlen(s);
00274 RawFP fp;
00275 Unpermute( fp);
00276 RawFPExtend( fp, s, len);
00277 Permute(fp);
00278 return *this;
00279 }
00280
00281 FP::Tag& FP::Tag::Extend(char c) throw ()
00282 {
00283 RawFP fp;
00284 Unpermute( fp);
00285 ExtendByChar( fp, c);
00286 Permute(fp);
00287 return *this;
00288 }
00289
00290 void FP::Tag::ExtendRaw( RawFP &fp, const char *s, int len)
00291 throw ()
00292 {
00293 if (len < 0) len = strlen(s);
00294 RawFPExtend( fp, s, len);
00295 }
00296
00297 void FP::Tag::ExtendRaw( RawFP &fp, char c) throw ()
00298 {
00299 ExtendByChar( fp, c);
00300 }
00301
00302 Word FP::Tag::Hash() const throw ()
00303 {
00304 Word res = w[0];
00305 for (int i = 1; i < FP::WordCnt; i++) res ^= w[i];
00306 return res;
00307 }
00308
00309 void FP::Tag::ToBytes(unsigned char *buffer) const throw ()
00310 {
00311 unsigned int i = 0;
00312 for(unsigned int word = 0; word < FP::WordCnt; word++)
00313 {
00314 for(unsigned int bit = 0; bit < WordBits; bit +=8)
00315 {
00316 buffer[i++] = (this->w[word] >> bit);
00317 }
00318 }
00319 assert(i == FP::ByteCnt);
00320 }
00321
00322 void FP::Tag::FromBytes(const unsigned char *buffer) throw ()
00323 {
00324 unsigned int i = 0;
00325 for(unsigned int word = 0; word < FP::WordCnt; word++)
00326 {
00327 this->w[word] = 0;
00328 for(unsigned int bit = 0; bit < WordBits; bit +=8)
00329 {
00330 this->w[word] |= (((Word) buffer[i++]) << bit);
00331 }
00332 }
00333 assert(i == FP::ByteCnt);
00334 }
00335
00336 bool FP::Tag::operator == (const FP::Tag& other) const throw ()
00337 {
00338 for (int i = 0; i < FP::WordCnt; i++) {
00339 if (this->w[i] != other.w[i]) return false;
00340 }
00341 return true;
00342 }
00343
00344 bool FP::Tag::operator != (const FP::Tag& other) const throw ()
00345 {
00346 for (int i = 0; i < FP::WordCnt; i++) {
00347 if (this->w[i] != other.w[i]) return true;
00348 }
00349 return false;
00350 }
00351
00352 void FP::Tag::Print(ostream &os, const char *word_separator)
00353 const throw ()
00354 {
00355 char buff[17];
00356 for (int i = 0; i < FP::WordCnt; i++) {
00357 sprintf(buff, "%016" FORMAT_LENGTH_INT_64 "x", this->w[i]);
00358 os << buff;
00359 if (i < FP::WordCnt - 1) os << word_separator;
00360 }
00361 }
00362
00363 int Compare(const FP::Tag& fp1, const FP::Tag& fp2) throw ()
00364 {
00365 for (int i = 0; i < FP::WordCnt; i++) {
00366 if (fp1.w[i] != fp2.w[i]) {
00367 return ((fp1.w[i] < fp2.w[i]) ? -1 : 1);
00368 }
00369 }
00370 return 0;
00371 }
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386 const Word
00387 A[2][2] = {{CONST_INT_64(0xce36f163f737a677),
00388 CONST_INT_64(0x431bf4ecc646b337)},
00389 {CONST_INT_64(0x1960326FA38D04D0),
00390 CONST_INT_64(0x10155F23A2F024F9)}},
00391 B[2][2] = {{CONST_INT_64(0x94033a389a279d77),
00392 CONST_INT_64(0xd79f3b15576598a7)},
00393 {CONST_INT_64(0x67f2d59b2369b1d0),
00394 CONST_INT_64(0x63e096e4228c019)}};
00395
00396 const unsigned char
00397 perm[256] = {89, 171, 235, 183, 176, 181, 91, 54, 49,
00398 151, 11, 0, 73, 138, 118, 160, 172, 251, 255, 192, 102, 39, 15, 169,
00399 149, 110, 240, 133, 213, 196, 217, 199, 29, 43, 52, 153, 32, 2, 179,
00400 6, 211, 165, 161, 224, 194, 209, 8, 93, 197, 162, 207, 229, 83, 247,
00401 129, 188, 145, 186, 59, 147, 202, 109, 141, 78, 38, 92, 68, 190,
00402 252, 116, 85, 184, 34, 103, 88, 140, 123, 76, 131, 67, 26, 166, 185,
00403 63, 90, 86, 5, 246, 58, 238, 231, 232, 241, 106, 7, 225, 75, 45,
00404 146, 19, 23, 99, 9, 216, 96, 236, 95, 218, 182, 40, 124, 201, 82,
00405 230, 214, 206, 107, 137, 249, 212, 77, 119, 253, 1, 210, 35, 69,
00406 167, 79, 4, 198, 180, 226, 122, 128, 244, 163, 250, 121, 55, 135,
00407 14, 154, 100, 243, 187, 173, 3, 46, 33, 157, 42, 152, 51, 30, 142,
00408 98, 48, 148, 254, 223, 159, 41, 74, 155, 248, 205, 18, 175, 108, 56,
00409 228, 195, 17, 237, 104, 62, 47, 12, 72, 158, 25, 134, 234, 239, 242,
00410 80, 143, 101, 203, 81, 215, 10, 27, 204, 24, 37, 191, 105, 208, 132,
00411 126, 50, 156, 227, 125, 65, 130, 139, 136, 31, 44, 97, 94, 53, 127,
00412 233, 221, 84, 117, 220, 219, 200, 164, 120, 20, 113, 22, 168, 66,
00413 170, 87, 150, 70, 193, 189, 177, 28, 36, 114, 178, 13, 71, 64, 115,
00414 16, 144, 57, 245, 111, 222, 60, 174, 61, 112, 21},
00415 perminv[256] = {11, 123, 37, 147, 129, 86, 39, 94, 46, 102, 192, 10,
00416 178, 241, 141, 22, 245, 173, 167, 99, 225, 255, 227, 100, 195, 181,
00417 80, 193, 237, 32, 154, 210, 36, 149, 72, 125, 238, 196, 64, 21, 109,
00418 162, 151, 33, 211, 97, 148, 177, 157, 8, 202, 153, 34, 214, 7, 139,
00419 170, 247, 88, 58, 251, 253, 176, 83, 243, 206, 229, 79, 66, 126,
00420 233, 242, 179, 12, 163, 96, 77, 120, 63, 128, 186, 190, 112, 52,
00421 218, 70, 85, 231, 74, 0, 84, 6, 65, 47, 213, 106, 104, 212, 156,
00422 101, 143, 188, 20, 73, 175, 198, 93, 116, 169, 61, 25, 249, 254,
00423 226, 239, 244, 69, 219, 14, 121, 224, 138, 133, 76, 110, 205, 201,
00424 215, 134, 54, 207, 78, 200, 27, 182, 140, 209, 117, 13, 208, 75, 62,
00425 155, 187, 246, 56, 98, 59, 158, 24, 232, 9, 152, 35, 142, 164, 203,
00426 150, 180, 161, 15, 42, 49, 136, 223, 41, 81, 127, 228, 23, 230, 1,
00427 16, 146, 252, 168, 4, 236, 240, 38, 131, 5, 108, 3, 71, 82, 57, 145,
00428 55, 235, 67, 197, 19, 234, 44, 172, 29, 48, 130, 31, 222, 111, 60,
00429 189, 194, 166, 115, 50, 199, 45, 124, 40, 119, 28, 114, 191, 103,
00430 30, 107, 221, 220, 217, 250, 160, 43, 95, 132, 204, 171, 51, 113,
00431 90, 91, 216, 183, 2, 105, 174, 89, 184, 26, 92, 185, 144, 135, 248,
00432 87, 53, 165, 118, 137, 17, 68, 122, 159, 18};
00433
00434 void FP::Tag::Permute(const RawFP &f) throw ()
00435 {
00436 unsigned char *p = (unsigned char *) &(f.w);
00437
00438
00439 int i;
00440 for (i=0; i < FP::ByteCnt; i++, p++) {
00441 *p = perm[*p];
00442 }
00443
00444
00445 this->w[0] = f.w[0] * A[0][0] + f.w[1] * A[1][0];
00446 this->w[1] = f.w[0] * A[0][1] + f.w[1] * A[1][1];
00447 }
00448
00449 void FP::Tag::Unpermute( RawFP &res) const throw ()
00450 {
00451
00452 res.w[0] = w[0] * B[0][0] + w[1] * B[1][0];
00453 res.w[1] = w[0] * B[0][1] + w[1] * B[1][1];
00454
00455
00456 int i;
00457 unsigned char *p = (unsigned char *) &(res.w);
00458 for (i=0; i < FP::ByteCnt; i++, p++) {
00459 *p = perminv[*p];
00460 }
00461 }
00462
00463
00464
00465 void FP::List::Log(VestaLog& log) const throw (VestaLog::Error)
00466 {
00467 log.write((char *)(&(this->len)), sizeof(int));
00468 for (int i = 0; i < this->len; i++) {
00469 this->fp[i].Log(log);
00470 }
00471 }
00472
00473 void FP::List::Recover(RecoveryReader &rd)
00474 throw (VestaLog::Error, VestaLog::Eof)
00475 {
00476 rd.readAll((char *)(&(this->len)), sizeof(int));
00477 if (this->len > 0) {
00478 this->fp = NEW_PTRFREE_ARRAY(FP::Tag, len);
00479 for (int i = 0; i < this->len; i++) {
00480 this->fp[i].Recover(rd);
00481 }
00482 } else {
00483 this->fp = (FP::Tag *)NULL;
00484 }
00485 }
00486
00487 void FP::List::Write(ostream &ofs) const throw (FS::Failure)
00488 {
00489 FS::Write(ofs, (char *)(&(this->len)), sizeof(int));
00490 for (int i = 0; i < this->len; i++) {
00491 this->fp[i].Write(ofs);
00492 }
00493 }
00494
00495 void FP::List::Read(istream &ifs) throw (FS::EndOfFile, FS::Failure)
00496 {
00497 FS::Read(ifs, (char *)(&(this->len)), sizeof(int));
00498 if (this->len > 0) {
00499 this->fp = NEW_PTRFREE_ARRAY(FP::Tag, this->len);
00500 for (int i = 0; i < this->len; i++) {
00501 this->fp[i].Read(ifs);
00502 }
00503 } else {
00504 this->fp = (FP::Tag *)NULL;
00505 }
00506 }
00507
00508 void FP::List::Send(SRPC &srpc) const throw (SRPC::failure)
00509 {
00510 srpc.send_seq_start(this->len);
00511 for (int i = 0; i < this->len; i++) {
00512 this->fp[i].Send(srpc);
00513 }
00514 srpc.send_seq_end();
00515 }
00516
00517 void FP::List::Recv(SRPC &srpc) throw (SRPC::failure)
00518 {
00519 srpc.recv_seq_start(&(this->len), NULL);
00520 this->fp = NEW_PTRFREE_ARRAY(FP::Tag, this->len);
00521 for (int i = 0; i < this->len; i++) {
00522 this->fp[i].Recv(srpc);
00523 }
00524 srpc.recv_seq_end();
00525 }
00526
00527 inline void Indent(ostream &os, int indent) throw ()
00528 {
00529 for (int i = 0; i < indent; i++) os << " ";
00530 }
00531
00532 void FP::List::Print(ostream &os, int indent) const throw ()
00533 {
00534 if (this->len > 0) {
00535 for (int i = 0; i < this->len; i++) {
00536 Indent(os, indent);
00537 os << "fp[" << i << "] = " << this->fp[i] << "\n";
00538 }
00539 } else {
00540 Indent(os, indent);
00541 os << "<< no fingerprints >>\n";
00542 }
00543 }
00544
00545
00546
00547 void FP::FileContents(istream &ifs, FP::Tag &fp)
00548 throw (FS::Failure)
00549 {
00550 const int BuffSize = 1024;
00551 char buff[BuffSize];
00552 while (true) {
00553
00554 if (ifs.read(buff, BuffSize)) {
00555
00556 fp.Extend(buff, BuffSize);
00557 } else {
00558
00559 int numRead = ifs.gcount();
00560 if (ifs.rdstate() & ios::failbit && numRead < BuffSize) {
00561
00562 fp.Extend(buff, numRead);
00563
00564 break;
00565 } else {
00566
00567 throw (FS::Failure("FP::FileContents"));
00568 }
00569 }
00570 }
00571 }