DOSBox-X
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
src/ints/qcow2_disk.cpp
00001 /*
00002  *  Copyright (C) 2016  Michael Greger
00003  *
00004  *  This program is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  This program is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License along
00015  *  with this program; if not, write to the Free Software Foundation, Inc.,
00016  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  */
00018 
00019 
00020 #include "qcow2_disk.h"
00021 
00022 #if defined(_MSC_VER)
00023 # pragma warning(disable:4244) /* const fmath::local::uint64_t to double possible loss of data */
00024 #endif
00025 
00026 using namespace std;
00027 
00028 
00029 //Public constant.
00030         const Bit32u QCow2Image::magic = 0x514649FB;
00031 
00032 
00033 //Public function to read a QCow2 header.
00034         QCow2Image::QCow2Header QCow2Image::read_header(FILE* qcow2File){
00035                 QCow2Header header;
00036                 fseeko64(qcow2File, 0, SEEK_SET);
00037                 if (1 != fread(&header, sizeof header, 1, qcow2File)){
00038                         clearerr(qcow2File);  /*If we fail, reset the file stream's status*/
00039                         return QCow2Header(); /*Return an empty header*/
00040                 }
00041                 header.magic = host_read32(header.magic);
00042                 header.version = host_read32(header.version);
00043                 header.backing_file_offset = host_read64(header.backing_file_offset);
00044                 header.backing_file_size = host_read32(header.backing_file_size);
00045                 header.cluster_bits = host_read32(header.cluster_bits);
00046                 header.size = host_read64(header.size);
00047                 header.crypt_method = host_read32(header.crypt_method);
00048                 header.l1_size = host_read32(header.l1_size);
00049                 header.l1_table_offset = host_read64(header.l1_table_offset);
00050                 header.refcount_table_offset = host_read64(header.refcount_table_offset);
00051                 header.refcount_table_clusters = host_read32(header.refcount_table_clusters);
00052                 header.nb_snapshots = host_read32(header.nb_snapshots);
00053                 header.snapshots_offset = host_read64(header.snapshots_offset);
00054                 return header;
00055         }
00056 
00057 
00058 //Public Constructor.
00059         QCow2Image::QCow2Image(QCow2Image::QCow2Header& qcow2Header, FILE *qcow2File, const char* imageName, Bit32u sectorSizeBytes) : file(qcow2File), header(qcow2Header), sector_size(sectorSizeBytes), backing_image(NULL)
00060         {
00061                 cluster_mask = mask64(header.cluster_bits);
00062                 cluster_size = cluster_mask + 1;
00063                 sectors_per_cluster = cluster_size / sector_size;
00064                 l2_bits = header.cluster_bits - 3;
00065                 l2_mask = mask64(l2_bits);
00066                 l1_bits = header.cluster_bits + l2_bits;
00067                 refcount_bits = header.cluster_bits - 1;
00068                 refcount_mask = mask64(refcount_bits);
00069                 if (header.backing_file_offset != 0 && header.backing_file_size != 0){
00070                         char* backing_file_name = new char[header.backing_file_size + 1];
00071                         backing_file_name[header.backing_file_size] = 0;
00072                         fseeko64(file, (off_t)header.backing_file_offset, SEEK_SET);
00073             size_t readResult = fread(backing_file_name, header.backing_file_size, 1, file);
00074             if (readResult != 1) {
00075                 LOG(LOG_IO, LOG_ERROR) ("Reading error in QCow2Image constructor\n");
00076                 delete[] backing_file_name;
00077                 return;
00078             }
00079                         if (backing_file_name[0] != 0x2F){
00080                                 for (int image_name_index = (int)strlen(imageName); image_name_index > -1; image_name_index--){
00081                                         if (imageName[image_name_index] == 0x2F){
00082                                                 int full_name_length = (int)((unsigned int)header.backing_file_size + (unsigned int)image_name_index + 2u);
00083                                                 char* full_name = new char[full_name_length];
00084                                                 for(int full_name_index = 0; full_name_index < full_name_length; full_name_index++){
00085                                                         if (full_name_index <= image_name_index){
00086                                                                 full_name[full_name_index] = imageName[full_name_index];
00087                                                         } else {
00088                                                                 full_name[full_name_index] = backing_file_name[full_name_index - (image_name_index + 1)];
00089                                                         }
00090                                                 }
00091                                                 delete[] backing_file_name;
00092                                                 backing_file_name = full_name;
00093                                                 break;
00094                                         }
00095                                 }
00096                         }
00097                         FILE* backing_file = fopen(backing_file_name, "rb");
00098                         if (backing_file != NULL){
00099                                 QCow2Header backing_header = read_header(backing_file);
00100                                 backing_image = new QCow2Image(backing_header, backing_file, backing_file_name, sectorSizeBytes);
00101                         } else {
00102                                 LOG_MSG("Failed to load QCow2 backing image: %s", backing_file_name);
00103                         }
00104                         delete[] backing_file_name;
00105                 }
00106         }
00107 
00108 
00109 //Public Destructor.
00110         QCow2Image::~QCow2Image(){
00111                 if (backing_image != NULL){
00112                         fclose(backing_image->file);
00113                         delete backing_image;
00114                 }
00115         }
00116 
00117 
00118 //Public function to a read a sector.
00119         Bit8u QCow2Image::read_sector(Bit32u sectnum, Bit8u* data){
00120                 const Bit64u address = (Bit64u)sectnum * sector_size;
00121                 if (address >= header.size){
00122                         return 0x05;
00123                 }
00124                 Bit64u l2_table_offset;
00125                 if (0 != read_l1_table(address, l2_table_offset)){
00126                         return 0x05;
00127                 }
00128                 if (0 == l2_table_offset){
00129                         return read_unallocated_sector(sectnum, data);
00130                 }
00131                 Bit64u data_cluster_offset;
00132                 if (0 != read_l2_table(l2_table_offset, address, data_cluster_offset)){
00133                         return 0x05;
00134                 }
00135                 if (0 == data_cluster_offset){
00136                         return read_unallocated_sector(sectnum, data);
00137                 }
00138                 return read_allocated_data(data_cluster_offset + (address & cluster_mask), data, sector_size);
00139         }
00140 
00141 
00142 //Public function to a write a sector.
00143         Bit8u QCow2Image::write_sector(Bit32u sectnum, Bit8u* data){
00144                 const Bit64u address = (Bit64u)sectnum * sector_size;
00145                 if (address >= header.size){
00146                         return 0x05;
00147                 }
00148                 Bit64u l2_table_offset;
00149                 if (0 != read_l1_table(address, l2_table_offset)){
00150                         return 0x05;
00151                 }
00152                 if (0 == l2_table_offset){
00153                         if (0 != pad_file(l2_table_offset)){
00154                                 return 0x05;
00155                         }
00156                         if (0 != write_l1_table_entry(address, l2_table_offset)){
00157                                 return 0x05;
00158                         }
00159                         Bit8u* cluster_buffer = new Bit8u[cluster_size];
00160                         std::fill(cluster_buffer, cluster_buffer + cluster_size, 0);
00161                         if (0 != write_data(l2_table_offset, cluster_buffer, cluster_size)){
00162                                 delete[] cluster_buffer;
00163                                 return 0x05;
00164                         }
00165                         if (0 != update_reference_count(l2_table_offset, cluster_buffer)){
00166                                 delete[] cluster_buffer;
00167                                 return 0x05;
00168                         }
00169                         delete[] cluster_buffer;
00170                 }
00171                 Bit64u data_cluster_offset;
00172                 if (0 != read_l2_table(l2_table_offset, address, data_cluster_offset)){
00173                         return 0x05;
00174                 }
00175                 if (data_cluster_offset == 0){
00176                         if (0 != pad_file(data_cluster_offset)){
00177                                 return 0x05;
00178                         }
00179                         if (0 != write_l2_table_entry(l2_table_offset, address, data_cluster_offset)){
00180                                 return 0x05;
00181                         }
00182                         Bit8u* cluster_buffer = new Bit8u[cluster_size];
00183                         if ( 0 != read_unallocated_cluster(address/cluster_size, cluster_buffer)){
00184                                 delete[] cluster_buffer;
00185                                 return 0x05;
00186                         }
00187                         const Bit64u cluster_buffer_sector_offset = address & cluster_mask;
00188                         for (Bit64u i = 0; i < sector_size; i++){
00189                                 cluster_buffer[cluster_buffer_sector_offset + i] = data[i];
00190                         }
00191                         if (0 != write_data(data_cluster_offset, cluster_buffer, cluster_size)){
00192                                 delete[] cluster_buffer;
00193                                 return 0x05;
00194                         }
00195                         if (0 != update_reference_count(data_cluster_offset, cluster_buffer)){
00196                                 delete[] cluster_buffer;
00197                                 return 0x05;
00198                         }
00199                         delete[] cluster_buffer;
00200                         return 0;
00201                 }
00202                 return write_data(data_cluster_offset + (address & cluster_mask), data, sector_size);
00203         }
00204 
00205 
00206 //Private constants.
00207         const Bit64u QCow2Image::copy_flag = 0x8000000000000000;
00208         const Bit64u QCow2Image::empty_mask = 0xFFFFFFFFFFFFFFFF;
00209         const Bit64u QCow2Image::table_entry_mask = 0x00FFFFFFFFFFFFFF;
00210 
00211 
00212 //Helper functions for endianness. QCOW format is big endian so we need different functions than those defined in mem.h.
00213 #if defined(WORDS_BIGENDIAN) || !defined(C_UNALIGNED_MEMORY)
00214     inline Bit16u QCow2Image::host_read16(Bit16u buffer) {
00215         return buffer;
00216     }
00217 
00218     inline Bit32u QCow2Image::host_read32(Bit32u buffer) {
00219         return buffer;
00220     }
00221 
00222     inline Bit64u QCow2Image::host_read64(Bit64u buffer) {
00223         return buffer;
00224     }
00225 #else
00226     inline Bit16u QCow2Image::host_read16(Bit16u buffer) {
00227         return (buffer >> 8) | (buffer << 8);
00228     }
00229 
00230     inline Bit32u QCow2Image::host_read32(Bit32u buffer) {
00231         return (buffer >> 24) | (((buffer >> 16) & 0xff) << 8) |
00232             (((buffer >> 8) & 0xff) << 16) | (buffer << 24);
00233     }
00234 
00235     inline Bit64u QCow2Image::host_read64(Bit64u buffer) {
00236         return
00237             (buffer >> 56) | (((buffer >> 48) & 0xff) << 8) |
00238             (((buffer >> 40) & 0xff) << 16) | (((buffer >> 32) & 0xff) << 24) |
00239             (((buffer >> 24) & 0xff) << 32) | (((buffer >> 16) & 0xff) << 40) |
00240             (((buffer >> 8) & 0xff) << 48) | (buffer << 56);
00241     }
00242 #endif
00243 
00244 
00245 //Generate a mask for a given number of bits.
00246         inline Bit64u QCow2Image::mask64(Bit64u bits){
00247                 return (1ull << bits) - 1ull;
00248         }
00249 
00250 
00251 //Pad a file with zeros if it doesn't end on a cluster boundary.
00252         Bit8u QCow2Image::pad_file(Bit64u& new_file_length){
00253                 if (0 != fseeko64(file, 0, SEEK_END)){
00254                         return 0x05;
00255                 }
00256                 const Bit64u old_file_length = (Bit64u)ftello64(file);
00257                 const Bit64u padding_size = (cluster_size - (old_file_length % cluster_size)) % cluster_size;
00258                 new_file_length = old_file_length + padding_size;
00259                 if (0 == padding_size){
00260                         return 0;
00261                 }
00262                 Bit8u* padding = new Bit8u[padding_size];
00263                 std::fill(padding, padding + padding_size, 0);
00264                 Bit8u result = write_data(old_file_length, padding, padding_size);
00265                 delete[] padding;
00266                 return result;
00267         }
00268 
00269 
00270 //Read data of arbitrary length that is present in the image file.
00271         Bit8u QCow2Image::read_allocated_data(Bit64u file_offset, Bit8u* data, Bit64u data_size)
00272         {
00273                 if (0 != fseeko64(file, (off_t)file_offset, SEEK_SET)){
00274                         return 0x05;
00275                 }
00276                 if (1 != fread(data, data_size, 1, file)){
00277                         return 0x05;
00278                 }
00279                 return 0;
00280         }
00281 
00282 
00283 //Read an entire cluster that may or may not be allocated in the image file.
00284         Bit8u QCow2Image::read_cluster(Bit64u data_cluster_number, Bit8u* data)
00285         {
00286                 const Bit64u address = data_cluster_number * cluster_size;
00287                 if (address >= header.size){
00288                         return 0x05;
00289                 }
00290                 Bit64u l2_table_offset;
00291                 if (0 != read_l1_table(address, l2_table_offset)){
00292                         return 0x05;
00293                 }
00294                 if (0 == l2_table_offset){
00295                         return read_unallocated_cluster(data_cluster_number, data);
00296                 }
00297                 Bit64u data_cluster_offset;
00298                 if (0 != read_l2_table(l2_table_offset, address, data_cluster_offset)){
00299                         return 0x05;
00300                 }
00301                 if (0 == data_cluster_offset){
00302                         return read_unallocated_cluster(data_cluster_number, data);
00303                 }
00304                 return read_allocated_data(data_cluster_offset, data, cluster_size);
00305         }
00306 
00307 
00308 //Read the L1 table to get the offset of the L2 table for a given address.
00309         inline Bit8u QCow2Image::read_l1_table(Bit64u address, Bit64u& l2_table_offset){
00310                 const Bit64u l1_entry_offset = header.l1_table_offset + ((address >> l1_bits) << 3);
00311                 return read_table(l1_entry_offset, table_entry_mask, l2_table_offset);
00312         }
00313 
00314 
00315 //Read an L2 table to get the offset of the data cluster for a given address.
00316         inline Bit8u QCow2Image::read_l2_table(Bit64u l2_table_offset, Bit64u address, Bit64u& data_cluster_offset){
00317                 const Bit64u l2_entry_offset = l2_table_offset + (((address >> header.cluster_bits) & l2_mask) << 3);
00318                 return read_table(l2_entry_offset, table_entry_mask, data_cluster_offset);
00319         }
00320 
00321 
00322 //Read the refcount table to get the offset of the refcount cluster for a given address.
00323         inline Bit8u QCow2Image::read_refcount_table(Bit64u data_cluster_offset, Bit64u& refcount_cluster_offset){
00324                 const Bit64u refcount_entry_offset = header.refcount_table_offset + (((data_cluster_offset/cluster_size) >> refcount_bits) << 3);
00325                 return read_table(refcount_entry_offset, empty_mask, refcount_cluster_offset);
00326         }
00327 
00328 
00329 //Read a table entry at the given offset.
00330         inline Bit8u QCow2Image::read_table(Bit64u entry_offset, Bit64u entry_mask, Bit64u& entry_value){
00331         (void)entry_mask;//UNUSED
00332                 Bit64u buffer;
00333                 if (0 != read_allocated_data(entry_offset, (Bit8u*)&buffer, sizeof buffer)){
00334                         return 0x05;
00335                 }
00336                 entry_value = host_read64(buffer) & table_entry_mask;
00337                 return 0;
00338         }
00339 
00340 
00341 //Read a cluster not currently allocated in the image file.
00342         inline Bit8u QCow2Image::read_unallocated_cluster(Bit64u data_cluster_number, Bit8u* data)
00343         {
00344                 if(backing_image == NULL){
00345                         std::fill(data, data + cluster_size, 0);
00346                         return 0;
00347                 }
00348                 return backing_image->read_cluster(data_cluster_number, data);
00349         }
00350 
00351 
00352 //Read a sector not currently allocated in the image file.
00353         inline Bit8u QCow2Image::read_unallocated_sector(Bit32u sectnum, Bit8u* data){
00354                 if(backing_image == NULL){
00355                         std::fill(data, data+sector_size, 0);
00356                         return 0;
00357                 }
00358                 return backing_image->read_sector(sectnum, data);
00359         }
00360 
00361 //Update the reference count for a cluster.
00362         Bit8u QCow2Image::update_reference_count(Bit64u cluster_offset, Bit8u* cluster_buffer){
00363                 Bit64u refcount_cluster_offset;
00364                 if (0 != read_refcount_table(cluster_offset, refcount_cluster_offset)){
00365                         return 0x05;
00366                 }
00367                 if (0 == refcount_cluster_offset){
00368                         refcount_cluster_offset = cluster_offset + cluster_size;
00369                         std::fill(cluster_buffer, cluster_buffer + cluster_size, 0);
00370                         if (0 != write_refcount_table_entry(cluster_offset, refcount_cluster_offset)){
00371                                 return 0x05;
00372                         }
00373                         if (0 != write_data(refcount_cluster_offset, cluster_buffer, cluster_size)){
00374                         return 0x05;
00375                         }
00376                         if (0 != write_refcount(refcount_cluster_offset, refcount_cluster_offset, 0x1)){
00377                                 return 0x05;
00378                         }
00379                 }
00380                 if (0 != write_refcount(cluster_offset, refcount_cluster_offset, 0x1)){
00381                         return 0x05;
00382                 }
00383                 return 0;
00384         }
00385 
00386 
00387 //Write data of arbitrary length to the image file.
00388         Bit8u QCow2Image::write_data(Bit64u file_offset, Bit8u* data, Bit64u data_size){
00389                 if (0 != fseeko64(file, (off_t)file_offset, SEEK_SET)){
00390                         return 0x05;
00391                 }
00392                 if (1 != fwrite(data, data_size, 1, file)){
00393                         return 0x05;
00394                 }
00395                 return 0;
00396         }
00397 
00398 
00399 //Write an L2 table offset into the L1 table.
00400         inline Bit8u QCow2Image::write_l1_table_entry(Bit64u address, Bit64u l2_table_offset){
00401                 const Bit64u l1_entry_offset = header.l1_table_offset + ((address >> l1_bits) << 3);
00402                 return write_table_entry(l1_entry_offset, l2_table_offset | copy_flag);
00403         }
00404 
00405 
00406 //Write a data cluster offset into an L2 table.
00407         inline Bit8u QCow2Image::write_l2_table_entry(Bit64u l2_table_offset, Bit64u address, Bit64u data_cluster_offset){
00408                 const Bit64u l2_entry_offset = l2_table_offset + (((address >> header.cluster_bits) & l2_mask) << 3);
00409                 return write_table_entry(l2_entry_offset, data_cluster_offset | copy_flag);
00410         }
00411 
00412 
00413 //Write a refcount.
00414         inline Bit8u QCow2Image::write_refcount(Bit64u cluster_offset, Bit64u refcount_cluster_offset, Bit16u refcount){
00415                 const Bit64u refcount_offset = refcount_cluster_offset + (((cluster_offset/cluster_size) & refcount_mask) << 1);
00416                 Bit16u buffer = host_read16(refcount);
00417                 return write_data(refcount_offset, (Bit8u*)&buffer, sizeof buffer);
00418         }
00419 
00420 
00421 //Write a refcount table entry.
00422         inline Bit8u QCow2Image::write_refcount_table_entry(Bit64u cluster_offset, Bit64u refcount_cluster_offset){
00423                 const Bit64u refcount_entry_offset = header.refcount_table_offset + (((cluster_offset/cluster_size) >> refcount_bits) << 3);
00424                 return write_table_entry(refcount_entry_offset, refcount_cluster_offset);
00425         }
00426 
00427 
00428 //Write a table entry at the given offset.
00429         inline Bit8u QCow2Image::write_table_entry(Bit64u entry_offset, Bit64u entry_value){
00430                 Bit64u buffer = host_read64(entry_value);
00431                 return write_data(entry_offset, (Bit8u*)&buffer, sizeof buffer);
00432         }
00433 
00434 
00435 //Public Constructor.
00436         QCow2Disk::QCow2Disk(QCow2Image::QCow2Header& qcow2Header, FILE *qcow2File, Bit8u *imgName, Bit32u imgSizeK, Bit32u sectorSizeBytes, bool isHardDisk) : imageDisk(qcow2File, imgName, imgSizeK, isHardDisk), qcowImage(qcow2Header, qcow2File, (const char*) imgName, sectorSizeBytes){
00437         }
00438 
00439 
00440 //Public Destructor.
00441         QCow2Disk::~QCow2Disk(){
00442         }
00443 
00444 
00445 //Public function to a read a sector.
00446         Bit8u QCow2Disk::Read_AbsoluteSector(Bit32u sectnum, void* data){
00447                 return qcowImage.read_sector(sectnum, (Bit8u*)data);
00448         }
00449 
00450 
00451 //Public function to a write a sector.
00452         Bit8u QCow2Disk::Write_AbsoluteSector(Bit32u sectnum,const void* data){
00453                 return qcowImage.write_sector(sectnum, (Bit8u*)data);
00454         }