1 // -*- mode: cpp; mode: fold -*-
3 // $Id: filelist.cc,v 1.14 1999/12/26 06:59:00 jgg Exp $
4 /* ######################################################################
8 This module has a large group of services all relating to the binary
9 file list. Each individual record type has an read and write function
10 that can be used to store it into a unpacked structure.
12 ##################################################################### */
14 // Include files /*{{{*/
16 #pragma implementation "dsync/filelist.h"
19 #include <dsync/filelist.h>
20 #include <dsync/error.h>
29 // FList::Step - Step to the next record /*{{{*/
30 // ---------------------------------------------------------------------
31 /* This is an encompassing function to read a single record of any type
33 bool dsFList::Step(IO &IO)
35 if (!(_error->PendingError() == false && IO.ReadInt(Tag,1) == true))
43 case dsFList::tHeader:
49 case dsFList::tDirMarker:
50 case dsFList::tDirStart:
51 case dsFList::tDirectory:
56 case dsFList::tNormalFile:
60 return NFile.Read(IO);
62 case dsFList::tSymlink:
65 return SLink.Read(IO);
67 case dsFList::tDeviceSpecial:
70 return DevSpecial.Read(IO);
72 case dsFList::tFilter:
76 case dsFList::tUidMap:
80 case dsFList::tGidMap:
84 case dsFList::tHardLink:
88 return HLink.Read(IO);
90 case dsFList::tTrailer:
92 return Trail.Read(IO);
94 case dsFList::tRSyncChecksum:
98 case dsFList::tAggregateFile:
100 return AgFile.Read(IO);
107 return _error->Error("Corrupted file list");
112 // FList::Print - Print out the record /*{{{*/
113 // ---------------------------------------------------------------------
114 /* This simply displays the record */
115 bool dsFList::Print(ostream &out)
122 snprintf(S,sizeof(S),"H Sig=%lx Maj=%lu Min=%lu Epoch=%lu Count=%lu\n",
123 Head.Signature,Head.MajorVersion,Head.MinorVersion,
124 Head.Epoch,Head.FlagCount);
133 if (Tag == tDirMarker)
134 snprintf(S,sizeof(S),"DM Mod=%lu",
135 Dir.ModTime+Head.Epoch);
136 if (Tag == tDirStart)
137 snprintf(S,sizeof(S),"DS Mod=%lu",
138 Dir.ModTime+Head.Epoch);
139 if (Tag == tDirectory)
140 snprintf(S,sizeof(S),"D Mod=%lu",
141 Dir.ModTime+Head.Epoch);
143 if ((Head.Flags[Tag] & Directory::FlPerm) != 0)
145 snprintf(S,sizeof(S)," Perm=%lo",Dir.Permissions);
149 if ((Head.Flags[Tag] & Directory::FlOwner) != 0)
151 snprintf(S,sizeof(S)," U=%lu G=%lu",Dir.User,Dir.Group);
155 snprintf(S,sizeof(S)," N='%s'\n",Dir.Name.c_str());
167 snprintf(S,sizeof(S),"F Mod=%lu",File->ModTime+Head.Epoch);
169 if ((Head.Flags[Tag] & NormalFile::FlPerm) != 0)
171 snprintf(S,sizeof(S)," Perm=%lo",File->Permissions);
174 if ((Head.Flags[Tag] & NormalFile::FlOwner) != 0)
176 snprintf(S,sizeof(S)," U=%lu G=%lu",File->User,File->Group);
179 if ((Head.Flags[Tag] & NormalFile::FlMD5) != 0)
182 for (unsigned int I = 0; I != 16; I++)
183 sprintf(S+2*I,"%02x",File->MD5[I]);
188 if (Tag == tHardLink)
189 out << " Ser=" << HLink.Serial;
190 snprintf(S,sizeof(S)," Sz=%lu N='%s'\n",File->Size,File->Name.c_str());
198 snprintf(S,sizeof(S),"S Mod=%lu",DevSpecial.ModTime+Head.Epoch);
200 if ((Head.Flags[Tag] & DeviceSpecial::FlPerm) != 0)
202 snprintf(S,sizeof(S)," Perm=%lo",DevSpecial.Permissions);
205 if ((Head.Flags[Tag] & DeviceSpecial::FlOwner) != 0)
207 snprintf(S,sizeof(S)," U=%lu G=%lu",DevSpecial.User,DevSpecial.Group);
210 snprintf(S,sizeof(S)," N='%s'\n",DevSpecial.Name.c_str());
217 snprintf(S,sizeof(S),"L Mod=%lu",SLink.ModTime+Head.Epoch);
219 if ((Head.Flags[Tag] & Symlink::FlOwner) != 0)
221 snprintf(S,sizeof(S)," U=%lu G=%lu",SLink.User,SLink.Group);
225 snprintf(S,sizeof(S)," N='%s' T='%s'\n",SLink.Name.c_str(),SLink.To.c_str());
230 case dsFList::tTrailer:
232 snprintf(S,sizeof(S),"T Sig=%lx\n",Trail.Signature);
237 case dsFList::tRSyncChecksum:
239 snprintf(S,sizeof(S),"RC BlockSize=%lu FileSize=%lu\n",RChk.BlockSize,RChk.FileSize);
244 case dsFList::tAggregateFile:
246 snprintf(S,sizeof(S),"RAG File='%s'\n",AgFile.File.c_str());
251 out << "RSE" << endl;
255 return _error->Error("Unknown tag %u",Tag);
261 // IO::IO - Constructor /*{{{*/
262 // ---------------------------------------------------------------------
269 // IO::ReadNum - Read a variable byte number coded with WriteNum /*{{{*/
270 // ---------------------------------------------------------------------
271 /* Read a variable byte encoded number, see WriteNum */
272 bool dsFList::IO::ReadNum(unsigned long &Number)
278 unsigned char Byte = 0;
279 if (Read(&Byte,1) == false)
281 Number |= (Byte & 0x7F) << 7*I;
282 if ((Byte & (1<<7)) == 0)
288 // IO::WriteNum - Write a variable byte number /*{{{*/
289 // ---------------------------------------------------------------------
290 /* This encodes the given number into a variable number of bytes and writes
291 it to the stream. This is done by encoding it in 7 bit chunks and using
292 the 8th bit as a continuation flag */
293 bool dsFList::IO::WriteNum(unsigned long Number)
295 unsigned char Bytes[10];
299 Bytes[I] = Number & 0x7F;
307 return Write(Bytes,I+1);
310 // IO::ReadInt - Read an unsigned int written by WriteInt /*{{{*/
311 // ---------------------------------------------------------------------
312 /* Read an unsigned integer of a given number of bytes, see WriteInt */
313 bool dsFList::IO::ReadInt(unsigned long &Number,unsigned char Count)
315 unsigned char Bytes[8];
316 if (Read(&Bytes,Count) == false)
320 for (unsigned int I = 0; I != Count; I++)
321 Number |= (Bytes[I] << I*8);
325 // IO::WriteInt - Write an unsigned int with a number of bytes /*{{{*/
326 // ---------------------------------------------------------------------
327 /* This writes the number of bytes in least-significant-byte first order */
328 bool dsFList::IO::WriteInt(unsigned long Number,unsigned char Count)
330 unsigned char Bytes[8];
331 for (unsigned int I = 0; I != Count; I++)
332 Bytes[I] = (Number >> I*8);
333 return Write(Bytes,Count);
336 // IO::ReadInt - Read an signed int written by WriteInt /*{{{*/
337 // ---------------------------------------------------------------------
338 /* Read a signed integer of a given number of bytes, see WriteInt */
339 bool dsFList::IO::ReadInt(signed long &Number,unsigned char Count)
341 unsigned char Bytes[8];
342 if (Read(&Bytes,Count) == false)
346 for (unsigned int I = 0; I != Count; I++)
347 Number |= (Bytes[I] << I*8);
351 // IO::WriteInt - Write an signed int with a number of bytes /*{{{*/
352 // ---------------------------------------------------------------------
353 /* This writes the number of bytes in least-significant-byte first order */
354 bool dsFList::IO::WriteInt(signed long Number,unsigned char Count)
356 unsigned char Bytes[8];
357 for (unsigned int I = 0; I != Count; I++)
358 Bytes[I] = (Number >> I*8);
359 return Write(Bytes,Count);
362 // IO::ReadString - Read a string written by WriteString /*{{{*/
363 // ---------------------------------------------------------------------
364 /* If NoStrings is set then the string is not allocated into memory, this
365 saves time when scanning a file */
366 bool dsFList::IO::ReadString(string &Foo)
370 if (ReadNum(Len) == false)
372 if (Len >= sizeof(S))
373 return _error->Error("String buffer too small");
374 if (Read(S,Len) == false)
378 if (NoStrings == false)
386 // IO::WriteString - Write a string to the stream /*{{{*/
387 // ---------------------------------------------------------------------
388 /* Write a string, we encode a Number contianing the length and then the
390 bool dsFList::IO::WriteString(string const &Foo)
392 return WriteNum(Foo.length()) && Write(Foo.c_str(),strlen(Foo.c_str()));
396 // Header::Header - Constructor /*{{{*/
397 // ---------------------------------------------------------------------
398 /* The constructor sets the current signature and version information */
399 dsFList::Header::Header() : Signature(0x97E78AB), MajorVersion(0),
402 Tag = dsFList::tHeader;
403 FlagCount = _count(Flags);
404 memset(Flags,0,sizeof(Flags));
406 Epoch = (unsigned long)time(0);
409 // Header::Read - Read the coded header /*{{{*/
410 // ---------------------------------------------------------------------
412 bool dsFList::Header::Read(IO &IO)
415 if ((IO.ReadInt(Signature,4) &&
416 IO.ReadInt(MajorVersion,2) && IO.ReadInt(MinorVersion,2) &&
417 IO.ReadNum(Epoch) && IO.ReadInt(FlagCount,1)) == false)
420 unsigned long RealFlagCount = FlagCount;
421 if (FlagCount > _count(Flags))
422 FlagCount = _count(Flags);
424 // Read the flag array
425 for (unsigned int I = 0; I != RealFlagCount; I++)
430 if (IO.ReadInt(Jnk,4) == false)
435 if (IO.ReadInt(Flags[I],4) == false)
443 // Header::Write - Write the coded header /*{{{*/
444 // ---------------------------------------------------------------------
446 bool dsFList::Header::Write(IO &IO)
448 FlagCount = _count(Flags);
450 // Write the contents
451 if ((IO.WriteInt(Tag,1) && IO.WriteInt(Signature,4) &&
452 IO.WriteInt(MajorVersion,2) && IO.WriteInt(MinorVersion,2) &&
453 IO.WriteNum(Epoch) && IO.WriteInt(FlagCount,1)) == false)
456 // Write the flag array
457 for (unsigned int I = 0; I != FlagCount; I++)
458 if (IO.WriteInt(Flags[I],4) == false)
463 // Directory::Read - Read a coded directory record /*{{{*/
464 // ---------------------------------------------------------------------
466 bool dsFList::Directory::Read(IO &IO)
468 unsigned long F = IO.Header.Flags[Tag];
470 if ((IO.ReadInt(ModTime,4)) == false)
472 if ((F & FlPerm) == FlPerm && IO.ReadInt(Permissions,2) == false)
474 if ((F & FlOwner) == FlOwner && (IO.ReadNum(User) &&
475 IO.ReadNum(Group)) == false)
477 if (IO.ReadString(Name) == false)
482 // Directory::Write - Write a compacted directory record /*{{{*/
483 // ---------------------------------------------------------------------
485 bool dsFList::Directory::Write(IO &IO)
487 unsigned long F = IO.Header.Flags[Tag];
489 if ((IO.WriteInt(Tag,1) && IO.WriteInt(ModTime,4)) == false)
491 if ((F & FlPerm) == FlPerm && IO.WriteInt(Permissions,2) == false)
493 if ((F & FlOwner) == FlOwner && (IO.WriteNum(User) &&
494 IO.WriteNum(Group)) == false)
496 if (IO.WriteString(Name) == false)
501 // NormalFile::Read - Read the compacted file record /*{{{*/
502 // ---------------------------------------------------------------------
504 bool dsFList::NormalFile::Read(IO &IO)
506 unsigned long F = IO.Header.Flags[Tag];
508 if ((IO.ReadInt(ModTime,4)) == false)
510 if ((F & FlPerm) == FlPerm && IO.ReadInt(Permissions,2) == false)
512 if ((F & FlOwner) == FlOwner && (IO.ReadNum(User) &&
513 IO.ReadNum(Group)) == false)
515 if ((IO.ReadString(Name) && IO.ReadNum(Size)) == false)
517 if ((F & FlMD5) == FlMD5 && IO.Read(&MD5,16) == false)
523 // NormalFile::write - Write the compacted file record /*{{{*/
524 // ---------------------------------------------------------------------
526 bool dsFList::NormalFile::Write(IO &IO)
528 unsigned long F = IO.Header.Flags[Tag];
530 if ((IO.WriteInt(Tag,1) && IO.WriteInt(ModTime,4)) == false)
532 if ((F & FlPerm) == FlPerm && IO.WriteInt(Permissions,2) == false)
534 if ((F & FlOwner) == FlOwner && (IO.WriteNum(User) &&
535 IO.WriteNum(Group)) == false)
537 if ((IO.WriteString(Name) && IO.WriteNum(Size)) == false)
539 if ((F & FlMD5) == FlMD5 && IO.Write(&MD5,16) == false)
545 // Symlink::Read - Read a compacted symlink record /*{{{*/
546 // ---------------------------------------------------------------------
548 bool dsFList::Symlink::Read(IO &IO)
550 unsigned long F = IO.Header.Flags[Tag];
552 if ((IO.ReadInt(ModTime,4)) == false)
554 if ((F & FlOwner) == FlOwner && (IO.ReadNum(User) &&
555 IO.ReadNum(Group)) == false)
557 if ((IO.ReadString(Name) && IO.ReadInt(Compress,1) &&
558 IO.ReadString(To)) == false)
561 // Decompress the string
564 if ((Compress & (1<<7)) == (1<<7))
566 if ((Compress & 0x7F) != 0)
567 To = string(IO.LastSymlink,0,Compress & 0x7F) + To;
574 // Symlink::Write - Write a compacted symlink record /*{{{*/
575 // ---------------------------------------------------------------------
576 /* This performs the symlink compression described in the file list
578 bool dsFList::Symlink::Write(IO &IO)
580 unsigned long F = IO.Header.Flags[Tag];
582 if ((IO.WriteInt(Tag,1) && IO.WriteInt(ModTime,4)) == false)
584 if ((F & FlOwner) == FlOwner && (IO.WriteNum(User) &&
585 IO.WriteNum(Group)) == false)
588 if (IO.WriteString(Name) == false)
591 // Attempt to remove the trailing text
593 if (To.length() >= Name.length())
595 unsigned int I = To.length() - Name.length();
596 for (unsigned int J = 0; I < To.length(); I++, J++)
597 if (To[I] != Name[J])
599 if (I == To.length())
603 // Compress the symlink target
605 unsigned int Len = To.length();
607 Len -= Name.length();
608 for (; Compress < Len && Compress < IO.LastSymlink.length() &&
609 Compress < 0x7F; Compress++)
610 if (To[Compress] != IO.LastSymlink[Compress])
613 // Set the trail flag
617 // Write the compresion byte
618 if (IO.WriteInt(Compress,1) == false)
621 // Write the data string
624 if (IO.WriteString(string(To,Compress & 0x7F,To.length() - Name.length() - (Compress & 0x7F))) == false)
629 if (IO.WriteString(string(To,Compress,To.length() - Compress)) == false)
638 // DeviceSpecial::Read - Read a compacted device special record /*{{{*/
639 // ---------------------------------------------------------------------
641 bool dsFList::DeviceSpecial::Read(IO &IO)
643 unsigned long F = IO.Header.Flags[Tag];
645 if ((IO.ReadInt(ModTime,4)) == false)
647 if (IO.ReadInt(Permissions,2) == false)
649 if ((F & FlOwner) == FlOwner && (IO.ReadNum(User) &&
650 IO.ReadNum(Group)) == false)
652 if ((IO.ReadNum(Dev) && IO.ReadString(Name)) == false)
657 // DeviceSpecial::Write - Write a compacted device special record /*{{{*/
658 // ---------------------------------------------------------------------
660 bool dsFList::DeviceSpecial::Write(IO &IO)
662 unsigned long F = IO.Header.Flags[Tag];
664 if ((IO.WriteInt(Tag,1) && IO.WriteInt(ModTime,4)) == false)
666 if (IO.WriteInt(Permissions,2) == false)
668 if ((F & FlOwner) == FlOwner && (IO.WriteNum(User) &&
669 IO.WriteNum(Group)) == false)
671 if ((IO.WriteNum(Dev) && IO.WriteString(Name)) == false)
676 // Filter::Read - Read a compacted filter record /*{{{*/
677 // ---------------------------------------------------------------------
679 bool dsFList::Filter::Read(IO &IO)
681 if ((IO.ReadInt(Type,1) &&
682 IO.ReadString(Pattern)) == false)
687 // Filter::Write - Write a compacted filter record /*{{{*/
688 // ---------------------------------------------------------------------
690 bool dsFList::Filter::Write(IO &IO)
692 if ((IO.WriteInt(Tag,1) && IO.WriteInt(Type,1) &&
693 IO.WriteString(Pattern)) == false)
698 // UidGidMap::Read - Read a compacted Uid/Gid map record /*{{{*/
699 // ---------------------------------------------------------------------
701 bool dsFList::UidGidMap::Read(IO &IO)
703 unsigned long F = IO.Header.Flags[Tag];
704 if ((IO.ReadNum(FileID)) == false)
707 if ((F & FlRealID) == FlRealID && IO.ReadNum(RealID) == false)
709 if (IO.ReadString(Name) == false)
714 // UidGidMap::Write - Write a compacted Uid/Gid map record /*{{{*/
715 // ---------------------------------------------------------------------
717 bool dsFList::UidGidMap::Write(IO &IO)
719 unsigned long F = IO.Header.Flags[Tag];
720 if ((IO.WriteInt(Tag,1) && IO.WriteNum(FileID)) == false)
723 if ((F & FlRealID) == FlRealID && IO.WriteNum(RealID) == false)
725 if (IO.WriteString(Name) == false)
730 // HardLink::Read - Read the compacted link record /*{{{*/
731 // ---------------------------------------------------------------------
733 bool dsFList::HardLink::Read(IO &IO)
735 unsigned long F = IO.Header.Flags[Tag];
737 if ((IO.ReadInt(ModTime,4) && IO.ReadNum(Serial)) == false)
739 if ((F & FlPerm) == FlPerm && IO.ReadInt(Permissions,2) == false)
741 if ((F & FlOwner) == FlOwner && (IO.ReadNum(User) &&
742 IO.ReadNum(Group)) == false)
744 if ((IO.ReadString(Name) && IO.ReadNum(Size)) == false)
746 if ((F & FlMD5) == FlMD5 && IO.Read(&MD5,16) == false)
752 // HardLink::Write - Write the compacted file record /*{{{*/
753 // ---------------------------------------------------------------------
755 bool dsFList::HardLink::Write(IO &IO)
757 unsigned long F = IO.Header.Flags[Tag];
759 if ((IO.WriteInt(Tag,1) && IO.WriteInt(ModTime,4) &&
760 IO.ReadNum(Serial)) == false)
762 if ((F & FlPerm) == FlPerm && IO.WriteInt(Permissions,2) == false)
764 if ((F & FlOwner) == FlOwner && (IO.WriteNum(User) &&
765 IO.WriteNum(Group)) == false)
767 if ((IO.WriteString(Name) && IO.WriteNum(Size)) == false)
769 if ((F & FlMD5) == FlMD5 && IO.Write(&MD5,16) == false)
775 // Trailer::Trailer - Constructor /*{{{*/
776 // ---------------------------------------------------------------------
778 dsFList::Trailer::Trailer() : Tag(dsFList::tTrailer), Signature(0xBA87E79)
782 // Trailer::Read - Read a compacted tail record /*{{{*/
783 // ---------------------------------------------------------------------
785 bool dsFList::Trailer::Read(IO &IO)
787 if (IO.ReadInt(Signature,4) == false)
792 // Trailer::Write - Write a compacted tail record /*{{{*/
793 // ---------------------------------------------------------------------
795 bool dsFList::Trailer::Write(IO &IO)
797 if ((IO.WriteInt(Tag,1) &&
798 IO.WriteInt(Signature,4)) == false)
803 // RSyncChecksum::RSyncChecksum - Constructor /*{{{*/
804 // ---------------------------------------------------------------------
806 dsFList::RSyncChecksum::RSyncChecksum() : Tag(dsFList::tRSyncChecksum),
811 // RSyncChecksum::~RSyncChecksum - Constructor /*{{{*/
812 // ---------------------------------------------------------------------
814 dsFList::RSyncChecksum::~RSyncChecksum()
819 // RSyncChecksum::Read - Read a compacted device special record /*{{{*/
820 // ---------------------------------------------------------------------
822 bool dsFList::RSyncChecksum::Read(IO &IO)
824 if ((IO.ReadNum(BlockSize) && IO.ReadNum(FileSize)) == false)
827 // Read in the checksum table
829 Sums = new unsigned char[(FileSize + BlockSize-1)/BlockSize*20];
830 if (IO.Read(Sums,(FileSize + BlockSize-1)/BlockSize*20) == false)
836 // RSyncChecksum::Write - Write a compacted device special record /*{{{*/
837 // ---------------------------------------------------------------------
839 bool dsFList::RSyncChecksum::Write(IO &IO)
841 if ((IO.WriteInt(Tag,1) && IO.WriteNum(BlockSize) &&
842 IO.WriteNum(FileSize)) == false)
845 if (IO.Write(Sums,(FileSize + BlockSize-1)/BlockSize*20) == false)
850 // AggregateFile::Read - Read a aggregate file record /*{{{*/
851 // ---------------------------------------------------------------------
853 bool dsFList::AggregateFile::Read(IO &IO)
855 return IO.ReadString(File);
858 // AggregateFile::Write - Write a compacted filter record /*{{{*/
859 // ---------------------------------------------------------------------
861 bool dsFList::AggregateFile::Write(IO &IO)
863 if ((IO.WriteInt(Tag,1) && IO.WriteString(File)) == false)