30 void revcpy(
char *dest,
const char *src,
int num)
32 const char *pend = src + num*N;
33 for (
const char *ptr = src; ptr<pend; ptr+=N, dest+=N)
34 std::reverse_copy(ptr, ptr+N, dest);
41 if (value < 10000000000) str <<
" ";
42 if (value < 1000000000) str <<
" ";
43 if (value < 100000000) str <<
" ";
44 if (value < 10000000) str <<
" ";
45 if (value < 1000000) str <<
" ";
46 if (value < 100000) str <<
" ";
47 if (value < 10000) str <<
" ";
48 if (value < 1000) str <<
" ";
49 if (value < 100) str <<
" ";
50 if (value < 10) str <<
" ";
56 int main(
int argc,
char** argv)
60 cout <<
"Only one argument please: the input filename" << endl;
64 ifstream input(argv[1], ios::in | ios::binary);
68 cout <<
"Impossible to open file named \"" << argv[1] <<
"\"" << endl;
74 char* fits_buffer =
new char[81];
76 unsigned int n_lines_read = 0;
77 unsigned int num_start_tables = 0;
78 unsigned int num_end_tables = 0;
79 streampos start_of_table_header = 0;
82 while (num_start_tables != 2 || num_end_tables != 3)
84 input.read(fits_buffer, 80);
85 if (input.eof())
break;
87 if (!strcmp(fits_buffer,
"XTENSION= 'BINTABLE' / binary table extension "))
90 if (num_start_tables == 2)
91 start_of_table_header = input.tellg() - streampos(80);
93 if (!strcmp(fits_buffer,
"END "))
96 if (num_start_tables == 2)
99 cout << fits_buffer << endl;
103 if (num_start_tables != 2 || num_end_tables != 3)
105 cout <<
"Could not reach the end of the data table header: nothing could be recovered... sorry." << endl;
110 int i_end = (36-(n_lines_read%36));
112 for (
int i=0;
i<i_end;
i++)
114 input.read(fits_buffer, 80);
115 if (input.eof())
break;
119 streampos catalog_beginning = input.tellg();
120 size_t catalog_reserved_size = 4800000;
122 input.seekg(catalog_beginning + (streampos)(catalog_reserved_size));
123 n_lines_read += 60000;
126 list<FITS::TileHeader> good_tiles;
128 streampos data_beginning = input.tellg();
129 streampos previous_tile_begin = input.tellg();
131 input.read(fits_buffer, 80);
133 if (memcmp(fits_buffer,
"TILE", 4))
135 cout <<
"Compressed data does not start by string TILE: nothing could be recovered, sorry." << endl;
145 input.seekg(previous_tile_begin + (streampos)(thead->
size));
146 streampos this_tile_start = input.tellg();
147 input.read(fits_buffer, 80);
150 if (fits_buffer[0] !=
'T' || fits_buffer[1] !=
'I' || fits_buffer[2] !=
'L' || fits_buffer[3] !=
'E')
154 good_tiles.push_back(previous_tile);
155 previous_tile = *thead;
156 previous_tile_begin = this_tile_start;
159 unsigned int num_tiles_recovered = good_tiles.size();
161 cout <<
"We have found " << num_tiles_recovered <<
" valid tiles. Recovering catalog now " << endl;
163 std::vector<std::vector<std::pair<int64_t, int64_t> > > catalog;
167 streamoff offset_in_heap = 0;
168 streamoff valid_data = 0;
169 unsigned int num_cols = 9;
171 input.open(argv[1], ios::in | ios::binary);
172 input.seekg(data_beginning);
173 for (
unsigned int i=0;
i<num_tiles_recovered;
i++)
178 if (memcmp(thead->
id,
"TILE", 4))
181 catalog.emplace_back();
185 for (
unsigned int i=0;
i<num_cols;
i++)
192 catalog.back().emplace_back((int64_t)(bhead.
size), offset_in_heap);
193 offset_in_heap += bhead.
size;
194 input.seekg(data_beginning + offset_in_heap);
198 catalog.back().emplace_back(0,0);
205 valid_data = offset_in_heap;
208 if (catalog.size() != num_tiles_recovered)
209 cout <<
"Notice: some apparently OK tiles are in fact corrupted: could only recover " << catalog.size() <<
" tiles." << endl;
211 string recovered_filename(argv[1]);
212 recovered_filename = recovered_filename +
".recovered";
214 cout <<
"Catalog recovered. Now writing " << recovered_filename << endl;
216 ifstream test_input(recovered_filename.c_str(), ios::in | ios::binary);
220 cout <<
"Error: output file already exists. Aborting. " << endl;
224 ofstream output(recovered_filename.c_str(), ios::out | ios::binary);
226 input.open(argv[1], ios::in | ios::binary);
228 cout <<
"Writing calibration table...";
231 while (input.tellg() != start_of_table_header)
233 input.read(fits_buffer, 80);
234 output.write(fits_buffer, 80);
237 cout <<
"done." << endl <<
"Writing updated table header...";
240 ostringstream updated_key;
242 unsigned long theap = 160*num_tiles_recovered;
243 unsigned long pcount = valid_data + catalog_reserved_size - theap;
245 while (input.tellg() != catalog_beginning)
247 input.read(fits_buffer, 80);
248 if (!memcmp(fits_buffer,
"NAXIS2", 6))
251 updated_key <<
"NAXIS2 =" <<
format_integer(num_tiles_recovered) <<
"/ number of rows in table ";
252 output.write(updated_key.str().c_str(), 80);
255 if (!memcmp(fits_buffer,
"PCOUNT", 6))
258 updated_key <<
"PCOUNT =" <<
format_integer(pcount) <<
"/ size of special data area ";
259 output.write(updated_key.str().c_str(), 80);
262 if (!memcmp(fits_buffer,
"ZNAXIS2", 7))
265 updated_key <<
"ZNAXIS2 =" <<
format_integer(num_tiles_recovered) <<
"/ Number of uncompressed rows ";
266 output.write(updated_key.str().c_str(), 80);
269 if (!memcmp(fits_buffer,
"ZHEAPPTR", 8))
272 updated_key <<
"ZHEAPPTR=" <<
format_integer(catalog_reserved_size) <<
" ";
273 output.write(updated_key.str().c_str(), 80);
276 if (!memcmp(fits_buffer,
"THEAP", 5))
280 output.write(updated_key.str().c_str(), 80);
284 output.write(fits_buffer, 80);
286 cout <<
"num tiles recovered: " << num_tiles_recovered << endl;
287 cout <<
"pcount: " << pcount << endl;
288 cout <<
"catalog_reserved_size: " << catalog_reserved_size << endl;
289 cout <<
"theap: " << theap << endl;
290 cout <<
"offset in heap: " << offset_in_heap << endl;
291 cout <<
"valid data: " << valid_data << endl;
292 cout <<
"done." << endl <<
"Writing updated catalog...";
296 vector<char> swapped_catalog(catalog_reserved_size);
297 unsigned int shift = 0;
298 for (
auto it=catalog.cbegin(); it!=catalog.cend(); it++)
300 revcpy<sizeof(uint64_t)>(swapped_catalog.data() + shift, (
char*)(it->data()), (num_cols+1)*2);
304 if (catalog.size() < 30000)
305 memset(swapped_catalog.data()+shift, 0, catalog_reserved_size - shift);
307 output.write(swapped_catalog.data(), catalog_reserved_size);
309 cout <<
"done." << endl <<
"Writing recovered data...";
313 input.seekg(input.tellg() + (streampos)(catalog_reserved_size));
314 cout <<
"starting writing data at " << output.tellp() << endl;
315 unsigned int actual_data_size = pcount + theap - catalog_reserved_size;
317 for (;i<actual_data_size-80;i+=80)
319 input.read(fits_buffer, 80);
320 output.write(fits_buffer, 80);
323 input.read(fits_buffer, actual_data_size%80);
324 output.write(fits_buffer, actual_data_size%80);
325 cout <<
"ended writing data at " << output.tellp() << endl;
326 cout <<
"done." << endl <<
"Writing FITS padding...";
328 cout <<
"Current extra chars: " << output.tellp()%(80*36) << endl;
329 cout <<
"Will write " << 2880 - output.tellp()%(2880) <<
" filling bytes while at byte " << output.tellp() << endl;
331 if (output.tellp()%(80*36) > 0)
333 std::vector<char> filler(2880-output.tellp()%(2880), 0);
334 output.write(filler.data(), filler.size());
337 cout <<
"All done !." << endl;
338 cout <<
"TSTOP is also most likely invalid, so:" << endl;
339 cout <<
" - run /swdev_nfs/FACT++/fitsdump <filename> -c UnixTimeUTC --minmax --nozero" << endl;
340 cout <<
" - update header key using e.g. fv" << endl;
341 cout <<
"Checksums are now invalid: please run fchecksum <filename> update+ datasum+ " << endl;
void revcpy(char *dest, const char *src, int num)
string format_integer(unsigned long value)
int main(int argc, char **argv)