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
get_stream_size(FILE * stream)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
get_block_device_size(int fd)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
get_file_size(int fd)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
get_file_size64(int fd)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
strip(char * str)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
wipe_block_device(int fd,int64_t len)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
create_temp_file()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
bulk_write(int bulk_in,const char * buf,size_t length)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
bulk_read(int bulk_out,char * buf,size_t length)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
wait_for_property(const char * name,const char * desired_value,int maxwait)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
service_start(const char * service_name)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
service_stop(const char * service_name)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
ssh_server_start()257 int ssh_server_start()
258 {
259 return service_start("sshd");
260 }
261