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