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