blob: 4c3a2e8119109971bb763047b8af1cd8b37f1a9a [file] [log] [blame]
Szymon Starzyckib6c5f282013-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 */
Elliott Hughes0badbd62014-12-29 12:24:25 -080031#include <errno.h>
Szymon Starzyckib6c5f282013-07-24 17:08:04 -070032#include <sys/types.h>
33#include <sys/stat.h>
34#include <unistd.h>
35#include <stdio.h>
36#include <sys/ioctl.h>
37#include <linux/fs.h>
Szymon Starzycki2a656c32013-09-05 14:26:28 -070038#include <stdlib.h>
Elliott Hughesa744b052015-01-28 11:37:57 -080039#include <string.h>
Szymon Starzyckibc849f12013-09-13 15:37:08 -070040#include <cutils/properties.h>
Szymon Starzyckib6c5f282013-07-24 17:08:04 -070041
42#include "utils.h"
43#include "debug.h"
44
45#ifndef BLKDISCARD
46#define BLKDISCARD _IO(0x12,119)
47#endif
48
49#ifndef BLKSECDISCARD
50#define BLKSECDISCARD _IO(0x12,125)
51#endif
52
Szymon Starzycki2a656c32013-09-05 14:26:28 -070053#define READ_BUF_SIZE (16*1024)
Szymon Starzyckib6c5f282013-07-24 17:08:04 -070054
55int get_stream_size(FILE *stream) {
56 int size;
57 fseek(stream, 0, SEEK_END);
58 size = ftell(stream);
59 fseek(stream, 0, SEEK_SET);
60 return size;
61}
62
63uint64_t get_block_device_size(int fd)
64{
65 uint64_t size = 0;
66 int ret;
67
68 ret = ioctl(fd, BLKGETSIZE64, &size);
69
70 if (ret)
71 return 0;
72
73 return size;
74}
75
76uint64_t get_file_size(int fd)
77{
78 struct stat buf;
79 int ret;
80 int64_t computed_size;
81
82 ret = fstat(fd, &buf);
83 if (ret)
84 return 0;
85
86 if (S_ISREG(buf.st_mode))
87 computed_size = buf.st_size;
88 else if (S_ISBLK(buf.st_mode))
89 computed_size = get_block_device_size(fd);
90 else
91 computed_size = 0;
92
93 return computed_size;
94}
95
96uint64_t get_file_size64(int fd)
97{
98 struct stat64 buf;
99 int ret;
100 uint64_t computed_size;
101
102 ret = fstat64(fd, &buf);
103 if (ret)
104 return 0;
105
106 if (S_ISREG(buf.st_mode))
107 computed_size = buf.st_size;
108 else if (S_ISBLK(buf.st_mode))
109 computed_size = get_block_device_size(fd);
110 else
111 computed_size = 0;
112
113 return computed_size;
114}
115
116
117char *strip(char *str)
118{
119 int n;
120
121 n = strspn(str, " \t");
122 str += n;
123 n = strcspn(str, " \t");
124 str[n] = '\0';
125
126 return str;
127}
128
129int wipe_block_device(int fd, int64_t len)
130{
131 uint64_t range[2];
132 int ret;
133
134 range[0] = 0;
135 range[1] = len;
136 ret = ioctl(fd, BLKSECDISCARD, &range);
137 if (ret < 0) {
138 range[0] = 0;
139 range[1] = len;
140 ret = ioctl(fd, BLKDISCARD, &range);
141 if (ret < 0) {
142 D(WARN, "Discard failed\n");
143 return 1;
144 } else {
145 D(WARN, "Wipe via secure discard failed, used discard instead\n");
146 return 0;
147 }
148 }
149
150 return 0;
151}
152
Szymon Starzycki2a656c32013-09-05 14:26:28 -0700153int create_temp_file() {
154 char tempname[] = "/dev/fastboot_data_XXXXXX";
155 int fd;
156
157 fd = mkstemp(tempname);
158 if (fd < 0)
159 return -1;
160
161 unlink(tempname);
162
163 return fd;
164}
165
166ssize_t bulk_write(int bulk_in, const char *buf, size_t length)
167{
168 size_t count = 0;
169 ssize_t ret;
170
171 do {
172 ret = TEMP_FAILURE_RETRY(write(bulk_in, buf + count, length - count));
173 if (ret < 0) {
Elliott Hughes4f241252014-01-14 16:17:08 -0800174 D(WARN, "[ bulk_write failed fd=%d length=%zu errno=%d %s ]",
Szymon Starzycki2a656c32013-09-05 14:26:28 -0700175 bulk_in, length, errno, strerror(errno));
176 return -1;
177 } else {
178 count += ret;
179 }
180 } while (count < length);
181
182 D(VERBOSE, "[ bulk_write done fd=%d ]", bulk_in);
183 return count;
184}
185
186ssize_t bulk_read(int bulk_out, char *buf, size_t length)
187{
188 ssize_t ret;
189 size_t n = 0;
190
191 while (n < length) {
192 size_t to_read = (length - n > READ_BUF_SIZE) ? READ_BUF_SIZE : length - n;
193 ret = TEMP_FAILURE_RETRY(read(bulk_out, buf + n, to_read));
194 if (ret < 0) {
Elliott Hughes4f241252014-01-14 16:17:08 -0800195 D(WARN, "[ bulk_read failed fd=%d length=%zu errno=%d %s ]",
Szymon Starzycki2a656c32013-09-05 14:26:28 -0700196 bulk_out, length, errno, strerror(errno));
197 return ret;
198 }
199 n += ret;
200 if (ret < (ssize_t)to_read) {
Elliott Hughes4f241252014-01-14 16:17:08 -0800201 D(VERBOSE, "bulk_read short read, ret=%zd to_read=%zu n=%zu length=%zu",
Szymon Starzycki2a656c32013-09-05 14:26:28 -0700202 ret, to_read, n, length);
203 break;
204 }
205 }
206
207 return n;
208}
209
Szymon Starzyckibc849f12013-09-13 15:37:08 -0700210#define NAP_TIME 200 // 200 ms between polls
211static int wait_for_property(const char *name, const char *desired_value, int maxwait)
212{
213 char value[PROPERTY_VALUE_MAX] = {'\0'};
214 int maxnaps = (maxwait * 1000) / NAP_TIME;
215
216 if (maxnaps < 1) {
217 maxnaps = 1;
218 }
219
220 while (maxnaps-- > 0) {
221 usleep(NAP_TIME * 1000);
222 if (property_get(name, value, NULL)) {
223 if (desired_value == NULL || strcmp(value, desired_value) == 0) {
224 return 0;
225 }
226 }
227 }
228 return -1; /* failure */
229}
230
231int service_start(const char *service_name)
232{
233 int result = 0;
234 char property_value[PROPERTY_VALUE_MAX];
235
236 property_get(service_name, property_value, "");
237 if (strcmp("running", property_value) != 0) {
Szymon Starzycki27ea99f2013-09-18 16:12:43 -0700238 D(INFO, "Starting %s", service_name);
Szymon Starzyckibc849f12013-09-13 15:37:08 -0700239 property_set("ctl.start", service_name);
240 if (wait_for_property(service_name, "running", 5))
241 result = -1;
242 }
243
244 return result;
245}
246
247int service_stop(const char *service_name)
248{
249 int result = 0;
250
251 D(INFO, "Stopping MDNSD");
252 property_set("ctl.stop", service_name);
253 if (wait_for_property(service_name, "stopped", 5))
254 result = -1;
255
256 return result;
257}
258
Szymon Starzycki27ea99f2013-09-18 16:12:43 -0700259int ssh_server_start()
260{
261 return service_start("sshd");
262}