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
33int
34write_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
112fail:
113    if (dst_fd >= 0)
114        close(dst_fd);
115    if (src_fd >= 0)
116        close(src_fd);
117    return 1;
118}
119