utils.c revision 2a656c332b792c84fa6e96d8b40e2c8c0fe94ef9
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
39#include "utils.h"
40#include "debug.h"
41
42#ifndef BLKDISCARD
43#define BLKDISCARD _IO(0x12,119)
44#endif
45
46#ifndef BLKSECDISCARD
47#define BLKSECDISCARD _IO(0x12,125)
48#endif
49
50#define READ_BUF_SIZE (16*1024)
51
52int get_stream_size(FILE *stream) {
53    int size;
54    fseek(stream, 0, SEEK_END);
55    size = ftell(stream);
56    fseek(stream, 0, SEEK_SET);
57    return size;
58}
59
60uint64_t get_block_device_size(int fd)
61{
62    uint64_t size = 0;
63    int ret;
64
65    ret = ioctl(fd, BLKGETSIZE64, &size);
66
67    if (ret)
68        return 0;
69
70    return size;
71}
72
73uint64_t get_file_size(int fd)
74{
75    struct stat buf;
76    int ret;
77    int64_t computed_size;
78
79    ret = fstat(fd, &buf);
80    if (ret)
81        return 0;
82
83    if (S_ISREG(buf.st_mode))
84        computed_size = buf.st_size;
85    else if (S_ISBLK(buf.st_mode))
86        computed_size = get_block_device_size(fd);
87    else
88        computed_size = 0;
89
90    return computed_size;
91}
92
93uint64_t get_file_size64(int fd)
94{
95    struct stat64 buf;
96    int ret;
97    uint64_t computed_size;
98
99    ret = fstat64(fd, &buf);
100    if (ret)
101        return 0;
102
103    if (S_ISREG(buf.st_mode))
104        computed_size = buf.st_size;
105    else if (S_ISBLK(buf.st_mode))
106        computed_size = get_block_device_size(fd);
107    else
108        computed_size = 0;
109
110    return computed_size;
111}
112
113
114char *strip(char *str)
115{
116    int n;
117
118    n = strspn(str, " \t");
119    str += n;
120    n = strcspn(str, " \t");
121    str[n] = '\0';
122
123    return str;
124}
125
126int wipe_block_device(int fd, int64_t len)
127{
128    uint64_t range[2];
129    int ret;
130
131    range[0] = 0;
132    range[1] = len;
133    ret = ioctl(fd, BLKSECDISCARD, &range);
134    if (ret < 0) {
135        range[0] = 0;
136        range[1] = len;
137        ret = ioctl(fd, BLKDISCARD, &range);
138        if (ret < 0) {
139            D(WARN, "Discard failed\n");
140            return 1;
141        } else {
142            D(WARN, "Wipe via secure discard failed, used discard instead\n");
143            return 0;
144        }
145    }
146
147    return 0;
148}
149
150int create_temp_file() {
151    char tempname[] = "/dev/fastboot_data_XXXXXX";
152    int fd;
153
154    fd = mkstemp(tempname);
155    if (fd < 0)
156        return -1;
157
158    unlink(tempname);
159
160    return fd;
161}
162
163ssize_t bulk_write(int bulk_in, const char *buf, size_t length)
164{
165    size_t count = 0;
166    ssize_t ret;
167
168    do {
169        ret = TEMP_FAILURE_RETRY(write(bulk_in, buf + count, length - count));
170        if (ret < 0) {
171            D(WARN, "[ bulk_write failed fd=%d length=%d errno=%d %s ]",
172                    bulk_in, length, errno, strerror(errno));
173            return -1;
174        } else {
175            count += ret;
176        }
177    } while (count < length);
178
179    D(VERBOSE, "[ bulk_write done fd=%d ]", bulk_in);
180    return count;
181}
182
183ssize_t bulk_read(int bulk_out, char *buf, size_t length)
184{
185    ssize_t ret;
186    size_t n = 0;
187
188    while (n < length) {
189        size_t to_read = (length - n > READ_BUF_SIZE) ? READ_BUF_SIZE : length - n;
190        ret = TEMP_FAILURE_RETRY(read(bulk_out, buf + n, to_read));
191        if (ret < 0) {
192            D(WARN, "[ bulk_read failed fd=%d length=%d errno=%d %s ]",
193                    bulk_out, length, errno, strerror(errno));
194            return ret;
195        }
196        n += ret;
197        if (ret < (ssize_t)to_read) {
198            D(VERBOSE, "bulk_read short read, ret=%zd to_read=%u n=%u length=%u",
199                    ret, to_read, n, length);
200            break;
201        }
202    }
203
204    return n;
205}
206
207