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>
22 #include <inttypes.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <unistd.h>
27 #include <sys/stat.h>
28 
29 #include <log/log.h>
30 
31 #include <diskconfig/diskconfig.h>
32 
33 int
write_raw_image(const char * dst,const char * src,loff_t offset,int test)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];
39     ssize_t nr_bytes;
40     ssize_t tmp;
41     int done = 0;
42     uint64_t total = 0;
43 
44     ALOGI("Writing RAW image '%s' to '%s' (offset=%llu)", src, dst, (unsigned long long)offset);
45     if ((src_fd = open(src, O_RDONLY)) < 0) {
46         ALOGE("Could not open %s for reading (errno=%d).", src, errno);
47         goto fail;
48     }
49 
50     if (!test) {
51         if ((dst_fd = open(dst, O_RDWR)) < 0) {
52             ALOGE("Could not open '%s' for read/write (errno=%d).", dst, errno);
53             goto fail;
54         }
55 
56         if (lseek64(dst_fd, offset, SEEK_SET) != offset) {
57             ALOGE("Could not seek to offset %lld in %s.", (long long)offset, dst);
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;
67             ALOGE("Error (%d) while reading from '%s'", errno, src);
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;
88                 ALOGE("Error (%d) while writing to '%s'", errno, dst);
89                 goto fail;
90             }
91             if (!tmp)
92                 continue;
93             nr_bytes -= tmp;
94         }
95     }
96 
97     if (!done) {
98         ALOGE("Exited read/write loop without setting flag! WTF?!");
99         goto fail;
100     }
101 
102     if (dst_fd >= 0)
103         fsync(dst_fd);
104 
105     ALOGI("Wrote %" PRIu64 " bytes to %s @ %lld", total, dst, (long long)offset);
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 }
119