176adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker/*
276adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker * Copyright (C) 2014 The Android Open Source Project
376adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker *
476adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker * Licensed under the Apache License, Version 2.0 (the "License");
576adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker * you may not use this file except in compliance with the License.
676adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker * You may obtain a copy of the License at
776adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker *
876adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker *      http://www.apache.org/licenses/LICENSE-2.0
976adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker *
1076adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker * Unless required by applicable law or agreed to in writing, software
1176adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker * distributed under the License is distributed on an "AS IS" BASIS,
1276adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1376adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker * See the License for the specific language governing permissions and
1476adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker * limitations under the License.
1576adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker */
1676adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker
1776adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker// This program takes a file on an ext4 filesystem and produces a list
1876adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker// of the blocks that file occupies, which enables the file contents
1976adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker// to be read directly from the block device without mounting the
2076adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker// filesystem.
2176adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker//
2276adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker// If the filesystem is using an encrypted block device, it will also
2376adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker// read the file and rewrite it to the same blocks of the underlying
2476adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker// (unencrypted) block device, so the file contents can be read
2576adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker// without the need for the decryption key.
2676adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker//
2776adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker// The output of this program is a "block map" which looks like this:
2876adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker//
2976adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker//     /dev/block/platform/msm_sdcc.1/by-name/userdata     # block device
3076adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker//     49652 4096                        # file size in bytes, block size
3176adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker//     3                                 # count of block ranges
3276adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker//     1000 1008                         # block range 0
3376adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker//     2100 2102                         # ... block range 1
3476adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker//     30 33                             # ... block range 2
3576adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker//
3676adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker// Each block range represents a half-open interval; the line "30 33"
3776adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker// reprents the blocks [30, 31, 32].
3876adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker//
3976adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker// Recovery can take this block map file and retrieve the underlying
4076adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker// file data to use as an update package.
4176adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker
423a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao/**
433a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao * In addition to the uncrypt work, uncrypt also takes care of setting and
443a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao * clearing the bootloader control block (BCB) at /misc partition.
453a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao *
463a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao * uncrypt is triggered as init services on demand. It uses socket to
473a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao * communicate with its caller (i.e. system_server). The socket is managed by
483a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao * init (i.e. created prior to the service starts, and destroyed when uncrypt
493a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao * exits).
503a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao *
513a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao * Below is the uncrypt protocol.
523a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao *
533a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao *    a. caller                 b. init                    c. uncrypt
543a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao * ---------------            ------------               --------------
553a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao *  a1. ctl.start:
563a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao *    setup-bcb /
573a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao *    clear-bcb /
583a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao *    uncrypt
593a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao *
603a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao *                         b2. create socket at
613a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao *                           /dev/socket/uncrypt
623a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao *
633a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao *                                                   c3. listen and accept
643a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao *
653a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao *  a4. send a 4-byte int
663a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao *    (message length)
673a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao *                                                   c5. receive message length
683a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao *  a6. send message
693a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao *                                                   c7. receive message
703a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao *                                                   c8. <do the work; may send
713a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao *                                                      the progress>
723a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao *  a9. <may handle progress>
733a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao *                                                   c10. <upon finishing>
743a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao *                                                     send "100" or "-1"
753a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao *
763a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao *  a11. receive status code
773a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao *  a12. send a 4-byte int to
783a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao *    ack the receive of the
793a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao *    final status code
803a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao *                                                   c13. receive and exit
813a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao *
823a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao *                          b14. destroy the socket
833a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao *
843a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao * Note that a12 and c13 are necessary to ensure a11 happens before the socket
853a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao * gets destroyed in b14.
863a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao */
873a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao
883a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao#include <arpa/inet.h>
89d4d4c2456ac6649f65fd561998b2cb8eb2c97eddElliott Hughes#include <errno.h>
90752386319c0d9fb7e4e429a0644086b318d3b4b5Tao Bao#include <fcntl.h>
91b8df5fb90e4b7244fa7925b9706cdd218e18a2aaTao Bao#include <inttypes.h>
9225dd0386fe69460cd1d39de116197dd2c7bf9ec2Yabin Cui#include <libgen.h>
93752386319c0d9fb7e4e429a0644086b318d3b4b5Tao Bao#include <linux/fs.h>
94752386319c0d9fb7e4e429a0644086b318d3b4b5Tao Bao#include <stdarg.h>
9576adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker#include <stdio.h>
9676adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker#include <stdlib.h>
97cd3c55ab40efd12f5a2d396dbb57509e4d071641Elliott Hughes#include <string.h>
9876adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker#include <sys/mman.h>
993a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao#include <sys/socket.h>
100383b00d0e498e1f3b84e9dcfc6dddec6a76379d7Tao Bao#include <sys/stat.h>
101383b00d0e498e1f3b84e9dcfc6dddec6a76379d7Tao Bao#include <sys/types.h>
102752386319c0d9fb7e4e429a0644086b318d3b4b5Tao Bao#include <unistd.h>
10376adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker
10425dd0386fe69460cd1d39de116197dd2c7bf9ec2Yabin Cui#include <algorithm>
105c754792a07d340c30128b2fd064a58b1f15623daTao Bao#include <memory>
10625dd0386fe69460cd1d39de116197dd2c7bf9ec2Yabin Cui#include <vector>
107c754792a07d340c30128b2fd064a58b1f15623daTao Bao
1084b166f0e69d46858ff998414da2a01e0266fa339Elliott Hughes#include <android-base/file.h>
1092d46da57e19612b0a29ee0b8601146cf8fb9ff5eYabin Cui#include <android-base/logging.h>
11091e3aee9bdc1a503affdd925dd4da352a198abcaElliott Hughes#include <android-base/properties.h>
11125dd0386fe69460cd1d39de116197dd2c7bf9ec2Yabin Cui#include <android-base/stringprintf.h>
1124b166f0e69d46858ff998414da2a01e0266fa339Elliott Hughes#include <android-base/strings.h>
113bcabd0929316fdd022ea102cc86396547ad9f070Elliott Hughes#include <android-base/unique_fd.h>
1142f272c0551f984e83bc5abaf240e0dddb38a3326Yabin Cui#include <bootloader_message/bootloader_message.h>
115752386319c0d9fb7e4e429a0644086b318d3b4b5Tao Bao#include <cutils/android_reboot.h>
1163a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao#include <cutils/sockets.h>
11776adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker#include <fs_mgr.h>
11876adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker
1191fc5bf353a8719d16fd9ba29a661d211bad4038fTao Bao#include "otautil/error_code.h"
120da44cf18f3ce4bbffa85ad0a50bb25e9cb54a86dTianjie Xu
121bc42603a8daae62b158d159c97ef8acfaa39d70dTianjie Xustatic constexpr int WINDOW_SIZE = 5;
122bc42603a8daae62b158d159c97ef8acfaa39d70dTianjie Xustatic constexpr int FIBMAP_RETRY_LIMIT = 3;
123383b00d0e498e1f3b84e9dcfc6dddec6a76379d7Tao Bao
1243a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao// uncrypt provides three services: SETUP_BCB, CLEAR_BCB and UNCRYPT.
1253a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao//
1263a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao// SETUP_BCB and CLEAR_BCB services use socket communication and do not rely
1273a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao// on /cache partitions. They will handle requests to reboot into recovery
1283a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao// (for applying updates for non-A/B devices, or factory resets for all
1293a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao// devices).
1303a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao//
1313a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao// UNCRYPT service still needs files on /cache partition (UNCRYPT_PATH_FILE
1323a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao// and CACHE_BLOCK_MAP). It will be working (and needed) only for non-A/B
1333a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao// devices, on which /cache partitions always exist.
1342d46da57e19612b0a29ee0b8601146cf8fb9ff5eYabin Cuistatic const std::string CACHE_BLOCK_MAP = "/cache/recovery/block.map";
1352d46da57e19612b0a29ee0b8601146cf8fb9ff5eYabin Cuistatic const std::string UNCRYPT_PATH_FILE = "/cache/recovery/uncrypt_file";
136e16e799dfdff5392d2bdc460f41353100d082e96Tianjie Xustatic const std::string UNCRYPT_STATUS = "/cache/recovery/uncrypt_status";
1373a2bb594df4b48c6afb1f029041dd6db0735de58Tao Baostatic const std::string UNCRYPT_SOCKET = "uncrypt";
13876adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker
1393a2bb594df4b48c6afb1f029041dd6db0735de58Tao Baostatic struct fstab* fstab = nullptr;
1402efc9d994ce59f9ebfc2290c2adc5d760e8939c2Doug Zongker
141381f455cac0905b023dde79625b06c27b6165dd0Tao Baostatic int write_at_offset(unsigned char* buffer, size_t size, int wfd, off64_t offset) {
1427bad7c4646ee8fd8d6e6ed0ffd3ddbb0c1b41a2fElliott Hughes    if (TEMP_FAILURE_RETRY(lseek64(wfd, offset, SEEK_SET)) == -1) {
143747781433fb01f745529c7e9dd97c5599070ad0dTianjie Xu        PLOG(ERROR) << "error seeking to offset " << offset;
1447bad7c4646ee8fd8d6e6ed0ffd3ddbb0c1b41a2fElliott Hughes        return -1;
1457bad7c4646ee8fd8d6e6ed0ffd3ddbb0c1b41a2fElliott Hughes    }
14625dd0386fe69460cd1d39de116197dd2c7bf9ec2Yabin Cui    if (!android::base::WriteFully(wfd, buffer, size)) {
147747781433fb01f745529c7e9dd97c5599070ad0dTianjie Xu        PLOG(ERROR) << "error writing offset " << offset;
14825dd0386fe69460cd1d39de116197dd2c7bf9ec2Yabin Cui        return -1;
14976adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker    }
15076adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker    return 0;
15176adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker}
15276adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker
15325dd0386fe69460cd1d39de116197dd2c7bf9ec2Yabin Cuistatic void add_block_to_ranges(std::vector<int>& ranges, int new_block) {
15425dd0386fe69460cd1d39de116197dd2c7bf9ec2Yabin Cui    if (!ranges.empty() && new_block == ranges.back()) {
15576adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker        // If the new block comes immediately after the current range,
15676adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker        // all we have to do is extend the current range.
15725dd0386fe69460cd1d39de116197dd2c7bf9ec2Yabin Cui        ++ranges.back();
15876adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker    } else {
15976adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker        // We need to start a new range.
16025dd0386fe69460cd1d39de116197dd2c7bf9ec2Yabin Cui        ranges.push_back(new_block);
16125dd0386fe69460cd1d39de116197dd2c7bf9ec2Yabin Cui        ranges.push_back(new_block + 1);
16276adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker    }
16376adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker}
16476adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker
165381f455cac0905b023dde79625b06c27b6165dd0Tao Baostatic struct fstab* read_fstab() {
166d13b6cf29c71412adac3b0dca5eddcd6c75f5163Bowgo Tsai    fstab = fs_mgr_read_fstab_default();
16776adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker    if (!fstab) {
168d13b6cf29c71412adac3b0dca5eddcd6c75f5163Bowgo Tsai        LOG(ERROR) << "failed to read default fstab";
16976adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker        return NULL;
17076adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker    }
17176adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker
1722efc9d994ce59f9ebfc2290c2adc5d760e8939c2Doug Zongker    return fstab;
1732efc9d994ce59f9ebfc2290c2adc5d760e8939c2Doug Zongker}
1742efc9d994ce59f9ebfc2290c2adc5d760e8939c2Doug Zongker
175848f227eea524a48208bdd4181f90fb63a31ed2bJaegeuk Kimstatic const char* find_block_device(const char* path, bool* encryptable, bool* encrypted, bool *f2fs_fs) {
17676adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker    // Look for a volume whose mount point is the prefix of path and
17776adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker    // return its block device.  Set encrypted if it's currently
17876adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker    // encrypted.
179848f227eea524a48208bdd4181f90fb63a31ed2bJaegeuk Kim
180848f227eea524a48208bdd4181f90fb63a31ed2bJaegeuk Kim    // ensure f2fs_fs is set to 0 first.
181848f227eea524a48208bdd4181f90fb63a31ed2bJaegeuk Kim    if (f2fs_fs)
182848f227eea524a48208bdd4181f90fb63a31ed2bJaegeuk Kim        *f2fs_fs = false;
183381f455cac0905b023dde79625b06c27b6165dd0Tao Bao    for (int i = 0; i < fstab->num_entries; ++i) {
18476adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker        struct fstab_rec* v = &fstab->recs[i];
185381f455cac0905b023dde79625b06c27b6165dd0Tao Bao        if (!v->mount_point) {
186381f455cac0905b023dde79625b06c27b6165dd0Tao Bao            continue;
187381f455cac0905b023dde79625b06c27b6165dd0Tao Bao        }
18876adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker        int len = strlen(v->mount_point);
18976adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker        if (strncmp(path, v->mount_point, len) == 0 &&
19076adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker            (path[len] == '/' || path[len] == 0)) {
191381f455cac0905b023dde79625b06c27b6165dd0Tao Bao            *encrypted = false;
192381f455cac0905b023dde79625b06c27b6165dd0Tao Bao            *encryptable = false;
1937cf50c60b5c955010a8b8d0c23264f03ab673debTao Bao            if (fs_mgr_is_encryptable(v) || fs_mgr_is_file_encrypted(v)) {
194381f455cac0905b023dde79625b06c27b6165dd0Tao Bao                *encryptable = true;
19591e3aee9bdc1a503affdd925dd4da352a198abcaElliott Hughes                if (android::base::GetProperty("ro.crypto.state", "") == "encrypted") {
196381f455cac0905b023dde79625b06c27b6165dd0Tao Bao                    *encrypted = true;
19776adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker                }
19876adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker            }
199848f227eea524a48208bdd4181f90fb63a31ed2bJaegeuk Kim            if (f2fs_fs && strcmp(v->fs_type, "f2fs") == 0)
200848f227eea524a48208bdd4181f90fb63a31ed2bJaegeuk Kim                *f2fs_fs = true;
20176adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker            return v->blk_device;
20276adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker        }
20376adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker    }
20476adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker
20576adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker    return NULL;
20676adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker}
20776adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker
2083a2bb594df4b48c6afb1f029041dd6db0735de58Tao Baostatic bool write_status_to_socket(int status, int socket) {
20928c1e5d3aa9610db6e141380b1435937fc7f07dbTianjie Xu    // If socket equals -1, uncrypt is in debug mode without socket communication.
21028c1e5d3aa9610db6e141380b1435937fc7f07dbTianjie Xu    // Skip writing and return success.
21128c1e5d3aa9610db6e141380b1435937fc7f07dbTianjie Xu    if (socket == -1) {
21228c1e5d3aa9610db6e141380b1435937fc7f07dbTianjie Xu        return true;
21328c1e5d3aa9610db6e141380b1435937fc7f07dbTianjie Xu    }
2143a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao    int status_out = htonl(status);
2153a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao    return android::base::WriteFully(socket, &status_out, sizeof(int));
2163a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao}
2173a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao
218383b00d0e498e1f3b84e9dcfc6dddec6a76379d7Tao Bao// Parse uncrypt_file to find the update package name.
2192d46da57e19612b0a29ee0b8601146cf8fb9ff5eYabin Cuistatic bool find_uncrypt_package(const std::string& uncrypt_path_file, std::string* package_name) {
2202d46da57e19612b0a29ee0b8601146cf8fb9ff5eYabin Cui    CHECK(package_name != nullptr);
2212d46da57e19612b0a29ee0b8601146cf8fb9ff5eYabin Cui    std::string uncrypt_path;
2222d46da57e19612b0a29ee0b8601146cf8fb9ff5eYabin Cui    if (!android::base::ReadFileToString(uncrypt_path_file, &uncrypt_path)) {
223747781433fb01f745529c7e9dd97c5599070ad0dTianjie Xu        PLOG(ERROR) << "failed to open \"" << uncrypt_path_file << "\"";
224383b00d0e498e1f3b84e9dcfc6dddec6a76379d7Tao Bao        return false;
22576adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker    }
22676adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker
227383b00d0e498e1f3b84e9dcfc6dddec6a76379d7Tao Bao    // Remove the trailing '\n' if present.
2282d46da57e19612b0a29ee0b8601146cf8fb9ff5eYabin Cui    *package_name = android::base::Trim(uncrypt_path);
229383b00d0e498e1f3b84e9dcfc6dddec6a76379d7Tao Bao    return true;
23076adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker}
23176adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker
232bc42603a8daae62b158d159c97ef8acfaa39d70dTianjie Xustatic int retry_fibmap(const int fd, const char* name, int* block, const int head_block) {
233bc42603a8daae62b158d159c97ef8acfaa39d70dTianjie Xu    CHECK(block != nullptr);
234bc42603a8daae62b158d159c97ef8acfaa39d70dTianjie Xu    for (size_t i = 0; i < FIBMAP_RETRY_LIMIT; i++) {
235bc42603a8daae62b158d159c97ef8acfaa39d70dTianjie Xu        if (fsync(fd) == -1) {
236bc42603a8daae62b158d159c97ef8acfaa39d70dTianjie Xu            PLOG(ERROR) << "failed to fsync \"" << name << "\"";
237bc42603a8daae62b158d159c97ef8acfaa39d70dTianjie Xu            return kUncryptFileSyncError;
238bc42603a8daae62b158d159c97ef8acfaa39d70dTianjie Xu        }
239bc42603a8daae62b158d159c97ef8acfaa39d70dTianjie Xu        if (ioctl(fd, FIBMAP, block) != 0) {
240bc42603a8daae62b158d159c97ef8acfaa39d70dTianjie Xu            PLOG(ERROR) << "failed to find block " << head_block;
241bc42603a8daae62b158d159c97ef8acfaa39d70dTianjie Xu            return kUncryptIoctlError;
242bc42603a8daae62b158d159c97ef8acfaa39d70dTianjie Xu        }
243bc42603a8daae62b158d159c97ef8acfaa39d70dTianjie Xu        if (*block != 0) {
244bc42603a8daae62b158d159c97ef8acfaa39d70dTianjie Xu            return kUncryptNoError;
245bc42603a8daae62b158d159c97ef8acfaa39d70dTianjie Xu        }
246bc42603a8daae62b158d159c97ef8acfaa39d70dTianjie Xu        sleep(1);
247bc42603a8daae62b158d159c97ef8acfaa39d70dTianjie Xu    }
248bc42603a8daae62b158d159c97ef8acfaa39d70dTianjie Xu    LOG(ERROR) << "fibmap of " << head_block << "always returns 0";
249bc42603a8daae62b158d159c97ef8acfaa39d70dTianjie Xu    return kUncryptIoctlError;
250bc42603a8daae62b158d159c97ef8acfaa39d70dTianjie Xu}
251bc42603a8daae62b158d159c97ef8acfaa39d70dTianjie Xu
252381f455cac0905b023dde79625b06c27b6165dd0Tao Baostatic int produce_block_map(const char* path, const char* map_file, const char* blk_dev,
253848f227eea524a48208bdd4181f90fb63a31ed2bJaegeuk Kim                             bool encrypted, bool f2fs_fs, int socket) {
25425dd0386fe69460cd1d39de116197dd2c7bf9ec2Yabin Cui    std::string err;
25525dd0386fe69460cd1d39de116197dd2c7bf9ec2Yabin Cui    if (!android::base::RemoveFileIfExists(map_file, &err)) {
256747781433fb01f745529c7e9dd97c5599070ad0dTianjie Xu        LOG(ERROR) << "failed to remove the existing map file " << map_file << ": " << err;
257da44cf18f3ce4bbffa85ad0a50bb25e9cb54a86dTianjie Xu        return kUncryptFileRemoveError;
25825dd0386fe69460cd1d39de116197dd2c7bf9ec2Yabin Cui    }
25925dd0386fe69460cd1d39de116197dd2c7bf9ec2Yabin Cui    std::string tmp_map_file = std::string(map_file) + ".tmp";
260bcabd0929316fdd022ea102cc86396547ad9f070Elliott Hughes    android::base::unique_fd mapfd(open(tmp_map_file.c_str(),
261bcabd0929316fdd022ea102cc86396547ad9f070Elliott Hughes                                        O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR));
262bcabd0929316fdd022ea102cc86396547ad9f070Elliott Hughes    if (mapfd == -1) {
263747781433fb01f745529c7e9dd97c5599070ad0dTianjie Xu        PLOG(ERROR) << "failed to open " << tmp_map_file;
264da44cf18f3ce4bbffa85ad0a50bb25e9cb54a86dTianjie Xu        return kUncryptFileOpenError;
265a72512cd058da7de4cdb667776ed47fad873f12cSungmin Choi    }
26676adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker
2673a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao    // Make sure we can write to the socket.
2683a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao    if (!write_status_to_socket(0, socket)) {
269747781433fb01f745529c7e9dd97c5599070ad0dTianjie Xu        LOG(ERROR) << "failed to write to socket " << socket;
270da44cf18f3ce4bbffa85ad0a50bb25e9cb54a86dTianjie Xu        return kUncryptSocketWriteError;
271383b00d0e498e1f3b84e9dcfc6dddec6a76379d7Tao Bao    }
272383b00d0e498e1f3b84e9dcfc6dddec6a76379d7Tao Bao
273381f455cac0905b023dde79625b06c27b6165dd0Tao Bao    struct stat sb;
274c754792a07d340c30128b2fd064a58b1f15623daTao Bao    if (stat(path, &sb) != 0) {
275747781433fb01f745529c7e9dd97c5599070ad0dTianjie Xu        LOG(ERROR) << "failed to stat " << path;
276da44cf18f3ce4bbffa85ad0a50bb25e9cb54a86dTianjie Xu        return kUncryptFileStatError;
27776adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker    }
27876adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker
279747781433fb01f745529c7e9dd97c5599070ad0dTianjie Xu    LOG(INFO) << " block size: " << sb.st_blksize << " bytes";
28076adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker
28176adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker    int blocks = ((sb.st_size-1) / sb.st_blksize) + 1;
282747781433fb01f745529c7e9dd97c5599070ad0dTianjie Xu    LOG(INFO) << "  file size: " << sb.st_size << " bytes, " << blocks << " blocks";
28376adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker
28425dd0386fe69460cd1d39de116197dd2c7bf9ec2Yabin Cui    std::vector<int> ranges;
28576adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker
28654a2747ef305c10d07d8db393125dbcbb461c428Chih-Hung Hsieh    std::string s = android::base::StringPrintf("%s\n%" PRId64 " %" PRId64 "\n",
28754a2747ef305c10d07d8db393125dbcbb461c428Chih-Hung Hsieh                       blk_dev, static_cast<int64_t>(sb.st_size),
28854a2747ef305c10d07d8db393125dbcbb461c428Chih-Hung Hsieh                       static_cast<int64_t>(sb.st_blksize));
289bcabd0929316fdd022ea102cc86396547ad9f070Elliott Hughes    if (!android::base::WriteStringToFd(s, mapfd)) {
290747781433fb01f745529c7e9dd97c5599070ad0dTianjie Xu        PLOG(ERROR) << "failed to write " << tmp_map_file;
291da44cf18f3ce4bbffa85ad0a50bb25e9cb54a86dTianjie Xu        return kUncryptWriteError;
29225dd0386fe69460cd1d39de116197dd2c7bf9ec2Yabin Cui    }
29376adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker
29425dd0386fe69460cd1d39de116197dd2c7bf9ec2Yabin Cui    std::vector<std::vector<unsigned char>> buffers;
29576adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker    if (encrypted) {
29625dd0386fe69460cd1d39de116197dd2c7bf9ec2Yabin Cui        buffers.resize(WINDOW_SIZE, std::vector<unsigned char>(sb.st_blksize));
29776adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker    }
29876adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker    int head_block = 0;
29976adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker    int head = 0, tail = 0;
30076adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker
301bcabd0929316fdd022ea102cc86396547ad9f070Elliott Hughes    android::base::unique_fd fd(open(path, O_RDONLY));
302bcabd0929316fdd022ea102cc86396547ad9f070Elliott Hughes    if (fd == -1) {
303747781433fb01f745529c7e9dd97c5599070ad0dTianjie Xu        PLOG(ERROR) << "failed to open " << path << " for reading";
304da44cf18f3ce4bbffa85ad0a50bb25e9cb54a86dTianjie Xu        return kUncryptFileOpenError;
30576adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker    }
30676adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker
307bcabd0929316fdd022ea102cc86396547ad9f070Elliott Hughes    android::base::unique_fd wfd;
30876adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker    if (encrypted) {
309bcabd0929316fdd022ea102cc86396547ad9f070Elliott Hughes        wfd.reset(open(blk_dev, O_WRONLY));
310bcabd0929316fdd022ea102cc86396547ad9f070Elliott Hughes        if (wfd == -1) {
311747781433fb01f745529c7e9dd97c5599070ad0dTianjie Xu            PLOG(ERROR) << "failed to open " << blk_dev << " for writing";
312da44cf18f3ce4bbffa85ad0a50bb25e9cb54a86dTianjie Xu            return kUncryptBlockOpenError;
31376adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker        }
31476adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker    }
31576adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker
316848f227eea524a48208bdd4181f90fb63a31ed2bJaegeuk Kim#ifndef F2FS_IOC_SET_DONTMOVE
317848f227eea524a48208bdd4181f90fb63a31ed2bJaegeuk Kim#ifndef F2FS_IOCTL_MAGIC
318848f227eea524a48208bdd4181f90fb63a31ed2bJaegeuk Kim#define F2FS_IOCTL_MAGIC		0xf5
319848f227eea524a48208bdd4181f90fb63a31ed2bJaegeuk Kim#endif
320848f227eea524a48208bdd4181f90fb63a31ed2bJaegeuk Kim#define F2FS_IOC_SET_DONTMOVE		_IO(F2FS_IOCTL_MAGIC, 13)
321848f227eea524a48208bdd4181f90fb63a31ed2bJaegeuk Kim#endif
322848f227eea524a48208bdd4181f90fb63a31ed2bJaegeuk Kim    if (f2fs_fs && ioctl(fd, F2FS_IOC_SET_DONTMOVE) < 0) {
323848f227eea524a48208bdd4181f90fb63a31ed2bJaegeuk Kim        PLOG(ERROR) << "Failed to set non-movable file for f2fs: " << path << " on " << blk_dev;
324848f227eea524a48208bdd4181f90fb63a31ed2bJaegeuk Kim        return kUncryptIoctlError;
325848f227eea524a48208bdd4181f90fb63a31ed2bJaegeuk Kim    }
326848f227eea524a48208bdd4181f90fb63a31ed2bJaegeuk Kim
327b8df5fb90e4b7244fa7925b9706cdd218e18a2aaTao Bao    off64_t pos = 0;
328383b00d0e498e1f3b84e9dcfc6dddec6a76379d7Tao Bao    int last_progress = 0;
32976adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker    while (pos < sb.st_size) {
330383b00d0e498e1f3b84e9dcfc6dddec6a76379d7Tao Bao        // Update the status file, progress must be between [0, 99].
331383b00d0e498e1f3b84e9dcfc6dddec6a76379d7Tao Bao        int progress = static_cast<int>(100 * (double(pos) / double(sb.st_size)));
332383b00d0e498e1f3b84e9dcfc6dddec6a76379d7Tao Bao        if (progress > last_progress) {
3333a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao            last_progress = progress;
3343a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao            write_status_to_socket(progress, socket);
335383b00d0e498e1f3b84e9dcfc6dddec6a76379d7Tao Bao        }
336383b00d0e498e1f3b84e9dcfc6dddec6a76379d7Tao Bao
33776adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker        if ((tail+1) % WINDOW_SIZE == head) {
33876adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker            // write out head buffer
33976adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker            int block = head_block;
340bcabd0929316fdd022ea102cc86396547ad9f070Elliott Hughes            if (ioctl(fd, FIBMAP, &block) != 0) {
341da44cf18f3ce4bbffa85ad0a50bb25e9cb54a86dTianjie Xu                PLOG(ERROR) << "failed to find block " << head_block;
342da44cf18f3ce4bbffa85ad0a50bb25e9cb54a86dTianjie Xu                return kUncryptIoctlError;
34376adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker            }
344bc42603a8daae62b158d159c97ef8acfaa39d70dTianjie Xu
345bc42603a8daae62b158d159c97ef8acfaa39d70dTianjie Xu            if (block == 0) {
346bc42603a8daae62b158d159c97ef8acfaa39d70dTianjie Xu                LOG(ERROR) << "failed to find block " << head_block << ", retrying";
347bc42603a8daae62b158d159c97ef8acfaa39d70dTianjie Xu                int error = retry_fibmap(fd, path, &block, head_block);
348bc42603a8daae62b158d159c97ef8acfaa39d70dTianjie Xu                if (error != kUncryptNoError) {
349bc42603a8daae62b158d159c97ef8acfaa39d70dTianjie Xu                    return error;
350bc42603a8daae62b158d159c97ef8acfaa39d70dTianjie Xu                }
351bc42603a8daae62b158d159c97ef8acfaa39d70dTianjie Xu            }
352bc42603a8daae62b158d159c97ef8acfaa39d70dTianjie Xu
35325dd0386fe69460cd1d39de116197dd2c7bf9ec2Yabin Cui            add_block_to_ranges(ranges, block);
35476adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker            if (encrypted) {
355bcabd0929316fdd022ea102cc86396547ad9f070Elliott Hughes                if (write_at_offset(buffers[head].data(), sb.st_blksize, wfd,
356bcabd0929316fdd022ea102cc86396547ad9f070Elliott Hughes                                    static_cast<off64_t>(sb.st_blksize) * block) != 0) {
357da44cf18f3ce4bbffa85ad0a50bb25e9cb54a86dTianjie Xu                    return kUncryptWriteError;
35876adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker                }
35976adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker            }
36076adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker            head = (head + 1) % WINDOW_SIZE;
36176adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker            ++head_block;
36276adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker        }
36376adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker
36476adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker        // read next block to tail
36576adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker        if (encrypted) {
36625dd0386fe69460cd1d39de116197dd2c7bf9ec2Yabin Cui            size_t to_read = static_cast<size_t>(
36725dd0386fe69460cd1d39de116197dd2c7bf9ec2Yabin Cui                    std::min(static_cast<off64_t>(sb.st_blksize), sb.st_size - pos));
368bcabd0929316fdd022ea102cc86396547ad9f070Elliott Hughes            if (!android::base::ReadFully(fd, buffers[tail].data(), to_read)) {
369747781433fb01f745529c7e9dd97c5599070ad0dTianjie Xu                PLOG(ERROR) << "failed to read " << path;
370da44cf18f3ce4bbffa85ad0a50bb25e9cb54a86dTianjie Xu                return kUncryptReadError;
37176adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker            }
37225dd0386fe69460cd1d39de116197dd2c7bf9ec2Yabin Cui            pos += to_read;
37376adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker        } else {
37476adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker            // If we're not encrypting; we don't need to actually read
37576adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker            // anything, just skip pos forward as if we'd read a
37676adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker            // block.
37776adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker            pos += sb.st_blksize;
37876adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker        }
37976adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker        tail = (tail+1) % WINDOW_SIZE;
38076adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker    }
38176adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker
38276adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker    while (head != tail) {
38376adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker        // write out head buffer
38476adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker        int block = head_block;
385bcabd0929316fdd022ea102cc86396547ad9f070Elliott Hughes        if (ioctl(fd, FIBMAP, &block) != 0) {
386da44cf18f3ce4bbffa85ad0a50bb25e9cb54a86dTianjie Xu            PLOG(ERROR) << "failed to find block " << head_block;
387da44cf18f3ce4bbffa85ad0a50bb25e9cb54a86dTianjie Xu            return kUncryptIoctlError;
38876adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker        }
389bc42603a8daae62b158d159c97ef8acfaa39d70dTianjie Xu
390bc42603a8daae62b158d159c97ef8acfaa39d70dTianjie Xu        if (block == 0) {
391bc42603a8daae62b158d159c97ef8acfaa39d70dTianjie Xu            LOG(ERROR) << "failed to find block " << head_block << ", retrying";
392bc42603a8daae62b158d159c97ef8acfaa39d70dTianjie Xu            int error = retry_fibmap(fd, path, &block, head_block);
393bc42603a8daae62b158d159c97ef8acfaa39d70dTianjie Xu            if (error != kUncryptNoError) {
394bc42603a8daae62b158d159c97ef8acfaa39d70dTianjie Xu                return error;
395bc42603a8daae62b158d159c97ef8acfaa39d70dTianjie Xu            }
396bc42603a8daae62b158d159c97ef8acfaa39d70dTianjie Xu        }
397bc42603a8daae62b158d159c97ef8acfaa39d70dTianjie Xu
39825dd0386fe69460cd1d39de116197dd2c7bf9ec2Yabin Cui        add_block_to_ranges(ranges, block);
39976adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker        if (encrypted) {
400bcabd0929316fdd022ea102cc86396547ad9f070Elliott Hughes            if (write_at_offset(buffers[head].data(), sb.st_blksize, wfd,
401bcabd0929316fdd022ea102cc86396547ad9f070Elliott Hughes                                static_cast<off64_t>(sb.st_blksize) * block) != 0) {
402da44cf18f3ce4bbffa85ad0a50bb25e9cb54a86dTianjie Xu                return kUncryptWriteError;
40376adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker            }
40476adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker        }
40576adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker        head = (head + 1) % WINDOW_SIZE;
40676adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker        ++head_block;
40776adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker    }
40876adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker
40925dd0386fe69460cd1d39de116197dd2c7bf9ec2Yabin Cui    if (!android::base::WriteStringToFd(
410bcabd0929316fdd022ea102cc86396547ad9f070Elliott Hughes            android::base::StringPrintf("%zu\n", ranges.size() / 2), mapfd)) {
411747781433fb01f745529c7e9dd97c5599070ad0dTianjie Xu        PLOG(ERROR) << "failed to write " << tmp_map_file;
412da44cf18f3ce4bbffa85ad0a50bb25e9cb54a86dTianjie Xu        return kUncryptWriteError;
41325dd0386fe69460cd1d39de116197dd2c7bf9ec2Yabin Cui    }
41425dd0386fe69460cd1d39de116197dd2c7bf9ec2Yabin Cui    for (size_t i = 0; i < ranges.size(); i += 2) {
41525dd0386fe69460cd1d39de116197dd2c7bf9ec2Yabin Cui        if (!android::base::WriteStringToFd(
416bcabd0929316fdd022ea102cc86396547ad9f070Elliott Hughes                android::base::StringPrintf("%d %d\n", ranges[i], ranges[i+1]), mapfd)) {
417747781433fb01f745529c7e9dd97c5599070ad0dTianjie Xu            PLOG(ERROR) << "failed to write " << tmp_map_file;
418da44cf18f3ce4bbffa85ad0a50bb25e9cb54a86dTianjie Xu            return kUncryptWriteError;
41925dd0386fe69460cd1d39de116197dd2c7bf9ec2Yabin Cui        }
42076adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker    }
42176adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker
422bcabd0929316fdd022ea102cc86396547ad9f070Elliott Hughes    if (fsync(mapfd) == -1) {
423747781433fb01f745529c7e9dd97c5599070ad0dTianjie Xu        PLOG(ERROR) << "failed to fsync \"" << tmp_map_file << "\"";
424da44cf18f3ce4bbffa85ad0a50bb25e9cb54a86dTianjie Xu        return kUncryptFileSyncError;
42525dd0386fe69460cd1d39de116197dd2c7bf9ec2Yabin Cui    }
426bcabd0929316fdd022ea102cc86396547ad9f070Elliott Hughes    if (close(mapfd.release()) == -1) {
427747781433fb01f745529c7e9dd97c5599070ad0dTianjie Xu        PLOG(ERROR) << "failed to close " << tmp_map_file;
428da44cf18f3ce4bbffa85ad0a50bb25e9cb54a86dTianjie Xu        return kUncryptFileCloseError;
429fb4ccef1df4f0bd8fa830c750f2970dd2df9e51bTao Bao    }
43025dd0386fe69460cd1d39de116197dd2c7bf9ec2Yabin Cui
43176adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker    if (encrypted) {
432bcabd0929316fdd022ea102cc86396547ad9f070Elliott Hughes        if (fsync(wfd) == -1) {
433747781433fb01f745529c7e9dd97c5599070ad0dTianjie Xu            PLOG(ERROR) << "failed to fsync \"" << blk_dev << "\"";
434da44cf18f3ce4bbffa85ad0a50bb25e9cb54a86dTianjie Xu            return kUncryptFileSyncError;
435fb4ccef1df4f0bd8fa830c750f2970dd2df9e51bTao Bao        }
436bcabd0929316fdd022ea102cc86396547ad9f070Elliott Hughes        if (close(wfd.release()) == -1) {
437747781433fb01f745529c7e9dd97c5599070ad0dTianjie Xu            PLOG(ERROR) << "failed to close " << blk_dev;
438da44cf18f3ce4bbffa85ad0a50bb25e9cb54a86dTianjie Xu            return kUncryptFileCloseError;
43925dd0386fe69460cd1d39de116197dd2c7bf9ec2Yabin Cui        }
44076adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker    }
44176adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker
44225dd0386fe69460cd1d39de116197dd2c7bf9ec2Yabin Cui    if (rename(tmp_map_file.c_str(), map_file) == -1) {
443747781433fb01f745529c7e9dd97c5599070ad0dTianjie Xu        PLOG(ERROR) << "failed to rename " << tmp_map_file << " to " << map_file;
444da44cf18f3ce4bbffa85ad0a50bb25e9cb54a86dTianjie Xu        return kUncryptFileRenameError;
44525dd0386fe69460cd1d39de116197dd2c7bf9ec2Yabin Cui    }
44625dd0386fe69460cd1d39de116197dd2c7bf9ec2Yabin Cui    // Sync dir to make rename() result written to disk.
44725dd0386fe69460cd1d39de116197dd2c7bf9ec2Yabin Cui    std::string file_name = map_file;
44825dd0386fe69460cd1d39de116197dd2c7bf9ec2Yabin Cui    std::string dir_name = dirname(&file_name[0]);
449bcabd0929316fdd022ea102cc86396547ad9f070Elliott Hughes    android::base::unique_fd dfd(open(dir_name.c_str(), O_RDONLY | O_DIRECTORY));
450bcabd0929316fdd022ea102cc86396547ad9f070Elliott Hughes    if (dfd == -1) {
451747781433fb01f745529c7e9dd97c5599070ad0dTianjie Xu        PLOG(ERROR) << "failed to open dir " << dir_name;
452da44cf18f3ce4bbffa85ad0a50bb25e9cb54a86dTianjie Xu        return kUncryptFileOpenError;
45325dd0386fe69460cd1d39de116197dd2c7bf9ec2Yabin Cui    }
454bcabd0929316fdd022ea102cc86396547ad9f070Elliott Hughes    if (fsync(dfd) == -1) {
455747781433fb01f745529c7e9dd97c5599070ad0dTianjie Xu        PLOG(ERROR) << "failed to fsync " << dir_name;
456da44cf18f3ce4bbffa85ad0a50bb25e9cb54a86dTianjie Xu        return kUncryptFileSyncError;
45725dd0386fe69460cd1d39de116197dd2c7bf9ec2Yabin Cui    }
458bcabd0929316fdd022ea102cc86396547ad9f070Elliott Hughes    if (close(dfd.release()) == -1) {
459747781433fb01f745529c7e9dd97c5599070ad0dTianjie Xu        PLOG(ERROR) << "failed to close " << dir_name;
460da44cf18f3ce4bbffa85ad0a50bb25e9cb54a86dTianjie Xu        return kUncryptFileCloseError;
46125dd0386fe69460cd1d39de116197dd2c7bf9ec2Yabin Cui    }
46276adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker    return 0;
46376adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker}
46476adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker
4653a2bb594df4b48c6afb1f029041dd6db0735de58Tao Baostatic int uncrypt(const char* input_path, const char* map_file, const int socket) {
466747781433fb01f745529c7e9dd97c5599070ad0dTianjie Xu    LOG(INFO) << "update package is \"" << input_path << "\"";
467f449db2f30235a0c2fef4bc7bc41776e271a60a0Doug Zongker
4688b8e23d5cc38d4f9139b3b3cdca4a9c5ec51139eTianjie Xu    // Turn the name of the file we're supposed to convert into an absolute path, so we can find
4698b8e23d5cc38d4f9139b3b3cdca4a9c5ec51139eTianjie Xu    // what filesystem it's on.
47076adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker    char path[PATH_MAX+1];
4718b8e23d5cc38d4f9139b3b3cdca4a9c5ec51139eTianjie Xu    if (realpath(input_path, path) == nullptr) {
472747781433fb01f745529c7e9dd97c5599070ad0dTianjie Xu        PLOG(ERROR) << "failed to convert \"" << input_path << "\" to absolute path";
4738b8e23d5cc38d4f9139b3b3cdca4a9c5ec51139eTianjie Xu        return kUncryptRealpathFindError;
47476adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker    }
47576adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker
476381f455cac0905b023dde79625b06c27b6165dd0Tao Bao    bool encryptable;
477381f455cac0905b023dde79625b06c27b6165dd0Tao Bao    bool encrypted;
478848f227eea524a48208bdd4181f90fb63a31ed2bJaegeuk Kim    bool f2fs_fs;
479848f227eea524a48208bdd4181f90fb63a31ed2bJaegeuk Kim    const char* blk_dev = find_block_device(path, &encryptable, &encrypted, &f2fs_fs);
4808b8e23d5cc38d4f9139b3b3cdca4a9c5ec51139eTianjie Xu    if (blk_dev == nullptr) {
481747781433fb01f745529c7e9dd97c5599070ad0dTianjie Xu        LOG(ERROR) << "failed to find block device for " << path;
4828b8e23d5cc38d4f9139b3b3cdca4a9c5ec51139eTianjie Xu        return kUncryptBlockDeviceFindError;
48376adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker    }
48476adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker
48576adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker    // If the filesystem it's on isn't encrypted, we only produce the
48676adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker    // block map, we don't rewrite the file contents (it would be
48776adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker    // pointless to do so).
488747781433fb01f745529c7e9dd97c5599070ad0dTianjie Xu    LOG(INFO) << "encryptable: " << (encryptable ? "yes" : "no");
489747781433fb01f745529c7e9dd97c5599070ad0dTianjie Xu    LOG(INFO) << "  encrypted: " << (encrypted ? "yes" : "no");
49076adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker
491574443d8956802f35347cac7fae7eb16240e3c16Doug Zongker    // Recovery supports installing packages from 3 paths: /cache,
492574443d8956802f35347cac7fae7eb16240e3c16Doug Zongker    // /data, and /sdcard.  (On a particular device, other locations
493574443d8956802f35347cac7fae7eb16240e3c16Doug Zongker    // may work, but those are three we actually expect.)
494574443d8956802f35347cac7fae7eb16240e3c16Doug Zongker    //
495574443d8956802f35347cac7fae7eb16240e3c16Doug Zongker    // On /data we want to convert the file to a block map so that we
496574443d8956802f35347cac7fae7eb16240e3c16Doug Zongker    // can read the package without mounting the partition.  On /cache
497574443d8956802f35347cac7fae7eb16240e3c16Doug Zongker    // and /sdcard we leave the file alone.
498383b00d0e498e1f3b84e9dcfc6dddec6a76379d7Tao Bao    if (strncmp(path, "/data/", 6) == 0) {
499747781433fb01f745529c7e9dd97c5599070ad0dTianjie Xu        LOG(INFO) << "writing block map " << map_file;
500848f227eea524a48208bdd4181f90fb63a31ed2bJaegeuk Kim        return produce_block_map(path, map_file, blk_dev, encrypted, f2fs_fs, socket);
50176adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker    }
50276adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker
503383b00d0e498e1f3b84e9dcfc6dddec6a76379d7Tao Bao    return 0;
504383b00d0e498e1f3b84e9dcfc6dddec6a76379d7Tao Bao}
505383b00d0e498e1f3b84e9dcfc6dddec6a76379d7Tao Bao
50668fc81e860ab58a5147a48093e57daab38ee84a3Tianjie Xustatic void log_uncrypt_error_code(UncryptErrorCode error_code) {
507da44cf18f3ce4bbffa85ad0a50bb25e9cb54a86dTianjie Xu    if (!android::base::WriteStringToFile(android::base::StringPrintf(
50868fc81e860ab58a5147a48093e57daab38ee84a3Tianjie Xu            "uncrypt_error: %d\n", error_code), UNCRYPT_STATUS)) {
509da44cf18f3ce4bbffa85ad0a50bb25e9cb54a86dTianjie Xu        PLOG(WARNING) << "failed to write to " << UNCRYPT_STATUS;
510da44cf18f3ce4bbffa85ad0a50bb25e9cb54a86dTianjie Xu    }
51168fc81e860ab58a5147a48093e57daab38ee84a3Tianjie Xu}
51268fc81e860ab58a5147a48093e57daab38ee84a3Tianjie Xu
51368fc81e860ab58a5147a48093e57daab38ee84a3Tianjie Xustatic bool uncrypt_wrapper(const char* input_path, const char* map_file, const int socket) {
51468fc81e860ab58a5147a48093e57daab38ee84a3Tianjie Xu    // Initialize the uncrypt error to kUncryptErrorPlaceholder.
51568fc81e860ab58a5147a48093e57daab38ee84a3Tianjie Xu    log_uncrypt_error_code(kUncryptErrorPlaceholder);
516da44cf18f3ce4bbffa85ad0a50bb25e9cb54a86dTianjie Xu
5172d46da57e19612b0a29ee0b8601146cf8fb9ff5eYabin Cui    std::string package;
5182d46da57e19612b0a29ee0b8601146cf8fb9ff5eYabin Cui    if (input_path == nullptr) {
5192d46da57e19612b0a29ee0b8601146cf8fb9ff5eYabin Cui        if (!find_uncrypt_package(UNCRYPT_PATH_FILE, &package)) {
5203a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao            write_status_to_socket(-1, socket);
521da44cf18f3ce4bbffa85ad0a50bb25e9cb54a86dTianjie Xu            // Overwrite the error message.
52268fc81e860ab58a5147a48093e57daab38ee84a3Tianjie Xu            log_uncrypt_error_code(kUncryptPackageMissingError);
5233a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao            return false;
524383b00d0e498e1f3b84e9dcfc6dddec6a76379d7Tao Bao        }
5252d46da57e19612b0a29ee0b8601146cf8fb9ff5eYabin Cui        input_path = package.c_str();
5262d46da57e19612b0a29ee0b8601146cf8fb9ff5eYabin Cui    }
5272d46da57e19612b0a29ee0b8601146cf8fb9ff5eYabin Cui    CHECK(map_file != nullptr);
528e16e799dfdff5392d2bdc460f41353100d082e96Tianjie Xu
529e16e799dfdff5392d2bdc460f41353100d082e96Tianjie Xu    auto start = std::chrono::system_clock::now();
5303a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao    int status = uncrypt(input_path, map_file, socket);
531da44cf18f3ce4bbffa85ad0a50bb25e9cb54a86dTianjie Xu    std::chrono::duration<double> duration = std::chrono::system_clock::now() - start;
532da44cf18f3ce4bbffa85ad0a50bb25e9cb54a86dTianjie Xu    int count = static_cast<int>(duration.count());
533da44cf18f3ce4bbffa85ad0a50bb25e9cb54a86dTianjie Xu
534da44cf18f3ce4bbffa85ad0a50bb25e9cb54a86dTianjie Xu    std::string uncrypt_message = android::base::StringPrintf("uncrypt_time: %d\n", count);
5352d46da57e19612b0a29ee0b8601146cf8fb9ff5eYabin Cui    if (status != 0) {
536da44cf18f3ce4bbffa85ad0a50bb25e9cb54a86dTianjie Xu        // Log the time cost and error code if uncrypt fails.
537da44cf18f3ce4bbffa85ad0a50bb25e9cb54a86dTianjie Xu        uncrypt_message += android::base::StringPrintf("uncrypt_error: %d\n", status);
538da44cf18f3ce4bbffa85ad0a50bb25e9cb54a86dTianjie Xu        if (!android::base::WriteStringToFile(uncrypt_message, UNCRYPT_STATUS)) {
539da44cf18f3ce4bbffa85ad0a50bb25e9cb54a86dTianjie Xu            PLOG(WARNING) << "failed to write to " << UNCRYPT_STATUS;
540da44cf18f3ce4bbffa85ad0a50bb25e9cb54a86dTianjie Xu        }
541da44cf18f3ce4bbffa85ad0a50bb25e9cb54a86dTianjie Xu
5423a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao        write_status_to_socket(-1, socket);
5433a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao        return false;
5442d46da57e19612b0a29ee0b8601146cf8fb9ff5eYabin Cui    }
545e16e799dfdff5392d2bdc460f41353100d082e96Tianjie Xu
546da44cf18f3ce4bbffa85ad0a50bb25e9cb54a86dTianjie Xu    if (!android::base::WriteStringToFile(uncrypt_message, UNCRYPT_STATUS)) {
547e16e799dfdff5392d2bdc460f41353100d082e96Tianjie Xu        PLOG(WARNING) << "failed to write to " << UNCRYPT_STATUS;
548e16e799dfdff5392d2bdc460f41353100d082e96Tianjie Xu    }
549e16e799dfdff5392d2bdc460f41353100d082e96Tianjie Xu
5503a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao    write_status_to_socket(100, socket);
551e16e799dfdff5392d2bdc460f41353100d082e96Tianjie Xu
5523a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao    return true;
5532d46da57e19612b0a29ee0b8601146cf8fb9ff5eYabin Cui}
554ac6aa7ede0b0b1df18b4149fdb9846c3e486918aTao Bao
5553a2bb594df4b48c6afb1f029041dd6db0735de58Tao Baostatic bool clear_bcb(const int socket) {
556a58a6dbe3d06aace0d1419838e162aa5267a4fc0Yabin Cui    std::string err;
557a58a6dbe3d06aace0d1419838e162aa5267a4fc0Yabin Cui    if (!clear_bootloader_message(&err)) {
558747781433fb01f745529c7e9dd97c5599070ad0dTianjie Xu        LOG(ERROR) << "failed to clear bootloader message: " << err;
5593a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao        write_status_to_socket(-1, socket);
5603a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao        return false;
5612d46da57e19612b0a29ee0b8601146cf8fb9ff5eYabin Cui    }
5623a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao    write_status_to_socket(100, socket);
5633a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao    return true;
5642d46da57e19612b0a29ee0b8601146cf8fb9ff5eYabin Cui}
5652d46da57e19612b0a29ee0b8601146cf8fb9ff5eYabin Cui
5663a2bb594df4b48c6afb1f029041dd6db0735de58Tao Baostatic bool setup_bcb(const int socket) {
5673a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao    // c5. receive message length
5683a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao    int length;
5693a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao    if (!android::base::ReadFully(socket, &length, 4)) {
570747781433fb01f745529c7e9dd97c5599070ad0dTianjie Xu        PLOG(ERROR) << "failed to read the length";
5713a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao        return false;
5722d46da57e19612b0a29ee0b8601146cf8fb9ff5eYabin Cui    }
5733a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao    length = ntohl(length);
5743a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao
5753a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao    // c7. receive message
5762d46da57e19612b0a29ee0b8601146cf8fb9ff5eYabin Cui    std::string content;
5773a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao    content.resize(length);
5783a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao    if (!android::base::ReadFully(socket, &content[0], length)) {
57910334088017c9bfcf1b171567e7c4794876c33c9Tao Bao        PLOG(ERROR) << "failed to read the message";
5803a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao        return false;
5812d46da57e19612b0a29ee0b8601146cf8fb9ff5eYabin Cui    }
582747781433fb01f745529c7e9dd97c5599070ad0dTianjie Xu    LOG(INFO) << "  received command: [" << content << "] (" << content.size() << ")";
5836faf0265c9b58db2c15b53f6d29025629d52f882Yabin Cui    std::vector<std::string> options = android::base::Split(content, "\n");
5846faf0265c9b58db2c15b53f6d29025629d52f882Yabin Cui    std::string wipe_package;
5856faf0265c9b58db2c15b53f6d29025629d52f882Yabin Cui    for (auto& option : options) {
5866faf0265c9b58db2c15b53f6d29025629d52f882Yabin Cui        if (android::base::StartsWith(option, "--wipe_package=")) {
5876faf0265c9b58db2c15b53f6d29025629d52f882Yabin Cui            std::string path = option.substr(strlen("--wipe_package="));
5886faf0265c9b58db2c15b53f6d29025629d52f882Yabin Cui            if (!android::base::ReadFileToString(path, &wipe_package)) {
589747781433fb01f745529c7e9dd97c5599070ad0dTianjie Xu                PLOG(ERROR) << "failed to read " << path;
5906faf0265c9b58db2c15b53f6d29025629d52f882Yabin Cui                return false;
5916faf0265c9b58db2c15b53f6d29025629d52f882Yabin Cui            }
5926faf0265c9b58db2c15b53f6d29025629d52f882Yabin Cui            option = android::base::StringPrintf("--wipe_package_size=%zu", wipe_package.size());
5936faf0265c9b58db2c15b53f6d29025629d52f882Yabin Cui        }
5946faf0265c9b58db2c15b53f6d29025629d52f882Yabin Cui    }
5953a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao
5963a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao    // c8. setup the bcb command
597a58a6dbe3d06aace0d1419838e162aa5267a4fc0Yabin Cui    std::string err;
5986faf0265c9b58db2c15b53f6d29025629d52f882Yabin Cui    if (!write_bootloader_message(options, &err)) {
599747781433fb01f745529c7e9dd97c5599070ad0dTianjie Xu        LOG(ERROR) << "failed to set bootloader message: " << err;
6003a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao        write_status_to_socket(-1, socket);
6013a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao        return false;
6022d46da57e19612b0a29ee0b8601146cf8fb9ff5eYabin Cui    }
6036faf0265c9b58db2c15b53f6d29025629d52f882Yabin Cui    if (!wipe_package.empty() && !write_wipe_package(wipe_package, &err)) {
604747781433fb01f745529c7e9dd97c5599070ad0dTianjie Xu        PLOG(ERROR) << "failed to set wipe package: " << err;
6056faf0265c9b58db2c15b53f6d29025629d52f882Yabin Cui        write_status_to_socket(-1, socket);
6066faf0265c9b58db2c15b53f6d29025629d52f882Yabin Cui        return false;
6076faf0265c9b58db2c15b53f6d29025629d52f882Yabin Cui    }
6083a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao    // c10. send "100" status
6093a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao    write_status_to_socket(100, socket);
6103a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao    return true;
6112d46da57e19612b0a29ee0b8601146cf8fb9ff5eYabin Cui}
612c5631fc09666a9542d2882299d40500d18d1f68cDaniel Micay
6132d46da57e19612b0a29ee0b8601146cf8fb9ff5eYabin Cuistatic void usage(const char* exename) {
6142d46da57e19612b0a29ee0b8601146cf8fb9ff5eYabin Cui    fprintf(stderr, "Usage of %s:\n", exename);
6152d46da57e19612b0a29ee0b8601146cf8fb9ff5eYabin Cui    fprintf(stderr, "%s [<package_path> <map_file>]  Uncrypt ota package.\n", exename);
6162d46da57e19612b0a29ee0b8601146cf8fb9ff5eYabin Cui    fprintf(stderr, "%s --clear-bcb  Clear BCB data in misc partition.\n", exename);
6172d46da57e19612b0a29ee0b8601146cf8fb9ff5eYabin Cui    fprintf(stderr, "%s --setup-bcb  Setup BCB data by command file.\n", exename);
6182d46da57e19612b0a29ee0b8601146cf8fb9ff5eYabin Cui}
6192d46da57e19612b0a29ee0b8601146cf8fb9ff5eYabin Cui
6202d46da57e19612b0a29ee0b8601146cf8fb9ff5eYabin Cuiint main(int argc, char** argv) {
62128c1e5d3aa9610db6e141380b1435937fc7f07dbTianjie Xu    enum { UNCRYPT, SETUP_BCB, CLEAR_BCB, UNCRYPT_DEBUG } action;
6223a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao    const char* input_path = nullptr;
6233a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao    const char* map_file = CACHE_BLOCK_MAP.c_str();
6243a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao
6253a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao    if (argc == 2 && strcmp(argv[1], "--clear-bcb") == 0) {
6263a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao        action = CLEAR_BCB;
6273a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao    } else if (argc == 2 && strcmp(argv[1], "--setup-bcb") == 0) {
6283a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao        action = SETUP_BCB;
6293a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao    } else if (argc == 1) {
6303a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao        action = UNCRYPT;
6313a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao    } else if (argc == 3) {
6323a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao        input_path = argv[1];
6333a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao        map_file = argv[2];
63428c1e5d3aa9610db6e141380b1435937fc7f07dbTianjie Xu        action = UNCRYPT_DEBUG;
6353a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao    } else {
6363a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao        usage(argv[0]);
6373a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao        return 2;
6383a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao    }
6393a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao
6403a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao    if ((fstab = read_fstab()) == nullptr) {
64168fc81e860ab58a5147a48093e57daab38ee84a3Tianjie Xu        log_uncrypt_error_code(kUncryptFstabReadError);
6423a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao        return 1;
6433a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao    }
6443a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao
64528c1e5d3aa9610db6e141380b1435937fc7f07dbTianjie Xu    if (action == UNCRYPT_DEBUG) {
646747781433fb01f745529c7e9dd97c5599070ad0dTianjie Xu        LOG(INFO) << "uncrypt called in debug mode, skip socket communication";
64728c1e5d3aa9610db6e141380b1435937fc7f07dbTianjie Xu        bool success = uncrypt_wrapper(input_path, map_file, -1);
64828c1e5d3aa9610db6e141380b1435937fc7f07dbTianjie Xu        if (success) {
649747781433fb01f745529c7e9dd97c5599070ad0dTianjie Xu            LOG(INFO) << "uncrypt succeeded";
65028c1e5d3aa9610db6e141380b1435937fc7f07dbTianjie Xu        } else{
651747781433fb01f745529c7e9dd97c5599070ad0dTianjie Xu            LOG(INFO) << "uncrypt failed";
65228c1e5d3aa9610db6e141380b1435937fc7f07dbTianjie Xu        }
65328c1e5d3aa9610db6e141380b1435937fc7f07dbTianjie Xu        return success ? 0 : 1;
65428c1e5d3aa9610db6e141380b1435937fc7f07dbTianjie Xu    }
65528c1e5d3aa9610db6e141380b1435937fc7f07dbTianjie Xu
6563a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao    // c3. The socket is created by init when starting the service. uncrypt
6573a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao    // will use the socket to communicate with its caller.
658d6ac68665dcef6c12d44ee6bcd7d938ab5028150Elliott Hughes    android::base::unique_fd service_socket(android_get_control_socket(UNCRYPT_SOCKET.c_str()));
659d6ac68665dcef6c12d44ee6bcd7d938ab5028150Elliott Hughes    if (service_socket == -1) {
660747781433fb01f745529c7e9dd97c5599070ad0dTianjie Xu        PLOG(ERROR) << "failed to open socket \"" << UNCRYPT_SOCKET << "\"";
66168fc81e860ab58a5147a48093e57daab38ee84a3Tianjie Xu        log_uncrypt_error_code(kUncryptSocketOpenError);
6623a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao        return 1;
6633a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao    }
664d6ac68665dcef6c12d44ee6bcd7d938ab5028150Elliott Hughes    fcntl(service_socket, F_SETFD, FD_CLOEXEC);
6653a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao
666d6ac68665dcef6c12d44ee6bcd7d938ab5028150Elliott Hughes    if (listen(service_socket, 1) == -1) {
667747781433fb01f745529c7e9dd97c5599070ad0dTianjie Xu        PLOG(ERROR) << "failed to listen on socket " << service_socket.get();
66868fc81e860ab58a5147a48093e57daab38ee84a3Tianjie Xu        log_uncrypt_error_code(kUncryptSocketListenError);
6693a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao        return 1;
6703a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao    }
6713a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao
672d6ac68665dcef6c12d44ee6bcd7d938ab5028150Elliott Hughes    android::base::unique_fd socket_fd(accept4(service_socket, nullptr, nullptr, SOCK_CLOEXEC));
673d6ac68665dcef6c12d44ee6bcd7d938ab5028150Elliott Hughes    if (socket_fd == -1) {
674747781433fb01f745529c7e9dd97c5599070ad0dTianjie Xu        PLOG(ERROR) << "failed to accept on socket " << service_socket.get();
67568fc81e860ab58a5147a48093e57daab38ee84a3Tianjie Xu        log_uncrypt_error_code(kUncryptSocketAcceptError);
6763a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao        return 1;
6773a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao    }
6783a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao
6793a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao    bool success = false;
6803a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao    switch (action) {
6813a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao        case UNCRYPT:
682d6ac68665dcef6c12d44ee6bcd7d938ab5028150Elliott Hughes            success = uncrypt_wrapper(input_path, map_file, socket_fd);
6833a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao            break;
6843a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao        case SETUP_BCB:
685d6ac68665dcef6c12d44ee6bcd7d938ab5028150Elliott Hughes            success = setup_bcb(socket_fd);
6863a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao            break;
6873a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao        case CLEAR_BCB:
688d6ac68665dcef6c12d44ee6bcd7d938ab5028150Elliott Hughes            success = clear_bcb(socket_fd);
6893a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao            break;
6903a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao        default:  // Should never happen.
691747781433fb01f745529c7e9dd97c5599070ad0dTianjie Xu            LOG(ERROR) << "Invalid uncrypt action code: " << action;
6923a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao            return 1;
6933a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao    }
6943a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao
6953a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao    // c13. Read a 4-byte code from the client before uncrypt exits. This is to
6963a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao    // ensure the client to receive the last status code before the socket gets
6973a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao    // destroyed.
6983a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao    int code;
699d6ac68665dcef6c12d44ee6bcd7d938ab5028150Elliott Hughes    if (android::base::ReadFully(socket_fd, &code, 4)) {
700747781433fb01f745529c7e9dd97c5599070ad0dTianjie Xu        LOG(INFO) << "  received " << code << ", exiting now";
7013a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao    } else {
702747781433fb01f745529c7e9dd97c5599070ad0dTianjie Xu        PLOG(ERROR) << "failed to read the code";
703381f455cac0905b023dde79625b06c27b6165dd0Tao Bao    }
7043a2bb594df4b48c6afb1f029041dd6db0735de58Tao Bao    return success ? 0 : 1;
70576adfc5309936a07218ce53b5ab284d5746fa84cDoug Zongker}
706