]> git.decadent.org.uk Git - dak.git/blob - tools/dsync-0.0/libdsync/filelist.cc
Merge commit 'godog/master' into merge
[dak.git] / tools / dsync-0.0 / libdsync / filelist.cc
1 // -*- mode: cpp; mode: fold -*-
2 // Description                                                          /*{{{*/
3 // $Id: filelist.cc,v 1.14 1999/12/26 06:59:00 jgg Exp $
4 /* ######################################################################
5    
6    File List Structures
7
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.
11    
12    ##################################################################### */
13                                                                         /*}}}*/
14 // Include files                                                        /*{{{*/
15 #ifdef __GNUG__
16 #pragma implementation "dsync/filelist.h"
17 #endif
18
19 #include <dsync/filelist.h>
20 #include <dsync/error.h>
21 #include <system.h>
22
23 #include <time.h>
24 #include <stdio.h>
25 #include <iostream>
26 using namespace std;
27                                                                         /*}}}*/
28
29 // FList::Step - Step to the next record                                /*{{{*/
30 // ---------------------------------------------------------------------
31 /* This is an encompassing function to read a single record of any type
32    from the IO */
33 bool dsFList::Step(IO &IO)
34 {
35    if (!(_error->PendingError() == false && IO.ReadInt(Tag,1) == true))
36       return false;
37
38    Entity = 0;
39    File = 0;
40    
41    switch (Tag)
42    {
43       case dsFList::tHeader:
44       Head.Tag = Tag;
45       Head.Read(IO);
46       IO.Header = Head;
47       break;
48          
49       case dsFList::tDirMarker:
50       case dsFList::tDirStart:
51       case dsFList::tDirectory:
52       Dir.Tag = Tag;
53       Entity = &Dir;
54       return Dir.Read(IO);
55              
56       case dsFList::tNormalFile:
57       NFile.Tag = Tag;
58       Entity = &NFile;
59       File = &NFile;
60       return NFile.Read(IO);
61          
62       case dsFList::tSymlink:
63       SLink.Tag = Tag;
64       Entity = &SLink;
65       return SLink.Read(IO);
66          
67       case dsFList::tDeviceSpecial:
68       DevSpecial.Tag = Tag;
69       Entity = &DevSpecial;
70       return DevSpecial.Read(IO);
71       
72       case dsFList::tFilter:
73       Filt.Tag = Tag;
74       return Filt.Read(IO);
75       
76       case dsFList::tUidMap:
77       UMap.Tag = Tag;
78       return UMap.Read(IO);
79       
80       case dsFList::tGidMap:
81       UMap.Tag = Tag;
82       return UMap.Read(IO);
83       
84       case dsFList::tHardLink:
85       HLink.Tag = Tag;
86       Entity = &HLink;
87       File = &HLink;
88       return HLink.Read(IO);
89       
90       case dsFList::tTrailer:
91       Trail.Tag = Tag;
92       return Trail.Read(IO);
93
94       case dsFList::tRSyncChecksum:
95       RChk.Tag = Tag;
96       return RChk.Read(IO);
97       
98       case dsFList::tAggregateFile:
99       AgFile.Tag = Tag;
100       return AgFile.Read(IO);
101          
102       case tRSyncEnd:
103       case tDirEnd:
104       return true;
105       
106       default:
107       return _error->Error("Corrupted file list");
108    }
109    return true;
110 }
111                                                                         /*}}}*/
112 // FList::Print - Print out the record                                  /*{{{*/
113 // ---------------------------------------------------------------------
114 /* This simply displays the record */
115 bool dsFList::Print(ostream &out)
116 {
117    char S[1024];
118    switch (Tag)
119    {
120       case tHeader:
121       {
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);
125          out << S;
126          break;
127       }
128          
129       case tDirMarker:
130       case tDirStart:
131       case tDirectory:
132       {
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);
142          out << S;
143          if ((Head.Flags[Tag] & Directory::FlPerm) != 0)
144          {
145             snprintf(S,sizeof(S)," Perm=%lo",Dir.Permissions);
146             out << S;
147          }
148          
149          if ((Head.Flags[Tag] & Directory::FlOwner) != 0)
150          {
151             snprintf(S,sizeof(S)," U=%lu G=%lu",Dir.User,Dir.Group);
152             out << S;
153          }
154          
155          snprintf(S,sizeof(S)," N='%s'\n",Dir.Name.c_str());
156          out << S;
157          break;
158       }
159       
160       case tDirEnd:
161       out << "DE" << endl;
162       break;
163
164       case tHardLink:
165       case tNormalFile:
166       {
167          snprintf(S,sizeof(S),"F Mod=%lu",File->ModTime+Head.Epoch);
168          out << S;
169          if ((Head.Flags[Tag] & NormalFile::FlPerm) != 0)
170          {
171             snprintf(S,sizeof(S)," Perm=%lo",File->Permissions);
172             out << S;
173          }
174          if ((Head.Flags[Tag] & NormalFile::FlOwner) != 0)
175          {
176             snprintf(S,sizeof(S)," U=%lu G=%lu",File->User,File->Group);
177             out << S;
178          }       
179          if ((Head.Flags[Tag] & NormalFile::FlMD5) != 0)
180          {
181             char S[16*2+1];
182             for (unsigned int I = 0; I != 16; I++)
183                sprintf(S+2*I,"%02x",File->MD5[I]);
184             S[16*2] = 0;
185             out << " MD5=" << S;
186          }
187          
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());
191          out << S;
192                     
193          break;
194       }
195
196       case tDeviceSpecial:
197       {
198          snprintf(S,sizeof(S),"S Mod=%lu",DevSpecial.ModTime+Head.Epoch);
199          out << S;
200          if ((Head.Flags[Tag] & DeviceSpecial::FlPerm) != 0)
201          {
202             snprintf(S,sizeof(S)," Perm=%lo",DevSpecial.Permissions);
203             out << S;
204          }
205          if ((Head.Flags[Tag] & DeviceSpecial::FlOwner) != 0)
206          {
207             snprintf(S,sizeof(S)," U=%lu G=%lu",DevSpecial.User,DevSpecial.Group);
208             out << S;
209          }       
210          snprintf(S,sizeof(S)," N='%s'\n",DevSpecial.Name.c_str());
211          out << S;
212          break;
213       }
214       
215       case tSymlink:
216       {
217          snprintf(S,sizeof(S),"L Mod=%lu",SLink.ModTime+Head.Epoch);
218          out << S;
219          if ((Head.Flags[Tag] & Symlink::FlOwner) != 0)
220          {
221             snprintf(S,sizeof(S)," U=%lu G=%lu",SLink.User,SLink.Group);
222             out << S;
223          }
224          
225          snprintf(S,sizeof(S)," N='%s' T='%s'\n",SLink.Name.c_str(),SLink.To.c_str());
226          out << S;
227          break;
228       }
229          
230       case dsFList::tTrailer:
231       {
232          snprintf(S,sizeof(S),"T Sig=%lx\n",Trail.Signature);
233          out << S;
234          break;
235       }
236
237       case dsFList::tRSyncChecksum:
238       {
239          snprintf(S,sizeof(S),"RC BlockSize=%lu FileSize=%lu\n",RChk.BlockSize,RChk.FileSize);
240          out << S;
241          break;
242       }
243       
244       case dsFList::tAggregateFile:
245       {
246          snprintf(S,sizeof(S),"RAG File='%s'\n",AgFile.File.c_str());
247          break;
248       }
249
250       case tRSyncEnd:
251       out << "RSE" << endl;
252       break;
253       
254       default:
255       return _error->Error("Unknown tag %u",Tag);
256    }
257    return true;
258 }
259                                                                         /*}}}*/
260
261 // IO::IO - Constructor                                                                 /*{{{*/
262 // ---------------------------------------------------------------------
263 /* */
264 dsFList::IO::IO()
265 {
266    NoStrings = false;
267 }
268                                                                         /*}}}*/
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)
273 {
274    unsigned int I = 0;
275    Number = 0;
276    while (1)
277    {
278       unsigned char Byte = 0;
279       if (Read(&Byte,1) == false)
280          return false;
281       Number |= (Byte & 0x7F) << 7*I;
282       if ((Byte & (1<<7)) == 0)
283          return true;
284       I++;
285    }   
286 }
287                                                                         /*}}}*/
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)
294 {
295    unsigned char Bytes[10];
296    unsigned int I = 0;
297    while (1)
298    {
299       Bytes[I] = Number & 0x7F;
300       Number >>= 7;
301       if (Number != 0)
302          Bytes[I] |= (1<<7);
303       else
304          break;
305       I++;
306    }
307    return Write(Bytes,I+1);
308 }
309                                                                         /*}}}*/
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)
314 {
315    unsigned char Bytes[8];
316    if (Read(&Bytes,Count) == false)
317       return false;
318    
319    Number = 0;
320    for (unsigned int I = 0; I != Count; I++)
321       Number |= (Bytes[I] << I*8);
322    return true;
323 }
324                                                                         /*}}}*/
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)
329 {
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);
334 }
335                                                                         /*}}}*/
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)
340 {
341    unsigned char Bytes[8];
342    if (Read(&Bytes,Count) == false)
343       return false;
344    
345    Number = 0;
346    for (unsigned int I = 0; I != Count; I++)
347       Number |= (Bytes[I] << I*8);
348    return true;
349 }
350                                                                         /*}}}*/
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)
355 {
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);
360 }
361                                                                         /*}}}*/
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)
367 {
368    char S[1024];
369    unsigned long Len;
370    if (ReadNum(Len) == false)
371       return false;
372    if (Len >= sizeof(S))
373       return _error->Error("String buffer too small");   
374    if (Read(S,Len) == false)
375       return false;
376    S[Len] = 0;
377    
378    if (NoStrings == false)
379       Foo = S;
380    else
381       Foo = string();
382    
383    return true;
384 }
385                                                                         /*}}}*/
386 // IO::WriteString - Write a string to the stream                       /*{{{*/
387 // ---------------------------------------------------------------------
388 /* Write a string, we encode a Number contianing the length and then the 
389    string itself */
390 bool dsFList::IO::WriteString(string const &Foo)
391 {
392    return WriteNum(Foo.length()) && Write(Foo.c_str(),strlen(Foo.c_str()));
393 }
394                                                                         /*}}}*/
395
396 // Header::Header - Constructor                                         /*{{{*/
397 // ---------------------------------------------------------------------
398 /* The constructor sets the current signature and version information */
399 dsFList::Header::Header() : Signature(0x97E78AB), MajorVersion(0), 
400                             MinorVersion(1)
401 {
402    Tag = dsFList::tHeader;
403    FlagCount = _count(Flags);
404    memset(Flags,0,sizeof(Flags));
405       
406    Epoch = (unsigned long)time(0);
407 }
408                                                                         /*}}}*/
409 // Header::Read - Read the coded header                                 /*{{{*/
410 // ---------------------------------------------------------------------
411 /* */
412 bool dsFList::Header::Read(IO &IO)
413 {
414    // Read the contents
415    if ((IO.ReadInt(Signature,4) && 
416         IO.ReadInt(MajorVersion,2) && IO.ReadInt(MinorVersion,2) && 
417         IO.ReadNum(Epoch) && IO.ReadInt(FlagCount,1)) == false)
418       return false;
419
420    unsigned long RealFlagCount = FlagCount;
421    if (FlagCount > _count(Flags))
422       FlagCount = _count(Flags);
423    
424    // Read the flag array
425    for (unsigned int I = 0; I != RealFlagCount; I++)
426    {
427       unsigned long Jnk;
428       if (I >= FlagCount)
429       {
430          if (IO.ReadInt(Jnk,4) == false)
431             return false;
432       }
433       else
434       {
435          if (IO.ReadInt(Flags[I],4) == false)
436             return false;
437       }
438    }
439    
440    return true;
441 }
442                                                                         /*}}}*/
443 // Header::Write - Write the coded header                               /*{{{*/
444 // ---------------------------------------------------------------------
445 /* */
446 bool dsFList::Header::Write(IO &IO)
447 {
448    FlagCount = _count(Flags);
449    
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)
454       return false;
455    
456    // Write the flag array
457    for (unsigned int I = 0; I != FlagCount; I++)
458       if (IO.WriteInt(Flags[I],4) == false)
459          return false;
460    return true;
461 }
462                                                                         /*}}}*/
463 // Directory::Read - Read a coded directory record                      /*{{{*/
464 // ---------------------------------------------------------------------
465 /* */
466 bool dsFList::Directory::Read(IO &IO)
467 {
468    unsigned long F = IO.Header.Flags[Tag];
469    
470    if ((IO.ReadInt(ModTime,4)) == false)
471       return false;
472    if ((F & FlPerm) == FlPerm && IO.ReadInt(Permissions,2) == false)
473       return false;
474    if ((F & FlOwner) == FlOwner && (IO.ReadNum(User) && 
475                                     IO.ReadNum(Group)) == false)
476       return false;   
477    if (IO.ReadString(Name) == false)
478       return false;
479    return true;
480 }
481                                                                         /*}}}*/
482 // Directory::Write - Write a compacted directory record                /*{{{*/
483 // ---------------------------------------------------------------------
484 /* */
485 bool dsFList::Directory::Write(IO &IO)
486 {
487    unsigned long F = IO.Header.Flags[Tag];
488    
489    if ((IO.WriteInt(Tag,1) && IO.WriteInt(ModTime,4)) == false)
490       return false;
491    if ((F & FlPerm) == FlPerm && IO.WriteInt(Permissions,2) == false)
492       return false;
493    if ((F & FlOwner) == FlOwner && (IO.WriteNum(User) && 
494                                     IO.WriteNum(Group)) == false)
495       return false;   
496    if (IO.WriteString(Name) == false)
497       return false;
498    return true;
499 }
500                                                                         /*}}}*/
501 // NormalFile::Read - Read the compacted file record                    /*{{{*/
502 // ---------------------------------------------------------------------
503 /* */
504 bool dsFList::NormalFile::Read(IO &IO)
505 {
506    unsigned long F = IO.Header.Flags[Tag];
507    
508    if ((IO.ReadInt(ModTime,4)) == false)
509       return false;
510    if ((F & FlPerm) == FlPerm && IO.ReadInt(Permissions,2) == false)
511       return false;
512    if ((F & FlOwner) == FlOwner && (IO.ReadNum(User) && 
513                                     IO.ReadNum(Group)) == false)
514       return false;   
515    if ((IO.ReadString(Name) && IO.ReadNum(Size)) == false)
516       return false;
517    if ((F & FlMD5) == FlMD5 && IO.Read(&MD5,16) == false)
518       return false;
519    
520    return true;
521 }
522                                                                         /*}}}*/
523 // NormalFile::write - Write the compacted file record                  /*{{{*/
524 // ---------------------------------------------------------------------
525 /* */
526 bool dsFList::NormalFile::Write(IO &IO)
527 {
528    unsigned long F = IO.Header.Flags[Tag];
529    
530    if ((IO.WriteInt(Tag,1) && IO.WriteInt(ModTime,4)) == false)
531       return false;
532    if ((F & FlPerm) == FlPerm && IO.WriteInt(Permissions,2) == false)
533       return false;
534    if ((F & FlOwner) == FlOwner && (IO.WriteNum(User) && 
535                                     IO.WriteNum(Group)) == false)
536       return false;   
537    if ((IO.WriteString(Name) && IO.WriteNum(Size)) == false)
538       return false;
539    if ((F & FlMD5) == FlMD5 && IO.Write(&MD5,16) == false)
540       return false;
541    
542    return true;
543 }
544                                                                         /*}}}*/
545 // Symlink::Read - Read a compacted symlink record                      /*{{{*/
546 // ---------------------------------------------------------------------
547 /* */
548 bool dsFList::Symlink::Read(IO &IO)
549 {
550    unsigned long F = IO.Header.Flags[Tag];
551    
552    if ((IO.ReadInt(ModTime,4)) == false)
553       return false;
554    if ((F & FlOwner) == FlOwner && (IO.ReadNum(User) &&
555                                     IO.ReadNum(Group)) == false)
556       return false;   
557    if ((IO.ReadString(Name) && IO.ReadInt(Compress,1) &&
558         IO.ReadString(To)) == false)
559       return false;
560
561    // Decompress the string
562    if (Compress != 0)
563    {
564       if ((Compress & (1<<7)) == (1<<7))
565          To += Name;
566       if ((Compress & 0x7F) != 0)
567          To = string(IO.LastSymlink,0,Compress & 0x7F) + To;
568    }
569    
570    IO.LastSymlink = To;
571    return true;
572 }
573                                                                         /*}}}*/
574 // Symlink::Write - Write a compacted symlink record                    /*{{{*/
575 // ---------------------------------------------------------------------
576 /* This performs the symlink compression described in the file list
577    document. */
578 bool dsFList::Symlink::Write(IO &IO)
579 {
580    unsigned long F = IO.Header.Flags[Tag];
581    
582    if ((IO.WriteInt(Tag,1) && IO.WriteInt(ModTime,4)) == false)
583       return false;
584    if ((F & FlOwner) == FlOwner && (IO.WriteNum(User) &&
585                                     IO.WriteNum(Group)) == false)
586       return false;
587    
588    if (IO.WriteString(Name) == false)
589       return false;
590    
591    // Attempt to remove the trailing text
592    bool Trail = false;
593    if (To.length() >= Name.length())
594    {
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])
598             break;
599       if (I == To.length())
600          Trail = true;
601    }
602    
603    // Compress the symlink target
604    Compress = 0;
605    unsigned int Len = To.length();
606    if (Trail == true)
607       Len -= Name.length();
608    for (; Compress < Len && Compress < IO.LastSymlink.length() &&
609         Compress < 0x7F; Compress++)
610       if (To[Compress] != IO.LastSymlink[Compress])
611           break;
612
613    // Set the trail flag
614    if (Trail == true)
615       Compress |= (1<<7);
616    
617    // Write the compresion byte
618    if (IO.WriteInt(Compress,1) == false)
619       return false;
620    
621    // Write the data string
622    if (Trail == true)
623    {
624       if (IO.WriteString(string(To,Compress & 0x7F,To.length() - Name.length() - (Compress & 0x7F))) == false)
625          return false;
626    }
627    else
628    {
629       if (IO.WriteString(string(To,Compress,To.length() - Compress)) == false)
630          return false;
631    }
632    
633    IO.LastSymlink = To;
634    
635    return true;
636 }
637                                                                         /*}}}*/
638 // DeviceSpecial::Read - Read a compacted device special record         /*{{{*/
639 // ---------------------------------------------------------------------
640 /* */
641 bool dsFList::DeviceSpecial::Read(IO &IO)
642 {
643    unsigned long F = IO.Header.Flags[Tag];
644    
645    if ((IO.ReadInt(ModTime,4)) == false)
646       return false;
647    if (IO.ReadInt(Permissions,2) == false)
648       return false;
649    if ((F & FlOwner) == FlOwner && (IO.ReadNum(User) &&
650                                     IO.ReadNum(Group)) == false)
651       return false;
652    if ((IO.ReadNum(Dev) && IO.ReadString(Name)) == false)
653       return false;
654    return true;
655 }
656                                                                         /*}}}*/
657 // DeviceSpecial::Write - Write a compacted device special record       /*{{{*/
658 // ---------------------------------------------------------------------
659 /* */
660 bool dsFList::DeviceSpecial::Write(IO &IO)
661 {
662    unsigned long F = IO.Header.Flags[Tag];
663    
664    if ((IO.WriteInt(Tag,1) && IO.WriteInt(ModTime,4)) == false)
665       return false;
666    if (IO.WriteInt(Permissions,2) == false)
667       return false;
668    if ((F & FlOwner) == FlOwner && (IO.WriteNum(User) &&
669                                     IO.WriteNum(Group)) == false)
670       return false;
671    if ((IO.WriteNum(Dev) && IO.WriteString(Name)) == false)
672       return false;
673    return true;
674 }
675                                                                         /*}}}*/
676 // Filter::Read - Read a compacted filter record                        /*{{{*/
677 // ---------------------------------------------------------------------
678 /* */
679 bool dsFList::Filter::Read(IO &IO)
680 {
681    if ((IO.ReadInt(Type,1) && 
682         IO.ReadString(Pattern)) == false)
683       return false;
684    return true;
685 }
686                                                                         /*}}}*/
687 // Filter::Write - Write a compacted filter record                      /*{{{*/
688 // ---------------------------------------------------------------------
689 /* */
690 bool dsFList::Filter::Write(IO &IO)
691 {
692    if ((IO.WriteInt(Tag,1) && IO.WriteInt(Type,1) &&
693         IO.WriteString(Pattern)) == false)
694       return false;
695    return true;
696 }
697                                                                         /*}}}*/
698 // UidGidMap::Read - Read a compacted Uid/Gid map record                /*{{{*/
699 // ---------------------------------------------------------------------
700 /* */
701 bool dsFList::UidGidMap::Read(IO &IO)
702 {
703    unsigned long F = IO.Header.Flags[Tag];
704    if ((IO.ReadNum(FileID)) == false)
705       return false;
706    
707    if ((F & FlRealID) == FlRealID && IO.ReadNum(RealID) == false)
708       return false;
709    if (IO.ReadString(Name) == false)
710       return false;
711    return true;
712 }
713                                                                         /*}}}*/
714 // UidGidMap::Write - Write a compacted Uid/Gid map record              /*{{{*/
715 // ---------------------------------------------------------------------
716 /* */
717 bool dsFList::UidGidMap::Write(IO &IO)
718 {
719    unsigned long F = IO.Header.Flags[Tag];
720    if ((IO.WriteInt(Tag,1) && IO.WriteNum(FileID)) == false)
721       return false;
722    
723    if ((F & FlRealID) == FlRealID && IO.WriteNum(RealID) == false)
724       return false;
725    if (IO.WriteString(Name) == false)
726       return false;
727    return true;
728 }
729                                                                         /*}}}*/
730 // HardLink::Read - Read the compacted link record                      /*{{{*/
731 // ---------------------------------------------------------------------
732 /* */
733 bool dsFList::HardLink::Read(IO &IO)
734 {
735    unsigned long F = IO.Header.Flags[Tag];
736    
737    if ((IO.ReadInt(ModTime,4) && IO.ReadNum(Serial)) == false)
738       return false;
739    if ((F & FlPerm) == FlPerm && IO.ReadInt(Permissions,2) == false)
740       return false;
741    if ((F & FlOwner) == FlOwner && (IO.ReadNum(User) && 
742                                     IO.ReadNum(Group)) == false)
743       return false;   
744    if ((IO.ReadString(Name) && IO.ReadNum(Size)) == false)
745       return false;
746    if ((F & FlMD5) == FlMD5 && IO.Read(&MD5,16) == false)
747       return false;
748    
749    return true;
750 }
751                                                                         /*}}}*/
752 // HardLink::Write - Write the compacted file record                    /*{{{*/
753 // ---------------------------------------------------------------------
754 /* */
755 bool dsFList::HardLink::Write(IO &IO)
756 {
757    unsigned long F = IO.Header.Flags[Tag];
758    
759    if ((IO.WriteInt(Tag,1) && IO.WriteInt(ModTime,4) && 
760         IO.ReadNum(Serial)) == false)
761       return false;
762    if ((F & FlPerm) == FlPerm && IO.WriteInt(Permissions,2) == false)
763       return false;
764    if ((F & FlOwner) == FlOwner && (IO.WriteNum(User) && 
765                                     IO.WriteNum(Group)) == false)
766       return false;   
767    if ((IO.WriteString(Name) && IO.WriteNum(Size)) == false)
768       return false;
769    if ((F & FlMD5) == FlMD5 && IO.Write(&MD5,16) == false)
770       return false;
771    
772    return true;
773 }
774                                                                         /*}}}*/
775 // Trailer::Trailer - Constructor                                       /*{{{*/
776 // ---------------------------------------------------------------------
777 /* */
778 dsFList::Trailer::Trailer() : Tag(dsFList::tTrailer), Signature(0xBA87E79)
779 {
780 }
781                                                                         /*}}}*/
782 // Trailer::Read - Read a compacted tail record                         /*{{{*/
783 // ---------------------------------------------------------------------
784 /* */
785 bool dsFList::Trailer::Read(IO &IO)
786 {
787    if (IO.ReadInt(Signature,4) == false)
788       return false;
789    return true;
790 }
791                                                                         /*}}}*/
792 // Trailer::Write - Write a compacted tail record                       /*{{{*/
793 // ---------------------------------------------------------------------
794 /* */
795 bool dsFList::Trailer::Write(IO &IO)
796 {
797    if ((IO.WriteInt(Tag,1) &&
798         IO.WriteInt(Signature,4)) == false)
799       return false;
800    return true;
801 }
802                                                                         /*}}}*/
803 // RSyncChecksum::RSyncChecksum - Constructor                           /*{{{*/
804 // ---------------------------------------------------------------------
805 /* */
806 dsFList::RSyncChecksum::RSyncChecksum() : Tag(dsFList::tRSyncChecksum),
807                                           Sums(0)
808 {
809 }
810                                                                         /*}}}*/
811 // RSyncChecksum::~RSyncChecksum - Constructor                          /*{{{*/
812 // ---------------------------------------------------------------------
813 /* */
814 dsFList::RSyncChecksum::~RSyncChecksum() 
815 {
816    delete [] Sums;
817 }
818                                                                         /*}}}*/
819 // RSyncChecksum::Read - Read a compacted device special record         /*{{{*/
820 // ---------------------------------------------------------------------
821 /* */
822 bool dsFList::RSyncChecksum::Read(IO &IO)
823 {
824    if ((IO.ReadNum(BlockSize) && IO.ReadNum(FileSize)) == false)
825       return false;
826    
827    // Read in the checksum table
828    delete [] Sums;
829    Sums = new unsigned char[(FileSize + BlockSize-1)/BlockSize*20];
830    if (IO.Read(Sums,(FileSize + BlockSize-1)/BlockSize*20) == false)
831       return false;
832    
833    return true;
834 }
835                                                                         /*}}}*/
836 // RSyncChecksum::Write - Write a compacted device special record       /*{{{*/
837 // ---------------------------------------------------------------------
838 /* */
839 bool dsFList::RSyncChecksum::Write(IO &IO)
840 {
841    if ((IO.WriteInt(Tag,1) && IO.WriteNum(BlockSize) &&
842         IO.WriteNum(FileSize)) == false)
843       return false;
844    
845    if (IO.Write(Sums,(FileSize + BlockSize-1)/BlockSize*20) == false)
846       return false;
847    return true;
848 }
849                                                                         /*}}}*/
850 // AggregateFile::Read - Read a aggregate file record                   /*{{{*/
851 // ---------------------------------------------------------------------
852 /* */
853 bool dsFList::AggregateFile::Read(IO &IO)
854 {
855    return IO.ReadString(File);
856 }
857                                                                         /*}}}*/
858 // AggregateFile::Write - Write a compacted filter record               /*{{{*/
859 // ---------------------------------------------------------------------
860 /* */
861 bool dsFList::AggregateFile::Write(IO &IO)
862 {
863    if ((IO.WriteInt(Tag,1) && IO.WriteString(File)) == false)
864       return false;
865    return true;
866 }
867                                                                         /*}}}*/