DOSBox-X
|
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 }