Home | History | Annotate | Download | only in fastbootd
      1 /*
      2  * Copyright (c) 2009-2013, Google Inc.
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  *  * Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  *  * Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in
     12  *    the documentation and/or other materials provided with the
     13  *    distribution.
     14  *  * Neither the name of Google, Inc. nor the names of its contributors
     15  *    may be used to endorse or promote products derived from this
     16  *    software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     21  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
     22  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
     23  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     24  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
     25  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     26  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     27  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     28  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     29  * SUCH DAMAGE.
     30  */
     31 #include <sys/types.h>
     32 #include <sys/stat.h>
     33 #include <unistd.h>
     34 #include <stdio.h>
     35 #include <sys/ioctl.h>
     36 #include <linux/fs.h>
     37 #include <stdlib.h>
     38 #include <cutils/properties.h>
     39 
     40 #include "utils.h"
     41 #include "debug.h"
     42 
     43 #ifndef BLKDISCARD
     44 #define BLKDISCARD _IO(0x12,119)
     45 #endif
     46 
     47 #ifndef BLKSECDISCARD
     48 #define BLKSECDISCARD _IO(0x12,125)
     49 #endif
     50 
     51 #define READ_BUF_SIZE (16*1024)
     52 
     53 int get_stream_size(FILE *stream) {
     54     int size;
     55     fseek(stream, 0, SEEK_END);
     56     size = ftell(stream);
     57     fseek(stream, 0, SEEK_SET);
     58     return size;
     59 }
     60 
     61 uint64_t get_block_device_size(int fd)
     62 {
     63     uint64_t size = 0;
     64     int ret;
     65 
     66     ret = ioctl(fd, BLKGETSIZE64, &size);
     67 
     68     if (ret)
     69         return 0;
     70 
     71     return size;
     72 }
     73 
     74 uint64_t get_file_size(int fd)
     75 {
     76     struct stat buf;
     77     int ret;
     78     int64_t computed_size;
     79 
     80     ret = fstat(fd, &buf);
     81     if (ret)
     82         return 0;
     83 
     84     if (S_ISREG(buf.st_mode))
     85         computed_size = buf.st_size;
     86     else if (S_ISBLK(buf.st_mode))
     87         computed_size = get_block_device_size(fd);
     88     else
     89         computed_size = 0;
     90 
     91     return computed_size;
     92 }
     93 
     94 uint64_t get_file_size64(int fd)
     95 {
     96     struct stat64 buf;
     97     int ret;
     98     uint64_t computed_size;
     99 
    100     ret = fstat64(fd, &buf);
    101     if (ret)
    102         return 0;
    103 
    104     if (S_ISREG(buf.st_mode))
    105         computed_size = buf.st_size;
    106     else if (S_ISBLK(buf.st_mode))
    107         computed_size = get_block_device_size(fd);
    108     else
    109         computed_size = 0;
    110 
    111     return computed_size;
    112 }
    113 
    114 
    115 char *strip(char *str)
    116 {
    117     int n;
    118 
    119     n = strspn(str, " \t");
    120     str += n;
    121     n = strcspn(str, " \t");
    122     str[n] = '\0';
    123 
    124     return str;
    125 }
    126 
    127 int wipe_block_device(int fd, int64_t len)
    128 {
    129     uint64_t range[2];
    130     int ret;
    131 
    132     range[0] = 0;
    133     range[1] = len;
    134     ret = ioctl(fd, BLKSECDISCARD, &range);
    135     if (ret < 0) {
    136         range[0] = 0;
    137         range[1] = len;
    138         ret = ioctl(fd, BLKDISCARD, &range);
    139         if (ret < 0) {
    140             D(WARN, "Discard failed\n");
    141             return 1;
    142         } else {
    143             D(WARN, "Wipe via secure discard failed, used discard instead\n");
    144             return 0;
    145         }
    146     }
    147 
    148     return 0;
    149 }
    150 
    151 int create_temp_file() {
    152     char tempname[] = "/dev/fastboot_data_XXXXXX";
    153     int fd;
    154 
    155     fd = mkstemp(tempname);
    156     if (fd < 0)
    157         return -1;
    158 
    159     unlink(tempname);
    160 
    161     return fd;
    162 }
    163 
    164 ssize_t bulk_write(int bulk_in, const char *buf, size_t length)
    165 {
    166     size_t count = 0;
    167     ssize_t ret;
    168 
    169     do {
    170         ret = TEMP_FAILURE_RETRY(write(bulk_in, buf + count, length - count));
    171         if (ret < 0) {
    172             D(WARN, "[ bulk_write failed fd=%d length=%zu errno=%d %s ]",
    173                     bulk_in, length, errno, strerror(errno));
    174             return -1;
    175         } else {
    176             count += ret;
    177         }
    178     } while (count < length);
    179 
    180     D(VERBOSE, "[ bulk_write done fd=%d ]", bulk_in);
    181     return count;
    182 }
    183 
    184 ssize_t bulk_read(int bulk_out, char *buf, size_t length)
    185 {
    186     ssize_t ret;
    187     size_t n = 0;
    188 
    189     while (n < length) {
    190         size_t to_read = (length - n > READ_BUF_SIZE) ? READ_BUF_SIZE : length - n;
    191         ret = TEMP_FAILURE_RETRY(read(bulk_out, buf + n, to_read));
    192         if (ret < 0) {
    193             D(WARN, "[ bulk_read failed fd=%d length=%zu errno=%d %s ]",
    194                     bulk_out, length, errno, strerror(errno));
    195             return ret;
    196         }
    197         n += ret;
    198         if (ret < (ssize_t)to_read) {
    199             D(VERBOSE, "bulk_read short read, ret=%zd to_read=%zu n=%zu length=%zu",
    200                     ret, to_read, n, length);
    201             break;
    202         }
    203     }
    204 
    205     return n;
    206 }
    207 
    208 #define NAP_TIME 200  // 200 ms between polls
    209 static int wait_for_property(const char *name, const char *desired_value, int maxwait)
    210 {
    211     char value[PROPERTY_VALUE_MAX] = {'\0'};
    212     int maxnaps = (maxwait * 1000) / NAP_TIME;
    213 
    214     if (maxnaps < 1) {
    215         maxnaps = 1;
    216     }
    217 
    218     while (maxnaps-- > 0) {
    219         usleep(NAP_TIME * 1000);
    220         if (property_get(name, value, NULL)) {
    221             if (desired_value == NULL || strcmp(value, desired_value) == 0) {
    222                 return 0;
    223             }
    224         }
    225     }
    226     return -1; /* failure */
    227 }
    228 
    229 int service_start(const char *service_name)
    230 {
    231     int result = 0;
    232     char property_value[PROPERTY_VALUE_MAX];
    233 
    234     property_get(service_name, property_value, "");
    235     if (strcmp("running", property_value) != 0) {
    236         D(INFO, "Starting %s", service_name);
    237         property_set("ctl.start", service_name);
    238         if (wait_for_property(service_name, "running", 5))
    239             result = -1;
    240     }
    241 
    242     return result;
    243 }
    244 
    245 int service_stop(const char *service_name)
    246 {
    247     int result = 0;
    248 
    249     D(INFO, "Stopping MDNSD");
    250     property_set("ctl.stop", service_name);
    251     if (wait_for_property(service_name, "stopped", 5))
    252         result = -1;
    253 
    254     return result;
    255 }
    256 
    257 int ssh_server_start()
    258 {
    259     return service_start("sshd");
    260 }
    261