/* * corruptFileFixer.cc * * Takes a compressed fits file as an input, and copy the "good" part of it to a _recovered.fits.fz * No tstart or tstop nor checksums are updated. For this the script fixHeaderKeys.sh should be used along with the ftools * * How to compile me: * * setenv PATH /gpfs/fact/swdev/root_v5.32.00/bin:/usr/lib64/qt-3.3/bin:/usr/local/bin:/bin:/usr/bin:/opt/dell/srvadmin/bin * * setenv LD_LIBRARY_PATH /lib64:/home/isdc/lyard/FACT++/.libs:/gpfs/fact/swdev/root_v5.32.00/lib:/swdev_nfs/FACT++/.libs: * * g++ -o corruptZFitsFixer --std=c++0x src/corruptFileFixer.cc -I./externals -DHAVE_ZLIB * * * Created on: Aug 23, 2016 * Author: lyard */ #include #include #include #include "factfits.h" using namespace std; template void revcpy(char *dest, const char *src, int num) { const char *pend = src + num*N; for (const char *ptr = src; ptr good_tiles; //remember where the data starts streampos data_beginning = input.tellg(); streampos previous_tile_begin = input.tellg(); //read the very first tile header input.read(fits_buffer, 80); if (memcmp(fits_buffer, "TILE", 4)) { cout << "Compressed data does not start by string TILE: nothing could be recovered, sorry." << endl; return -4; } FITS::TileHeader* thead = reinterpret_cast(fits_buffer); FITS::TileHeader previous_tile = *thead; //previous_tile has the previous tile header. Move forward, and remember the previous valid tile every time we find a new valid header while (!input.eof()) { //skip previous tile input.seekg(previous_tile_begin + (streampos)(thead->size)); streampos this_tile_start = input.tellg(); input.read(fits_buffer, 80); if (input.eof()) break; if (fits_buffer[0] != 'T' || fits_buffer[1] != 'I' || fits_buffer[2] != 'L' || fits_buffer[3] != 'E') break; //we've found a new valid tile header: remember the previous one good_tiles.push_back(previous_tile); previous_tile = *thead; previous_tile_begin = this_tile_start; } unsigned int num_tiles_recovered = good_tiles.size(); //done. cout << "We have found " << num_tiles_recovered << " valid tiles. Recovering catalog now " << endl; std::vector > > catalog; FITS::BlockHeader bhead; streamoff offset_in_heap = 0; streamoff valid_data = 0; unsigned int num_cols = 9; input.close(); input.open(argv[1], ios::in | ios::binary); input.seekg(data_beginning); for (unsigned int i=0;iid, "TILE", 4)) break; catalog.emplace_back(); offset_in_heap += sizeof(FITS::TileHeader); //skip through the columns for (unsigned int i=0;i swapped_catalog(catalog_reserved_size); unsigned int shift = 0; for (auto it=catalog.cbegin(); it!=catalog.cend(); it++) { revcpy(swapped_catalog.data() + shift, (char*)(it->data()), (num_cols+1)*2); shift += 160; } if (catalog.size() < 30000) memset(swapped_catalog.data()+shift, 0, catalog_reserved_size - shift); output.write(swapped_catalog.data(), catalog_reserved_size); cout << "done." << endl << "Writing recovered data..."; cout.flush(); //write the actual data input.seekg(input.tellg() + (streampos)(catalog_reserved_size)); cout << "starting writing data at " << output.tellp() << endl; unsigned int actual_data_size = pcount + theap - catalog_reserved_size; unsigned int i=0; for (;i 0) { std::vector filler(2880-output.tellp()%(2880), 0); output.write(filler.data(), filler.size()); } output.close(); cout << "All done !." << endl; cout << "TSTOP is also most likely invalid, so:" << endl; cout << " - run /swdev_nfs/FACT++/fitsdump -c UnixTimeUTC --minmax --nozero" << endl; cout << " - update header key using e.g. fv" << endl; cout << "Checksums are now invalid: please run fchecksum update+ datasum+ " << endl; return 0; }