1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #define _GNU_SOURCE 18 #define _FILE_OFFSET_BITS 64 19 #define _LARGEFILE64_SOURCE 1 20 21 #include <fcntl.h> 22 #include <stdarg.h> 23 #include <stdbool.h> 24 #include <stdint.h> 25 #include <stdio.h> 26 #include <stdlib.h> 27 #include <string.h> 28 #include <unistd.h> 29 30 #include <sparse/sparse.h> 31 32 #include "sparse_crc32.h" 33 #include "sparse_file.h" 34 #include "sparse_format.h" 35 36 #if defined(__APPLE__) && defined(__MACH__) 37 #define lseek64 lseek 38 #define off64_t off_t 39 #endif 40 41 #define SPARSE_HEADER_MAJOR_VER 1 42 #define SPARSE_HEADER_LEN (sizeof(sparse_header_t)) 43 #define CHUNK_HEADER_LEN (sizeof(chunk_header_t)) 44 45 #define COPY_BUF_SIZE (1024U*1024U) 46 static char *copybuf; 47 48 #define min(a, b) \ 49 ({ typeof(a) _a = (a); typeof(b) _b = (b); (_a < _b) ? _a : _b; }) 50 51 static void verbose_error(bool verbose, int err, const char *fmt, ...) 52 { 53 char *s = ""; 54 char *at = ""; 55 if (fmt) { 56 va_list argp; 57 int size; 58 59 va_start(argp, fmt); 60 size = vsnprintf(NULL, 0, fmt, argp); 61 va_end(argp); 62 63 if (size < 0) { 64 return; 65 } 66 67 at = malloc(size + 1); 68 if (at == NULL) { 69 return; 70 } 71 72 va_start(argp, fmt); 73 vsnprintf(at, size, fmt, argp); 74 va_end(argp); 75 at[size] = 0; 76 s = " at "; 77 } 78 if (verbose) { 79 #ifndef USE_MINGW 80 if (err == -EOVERFLOW) { 81 sparse_print_verbose("EOF while reading file%s%s\n", s, at); 82 } else 83 #endif 84 if (err == -EINVAL) { 85 sparse_print_verbose("Invalid sparse file format%s%s\n", s, at); 86 } else if (err == -ENOMEM) { 87 sparse_print_verbose("Failed allocation while reading file%s%s\n", 88 s, at); 89 } else { 90 sparse_print_verbose("Unknown error %d%s%s\n", err, s, at); 91 } 92 } 93 if (fmt) { 94 free(at); 95 } 96 } 97 98 static int process_raw_chunk(struct sparse_file *s, unsigned int chunk_size, 99 int fd, int64_t offset, unsigned int blocks, unsigned int block, 100 uint32_t *crc32) 101 { 102 int ret; 103 int chunk; 104 unsigned int len = blocks * s->block_size; 105 106 if (chunk_size % s->block_size != 0) { 107 return -EINVAL; 108 } 109 110 if (chunk_size / s->block_size != blocks) { 111 return -EINVAL; 112 } 113 114 ret = sparse_file_add_fd(s, fd, offset, len, block); 115 if (ret < 0) { 116 return ret; 117 } 118 119 if (crc32) { 120 while (len) { 121 chunk = min(len, COPY_BUF_SIZE); 122 ret = read_all(fd, copybuf, chunk); 123 if (ret < 0) { 124 return ret; 125 } 126 *crc32 = sparse_crc32(*crc32, copybuf, chunk); 127 len -= chunk; 128 } 129 } else { 130 lseek64(fd, len, SEEK_CUR); 131 } 132 133 return 0; 134 } 135 136 static int process_fill_chunk(struct sparse_file *s, unsigned int chunk_size, 137 int fd, unsigned int blocks, unsigned int block, uint32_t *crc32) 138 { 139 int ret; 140 int chunk; 141 int64_t len = (int64_t)blocks * s->block_size; 142 uint32_t fill_val; 143 uint32_t *fillbuf; 144 unsigned int i; 145 146 if (chunk_size != sizeof(fill_val)) { 147 return -EINVAL; 148 } 149 150 ret = read_all(fd, &fill_val, sizeof(fill_val)); 151 if (ret < 0) { 152 return ret; 153 } 154 155 ret = sparse_file_add_fill(s, fill_val, len, block); 156 if (ret < 0) { 157 return ret; 158 } 159 160 if (crc32) { 161 /* Fill copy_buf with the fill value */ 162 fillbuf = (uint32_t *)copybuf; 163 for (i = 0; i < (COPY_BUF_SIZE / sizeof(fill_val)); i++) { 164 fillbuf[i] = fill_val; 165 } 166 167 while (len) { 168 chunk = min(len, COPY_BUF_SIZE); 169 *crc32 = sparse_crc32(*crc32, copybuf, chunk); 170 len -= chunk; 171 } 172 } 173 174 return 0; 175 } 176 177 static int process_skip_chunk(struct sparse_file *s, unsigned int chunk_size, 178 int fd, unsigned int blocks, unsigned int block, uint32_t *crc32) 179 { 180 int ret; 181 int chunk; 182 int64_t len = (int64_t)blocks * s->block_size; 183 uint32_t fill_val; 184 uint32_t *fillbuf; 185 unsigned int i; 186 187 if (chunk_size != 0) { 188 return -EINVAL; 189 } 190 191 if (crc32) { 192 memset(copybuf, 0, COPY_BUF_SIZE); 193 194 while (len) { 195 chunk = min(len, COPY_BUF_SIZE); 196 *crc32 = sparse_crc32(*crc32, copybuf, chunk); 197 len -= chunk; 198 } 199 } 200 201 return 0; 202 } 203 204 static int process_crc32_chunk(int fd, unsigned int chunk_size, uint32_t crc32) 205 { 206 uint32_t file_crc32; 207 int ret; 208 209 if (chunk_size != sizeof(file_crc32)) { 210 return -EINVAL; 211 } 212 213 ret = read_all(fd, &file_crc32, sizeof(file_crc32)); 214 if (ret < 0) { 215 return ret; 216 } 217 218 if (file_crc32 != crc32) { 219 return -EINVAL; 220 } 221 222 return 0; 223 } 224 225 static int process_chunk(struct sparse_file *s, int fd, off64_t offset, 226 unsigned int chunk_hdr_sz, chunk_header_t *chunk_header, 227 unsigned int cur_block, uint32_t *crc_ptr) 228 { 229 int ret; 230 unsigned int chunk_data_size; 231 232 chunk_data_size = chunk_header->total_sz - chunk_hdr_sz; 233 234 switch (chunk_header->chunk_type) { 235 case CHUNK_TYPE_RAW: 236 ret = process_raw_chunk(s, chunk_data_size, fd, offset, 237 chunk_header->chunk_sz, cur_block, crc_ptr); 238 if (ret < 0) { 239 verbose_error(s->verbose, ret, "data block at %lld", offset); 240 return ret; 241 } 242 return chunk_header->chunk_sz; 243 case CHUNK_TYPE_FILL: 244 ret = process_fill_chunk(s, chunk_data_size, fd, 245 chunk_header->chunk_sz, cur_block, crc_ptr); 246 if (ret < 0) { 247 verbose_error(s->verbose, ret, "fill block at %lld", offset); 248 return ret; 249 } 250 return chunk_header->chunk_sz; 251 case CHUNK_TYPE_DONT_CARE: 252 ret = process_skip_chunk(s, chunk_data_size, fd, 253 chunk_header->chunk_sz, cur_block, crc_ptr); 254 if (chunk_data_size != 0) { 255 if (ret < 0) { 256 verbose_error(s->verbose, ret, "skip block at %lld", offset); 257 return ret; 258 } 259 } 260 return chunk_header->chunk_sz; 261 case CHUNK_TYPE_CRC32: 262 ret = process_crc32_chunk(fd, chunk_data_size, *crc_ptr); 263 if (ret < 0) { 264 verbose_error(s->verbose, -EINVAL, "crc block at %lld", 265 offset); 266 return ret; 267 } 268 return 0; 269 default: 270 verbose_error(s->verbose, -EINVAL, "unknown block %04X at %lld", 271 chunk_header->chunk_type, offset); 272 } 273 274 return 0; 275 } 276 277 static int sparse_file_read_sparse(struct sparse_file *s, int fd, bool crc) 278 { 279 int ret; 280 unsigned int i; 281 sparse_header_t sparse_header; 282 chunk_header_t chunk_header; 283 uint32_t crc32 = 0; 284 uint32_t *crc_ptr = 0; 285 unsigned int cur_block = 0; 286 off64_t offset; 287 288 if (!copybuf) { 289 copybuf = malloc(COPY_BUF_SIZE); 290 } 291 292 if (!copybuf) { 293 return -ENOMEM; 294 } 295 296 if (crc) { 297 crc_ptr = &crc32; 298 } 299 300 ret = read_all(fd, &sparse_header, sizeof(sparse_header)); 301 if (ret < 0) { 302 return ret; 303 } 304 305 if (sparse_header.magic != SPARSE_HEADER_MAGIC) { 306 return -EINVAL; 307 } 308 309 if (sparse_header.major_version != SPARSE_HEADER_MAJOR_VER) { 310 return -EINVAL; 311 } 312 313 if (sparse_header.file_hdr_sz < SPARSE_HEADER_LEN) { 314 return -EINVAL; 315 } 316 317 if (sparse_header.chunk_hdr_sz < sizeof(chunk_header)) { 318 return -EINVAL; 319 } 320 321 if (sparse_header.file_hdr_sz > SPARSE_HEADER_LEN) { 322 /* Skip the remaining bytes in a header that is longer than 323 * we expected. 324 */ 325 lseek64(fd, sparse_header.file_hdr_sz - SPARSE_HEADER_LEN, SEEK_CUR); 326 } 327 328 for (i = 0; i < sparse_header.total_chunks; i++) { 329 ret = read_all(fd, &chunk_header, sizeof(chunk_header)); 330 if (ret < 0) { 331 return ret; 332 } 333 334 if (sparse_header.chunk_hdr_sz > CHUNK_HEADER_LEN) { 335 /* Skip the remaining bytes in a header that is longer than 336 * we expected. 337 */ 338 lseek64(fd, sparse_header.chunk_hdr_sz - CHUNK_HEADER_LEN, SEEK_CUR); 339 } 340 341 offset = lseek64(fd, 0, SEEK_CUR); 342 343 ret = process_chunk(s, fd, offset, sparse_header.chunk_hdr_sz, &chunk_header, 344 cur_block, crc_ptr); 345 if (ret < 0) { 346 return ret; 347 } 348 349 cur_block += ret; 350 } 351 352 if (sparse_header.total_blks != cur_block) { 353 return -EINVAL; 354 } 355 356 return 0; 357 } 358 359 static int sparse_file_read_normal(struct sparse_file *s, int fd) 360 { 361 int ret; 362 uint32_t *buf = malloc(s->block_size); 363 unsigned int block = 0; 364 int64_t remain = s->len; 365 int64_t offset = 0; 366 unsigned int to_read; 367 char *ptr; 368 unsigned int i; 369 bool sparse_block; 370 371 if (!buf) { 372 return -ENOMEM; 373 } 374 375 while (remain > 0) { 376 to_read = min(remain, s->block_size); 377 ret = read_all(fd, buf, to_read); 378 if (ret < 0) { 379 error("failed to read sparse file"); 380 return ret; 381 } 382 383 if (to_read == s->block_size) { 384 sparse_block = true; 385 for (i = 1; i < s->block_size / sizeof(uint32_t); i++) { 386 if (buf[0] != buf[i]) { 387 sparse_block = false; 388 break; 389 } 390 } 391 } else { 392 sparse_block = false; 393 } 394 395 if (sparse_block) { 396 /* TODO: add flag to use skip instead of fill for buf[0] == 0 */ 397 sparse_file_add_fill(s, buf[0], to_read, block); 398 } else { 399 sparse_file_add_fd(s, fd, offset, to_read, block); 400 } 401 402 remain -= to_read; 403 offset += to_read; 404 block++; 405 } 406 407 return 0; 408 } 409 410 int sparse_file_read(struct sparse_file *s, int fd, bool sparse, bool crc) 411 { 412 if (crc && !sparse) { 413 return -EINVAL; 414 } 415 416 if (sparse) { 417 return sparse_file_read_sparse(s, fd, crc); 418 } else { 419 return sparse_file_read_normal(s, fd); 420 } 421 } 422 423 struct sparse_file *sparse_file_import(int fd, bool verbose, bool crc) 424 { 425 int ret; 426 sparse_header_t sparse_header; 427 int64_t len; 428 struct sparse_file *s; 429 430 ret = read_all(fd, &sparse_header, sizeof(sparse_header)); 431 if (ret < 0) { 432 verbose_error(verbose, ret, "header"); 433 return NULL; 434 } 435 436 if (sparse_header.magic != SPARSE_HEADER_MAGIC) { 437 verbose_error(verbose, -EINVAL, "header magic"); 438 return NULL; 439 } 440 441 if (sparse_header.major_version != SPARSE_HEADER_MAJOR_VER) { 442 verbose_error(verbose, -EINVAL, "header major version"); 443 return NULL; 444 } 445 446 if (sparse_header.file_hdr_sz < SPARSE_HEADER_LEN) { 447 return NULL; 448 } 449 450 if (sparse_header.chunk_hdr_sz < sizeof(chunk_header_t)) { 451 return NULL; 452 } 453 454 len = (int64_t)sparse_header.total_blks * sparse_header.blk_sz; 455 s = sparse_file_new(sparse_header.blk_sz, len); 456 if (!s) { 457 verbose_error(verbose, -EINVAL, NULL); 458 return NULL; 459 } 460 461 ret = lseek64(fd, 0, SEEK_SET); 462 if (ret < 0) { 463 verbose_error(verbose, ret, "seeking"); 464 sparse_file_destroy(s); 465 return NULL; 466 } 467 468 s->verbose = verbose; 469 470 ret = sparse_file_read(s, fd, true, crc); 471 if (ret < 0) { 472 sparse_file_destroy(s); 473 return NULL; 474 } 475 476 return s; 477 } 478 479 struct sparse_file *sparse_file_import_auto(int fd, bool crc) 480 { 481 struct sparse_file *s; 482 int64_t len; 483 int ret; 484 485 s = sparse_file_import(fd, true, crc); 486 if (s) { 487 return s; 488 } 489 490 len = lseek64(fd, 0, SEEK_END); 491 if (len < 0) { 492 return NULL; 493 } 494 495 lseek64(fd, 0, SEEK_SET); 496 497 s = sparse_file_new(4096, len); 498 if (!s) { 499 return NULL; 500 } 501 502 ret = sparse_file_read_normal(s, fd); 503 if (ret < 0) { 504 sparse_file_destroy(s); 505 return NULL; 506 } 507 508 return s; 509 } 510