Changeset bdad846 in mainline
- Timestamp:
- 2021-09-08T13:31:58Z (3 years ago)
- Children:
- d5309df7
- Parents:
- 2f7dfc2e
- Location:
- uspace/srv/bd/qcow_bd
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/srv/bd/qcow_bd/qcow_bd.c
r2f7dfc2e rbdad846 152 152 } 153 153 154 static errno_t compute_table_sizes()154 static void initialize_state() 155 155 { 156 156 /* Computing sizes in bytes */ … … 173 173 state.num_blocks = (header.size / state.block_size); 174 174 175 return EOK;176 }177 178 static errno_t read_l1_table()179 {180 /* Allocating memory for l1_table */181 175 state.l1_table_offset = header.l1_table_offset; 182 state.l2_references = (uint64_t*)malloc(state.l1_size);183 184 /* Reading all L2 table references from L1 table */185 clearerr(img);186 printf("READING 2,5\n");187 if (fseek(img, state.l1_table_offset, SEEK_SET) < 0)188 return EIO;189 190 size_t n_rd = fread(state.l2_references, state.l1_size, 1, img);191 192 if (n_rd < 1)193 return EINVAL;194 195 /* Clearing last bit in all references which tells us whether cluster is compressed */196 for (uint64_t i = 0; i < state.l1_size / sizeof(uint64_t); i++) {197 state.l2_references[i] = __builtin_bswap64(state.l2_references[i]);198 if (state.l2_references[i] & QCOW_OFLAG_COMPRESSED) {199 fprintf(stderr, "Compression is not supported!\n");200 return ENOTSUP;201 }202 }203 204 if (ferror(img))205 return EIO; /* Read error */206 return EOK;207 176 } 208 177 … … 222 191 /* Try to open file */ 223 192 img = fopen(fname, "rb+"); 224 if (img == NULL) 193 if (img == NULL) { 194 fprintf(stderr, "File opening failed!\n"); 225 195 return EINVAL; 196 } 226 197 227 198 if (fseek(img, 0, SEEK_END) != 0) { 199 fprintf(stderr, "Seeking end of file failed!\n"); 228 200 fclose(img); 229 201 return EIO; 230 202 } 231 203 232 if (fseek(img, 0, SEEK_SET) < 0) 204 if (fseek(img, 0, SEEK_SET) < 0) { 205 fprintf(stderr, "Seeking file header failed!\n"); 206 fclose(img); 233 207 return EIO; 208 } 234 209 235 210 /* Read the file header */ 236 211 size_t n_rd = fread(&header, sizeof(header), 1, img); 237 212 238 if (n_rd < 1) 213 if (n_rd < 1) { 214 fprintf(stderr, "Reading file header failed!\n"); 215 fclose(img); 239 216 return EINVAL; 217 } 218 240 219 241 220 /* Swap values to big-endian */ … … 249 228 header.l1_table_offset = __builtin_bswap64(header.l1_table_offset); 250 229 230 if (ferror(img)) { 231 fclose(img); 232 return EIO; 233 } 234 251 235 /* Verify all values from file header */ 252 if (ferror(img)) 253 return EIO; 254 255 if (header.magic == QCOW_MAGIC) { 256 errno_t error = compute_table_sizes(); 257 if (error != EOK) { 258 return error; 259 } 260 error = read_l1_table(); 261 if (error != EOK) { 262 return error; 263 } 264 } 236 if (header.magic == QCOW_MAGIC) 237 initialize_state(); 265 238 266 239 if (header.version != QCOW_VERSION) { 267 fprintf(stderr, "Version: %d is not supported!\n", header.version); 240 fprintf(stderr, "Version QCOW%d is not supported!\n", header.version); 241 fclose(img); 268 242 return ENOTSUP; 269 243 } … … 271 245 if (header.crypt_method != QCOW_CRYPT_NONE) { 272 246 fprintf(stderr, "Encryption is not supported!\n"); 247 fclose(img); 273 248 return ENOTSUP; 274 249 } … … 294 269 static errno_t qcow_bd_close(bd_srv_t *bd) 295 270 { 296 free(state.l2_references);297 271 fclose(img); 298 272 return EOK; … … 300 274 301 275 /** From the offset of the given block compute its offset which is relative from the start of qcow file. */ 302 static uint64_t get_block_offset(uint64_t offset, errno_t *error)276 static errno_t get_block_offset(uint64_t *offset) 303 277 { 304 278 /* Compute l1 table index from the offset */ 305 279 uint64_t l1_table_index_bit_shift = header.cluster_bits + header.l2_bits; 306 uint64_t l1_table_index = ( offset & 0x7fffffffffffffffULL) >> l1_table_index_bit_shift;280 uint64_t l1_table_index = (*offset & 0x7fffffffffffffffULL) >> l1_table_index_bit_shift; 307 281 308 282 /* Reading l2 reference from the l1 table */ 309 uint64_t l2_table_reference = state.l2_references[l1_table_index]; 310 311 if (l2_table_reference == QCOW_UNALLOCATED_REFERENCE) 312 return QCOW_UNALLOCATED_REFERENCE; 283 if (fseek(img, state.l1_table_offset + l1_table_index * sizeof(uint64_t), SEEK_SET) < 0) { 284 fprintf(stderr, "Seeking l2 reference in l1 table failed!\n"); 285 return EIO; 286 } 287 288 289 uint64_t l2_table_reference; 290 size_t n_rd = fread(&l2_table_reference, sizeof(uint64_t), 1, img); 291 292 if (n_rd < 1) { 293 fprintf(stderr, "Reading l2 reference from l1 table failed!\n"); 294 return EINVAL; 295 } 296 297 l2_table_reference = __builtin_bswap64(l2_table_reference); 298 299 if (l2_table_reference & QCOW_OFLAG_COMPRESSED) { 300 fprintf(stderr, "Compression is not supported!\n"); 301 return ENOTSUP; 302 } 303 304 if (l2_table_reference == QCOW_UNALLOCATED_REFERENCE) { 305 *offset = QCOW_UNALLOCATED_REFERENCE; 306 return EOK; 307 } 308 313 309 314 310 /* Compute l2 table index from the offset */ 315 uint64_t l2_table_index = ( offset >> header.cluster_bits) & (state.l2_size - 1);311 uint64_t l2_table_index = (*offset >> header.cluster_bits) & (state.l2_size - 1); 316 312 317 313 /* Reading cluster reference from the l2 table */ 318 if (fseek(img, l2_table_reference + l2_table_index * sizeof(uint64_t), SEEK_SET) < 0) {319 *error = EIO;314 if (fseek(img, l2_table_reference + l2_table_index * sizeof(uint64_t), SEEK_SET) < 0) { 315 fprintf(stderr, "Seeking cluster reference in l2 table failed!\n"); 320 316 return EIO; 321 317 } 322 318 323 319 uint64_t cluster_reference; 324 size_tn_rd = fread(&cluster_reference, sizeof(uint64_t), 1, img);320 n_rd = fread(&cluster_reference, sizeof(uint64_t), 1, img); 325 321 326 322 if (n_rd < 1) { 327 *error = EINVAL;323 fprintf(stderr, "Reading cluster reference from l2 table failed!\n"); 328 324 return EINVAL; 329 325 } … … 333 329 if (cluster_reference & QCOW_OFLAG_COMPRESSED) { 334 330 fprintf(stderr, "Compression is not supported!\n"); 335 *error = ENOTSUP;336 331 return ENOTSUP; 337 332 } 338 333 339 if (cluster_reference == QCOW_UNALLOCATED_REFERENCE) 340 return QCOW_UNALLOCATED_REFERENCE; 334 if (cluster_reference == QCOW_UNALLOCATED_REFERENCE) { 335 *offset = QCOW_UNALLOCATED_REFERENCE; 336 return EOK; 337 } 341 338 342 339 /* Compute cluster block offset from the offset */ 343 340 uint64_t cluster_block_bit_mask = ~(0xffffffffffffffffULL << header.cluster_bits); 344 uint64_t cluster_block_offset = offset & cluster_block_bit_mask; 345 346 return cluster_reference + cluster_block_offset; 341 uint64_t cluster_block_offset = *offset & cluster_block_bit_mask; 342 343 *offset = cluster_reference + cluster_block_offset; 344 return EOK; 347 345 } 348 346 … … 351 349 size_t size) 352 350 { 353 if (size < cnt * state.block_size) 351 if (size < cnt * state.block_size){ 352 fprintf(stderr, "Error: trying to read block behind the file"); 354 353 return EINVAL; 354 } 355 355 356 356 357 /* Check whether access is within device address bounds. */ … … 366 367 for (uint64_t i = 0; i < cnt; i++) { 367 368 /* Compute block offset which is relative from the start of qcow file */ 368 errno_t error = EOK; 369 uint64_t block_offset = get_block_offset((ba + i) * state.block_size, &error); 370 if (error != EOK) 369 uint64_t block_offset = (ba + i) * state.block_size; 370 errno_t error = get_block_offset(&block_offset); 371 if (error != EOK) { 372 fibril_mutex_unlock(&dev_lock); 371 373 return error; 374 } 375 372 376 373 377 /* If there is empty reference then continue */ -
uspace/srv/bd/qcow_bd/qcow_bd.h
r2f7dfc2e rbdad846 83 83 uint64_t l1_size; 84 84 uint64_t l1_table_offset; 85 uint64_t *l2_references;86 85 } QcowState; 87 86
Note:
See TracChangeset
for help on using the changeset viewer.