1 // This file is part of par2cmdline (a PAR 2.0 compatible file verification and
2 // repair tool). See http://parchive.sourceforge.net for details of PAR 2.0.
3 //
4 // Copyright (c) 2003 Peter Brian Clements
5 //
6 // par2cmdline is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 2 of the License, or
9 // (at your option) any later version.
10 //
11 // par2cmdline is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
19
20 #include "par2cmdline.h"
21
22 #ifdef _MSC_VER
23 #ifdef _DEBUG
24 #undef THIS_FILE
25 static char THIS_FILE[]=__FILE__;
26 #define new DEBUG_NEW
27 #endif
28 #endif
29
30
31 #ifdef WIN32
32 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
33
34 #define OffsetType __int64
35 #define MaxOffset 0x7fffffffffffffffI64
36 #define LengthType unsigned int
37 #define MaxLength 0xffffffffUL
38
DiskFile(void)39 DiskFile::DiskFile(void)
40 {
41 filename;
42 filesize = 0;
43 offset = 0;
44
45 hFile = INVALID_HANDLE_VALUE;
46
47 exists = false;
48 }
49
~DiskFile(void)50 DiskFile::~DiskFile(void)
51 {
52 if (hFile != INVALID_HANDLE_VALUE)
53 ::CloseHandle(hFile);
54 }
55
56 // Create new file on disk and make sure that there is enough
57 // space on disk for it.
Create(string _filename,u64 _filesize)58 bool DiskFile::Create(string _filename, u64 _filesize)
59 {
60 assert(hFile == INVALID_HANDLE_VALUE);
61
62 filename = _filename;
63 filesize = _filesize;
64
65 // Create the file
66 hFile = ::CreateFileA(_filename.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, NULL);
67 if (hFile == INVALID_HANDLE_VALUE)
68 {
69 DWORD error = ::GetLastError();
70
71 cerr << "Could not create \"" << _filename << "\": " << ErrorMessage(error) << endl;
72
73 return false;
74 }
75
76 if (filesize > 0)
77 {
78 // Seek to the end of the file
79 LONG lowoffset = ((LONG*)&filesize)[0];
80 LONG highoffset = ((LONG*)&filesize)[1];
81
82 if (INVALID_SET_FILE_POINTER == SetFilePointer(hFile, lowoffset, &highoffset, FILE_BEGIN))
83 {
84 DWORD error = ::GetLastError();
85
86 cerr << "Could not set size of \"" << _filename << "\": " << ErrorMessage(error) << endl;
87
88 ::CloseHandle(hFile);
89 hFile = INVALID_HANDLE_VALUE;
90 ::DeleteFile(_filename.c_str());
91
92 return false;
93 }
94
95 // Set the end of the file
96 if (!::SetEndOfFile(hFile))
97 {
98 DWORD error = ::GetLastError();
99
100 cerr << "Could not set size of \"" << _filename << "\": " << ErrorMessage(error) << endl;
101
102 ::CloseHandle(hFile);
103 hFile = INVALID_HANDLE_VALUE;
104 ::DeleteFile(_filename.c_str());
105
106 return false;
107 }
108 }
109
110 offset = filesize;
111
112 exists = true;
113 return true;
114 }
115
116 // Write some data to disk
117
Write(u64 _offset,const void * buffer,size_t length)118 bool DiskFile::Write(u64 _offset, const void *buffer, size_t length)
119 {
120 assert(hFile != INVALID_HANDLE_VALUE);
121
122 if (offset != _offset)
123 {
124 LONG lowoffset = ((LONG*)&_offset)[0];
125 LONG highoffset = ((LONG*)&_offset)[1];
126
127 // Seek to the required offset
128 if (INVALID_SET_FILE_POINTER == SetFilePointer(hFile, lowoffset, &highoffset, FILE_BEGIN))
129 {
130 DWORD error = ::GetLastError();
131
132 cerr << "Could not write " << (u64)length << " bytes to \"" << filename << "\" at offset " << _offset << ": " << ErrorMessage(error) << endl;
133
134 return false;
135 }
136 offset = _offset;
137 }
138
139 if (length > MaxLength)
140 {
141 cerr << "Could not write " << (u64)length << " bytes to \"" << filename << "\" at offset " << _offset << ": " << "Write too long" << endl;
142
143 return false;
144 }
145
146 DWORD write = (LengthType)length;
147 DWORD wrote;
148
149 // Write the data
150 if (!::WriteFile(hFile, buffer, write, &wrote, NULL))
151 {
152 DWORD error = ::GetLastError();
153
154 cerr << "Could not write " << (u64)length << " bytes to \"" << filename << "\" at offset " << _offset << ": " << ErrorMessage(error) << endl;
155
156 return false;
157 }
158
159 offset += length;
160
161 if (filesize < offset)
162 {
163 filesize = offset;
164 }
165
166 return true;
167 }
168
169 // Open the file
170
Open(string _filename,u64 _filesize)171 bool DiskFile::Open(string _filename, u64 _filesize)
172 {
173 assert(hFile == INVALID_HANDLE_VALUE);
174
175 filename = _filename;
176 filesize = _filesize;
177
178 hFile = ::CreateFileA(_filename.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
179 if (hFile == INVALID_HANDLE_VALUE)
180 {
181 DWORD error = ::GetLastError();
182
183 switch (error)
184 {
185 case ERROR_FILE_NOT_FOUND:
186 case ERROR_PATH_NOT_FOUND:
187 break;
188 default:
189 cerr << "Could not open \"" << _filename << "\": " << ErrorMessage(error) << endl;
190 }
191
192 return false;
193 }
194
195 offset = 0;
196 exists = true;
197
198 return true;
199 }
200
201 // Read some data from disk
202
Read(u64 _offset,void * buffer,size_t length)203 bool DiskFile::Read(u64 _offset, void *buffer, size_t length)
204 {
205 assert(hFile != INVALID_HANDLE_VALUE);
206
207 if (offset != _offset)
208 {
209 LONG lowoffset = ((LONG*)&_offset)[0];
210 LONG highoffset = ((LONG*)&_offset)[1];
211
212 // Seek to the required offset
213 if (INVALID_SET_FILE_POINTER == SetFilePointer(hFile, lowoffset, &highoffset, FILE_BEGIN))
214 {
215 DWORD error = ::GetLastError();
216
217 cerr << "Could not read " << (u64)length << " bytes from \"" << filename << "\" at offset " << _offset << ": " << ErrorMessage(error) << endl;
218
219 return false;
220 }
221 offset = _offset;
222 }
223
224 if (length > MaxLength)
225 {
226 cerr << "Could not read " << (u64)length << " bytes from \"" << filename << "\" at offset " << _offset << ": " << "Read too long" << endl;
227
228 return false;
229 }
230
231 DWORD want = (LengthType)length;
232 DWORD got;
233
234 // Read the data
235 if (!::ReadFile(hFile, buffer, want, &got, NULL))
236 {
237 DWORD error = ::GetLastError();
238
239 cerr << "Could not read " << (u64)length << " bytes from \"" << filename << "\" at offset " << _offset << ": " << ErrorMessage(error) << endl;
240
241 return false;
242 }
243
244 offset += length;
245
246 return true;
247 }
248
Close(void)249 void DiskFile::Close(void)
250 {
251 if (hFile != INVALID_HANDLE_VALUE)
252 {
253 ::CloseHandle(hFile);
254 hFile = INVALID_HANDLE_VALUE;
255 }
256 }
257
GetCanonicalPathname(string filename)258 string DiskFile::GetCanonicalPathname(string filename)
259 {
260 char fullname[MAX_PATH];
261 char *filepart;
262
263 // Resolve a relative path to a full path
264 int length = ::GetFullPathName(filename.c_str(), sizeof(fullname), fullname, &filepart);
265 if (length <= 0 || sizeof(fullname) < length)
266 return filename;
267
268 // Make sure the drive letter is upper case.
269 fullname[0] = toupper(fullname[0]);
270
271 // Translate all /'s to \'s
272 char *current = strchr(fullname, '/');
273 while (current)
274 {
275 *current++ = '\\';
276 current = strchr(current, '/');
277 }
278
279 // Copy the root directory to the output string
280 string longname(fullname, 3);
281
282 // Start processing at the first path component
283 current = &fullname[3];
284 char *limit = &fullname[length];
285
286 // Process until we reach the end of the full name
287 while (current < limit)
288 {
289 char *tail;
290
291 // Find the next \, or the end of the string
292 (tail = strchr(current, '\\')) || (tail = limit);
293 *tail = 0;
294
295 // Create a wildcard to search for the path
296 string wild = longname + current;
297 WIN32_FIND_DATA finddata;
298 HANDLE hFind = ::FindFirstFile(wild.c_str(), &finddata);
299 if (hFind == INVALID_HANDLE_VALUE)
300 {
301 // If the component was not found then just copy the rest of the path to the
302 // output buffer verbatim.
303 longname += current;
304 break;
305 }
306 ::FindClose(hFind);
307
308 // Copy the component found to the output
309 longname += finddata.cFileName;
310
311 current = tail + 1;
312
313 // If we have not reached the end of the name, add a "\"
314 if (current < limit)
315 longname += '\\';
316 }
317
318 return longname;
319 }
320
FindFiles(string path,string wildcard)321 list<string>* DiskFile::FindFiles(string path, string wildcard)
322 {
323 list<string> *matches = new list<string>;
324
325 wildcard = path + wildcard;
326 WIN32_FIND_DATA fd;
327 HANDLE h = ::FindFirstFile(wildcard.c_str(), &fd);
328 if (h != INVALID_HANDLE_VALUE)
329 {
330 do
331 {
332 if (0 == (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
333 {
334 matches->push_back(path + fd.cFileName);
335 }
336 } while (::FindNextFile(h, &fd));
337 ::FindClose(h);
338 }
339
340 return matches;
341 }
342
343
344
345
346 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
347 #else // !WIN32
348 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
349
350 #ifdef HAVE_FSEEKO
351 # define OffsetType off_t
352 # define MaxOffset ((off_t)0x7fffffffffffffffULL)
353 # define fseek fseeko
354 #else
355 # if _FILE_OFFSET_BITS == 64
356 # define OffsetType unsigned long long
357 # define MaxOffset 0x7fffffffffffffffULL
358 # else
359 # define OffsetType long
360 # define MaxOffset 0x7fffffffUL
361 # endif
362 #endif
363
364 #define LengthType unsigned int
365 #define MaxLength 0xffffffffUL
366
DiskFile(void)367 DiskFile::DiskFile(void)
368 {
369 //filename;
370 filesize = 0;
371 offset = 0;
372
373 file = 0;
374
375 exists = false;
376 }
377
~DiskFile(void)378 DiskFile::~DiskFile(void)
379 {
380 if (file != 0)
381 fclose(file);
382 }
383
384 // Create new file on disk and make sure that there is enough
385 // space on disk for it.
Create(string _filename,u64 _filesize)386 bool DiskFile::Create(string _filename, u64 _filesize)
387 {
388 assert(file == 0);
389
390 filename = _filename;
391 filesize = _filesize;
392
393 file = fopen(_filename.c_str(), "wb");
394 if (file == 0)
395 {
396 cerr << "Could not create: " << _filename << endl;
397
398 return false;
399 }
400
401 if (_filesize > (u64)MaxOffset)
402 {
403 cerr << "Requested file size for " << _filename << " is too large." << endl;
404 return false;
405 }
406
407 if (_filesize > 0)
408 {
409 if (fseek(file, (OffsetType)_filesize-1, SEEK_SET))
410 {
411 fclose(file);
412 file = 0;
413 ::remove(filename.c_str());
414
415 cerr << "Could not set end of file: " << _filename << endl;
416 return false;
417 }
418
419 if (1 != fwrite(&_filesize, 1, 1, file))
420 {
421 fclose(file);
422 file = 0;
423 ::remove(filename.c_str());
424
425 cerr << "Could not set end of file: " << _filename << endl;
426 return false;
427 }
428 }
429
430 offset = filesize;
431
432 exists = true;
433 return true;
434 }
435
436 // Write some data to disk
437
Write(u64 _offset,const void * buffer,size_t length)438 bool DiskFile::Write(u64 _offset, const void *buffer, size_t length)
439 {
440 assert(file != 0);
441
442 if (offset != _offset)
443 {
444 if (_offset > (u64)MaxOffset)
445 {
446 cerr << "Could not write " << (u64)length << " bytes to " << filename << " at offset " << _offset << endl;
447 return false;
448 }
449
450
451 if (fseek(file, (OffsetType)_offset, SEEK_SET))
452 {
453 cerr << "Could not write " << (u64)length << " bytes to " << filename << " at offset " << _offset << endl;
454 return false;
455 }
456 offset = _offset;
457 }
458
459 if (length > MaxLength)
460 {
461 cerr << "Could not write " << (u64)length << " bytes to " << filename << " at offset " << _offset << endl;
462 return false;
463 }
464
465 if (1 != fwrite(buffer, (LengthType)length, 1, file))
466 {
467 cerr << "Could not write " << (u64)length << " bytes to " << filename << " at offset " << _offset << endl;
468 return false;
469 }
470
471 offset += length;
472
473 if (filesize < offset)
474 {
475 filesize = offset;
476 }
477
478 return true;
479 }
480
481 // Open the file
482
Open(string _filename,u64 _filesize)483 bool DiskFile::Open(string _filename, u64 _filesize)
484 {
485 assert(file == 0);
486
487 filename = _filename;
488 filesize = _filesize;
489
490 if (_filesize > (u64)MaxOffset)
491 {
492 cerr << "File size for " << _filename << " is too large." << endl;
493 return false;
494 }
495
496 file = fopen(filename.c_str(), "rb");
497 if (file == 0)
498 {
499 return false;
500 }
501
502 offset = 0;
503 exists = true;
504
505 return true;
506 }
507
508 // Read some data from disk
509
Read(u64 _offset,void * buffer,size_t length)510 bool DiskFile::Read(u64 _offset, void *buffer, size_t length)
511 {
512 assert(file != 0);
513
514 if (offset != _offset)
515 {
516 if (_offset > (u64)MaxOffset)
517 {
518 cerr << "Could not read " << (u64)length << " bytes from " << filename << " at offset " << _offset << endl;
519 return false;
520 }
521
522
523 if (fseek(file, (OffsetType)_offset, SEEK_SET))
524 {
525 cerr << "Could not read " << (u64)length << " bytes from " << filename << " at offset " << _offset << endl;
526 return false;
527 }
528 offset = _offset;
529 }
530
531 if (length > MaxLength)
532 {
533 cerr << "Could not read " << (u64)length << " bytes from " << filename << " at offset " << _offset << endl;
534 return false;
535 }
536
537 if (1 != fread(buffer, (LengthType)length, 1, file))
538 {
539 cerr << "Could not read " << (u64)length << " bytes from " << filename << " at offset " << _offset << endl;
540 return false;
541 }
542
543 offset += length;
544
545 return true;
546 }
547
Close(void)548 void DiskFile::Close(void)
549 {
550 if (file != 0)
551 {
552 fclose(file);
553 file = 0;
554 }
555 }
556
557 // Attempt to get the full pathname of the file
GetCanonicalPathname(string filename)558 string DiskFile::GetCanonicalPathname(string filename)
559 {
560 // Is the supplied path already an absolute one
561 if (filename.size() == 0 || filename[0] == '/')
562 return filename;
563
564 // Get the current directory
565 char curdir[1000];
566 if (0 == getcwd(curdir, sizeof(curdir)))
567 {
568 return filename;
569 }
570
571
572 // Allocate a work buffer and copy the resulting full path into it.
573 char *work = new char[strlen(curdir) + filename.size() + 2];
574 strcpy(work, curdir);
575 if (work[strlen(work)-1] != '/')
576 strcat(work, "/");
577 strcat(work, filename.c_str());
578
579 char *in = work;
580 char *out = work;
581
582 while (*in)
583 {
584 if (*in == '/')
585 {
586 if (in[1] == '.' && in[2] == '/')
587 {
588 // skip the input past /./
589 in += 2;
590 }
591 else if (in[1] == '.' && in[2] == '.' && in[3] == '/')
592 {
593 // backtrack the output if /../ was found on the input
594 in += 3;
595 if (out > work)
596 {
597 do
598 {
599 out--;
600 } while (out > work && *out != '/');
601 }
602 }
603 else
604 {
605 *out++ = *in++;
606 }
607 }
608 else
609 {
610 *out++ = *in++;
611 }
612 }
613 *out = 0;
614
615 string result = work;
616 delete [] work;
617
618 return result;
619 }
620
FindFiles(string path,string wildcard)621 list<string>* DiskFile::FindFiles(string path, string wildcard)
622 {
623 list<string> *matches = new list<string>;
624
625 string::size_type where;
626
627 if ((where = wildcard.find_first_of('*')) != string::npos ||
628 (where = wildcard.find_first_of('?')) != string::npos)
629 {
630 string front = wildcard.substr(0, where);
631 bool multiple = wildcard[where] == '*';
632 string back = wildcard.substr(where+1);
633
634 DIR *dirp = opendir(path.c_str());
635 if (dirp != 0)
636 {
637 struct dirent *d;
638 while ((d = readdir(dirp)) != 0)
639 {
640 string name = d->d_name;
641
642 if (name == "." || name == "..")
643 continue;
644
645 if (multiple)
646 {
647 if (name.size() >= wildcard.size() &&
648 name.substr(0, where) == front &&
649 name.substr(name.size()-back.size()) == back)
650 {
651 matches->push_back(path + name);
652 }
653 }
654 else
655 {
656 if (name.size() == wildcard.size())
657 {
658 string::const_iterator pw = wildcard.begin();
659 string::const_iterator pn = name.begin();
660 while (pw != wildcard.end())
661 {
662 if (*pw != '?' && *pw != *pn)
663 break;
664 ++pw;
665 ++pn;
666 }
667
668 if (pw == wildcard.end())
669 {
670 matches->push_back(path + name);
671 }
672 }
673 }
674
675 }
676 closedir(dirp);
677 }
678 }
679 else
680 {
681 struct stat st;
682 string fn = path + wildcard;
683 if (stat(fn.c_str(), &st) == 0)
684 {
685 matches->push_back(path + wildcard);
686 }
687 }
688
689 return matches;
690 }
691
692 /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
693 #endif
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
Open(void)717 bool DiskFile::Open(void)
718 {
719 string _filename = filename;
720
721 return Open(_filename);
722 }
723
Open(string _filename)724 bool DiskFile::Open(string _filename)
725 {
726 return Open(_filename, GetFileSize(_filename));
727 }
728
729
730
731
732
733
734
735
736
737 // Delete the file
738
Delete(void)739 bool DiskFile::Delete(void)
740 {
741 #ifdef WIN32
742 assert(hFile == INVALID_HANDLE_VALUE);
743 #else
744 assert(file == 0);
745 #endif
746
747 if (filename.size() > 0 && 0 == unlink(filename.c_str()))
748 {
749 return true;
750 }
751 else
752 {
753 cerr << "Cannot delete " << filename << endl;
754
755 return false;
756 }
757 }
758
759
760
761
762
763
764
765
766
767 //string DiskFile::GetPathFromFilename(string filename)
768 //{
769 // string::size_type where;
770 //
771 // if (string::npos != (where = filename.find_last_of('/')) ||
772 // string::npos != (where = filename.find_last_of('\\')))
773 // {
774 // return filename.substr(0, where+1);
775 // }
776 // else
777 // {
778 // return "." PATHSEP;
779 // }
780 //}
781
SplitFilename(string filename,string & path,string & name)782 void DiskFile::SplitFilename(string filename, string &path, string &name)
783 {
784 string::size_type where;
785
786 if (string::npos != (where = filename.find_last_of('/')) ||
787 string::npos != (where = filename.find_last_of('\\')))
788 {
789 path = filename.substr(0, where+1);
790 name = filename.substr(where+1);
791 }
792 else
793 {
794 path = "." PATHSEP;
795 name = filename;
796 }
797 }
798
FileExists(string filename)799 bool DiskFile::FileExists(string filename)
800 {
801 struct stat st;
802 return ((0 == stat(filename.c_str(), &st)) && (0 != (st.st_mode & S_IFREG)));
803 }
804
GetFileSize(string filename)805 u64 DiskFile::GetFileSize(string filename)
806 {
807 struct stat st;
808 if ((0 == stat(filename.c_str(), &st)) && (0 != (st.st_mode & S_IFREG)))
809 {
810 return st.st_size;
811 }
812 else
813 {
814 return 0;
815 }
816 }
817
818
819
820 // Take a filename from a PAR2 file and replace any characters
821 // which would be illegal for a file on disk
TranslateFilename(string filename)822 string DiskFile::TranslateFilename(string filename)
823 {
824 string result;
825
826 string::iterator p = filename.begin();
827 while (p != filename.end())
828 {
829 unsigned char ch = *p;
830
831 bool ok = true;
832 #ifdef WIN32
833 if (ch < 32)
834 {
835 ok = false;
836 }
837 else
838 {
839 switch (ch)
840 {
841 case '"':
842 case '*':
843 case '/':
844 case ':':
845 case '<':
846 case '>':
847 case '?':
848 case '\\':
849 case '|':
850 ok = false;
851 }
852 }
853 #else
854 if (ch < 32)
855 {
856 ok = false;
857 }
858 else
859 {
860 switch (ch)
861 {
862 case '/':
863 ok = false;
864 }
865 }
866 #endif
867
868
869 if (ok)
870 {
871 result += ch;
872 }
873 else
874 {
875 // convert problem characters to hex
876 result += ((ch >> 4) < 10) ? (ch >> 4) + '0' : (ch >> 4) + 'A'-10;
877 result += ((ch & 0xf) < 10) ? (ch & 0xf) + '0' : (ch & 0xf) + 'A'-10;
878 }
879
880 ++p;
881 }
882
883 return result;
884 }
885
Rename(void)886 bool DiskFile::Rename(void)
887 {
888 char newname[_MAX_PATH+1];
889 u32 index = 0;
890
891 struct stat st;
892
893 do
894 {
895 int length = snprintf(newname, _MAX_PATH, "%s.%d", filename.c_str(), ++index);
896 if (length < 0 || length >= _MAX_PATH)
897 {
898 cerr << filename << " cannot be renamed." << endl;
899 return false;
900 }
901 newname[length] = 0;
902 } while (stat(newname, &st) == 0);
903
904 return Rename(newname);
905 }
906
Rename(string _filename)907 bool DiskFile::Rename(string _filename)
908 {
909 #ifdef WIN32
910 assert(hFile == INVALID_HANDLE_VALUE);
911 #else
912 assert(file == 0);
913 #endif
914
915 if (::rename(filename.c_str(), _filename.c_str()) == 0)
916 {
917 filename = _filename;
918
919 return true;
920 }
921 else
922 {
923 cerr << filename << " cannot be renamed to " << _filename << endl;
924
925 return false;
926 }
927 }
928
929 #ifdef WIN32
ErrorMessage(DWORD error)930 string DiskFile::ErrorMessage(DWORD error)
931 {
932 string result;
933
934 LPVOID lpMsgBuf;
935 if (::FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
936 NULL,
937 error,
938 MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
939 (LPSTR)&lpMsgBuf,
940 0,
941 NULL))
942 {
943 result = (char*)lpMsgBuf;
944 LocalFree(lpMsgBuf);
945 }
946 else
947 {
948 char message[40];
949 _snprintf(message, sizeof(message), "Unknown error code (%d)", error);
950 result = message;
951 }
952
953 return result;
954 }
955 #endif
956
DiskFileMap(void)957 DiskFileMap::DiskFileMap(void)
958 {
959 }
960
~DiskFileMap(void)961 DiskFileMap::~DiskFileMap(void)
962 {
963 map<string, DiskFile*>::iterator fi = diskfilemap.begin();
964 while (fi != diskfilemap.end())
965 {
966 delete (*fi).second;
967
968 ++fi;
969 }
970 }
971
Insert(DiskFile * diskfile)972 bool DiskFileMap::Insert(DiskFile *diskfile)
973 {
974 string filename = diskfile->FileName();
975 assert(filename.length() != 0);
976
977 pair<map<string,DiskFile*>::const_iterator,bool> location = diskfilemap.insert(pair<string,DiskFile*>(filename, diskfile));
978
979 return location.second;
980 }
981
Remove(DiskFile * diskfile)982 void DiskFileMap::Remove(DiskFile *diskfile)
983 {
984 string filename = diskfile->FileName();
985 assert(filename.length() != 0);
986
987 diskfilemap.erase(filename);
988 }
989
Find(string filename) const990 DiskFile* DiskFileMap::Find(string filename) const
991 {
992 assert(filename.length() != 0);
993
994 map<string, DiskFile*>::const_iterator f = diskfilemap.find(filename);
995
996 return (f != diskfilemap.end()) ? f->second : 0;
997 }
998