blob: 1db3013c6f9b896352b9201f260cb4486e89a2bf [file] [log] [blame]
Doug Zongker76adfc52014-01-13 10:04:25 -08001/*
2 * Copyright (C) 2014 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17// This program takes a file on an ext4 filesystem and produces a list
18// of the blocks that file occupies, which enables the file contents
19// to be read directly from the block device without mounting the
20// filesystem.
21//
22// If the filesystem is using an encrypted block device, it will also
23// read the file and rewrite it to the same blocks of the underlying
24// (unencrypted) block device, so the file contents can be read
25// without the need for the decryption key.
26//
27// The output of this program is a "block map" which looks like this:
28//
29// /dev/block/platform/msm_sdcc.1/by-name/userdata # block device
30// 49652 4096 # file size in bytes, block size
31// 3 # count of block ranges
32// 1000 1008 # block range 0
33// 2100 2102 # ... block range 1
34// 30 33 # ... block range 2
35//
36// Each block range represents a half-open interval; the line "30 33"
37// reprents the blocks [30, 31, 32].
38//
39// Recovery can take this block map file and retrieve the underlying
40// file data to use as an update package.
41
Elliott Hughesd4d4c242014-12-29 12:46:43 -080042#include <errno.h>
Tao Bao158e11d2015-05-21 16:44:44 -070043#include <fcntl.h>
44#include <linux/fs.h>
45#include <stdarg.h>
Doug Zongker76adfc52014-01-13 10:04:25 -080046#include <stdio.h>
47#include <stdlib.h>
Elliott Hughescd3c55a2015-01-29 20:50:08 -080048#include <string.h>
Doug Zongker76adfc52014-01-13 10:04:25 -080049#include <sys/mman.h>
Tao Bao158e11d2015-05-21 16:44:44 -070050#include <sys/stat.h>
51#include <sys/types.h>
52#include <unistd.h>
Doug Zongker76adfc52014-01-13 10:04:25 -080053
Tao Bao158e11d2015-05-21 16:44:44 -070054#include <base/file.h>
55#include <base/strings.h>
Doug Zongker76adfc52014-01-13 10:04:25 -080056#include <cutils/properties.h>
57#include <fs_mgr.h>
Tao Bao158e11d2015-05-21 16:44:44 -070058#define LOG_TAG "uncrypt"
59#include <log/log.h>
Doug Zongker76adfc52014-01-13 10:04:25 -080060
61#define WINDOW_SIZE 5
Tao Bao158e11d2015-05-21 16:44:44 -070062
63static const std::string cache_block_map = "/cache/recovery/block.map";
64static const std::string status_file = "/cache/recovery/uncrypt_status";
65static const std::string uncrypt_file = "/cache/recovery/uncrypt_file";
Doug Zongker76adfc52014-01-13 10:04:25 -080066
Doug Zongker2efc9d92014-08-18 15:55:28 -070067static struct fstab* fstab = NULL;
68
Tao Bao3e8d28b2015-05-05 18:36:45 -070069static int write_at_offset(unsigned char* buffer, size_t size, int wfd, off64_t offset) {
Elliott Hughes2f5feed2015-04-28 17:24:24 -070070 if (TEMP_FAILURE_RETRY(lseek64(wfd, offset, SEEK_SET)) == -1) {
71 ALOGE("error seeking to offset %lld: %s\n", offset, strerror(errno));
72 return -1;
73 }
Doug Zongker76adfc52014-01-13 10:04:25 -080074 size_t written = 0;
75 while (written < size) {
Elliott Hughes2f5feed2015-04-28 17:24:24 -070076 ssize_t wrote = TEMP_FAILURE_RETRY(write(wfd, buffer + written, size - written));
77 if (wrote == -1) {
78 ALOGE("error writing offset %lld: %s\n", (offset + written), strerror(errno));
Doug Zongker76adfc52014-01-13 10:04:25 -080079 return -1;
80 }
81 written += wrote;
82 }
83 return 0;
84}
85
Tao Bao3e8d28b2015-05-05 18:36:45 -070086static void add_block_to_ranges(int** ranges, int* range_alloc, int* range_used, int new_block) {
Doug Zongker76adfc52014-01-13 10:04:25 -080087 // If the current block start is < 0, set the start to the new
88 // block. (This only happens for the very first block of the very
89 // first range.)
90 if ((*ranges)[*range_used*2-2] < 0) {
91 (*ranges)[*range_used*2-2] = new_block;
92 (*ranges)[*range_used*2-1] = new_block;
93 }
94
95 if (new_block == (*ranges)[*range_used*2-1]) {
96 // If the new block comes immediately after the current range,
97 // all we have to do is extend the current range.
98 ++(*ranges)[*range_used*2-1];
99 } else {
100 // We need to start a new range.
101
102 // If there isn't enough room in the array, we need to expand it.
103 if (*range_used >= *range_alloc) {
104 *range_alloc *= 2;
Tao Bao3e8d28b2015-05-05 18:36:45 -0700105 *ranges = reinterpret_cast<int*>(realloc(*ranges, *range_alloc * 2 * sizeof(int)));
Doug Zongker76adfc52014-01-13 10:04:25 -0800106 }
107
108 ++*range_used;
109 (*ranges)[*range_used*2-2] = new_block;
110 (*ranges)[*range_used*2-1] = new_block+1;
111 }
112}
113
Tao Bao3e8d28b2015-05-05 18:36:45 -0700114static struct fstab* read_fstab() {
Doug Zongker2efc9d92014-08-18 15:55:28 -0700115 fstab = NULL;
116
Doug Zongker76adfc52014-01-13 10:04:25 -0800117 // The fstab path is always "/fstab.${ro.hardware}".
118 char fstab_path[PATH_MAX+1] = "/fstab.";
119 if (!property_get("ro.hardware", fstab_path+strlen(fstab_path), "")) {
Doug Zongkerf449db22014-08-26 09:15:08 -0700120 ALOGE("failed to get ro.hardware\n");
Doug Zongker76adfc52014-01-13 10:04:25 -0800121 return NULL;
122 }
123
Doug Zongker2efc9d92014-08-18 15:55:28 -0700124 fstab = fs_mgr_read_fstab(fstab_path);
Doug Zongker76adfc52014-01-13 10:04:25 -0800125 if (!fstab) {
Doug Zongkerf449db22014-08-26 09:15:08 -0700126 ALOGE("failed to read %s\n", fstab_path);
Doug Zongker76adfc52014-01-13 10:04:25 -0800127 return NULL;
128 }
129
Doug Zongker2efc9d92014-08-18 15:55:28 -0700130 return fstab;
131}
132
Tao Bao3e8d28b2015-05-05 18:36:45 -0700133static const char* find_block_device(const char* path, bool* encryptable, bool* encrypted) {
Doug Zongker76adfc52014-01-13 10:04:25 -0800134 // Look for a volume whose mount point is the prefix of path and
135 // return its block device. Set encrypted if it's currently
136 // encrypted.
Tao Bao3e8d28b2015-05-05 18:36:45 -0700137 for (int i = 0; i < fstab->num_entries; ++i) {
Doug Zongker76adfc52014-01-13 10:04:25 -0800138 struct fstab_rec* v = &fstab->recs[i];
Tao Bao3e8d28b2015-05-05 18:36:45 -0700139 if (!v->mount_point) {
140 continue;
141 }
Doug Zongker76adfc52014-01-13 10:04:25 -0800142 int len = strlen(v->mount_point);
143 if (strncmp(path, v->mount_point, len) == 0 &&
144 (path[len] == '/' || path[len] == 0)) {
Tao Bao3e8d28b2015-05-05 18:36:45 -0700145 *encrypted = false;
146 *encryptable = false;
Doug Zongker76adfc52014-01-13 10:04:25 -0800147 if (fs_mgr_is_encryptable(v)) {
Tao Bao3e8d28b2015-05-05 18:36:45 -0700148 *encryptable = true;
Doug Zongker76adfc52014-01-13 10:04:25 -0800149 char buffer[PROPERTY_VALUE_MAX+1];
150 if (property_get("ro.crypto.state", buffer, "") &&
151 strcmp(buffer, "encrypted") == 0) {
Tao Bao3e8d28b2015-05-05 18:36:45 -0700152 *encrypted = true;
Doug Zongker76adfc52014-01-13 10:04:25 -0800153 }
154 }
155 return v->blk_device;
156 }
157 }
158
159 return NULL;
160}
161
Tao Bao158e11d2015-05-21 16:44:44 -0700162// Parse uncrypt_file to find the update package name.
163static bool find_uncrypt_package(std::string& package_name)
Doug Zongker76adfc52014-01-13 10:04:25 -0800164{
Tao Bao158e11d2015-05-21 16:44:44 -0700165 if (!android::base::ReadFileToString(uncrypt_file, &package_name)) {
166 ALOGE("failed to open \"%s\": %s\n", uncrypt_file.c_str(), strerror(errno));
167 return false;
Maxim Siniavinee7b28882014-02-13 15:48:53 -0800168 }
Doug Zongker76adfc52014-01-13 10:04:25 -0800169
Tao Bao158e11d2015-05-21 16:44:44 -0700170 // Remove the trailing '\n' if present.
171 package_name = android::base::Trim(package_name);
172
173 return true;
Doug Zongker76adfc52014-01-13 10:04:25 -0800174}
175
Tao Bao3e8d28b2015-05-05 18:36:45 -0700176static int produce_block_map(const char* path, const char* map_file, const char* blk_dev,
Tao Bao158e11d2015-05-21 16:44:44 -0700177 bool encrypted, int status_fd) {
Sungmin Choia72512c2014-12-10 21:57:09 +0900178 int mapfd = open(map_file, O_WRONLY | O_CREAT | O_SYNC, S_IRUSR | S_IWUSR);
Tao Bao158e11d2015-05-21 16:44:44 -0700179 if (mapfd == -1) {
Sungmin Choia72512c2014-12-10 21:57:09 +0900180 ALOGE("failed to open %s\n", map_file);
181 return -1;
182 }
Michael Runge4b542392014-11-21 16:00:45 -0800183 FILE* mapf = fdopen(mapfd, "w");
Doug Zongker76adfc52014-01-13 10:04:25 -0800184
Tao Bao158e11d2015-05-21 16:44:44 -0700185 // Make sure we can write to the status_file.
186 if (!android::base::WriteStringToFd("0\n", status_fd)) {
187 ALOGE("failed to update \"%s\"\n", status_file.c_str());
188 return -1;
189 }
190
Tao Bao3e8d28b2015-05-05 18:36:45 -0700191 struct stat sb;
192 int ret = stat(path, &sb);
Doug Zongker76adfc52014-01-13 10:04:25 -0800193 if (ret != 0) {
Doug Zongkerf449db22014-08-26 09:15:08 -0700194 ALOGE("failed to stat %s\n", path);
Doug Zongker76adfc52014-01-13 10:04:25 -0800195 return -1;
196 }
197
Doug Zongkerf449db22014-08-26 09:15:08 -0700198 ALOGI(" block size: %ld bytes\n", (long)sb.st_blksize);
Doug Zongker76adfc52014-01-13 10:04:25 -0800199
200 int blocks = ((sb.st_size-1) / sb.st_blksize) + 1;
Doug Zongkerf449db22014-08-26 09:15:08 -0700201 ALOGI(" file size: %lld bytes, %d blocks\n", (long long)sb.st_size, blocks);
Doug Zongker76adfc52014-01-13 10:04:25 -0800202
Doug Zongker76adfc52014-01-13 10:04:25 -0800203 int range_alloc = 1;
204 int range_used = 1;
Tao Bao3e8d28b2015-05-05 18:36:45 -0700205 int* ranges = reinterpret_cast<int*>(malloc(range_alloc * 2 * sizeof(int)));
Doug Zongker76adfc52014-01-13 10:04:25 -0800206 ranges[0] = -1;
207 ranges[1] = -1;
208
Mark Salyzyn2605dec2014-03-19 15:30:25 -0700209 fprintf(mapf, "%s\n%lld %lu\n", blk_dev, (long long)sb.st_size, (unsigned long)sb.st_blksize);
Doug Zongker76adfc52014-01-13 10:04:25 -0800210
211 unsigned char* buffers[WINDOW_SIZE];
Doug Zongker76adfc52014-01-13 10:04:25 -0800212 if (encrypted) {
Tao Bao3e8d28b2015-05-05 18:36:45 -0700213 for (size_t i = 0; i < WINDOW_SIZE; ++i) {
214 buffers[i] = reinterpret_cast<unsigned char*>(malloc(sb.st_blksize));
Doug Zongker76adfc52014-01-13 10:04:25 -0800215 }
216 }
217 int head_block = 0;
218 int head = 0, tail = 0;
219 size_t pos = 0;
220
221 int fd = open(path, O_RDONLY);
222 if (fd < 0) {
Doug Zongkerf449db22014-08-26 09:15:08 -0700223 ALOGE("failed to open fd for reading: %s\n", strerror(errno));
Doug Zongker76adfc52014-01-13 10:04:25 -0800224 return -1;
225 }
Doug Zongker76adfc52014-01-13 10:04:25 -0800226
227 int wfd = -1;
228 if (encrypted) {
Michael Runge4b542392014-11-21 16:00:45 -0800229 wfd = open(blk_dev, O_WRONLY | O_SYNC);
Doug Zongker76adfc52014-01-13 10:04:25 -0800230 if (wfd < 0) {
Doug Zongkerf449db22014-08-26 09:15:08 -0700231 ALOGE("failed to open fd for writing: %s\n", strerror(errno));
Doug Zongker76adfc52014-01-13 10:04:25 -0800232 return -1;
233 }
234 }
235
Tao Bao158e11d2015-05-21 16:44:44 -0700236 int last_progress = 0;
Doug Zongker76adfc52014-01-13 10:04:25 -0800237 while (pos < sb.st_size) {
Tao Bao158e11d2015-05-21 16:44:44 -0700238 // Update the status file, progress must be between [0, 99].
239 int progress = static_cast<int>(100 * (double(pos) / double(sb.st_size)));
240 if (progress > last_progress) {
241 last_progress = progress;
242 android::base::WriteStringToFd(std::to_string(progress) + "\n", status_fd);
243 }
244
Doug Zongker76adfc52014-01-13 10:04:25 -0800245 if ((tail+1) % WINDOW_SIZE == head) {
246 // write out head buffer
247 int block = head_block;
248 ret = ioctl(fd, FIBMAP, &block);
249 if (ret != 0) {
Doug Zongkerf449db22014-08-26 09:15:08 -0700250 ALOGE("failed to find block %d\n", head_block);
Doug Zongker76adfc52014-01-13 10:04:25 -0800251 return -1;
252 }
253 add_block_to_ranges(&ranges, &range_alloc, &range_used, block);
254 if (encrypted) {
Tao Bao3e8d28b2015-05-05 18:36:45 -0700255 if (write_at_offset(buffers[head], sb.st_blksize, wfd,
256 (off64_t)sb.st_blksize * block) != 0) {
Doug Zongker76adfc52014-01-13 10:04:25 -0800257 return -1;
258 }
259 }
260 head = (head + 1) % WINDOW_SIZE;
261 ++head_block;
262 }
263
264 // read next block to tail
265 if (encrypted) {
266 size_t so_far = 0;
267 while (so_far < sb.st_blksize && pos < sb.st_size) {
Elliott Hughes2f5feed2015-04-28 17:24:24 -0700268 ssize_t this_read =
269 TEMP_FAILURE_RETRY(read(fd, buffers[tail] + so_far, sb.st_blksize - so_far));
270 if (this_read == -1) {
Doug Zongkerf449db22014-08-26 09:15:08 -0700271 ALOGE("failed to read: %s\n", strerror(errno));
Doug Zongker76adfc52014-01-13 10:04:25 -0800272 return -1;
273 }
274 so_far += this_read;
275 pos += this_read;
276 }
277 } else {
278 // If we're not encrypting; we don't need to actually read
279 // anything, just skip pos forward as if we'd read a
280 // block.
281 pos += sb.st_blksize;
282 }
283 tail = (tail+1) % WINDOW_SIZE;
284 }
285
286 while (head != tail) {
287 // write out head buffer
288 int block = head_block;
289 ret = ioctl(fd, FIBMAP, &block);
290 if (ret != 0) {
Doug Zongkerf449db22014-08-26 09:15:08 -0700291 ALOGE("failed to find block %d\n", head_block);
Doug Zongker76adfc52014-01-13 10:04:25 -0800292 return -1;
293 }
294 add_block_to_ranges(&ranges, &range_alloc, &range_used, block);
295 if (encrypted) {
Tao Bao3e8d28b2015-05-05 18:36:45 -0700296 if (write_at_offset(buffers[head], sb.st_blksize, wfd,
297 (off64_t)sb.st_blksize * block) != 0) {
Doug Zongker76adfc52014-01-13 10:04:25 -0800298 return -1;
299 }
300 }
301 head = (head + 1) % WINDOW_SIZE;
302 ++head_block;
303 }
304
305 fprintf(mapf, "%d\n", range_used);
Tao Bao3e8d28b2015-05-05 18:36:45 -0700306 for (int i = 0; i < range_used; ++i) {
Doug Zongker76adfc52014-01-13 10:04:25 -0800307 fprintf(mapf, "%d %d\n", ranges[i*2], ranges[i*2+1]);
308 }
309
Tao Bao8853cb22015-05-04 10:10:13 -0700310 if (fsync(mapfd) == -1) {
311 ALOGE("failed to fsync \"%s\": %s\n", map_file, strerror(errno));
312 return -1;
313 }
Doug Zongker76adfc52014-01-13 10:04:25 -0800314 fclose(mapf);
315 close(fd);
316 if (encrypted) {
Tao Bao8853cb22015-05-04 10:10:13 -0700317 if (fsync(wfd) == -1) {
318 ALOGE("failed to fsync \"%s\": %s\n", blk_dev, strerror(errno));
319 return -1;
320 }
Doug Zongker76adfc52014-01-13 10:04:25 -0800321 close(wfd);
322 }
323
324 return 0;
325}
326
Tao Bao3e8d28b2015-05-05 18:36:45 -0700327static void wipe_misc() {
Doug Zongkerf449db22014-08-26 09:15:08 -0700328 ALOGI("removing old commands from misc");
Tao Bao3e8d28b2015-05-05 18:36:45 -0700329 for (int i = 0; i < fstab->num_entries; ++i) {
Doug Zongker2efc9d92014-08-18 15:55:28 -0700330 struct fstab_rec* v = &fstab->recs[i];
331 if (!v->mount_point) continue;
332 if (strcmp(v->mount_point, "/misc") == 0) {
Michael Runge4b542392014-11-21 16:00:45 -0800333 int fd = open(v->blk_device, O_WRONLY | O_SYNC);
Doug Zongker2efc9d92014-08-18 15:55:28 -0700334 uint8_t zeroes[1088]; // sizeof(bootloader_message) from recovery
335 memset(zeroes, 0, sizeof(zeroes));
336
337 size_t written = 0;
338 size_t size = sizeof(zeroes);
339 while (written < size) {
Elliott Hughes2f5feed2015-04-28 17:24:24 -0700340 ssize_t w = TEMP_FAILURE_RETRY(write(fd, zeroes, size-written));
341 if (w == -1) {
Doug Zongkerf449db22014-08-26 09:15:08 -0700342 ALOGE("zero write failed: %s\n", strerror(errno));
Doug Zongker2efc9d92014-08-18 15:55:28 -0700343 return;
344 } else {
345 written += w;
346 }
347 }
Tao Bao8853cb22015-05-04 10:10:13 -0700348 if (fsync(fd) == -1) {
349 ALOGE("failed to fsync \"%s\": %s\n", v->blk_device, strerror(errno));
350 close(fd);
351 return;
352 }
Doug Zongker2efc9d92014-08-18 15:55:28 -0700353 close(fd);
354 }
355 }
356}
357
Tao Bao3e8d28b2015-05-05 18:36:45 -0700358static void reboot_to_recovery() {
Doug Zongkerf449db22014-08-26 09:15:08 -0700359 ALOGI("rebooting to recovery");
Doug Zongker76adfc52014-01-13 10:04:25 -0800360 property_set("sys.powerctl", "reboot,recovery");
361 sleep(10);
Doug Zongkerf449db22014-08-26 09:15:08 -0700362 ALOGE("reboot didn't succeed?");
Doug Zongker76adfc52014-01-13 10:04:25 -0800363}
364
Tao Bao158e11d2015-05-21 16:44:44 -0700365int uncrypt(const char* input_path, const char* map_file, int status_fd) {
Doug Zongker76adfc52014-01-13 10:04:25 -0800366
Tao Bao158e11d2015-05-21 16:44:44 -0700367 ALOGI("update package is \"%s\"", input_path);
Doug Zongkerf449db22014-08-26 09:15:08 -0700368
Doug Zongker76adfc52014-01-13 10:04:25 -0800369 // Turn the name of the file we're supposed to convert into an
370 // absolute path, so we can find what filesystem it's on.
371 char path[PATH_MAX+1];
372 if (realpath(input_path, path) == NULL) {
Tao Bao158e11d2015-05-21 16:44:44 -0700373 ALOGE("failed to convert \"%s\" to absolute path: %s", input_path, strerror(errno));
Doug Zongker76adfc52014-01-13 10:04:25 -0800374 return 1;
375 }
376
Doug Zongker2efc9d92014-08-18 15:55:28 -0700377 if (read_fstab() == NULL) {
378 return 1;
379 }
Tao Bao3e8d28b2015-05-05 18:36:45 -0700380
381 bool encryptable;
382 bool encrypted;
Doug Zongker76adfc52014-01-13 10:04:25 -0800383 const char* blk_dev = find_block_device(path, &encryptable, &encrypted);
384 if (blk_dev == NULL) {
Doug Zongkerf449db22014-08-26 09:15:08 -0700385 ALOGE("failed to find block device for %s", path);
Doug Zongker76adfc52014-01-13 10:04:25 -0800386 return 1;
387 }
388
389 // If the filesystem it's on isn't encrypted, we only produce the
390 // block map, we don't rewrite the file contents (it would be
391 // pointless to do so).
Doug Zongkerf449db22014-08-26 09:15:08 -0700392 ALOGI("encryptable: %s\n", encryptable ? "yes" : "no");
393 ALOGI(" encrypted: %s\n", encrypted ? "yes" : "no");
Doug Zongker76adfc52014-01-13 10:04:25 -0800394
Doug Zongker574443d2014-09-05 08:22:12 -0700395 // Recovery supports installing packages from 3 paths: /cache,
396 // /data, and /sdcard. (On a particular device, other locations
397 // may work, but those are three we actually expect.)
398 //
399 // On /data we want to convert the file to a block map so that we
400 // can read the package without mounting the partition. On /cache
401 // and /sdcard we leave the file alone.
Tao Bao158e11d2015-05-21 16:44:44 -0700402 if (strncmp(path, "/data/", 6) == 0) {
Doug Zongkerf449db22014-08-26 09:15:08 -0700403 ALOGI("writing block map %s", map_file);
Tao Bao158e11d2015-05-21 16:44:44 -0700404 if (produce_block_map(path, map_file, blk_dev, encrypted, status_fd) != 0) {
405 return 1;
406 }
407 }
408
409 return 0;
410}
411
412int main(int argc, char** argv) {
413 const char* input_path;
414 const char* map_file;
415
416 if (argc != 3 && argc != 1 && (argc == 2 && strcmp(argv[1], "--reboot") != 0)) {
417 fprintf(stderr, "usage: %s [--reboot] [<transform_path> <map_file>]\n", argv[0]);
418 return 2;
419 }
420
421 // When uncrypt is started with "--reboot", it wipes misc and reboots.
422 // Otherwise it uncrypts the package and writes the block map.
423 if (argc == 2) {
424 if (read_fstab() == NULL) {
Doug Zongker76adfc52014-01-13 10:04:25 -0800425 return 1;
426 }
Tao Bao8853cb22015-05-04 10:10:13 -0700427 wipe_misc();
Tao Bao158e11d2015-05-21 16:44:44 -0700428 reboot_to_recovery();
429 } else {
Tao Bao158e11d2015-05-21 16:44:44 -0700430 // The pipe has been created by the system server.
431 int status_fd = open(status_file.c_str(), O_WRONLY | O_CREAT | O_SYNC, S_IRUSR | S_IWUSR);
432 if (status_fd == -1) {
433 ALOGE("failed to open pipe \"%s\": %s\n", status_file.c_str(), strerror(errno));
434 return 1;
435 }
Tao Bao2c2cae82015-05-29 14:24:02 -0700436
437 if (argc == 3) {
438 // when command-line args are given this binary is being used
439 // for debugging.
440 input_path = argv[1];
441 map_file = argv[2];
442 } else {
443 std::string package;
444 if (!find_uncrypt_package(package)) {
445 android::base::WriteStringToFd("-1\n", status_fd);
446 close(status_fd);
447 return 1;
448 }
449 input_path = package.c_str();
450 map_file = cache_block_map.c_str();
451 }
452
Tao Bao158e11d2015-05-21 16:44:44 -0700453 int status = uncrypt(input_path, map_file, status_fd);
454 if (status != 0) {
455 android::base::WriteStringToFd("-1\n", status_fd);
456 close(status_fd);
457 return 1;
458 }
459
460 android::base::WriteStringToFd("100\n", status_fd);
461 close(status_fd);
Doug Zongker76adfc52014-01-13 10:04:25 -0800462 }
463
Doug Zongker76adfc52014-01-13 10:04:25 -0800464 return 0;
465}