Home | History | Annotate | Download | only in libdiskconfig
      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 <sys/stat.h>
     27 #include <unistd.h>
     28 
     29 #include <log/log.h>
     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];
     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