diff options
Diffstat (limited to 'src/hdb/hdbtest.cc')
| -rw-r--r-- | src/hdb/hdbtest.cc | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/src/hdb/hdbtest.cc b/src/hdb/hdbtest.cc new file mode 100644 index 0000000..89169da --- /dev/null +++ b/src/hdb/hdbtest.cc | |||
| @@ -0,0 +1,153 @@ | |||
| 1 | /************************************************************************* | ||
| 2 | * | ||
| 3 | * HTCd - Copyright (C) 1998-2006 Henrik Rydberg | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify | ||
| 6 | * it under the terms of the GNU General Public License as published by | ||
| 7 | * the Free Software Foundation; either version 2 of the License, or | ||
| 8 | * (at your option) any later version. | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | * | ||
| 15 | * You should have received a copy of the GNU General Public License | ||
| 16 | * along with this program; if not, write to the Free Software | ||
| 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <hdb/db.h> | ||
| 21 | |||
| 22 | static fp_stream mout(stdout),merr(stderr); | ||
| 23 | |||
| 24 | main(int argc,char* argv[]) try | ||
| 25 | { | ||
| 26 | if(argc<2) { | ||
| 27 | mout<<"Usage: "<<argv[0]<<" [-s] <path>\n"; | ||
| 28 | return -1; | ||
| 29 | } | ||
| 30 | mstring path; int silent; | ||
| 31 | if(argc>2) { silent=atoi(argv[1]); path=argv[2]; } | ||
| 32 | else { silent=0; path=argv[1]; } | ||
| 33 | mstring map; if(map.load(path)<0) THROW("hdbfix: could not open "<<path); | ||
| 34 | filemap::head_t head; | ||
| 35 | mstring version=First(sref(head.ident,sizeof(head.ident))); | ||
| 36 | memcpy(&head,map.data(),sizeof(head)); | ||
| 37 | mstring cver=First(sref(head.ident,sizeof(head.ident))); | ||
| 38 | mstring answer; | ||
| 39 | int save=0; | ||
| 40 | if(version!=cver) { | ||
| 41 | merr<<path<<": Not a "<<version<<" file\n"; | ||
| 42 | return -1; | ||
| 43 | } | ||
| 44 | else { | ||
| 45 | int top=head.frame.get(),last=0; | ||
| 46 | while(top<head.filetop.get()&&top<map.size()) { | ||
| 47 | filemap::rec_t* rec=(filemap::rec_t*)(map.data()+top); | ||
| 48 | if(rec->mem.get()<=0) break; | ||
| 49 | if(silent) { | ||
| 50 | if(silent==top) { | ||
| 51 | mout<<top<<" *************\n"; | ||
| 52 | for(int i=0;i<65536;i++) { | ||
| 53 | char c=map.data()[top+i]; | ||
| 54 | if(cset_printable.test(c)) mout.put(c); | ||
| 55 | } | ||
| 56 | mout<<"\n\n"; | ||
| 57 | } | ||
| 58 | } | ||
| 59 | else { | ||
| 60 | mout<<top<<" *************\n"; | ||
| 61 | for(int i=0;i<1024;i++) { | ||
| 62 | char c=map.data()[top+i]; | ||
| 63 | if(cset_printable.test(c)) mout.put(c); | ||
| 64 | } | ||
| 65 | mout<<"\n\n"; | ||
| 66 | } | ||
| 67 | last=top; top+=rec->mem.get(); | ||
| 68 | } | ||
| 69 | if(top==head.filetop.get()&&head.filesize.get()==map.size()) { | ||
| 70 | if(!silent) mout<<path<<": OK\n"; | ||
| 71 | } | ||
| 72 | else { | ||
| 73 | mout<<path<<": CORRUPTED\n"; | ||
| 74 | if(silent) return 0; | ||
| 75 | mout<<"\n"; | ||
| 76 | mout<<"Head info:\n"; | ||
| 77 | mout<<"Size: "<<head.filesize.get()<<"\n"; | ||
| 78 | mout<<"Frame: "<<head.frame.get()<<"\n"; | ||
| 79 | mout<<"Top: "<<head.filetop.get()<<"\n"; | ||
| 80 | mout<<"\n"; | ||
| 81 | |||
| 82 | mout<<"Actual sizes:\n"; | ||
| 83 | mout<<"Size: "<<map.size()<<"\n"; | ||
| 84 | mout<<"Last: "<<last<<"\n"; | ||
| 85 | mout<<"End: "<<top<<"\n"; | ||
| 86 | mout<<"\n"; | ||
| 87 | |||
| 88 | if(map.size()!=head.filesize.get()) { | ||
| 89 | mout<<"Filesizes differ - do you want to set the filesize to " | ||
| 90 | <<head.filesize.get()<<"?\n"; | ||
| 91 | getline(answer,stdin); answer.tolower(); | ||
| 92 | if(*answer=='y') { | ||
| 93 | map.resize(head.filesize.get()); | ||
| 94 | save=1; | ||
| 95 | mout<<"Done.\n"; | ||
| 96 | } | ||
| 97 | else { | ||
| 98 | mout<<"No change - quitting.\n"; | ||
| 99 | return 0; | ||
| 100 | } | ||
| 101 | } | ||
| 102 | |||
| 103 | int nend=0,end=head.filetop.get(); | ||
| 104 | for(int p=head.filetop.get()-4;p>=last;p-=4){ | ||
| 105 | unsigned val=*(unsigned*)(map.data()+p); | ||
| 106 | if(p+val==end) { nend++; end=p; } | ||
| 107 | } | ||
| 108 | int gap=end-top; | ||
| 109 | |||
| 110 | mout<<"GAP DATA\n"; | ||
| 111 | mout<<"==============================\n"; | ||
| 112 | for(int i=top;i<end;i++) { | ||
| 113 | if(cset_printable.test(map[i])) mout.put(map[i]); | ||
| 114 | else if(map[i]) mout<<"["<<(int)map[i]<<"]"; | ||
| 115 | } | ||
| 116 | mout<<"\n==============================\n"; | ||
| 117 | mout<<"\n"; | ||
| 118 | |||
| 119 | mout<<"At-end sequence:\n"; | ||
| 120 | mout<<"Start: "<<end<<"\n"; | ||
| 121 | mout<<"Gap: "<<gap<<"\n"; | ||
| 122 | mout<<"\n"; | ||
| 123 | |||
| 124 | if(gap>0) { | ||
| 125 | mout<<"Do you want to mark the gap as deleted?\n"; | ||
| 126 | getline(answer,stdin); answer.tolower(); | ||
| 127 | if(*answer=='y') { | ||
| 128 | filemap::rec_t* rec=(filemap::rec_t*)(map.data()+top); | ||
| 129 | rec->mem.set(gap); | ||
| 130 | rec->caps.set(0); | ||
| 131 | save=1; | ||
| 132 | mout<<"Done.\n"; | ||
| 133 | } | ||
| 134 | else { | ||
| 135 | mout<<"No change - quitting.\n"; | ||
| 136 | return 0; | ||
| 137 | } | ||
| 138 | } | ||
| 139 | } | ||
| 140 | } | ||
| 141 | |||
| 142 | if(save) map.save(path); | ||
| 143 | |||
| 144 | return 0; | ||
| 145 | } | ||
| 146 | catch(const merror_t& e) { | ||
| 147 | merr<<e.desc<<"\n"; | ||
| 148 | return -1; | ||
| 149 | } | ||
| 150 | catch(...) { | ||
| 151 | merr<<"FATAL ERROR\n"; | ||
| 152 | return -1; | ||
| 153 | } | ||
