blob: fe3f0f81c16afb7c54097aa53c9258a98b99fcbf [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 */
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 Starzycki2a656c32013-09-05 14:26:28 -070037#include <stdlib.h>
Szymon Starzyckibc849f12013-09-13 15:37:08 -070038#include <cutils/properties.h>
Szymon Starzyckib6c5f282013-07-24 17:08:04 -070039
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
Szymon Starzycki2a656c32013-09-05 14:26:28 -070051#define READ_BUF_SIZE (16*1024)
Szymon Starzyckib6c5f282013-07-24 17:08:04 -070052
53int 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
61uint64_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
74uint64_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
94uint64_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
115char *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
127int 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
Szymon Starzycki2a656c32013-09-05 14:26:28 -0700151int 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
164ssize_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=%d 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
184ssize_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=%d 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=%u n=%u length=%u",
200 ret, to_read, n, length);
201 break;
202 }
203 }
204
205 return n;
206}
207
Szymon Starzyckibc849f12013-09-13 15:37:08 -0700208#define NAP_TIME 200 // 200 ms between polls
209static 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
229int 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) {
Szymon Starzycki27ea99f2013-09-18 16:12:43 -0700236 D(INFO, "Starting %s", service_name);
Szymon Starzyckibc849f12013-09-13 15:37:08 -0700237 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
245int 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
Szymon Starzycki27ea99f2013-09-18 16:12:43 -0700257int ssh_server_start()
258{
259 return service_start("sshd");
260}