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