| San Mehat | a6391f1 | 2010-03-10 12:46:00 -0800 | [diff] [blame] | 1 | /* libs/diskconfig/diskutils.c | 
|  | 2 | * | 
|  | 3 | * Copyright 2008, The Android Open Source Project | 
|  | 4 | * | 
|  | 5 | * Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | 6 | * you may not use this file except in compliance with the License. | 
|  | 7 | * You may obtain a copy of the License at | 
|  | 8 | * | 
|  | 9 | *     http://www.apache.org/licenses/LICENSE-2.0 | 
|  | 10 | * | 
|  | 11 | * Unless required by applicable law or agreed to in writing, software | 
|  | 12 | * distributed under the License is distributed on an "AS IS" BASIS, | 
|  | 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | 14 | * See the License for the specific language governing permissions and | 
|  | 15 | * limitations under the License. | 
|  | 16 | */ | 
|  | 17 |  | 
|  | 18 | #define LOG_TAG "diskutils" | 
|  | 19 |  | 
|  | 20 | #include <errno.h> | 
|  | 21 | #include <fcntl.h> | 
| Mark Salyzyn | 1874e65 | 2014-03-13 16:38:43 -0700 | [diff] [blame] | 22 | #include <inttypes.h> | 
| San Mehat | a6391f1 | 2010-03-10 12:46:00 -0800 | [diff] [blame] | 23 | #include <stdio.h> | 
|  | 24 | #include <stdlib.h> | 
|  | 25 | #include <string.h> | 
| San Mehat | a6391f1 | 2010-03-10 12:46:00 -0800 | [diff] [blame] | 26 | #include <sys/stat.h> | 
| Mark Salyzyn | ff2dcd9 | 2016-09-28 15:54:45 -0700 | [diff] [blame] | 27 | #include <unistd.h> | 
| San Mehat | a6391f1 | 2010-03-10 12:46:00 -0800 | [diff] [blame] | 28 |  | 
| Mark Salyzyn | 30f991f | 2017-01-10 13:19:54 -0800 | [diff] [blame] | 29 | #include <log/log.h> | 
| San Mehat | a6391f1 | 2010-03-10 12:46:00 -0800 | [diff] [blame] | 30 |  | 
|  | 31 | #include <diskconfig/diskconfig.h> | 
|  | 32 |  | 
|  | 33 | int | 
|  | 34 | write_raw_image(const char *dst, const char *src, loff_t offset, int test) | 
|  | 35 | { | 
|  | 36 | int dst_fd = -1; | 
|  | 37 | int src_fd = -1; | 
|  | 38 | uint8_t buffer[2048]; | 
| Mark Salyzyn | 1874e65 | 2014-03-13 16:38:43 -0700 | [diff] [blame] | 39 | ssize_t nr_bytes; | 
|  | 40 | ssize_t tmp; | 
| San Mehat | a6391f1 | 2010-03-10 12:46:00 -0800 | [diff] [blame] | 41 | int done = 0; | 
|  | 42 | uint64_t total = 0; | 
|  | 43 |  | 
| Ying Wang | 9d4c76f | 2014-04-23 18:28:14 -0700 | [diff] [blame] | 44 | ALOGI("Writing RAW image '%s' to '%s' (offset=%llu)", src, dst, (unsigned long long)offset); | 
| San Mehat | a6391f1 | 2010-03-10 12:46:00 -0800 | [diff] [blame] | 45 | if ((src_fd = open(src, O_RDONLY)) < 0) { | 
| Steve Block | 01dda20 | 2012-01-06 14:13:42 +0000 | [diff] [blame] | 46 | ALOGE("Could not open %s for reading (errno=%d).", src, errno); | 
| San Mehat | a6391f1 | 2010-03-10 12:46:00 -0800 | [diff] [blame] | 47 | goto fail; | 
|  | 48 | } | 
|  | 49 |  | 
|  | 50 | if (!test) { | 
|  | 51 | if ((dst_fd = open(dst, O_RDWR)) < 0) { | 
| Steve Block | 01dda20 | 2012-01-06 14:13:42 +0000 | [diff] [blame] | 52 | ALOGE("Could not open '%s' for read/write (errno=%d).", dst, errno); | 
| San Mehat | a6391f1 | 2010-03-10 12:46:00 -0800 | [diff] [blame] | 53 | goto fail; | 
|  | 54 | } | 
|  | 55 |  | 
|  | 56 | if (lseek64(dst_fd, offset, SEEK_SET) != offset) { | 
| Ying Wang | 9d4c76f | 2014-04-23 18:28:14 -0700 | [diff] [blame] | 57 | ALOGE("Could not seek to offset %lld in %s.", (long long)offset, dst); | 
| San Mehat | a6391f1 | 2010-03-10 12:46:00 -0800 | [diff] [blame] | 58 | goto fail; | 
|  | 59 | } | 
|  | 60 | } | 
|  | 61 |  | 
|  | 62 | while (!done) { | 
|  | 63 | if ((nr_bytes = read(src_fd, buffer, sizeof(buffer))) < 0) { | 
|  | 64 | /* XXX: Should we not even bother with EINTR? */ | 
|  | 65 | if (errno == EINTR) | 
|  | 66 | continue; | 
| Steve Block | 01dda20 | 2012-01-06 14:13:42 +0000 | [diff] [blame] | 67 | ALOGE("Error (%d) while reading from '%s'", errno, src); | 
| San Mehat | a6391f1 | 2010-03-10 12:46:00 -0800 | [diff] [blame] | 68 | goto fail; | 
|  | 69 | } | 
|  | 70 |  | 
|  | 71 | if (!nr_bytes) { | 
|  | 72 | /* we're done. */ | 
|  | 73 | done = 1; | 
|  | 74 | break; | 
|  | 75 | } | 
|  | 76 |  | 
|  | 77 | total += nr_bytes; | 
|  | 78 |  | 
|  | 79 | /* skip the write loop if we're testing */ | 
|  | 80 | if (test) | 
|  | 81 | nr_bytes = 0; | 
|  | 82 |  | 
|  | 83 | while (nr_bytes > 0) { | 
|  | 84 | if ((tmp = write(dst_fd, buffer, nr_bytes)) < 0) { | 
|  | 85 | /* XXX: Should we not even bother with EINTR? */ | 
|  | 86 | if (errno == EINTR) | 
|  | 87 | continue; | 
| Steve Block | 01dda20 | 2012-01-06 14:13:42 +0000 | [diff] [blame] | 88 | ALOGE("Error (%d) while writing to '%s'", errno, dst); | 
| San Mehat | a6391f1 | 2010-03-10 12:46:00 -0800 | [diff] [blame] | 89 | goto fail; | 
|  | 90 | } | 
|  | 91 | if (!tmp) | 
|  | 92 | continue; | 
|  | 93 | nr_bytes -= tmp; | 
|  | 94 | } | 
|  | 95 | } | 
|  | 96 |  | 
|  | 97 | if (!done) { | 
| Steve Block | 01dda20 | 2012-01-06 14:13:42 +0000 | [diff] [blame] | 98 | ALOGE("Exited read/write loop without setting flag! WTF?!"); | 
| San Mehat | a6391f1 | 2010-03-10 12:46:00 -0800 | [diff] [blame] | 99 | goto fail; | 
|  | 100 | } | 
|  | 101 |  | 
|  | 102 | if (dst_fd >= 0) | 
|  | 103 | fsync(dst_fd); | 
|  | 104 |  | 
| Ying Wang | 9d4c76f | 2014-04-23 18:28:14 -0700 | [diff] [blame] | 105 | ALOGI("Wrote %" PRIu64 " bytes to %s @ %lld", total, dst, (long long)offset); | 
| San Mehat | a6391f1 | 2010-03-10 12:46:00 -0800 | [diff] [blame] | 106 |  | 
|  | 107 | close(src_fd); | 
|  | 108 | if (dst_fd >= 0) | 
|  | 109 | close(dst_fd); | 
|  | 110 | return 0; | 
|  | 111 |  | 
|  | 112 | fail: | 
|  | 113 | if (dst_fd >= 0) | 
|  | 114 | close(dst_fd); | 
|  | 115 | if (src_fd >= 0) | 
|  | 116 | close(src_fd); | 
|  | 117 | return 1; | 
|  | 118 | } |