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>
22a6391f1006b961ca89d1c79a826375380684a4deSan Mehat#include <stdio.h>
23a6391f1006b961ca89d1c79a826375380684a4deSan Mehat#include <stdlib.h>
24a6391f1006b961ca89d1c79a826375380684a4deSan Mehat#include <string.h>
25a6391f1006b961ca89d1c79a826375380684a4deSan Mehat#include <unistd.h>
26a6391f1006b961ca89d1c79a826375380684a4deSan Mehat#include <sys/stat.h>
27a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
28a6391f1006b961ca89d1c79a826375380684a4deSan Mehat#include <cutils/log.h>
29a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
30a6391f1006b961ca89d1c79a826375380684a4deSan Mehat#include <diskconfig/diskconfig.h>
31a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
32a6391f1006b961ca89d1c79a826375380684a4deSan Mehatint
33a6391f1006b961ca89d1c79a826375380684a4deSan Mehatwrite_raw_image(const char *dst, const char *src, loff_t offset, int test)
34a6391f1006b961ca89d1c79a826375380684a4deSan Mehat{
35a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    int dst_fd = -1;
36a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    int src_fd = -1;
37a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    uint8_t buffer[2048];
38a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    int nr_bytes;
39a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    int tmp;
40a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    int done = 0;
41a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    uint64_t total = 0;
42a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
43fe71a61e5b0cb666675900d206251a7c18ed944bSteve Block    ALOGI("Writing RAW image '%s' to '%s' (offset=%llu)", src, dst, offset);
44a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if ((src_fd = open(src, O_RDONLY)) < 0) {
4501dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block        ALOGE("Could not open %s for reading (errno=%d).", src, errno);
46a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        goto fail;
47a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
48a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
49a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (!test) {
50a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        if ((dst_fd = open(dst, O_RDWR)) < 0) {
5101dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block            ALOGE("Could not open '%s' for read/write (errno=%d).", dst, errno);
52a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            goto fail;
53a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        }
54a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
55a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        if (lseek64(dst_fd, offset, SEEK_SET) != offset) {
5601dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block            ALOGE("Could not seek to offset %lld in %s.", offset, dst);
57a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            goto fail;
58a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        }
59a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
60a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
61a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    while (!done) {
62a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        if ((nr_bytes = read(src_fd, buffer, sizeof(buffer))) < 0) {
63a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            /* XXX: Should we not even bother with EINTR? */
64a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            if (errno == EINTR)
65a6391f1006b961ca89d1c79a826375380684a4deSan Mehat                continue;
6601dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block            ALOGE("Error (%d) while reading from '%s'", errno, src);
67a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            goto fail;
68a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        }
69a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
70a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        if (!nr_bytes) {
71a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            /* we're done. */
72a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            done = 1;
73a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            break;
74a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        }
75a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
76a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        total += nr_bytes;
77a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
78a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        /* skip the write loop if we're testing */
79a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        if (test)
80a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            nr_bytes = 0;
81a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
82a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        while (nr_bytes > 0) {
83a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            if ((tmp = write(dst_fd, buffer, nr_bytes)) < 0) {
84a6391f1006b961ca89d1c79a826375380684a4deSan Mehat                /* XXX: Should we not even bother with EINTR? */
85a6391f1006b961ca89d1c79a826375380684a4deSan Mehat                if (errno == EINTR)
86a6391f1006b961ca89d1c79a826375380684a4deSan Mehat                    continue;
8701dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block                ALOGE("Error (%d) while writing to '%s'", errno, dst);
88a6391f1006b961ca89d1c79a826375380684a4deSan Mehat                goto fail;
89a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            }
90a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            if (!tmp)
91a6391f1006b961ca89d1c79a826375380684a4deSan Mehat                continue;
92a6391f1006b961ca89d1c79a826375380684a4deSan Mehat            nr_bytes -= tmp;
93a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        }
94a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
95a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
96a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (!done) {
9701dda204cd28fe181691b4a44a51be7e5666d0c8Steve Block        ALOGE("Exited read/write loop without setting flag! WTF?!");
98a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        goto fail;
99a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    }
100a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
101a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (dst_fd >= 0)
102a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        fsync(dst_fd);
103a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
104fe71a61e5b0cb666675900d206251a7c18ed944bSteve Block    ALOGI("Wrote %llu bytes to %s @ %lld", total, dst, offset);
105a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
106a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    close(src_fd);
107a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (dst_fd >= 0)
108a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        close(dst_fd);
109a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    return 0;
110a6391f1006b961ca89d1c79a826375380684a4deSan Mehat
111a6391f1006b961ca89d1c79a826375380684a4deSan Mehatfail:
112a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (dst_fd >= 0)
113a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        close(dst_fd);
114a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    if (src_fd >= 0)
115a6391f1006b961ca89d1c79a826375380684a4deSan Mehat        close(src_fd);
116a6391f1006b961ca89d1c79a826375380684a4deSan Mehat    return 1;
117a6391f1006b961ca89d1c79a826375380684a4deSan Mehat}
118