blob: cac55097f801470234a35fd55952591e8f31777f [file] [log] [blame]
Szymon Starzyckie160f812013-07-24 17:08:04 -07001/*
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>
Szymon Starzyckib015b162013-09-05 14:26:28 -070037#include <stdlib.h>
Szymon Starzyckie160f812013-07-24 17:08:04 -070038
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
Szymon Starzyckib015b162013-09-05 14:26:28 -070050#define READ_BUF_SIZE (16*1024)
Szymon Starzyckie160f812013-07-24 17:08:04 -070051
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
Szymon Starzyckib015b162013-09-05 14:26:28 -0700150int 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