1deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey/*
2deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey * Copyright (C) 2015 The Android Open Source Project
3deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey *
4deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License");
5deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey * you may not use this file except in compliance with the License.
6deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey * You may obtain a copy of the License at
7deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey *
8deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey *      http://www.apache.org/licenses/LICENSE-2.0
9deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey *
10deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey * Unless required by applicable law or agreed to in writing, software
11deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS,
12deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey * See the License for the specific language governing permissions and
14deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey * limitations under the License.
15deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey */
16deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey
17deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey#include "sehandle.h"
18deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey#include "Utils.h"
19deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey#include "Process.h"
20deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey
217e128fbe212c64492afa98bfd6d7fab6f1956831Elliott Hughes#include <android-base/file.h>
227e128fbe212c64492afa98bfd6d7fab6f1956831Elliott Hughes#include <android-base/logging.h>
237e128fbe212c64492afa98bfd6d7fab6f1956831Elliott Hughes#include <android-base/stringprintf.h>
24deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey#include <cutils/fs.h>
25c86ab6f538bec63638c168d6c843fe7cf73add3bJeff Sharkey#include <cutils/properties.h>
26deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey#include <private/android_filesystem_config.h>
279c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey#include <logwrap/logwrap.h>
28deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey
29ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey#include <mutex>
301d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey#include <dirent.h>
31deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey#include <fcntl.h>
32deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey#include <linux/fs.h>
33deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey#include <stdlib.h>
34deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey#include <sys/mount.h>
35deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey#include <sys/types.h>
36deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey#include <sys/stat.h>
37deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey#include <sys/wait.h>
381d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey#include <sys/statvfs.h>
39deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey
40deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey#ifndef UMOUNT_NOFOLLOW
41deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey#define UMOUNT_NOFOLLOW    0x00000008  /* Don't follow symlink on umount */
42deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey#endif
43deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey
44d0640f6358041f7e2657167560b357078db73526Jeff Sharkeyusing android::base::ReadFileToString;
459c48498f4529f623650c56d03e63324c8d813032Jeff Sharkeyusing android::base::StringPrintf;
469c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey
47deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkeynamespace android {
48deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkeynamespace vold {
49deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey
5095c87cce353ca2da79aa57a3a5336b45b6f1d018Jeff Sharkeysecurity_context_t sBlkidContext = nullptr;
5195c87cce353ca2da79aa57a3a5336b45b6f1d018Jeff Sharkeysecurity_context_t sBlkidUntrustedContext = nullptr;
5295c87cce353ca2da79aa57a3a5336b45b6f1d018Jeff Sharkeysecurity_context_t sFsckContext = nullptr;
5395c87cce353ca2da79aa57a3a5336b45b6f1d018Jeff Sharkeysecurity_context_t sFsckUntrustedContext = nullptr;
5495c87cce353ca2da79aa57a3a5336b45b6f1d018Jeff Sharkey
559c48498f4529f623650c56d03e63324c8d813032Jeff Sharkeystatic const char* kBlkidPath = "/system/bin/blkid";
56bc40cc8f07f69e0e26fc41516e2a83f0a8becbe0Jeff Sharkeystatic const char* kKeyPath = "/data/misc/vold";
579c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey
58d0640f6358041f7e2657167560b357078db73526Jeff Sharkeystatic const char* kProcFilesystems = "/proc/filesystems";
59d0640f6358041f7e2657167560b357078db73526Jeff Sharkey
60deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkeystatus_t CreateDeviceNode(const std::string& path, dev_t dev) {
61deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey    const char* cpath = path.c_str();
62deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey    status_t res = 0;
63deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey
64deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey    char* secontext = nullptr;
65deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey    if (sehandle) {
66deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey        if (!selabel_lookup(sehandle, &secontext, cpath, S_IFBLK)) {
67deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey            setfscreatecon(secontext);
68deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey        }
69deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey    }
70deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey
71deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey    mode_t mode = 0660 | S_IFBLK;
72deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey    if (mknod(cpath, mode, dev) < 0) {
73deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey        if (errno != EEXIST) {
7436801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey            PLOG(ERROR) << "Failed to create device node for " << major(dev)
7536801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey                    << ":" << minor(dev) << " at " << path;
76deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey            res = -errno;
77deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey        }
78deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey    }
79deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey
80deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey    if (secontext) {
81deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey        setfscreatecon(nullptr);
82deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey        freecon(secontext);
83deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey    }
84deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey
85deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey    return res;
86deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey}
87deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey
88deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkeystatus_t DestroyDeviceNode(const std::string& path) {
89deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey    const char* cpath = path.c_str();
90deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey    if (TEMP_FAILURE_RETRY(unlink(cpath))) {
91deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey        return -errno;
92deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey    } else {
93deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey        return OK;
94deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey    }
95deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey}
96deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey
97f0121c574ede0898e36eeba0a0e0affd0f8d81a7Jeff Sharkeystatus_t PrepareDir(const std::string& path, mode_t mode, uid_t uid, gid_t gid) {
98f0121c574ede0898e36eeba0a0e0affd0f8d81a7Jeff Sharkey    const char* cpath = path.c_str();
99f0121c574ede0898e36eeba0a0e0affd0f8d81a7Jeff Sharkey
100f0121c574ede0898e36eeba0a0e0affd0f8d81a7Jeff Sharkey    char* secontext = nullptr;
101f0121c574ede0898e36eeba0a0e0affd0f8d81a7Jeff Sharkey    if (sehandle) {
102f0121c574ede0898e36eeba0a0e0affd0f8d81a7Jeff Sharkey        if (!selabel_lookup(sehandle, &secontext, cpath, S_IFDIR)) {
103f0121c574ede0898e36eeba0a0e0affd0f8d81a7Jeff Sharkey            setfscreatecon(secontext);
104f0121c574ede0898e36eeba0a0e0affd0f8d81a7Jeff Sharkey        }
105f0121c574ede0898e36eeba0a0e0affd0f8d81a7Jeff Sharkey    }
106f0121c574ede0898e36eeba0a0e0affd0f8d81a7Jeff Sharkey
107f0121c574ede0898e36eeba0a0e0affd0f8d81a7Jeff Sharkey    int res = fs_prepare_dir(cpath, mode, uid, gid);
108f0121c574ede0898e36eeba0a0e0affd0f8d81a7Jeff Sharkey
109f0121c574ede0898e36eeba0a0e0affd0f8d81a7Jeff Sharkey    if (secontext) {
110f0121c574ede0898e36eeba0a0e0affd0f8d81a7Jeff Sharkey        setfscreatecon(nullptr);
111f0121c574ede0898e36eeba0a0e0affd0f8d81a7Jeff Sharkey        freecon(secontext);
112f0121c574ede0898e36eeba0a0e0affd0f8d81a7Jeff Sharkey    }
113f0121c574ede0898e36eeba0a0e0affd0f8d81a7Jeff Sharkey
114f0121c574ede0898e36eeba0a0e0affd0f8d81a7Jeff Sharkey    if (res == 0) {
115f0121c574ede0898e36eeba0a0e0affd0f8d81a7Jeff Sharkey        return OK;
116f0121c574ede0898e36eeba0a0e0affd0f8d81a7Jeff Sharkey    } else {
117f0121c574ede0898e36eeba0a0e0affd0f8d81a7Jeff Sharkey        return -errno;
118f0121c574ede0898e36eeba0a0e0affd0f8d81a7Jeff Sharkey    }
119f0121c574ede0898e36eeba0a0e0affd0f8d81a7Jeff Sharkey}
120f0121c574ede0898e36eeba0a0e0affd0f8d81a7Jeff Sharkey
121deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkeystatus_t ForceUnmount(const std::string& path) {
122deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey    const char* cpath = path.c_str();
123deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey    if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) {
124deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey        return OK;
125deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey    }
12689f74fbf2529d708534c041d2b711af0f1feff9fJeff Sharkey    // Apps might still be handling eject request, so wait before
12789f74fbf2529d708534c041d2b711af0f1feff9fJeff Sharkey    // we start sending signals
1289c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    sleep(5);
129ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey
13089f74fbf2529d708534c041d2b711af0f1feff9fJeff Sharkey    Process::killProcessesWithOpenFiles(cpath, SIGINT);
13189f74fbf2529d708534c041d2b711af0f1feff9fJeff Sharkey    sleep(5);
132ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey    if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) {
133ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey        return OK;
134ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey    }
135ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey
136f0121c574ede0898e36eeba0a0e0affd0f8d81a7Jeff Sharkey    Process::killProcessesWithOpenFiles(cpath, SIGTERM);
13789f74fbf2529d708534c041d2b711af0f1feff9fJeff Sharkey    sleep(5);
138deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey    if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) {
139deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey        return OK;
140deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey    }
141f0121c574ede0898e36eeba0a0e0affd0f8d81a7Jeff Sharkey
142f0121c574ede0898e36eeba0a0e0affd0f8d81a7Jeff Sharkey    Process::killProcessesWithOpenFiles(cpath, SIGKILL);
14389f74fbf2529d708534c041d2b711af0f1feff9fJeff Sharkey    sleep(5);
144deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey    if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) {
145deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey        return OK;
146deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey    }
147f0121c574ede0898e36eeba0a0e0affd0f8d81a7Jeff Sharkey
148deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey    return -errno;
149deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey}
150deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey
15189f74fbf2529d708534c041d2b711af0f1feff9fJeff Sharkeystatus_t KillProcessesUsingPath(const std::string& path) {
15289f74fbf2529d708534c041d2b711af0f1feff9fJeff Sharkey    const char* cpath = path.c_str();
15389f74fbf2529d708534c041d2b711af0f1feff9fJeff Sharkey    if (Process::killProcessesWithOpenFiles(cpath, SIGINT) == 0) {
15489f74fbf2529d708534c041d2b711af0f1feff9fJeff Sharkey        return OK;
15589f74fbf2529d708534c041d2b711af0f1feff9fJeff Sharkey    }
15689f74fbf2529d708534c041d2b711af0f1feff9fJeff Sharkey    sleep(5);
15789f74fbf2529d708534c041d2b711af0f1feff9fJeff Sharkey
15889f74fbf2529d708534c041d2b711af0f1feff9fJeff Sharkey    if (Process::killProcessesWithOpenFiles(cpath, SIGTERM) == 0) {
15989f74fbf2529d708534c041d2b711af0f1feff9fJeff Sharkey        return OK;
16089f74fbf2529d708534c041d2b711af0f1feff9fJeff Sharkey    }
16189f74fbf2529d708534c041d2b711af0f1feff9fJeff Sharkey    sleep(5);
16289f74fbf2529d708534c041d2b711af0f1feff9fJeff Sharkey
16389f74fbf2529d708534c041d2b711af0f1feff9fJeff Sharkey    if (Process::killProcessesWithOpenFiles(cpath, SIGKILL) == 0) {
16489f74fbf2529d708534c041d2b711af0f1feff9fJeff Sharkey        return OK;
16589f74fbf2529d708534c041d2b711af0f1feff9fJeff Sharkey    }
16689f74fbf2529d708534c041d2b711af0f1feff9fJeff Sharkey    sleep(5);
16789f74fbf2529d708534c041d2b711af0f1feff9fJeff Sharkey
16889f74fbf2529d708534c041d2b711af0f1feff9fJeff Sharkey    // Send SIGKILL a second time to determine if we've
16989f74fbf2529d708534c041d2b711af0f1feff9fJeff Sharkey    // actually killed everyone with open files
17089f74fbf2529d708534c041d2b711af0f1feff9fJeff Sharkey    if (Process::killProcessesWithOpenFiles(cpath, SIGKILL) == 0) {
17189f74fbf2529d708534c041d2b711af0f1feff9fJeff Sharkey        return OK;
17289f74fbf2529d708534c041d2b711af0f1feff9fJeff Sharkey    }
17389f74fbf2529d708534c041d2b711af0f1feff9fJeff Sharkey    PLOG(ERROR) << "Failed to kill processes using " << path;
17489f74fbf2529d708534c041d2b711af0f1feff9fJeff Sharkey    return -EBUSY;
17589f74fbf2529d708534c041d2b711af0f1feff9fJeff Sharkey}
17689f74fbf2529d708534c041d2b711af0f1feff9fJeff Sharkey
17736801cccf27152c9eca5aab6ba3527221525110fJeff Sharkeystatus_t BindMount(const std::string& source, const std::string& target) {
17836801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    if (::mount(source.c_str(), target.c_str(), "", MS_BIND, NULL)) {
17936801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        PLOG(ERROR) << "Failed to bind mount " << source << " to " << target;
18036801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey        return -errno;
18136801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    }
18236801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey    return OK;
18336801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey}
18436801cccf27152c9eca5aab6ba3527221525110fJeff Sharkey
18595c87cce353ca2da79aa57a3a5336b45b6f1d018Jeff Sharkeystatic status_t readMetadata(const std::string& path, std::string& fsType,
18695c87cce353ca2da79aa57a3a5336b45b6f1d018Jeff Sharkey        std::string& fsUuid, std::string& fsLabel, bool untrusted) {
1879c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    fsType.clear();
1889c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    fsUuid.clear();
1899c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    fsLabel.clear();
1909c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey
191ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey    std::vector<std::string> cmd;
192ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey    cmd.push_back(kBlkidPath);
193ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey    cmd.push_back("-c");
194ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey    cmd.push_back("/dev/null");
195eddf9bd63c1f7e0f9709f7c58a1035fa43338325Jeff Sharkey    cmd.push_back("-s");
196eddf9bd63c1f7e0f9709f7c58a1035fa43338325Jeff Sharkey    cmd.push_back("TYPE");
197eddf9bd63c1f7e0f9709f7c58a1035fa43338325Jeff Sharkey    cmd.push_back("-s");
198eddf9bd63c1f7e0f9709f7c58a1035fa43338325Jeff Sharkey    cmd.push_back("UUID");
199eddf9bd63c1f7e0f9709f7c58a1035fa43338325Jeff Sharkey    cmd.push_back("-s");
200eddf9bd63c1f7e0f9709f7c58a1035fa43338325Jeff Sharkey    cmd.push_back("LABEL");
201ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey    cmd.push_back(path);
202ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey
203ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey    std::vector<std::string> output;
204ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey    status_t res = ForkExecvp(cmd, output, untrusted ? sBlkidUntrustedContext : sBlkidContext);
205ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey    if (res != OK) {
206ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey        LOG(WARNING) << "blkid failed to identify " << path;
207ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey        return res;
2089c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    }
2099c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey
2109c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    char value[128];
21111a2ce8da33e0ec4be250fd85c47f706d6c91a10Chih-Hung Hsieh    for (const auto& line : output) {
2129c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        // Extract values from blkid output, if defined
213ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey        const char* cline = line.c_str();
21449ab5f9e6db637ad76ef75f5397f9cc919ada21dDan Austin        const char* start = strstr(cline, "TYPE=");
2159c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        if (start != nullptr && sscanf(start + 5, "\"%127[^\"]\"", value) == 1) {
2169c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey            fsType = value;
2179c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        }
2189c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey
219ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey        start = strstr(cline, "UUID=");
2209c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        if (start != nullptr && sscanf(start + 5, "\"%127[^\"]\"", value) == 1) {
2219c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey            fsUuid = value;
2229c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        }
2239c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey
224ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey        start = strstr(cline, "LABEL=");
2259c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        if (start != nullptr && sscanf(start + 6, "\"%127[^\"]\"", value) == 1) {
2269c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey            fsLabel = value;
2279c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        }
2289c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    }
2299c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey
230ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey    return OK;
2319c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey}
2329c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey
23395c87cce353ca2da79aa57a3a5336b45b6f1d018Jeff Sharkeystatus_t ReadMetadata(const std::string& path, std::string& fsType,
23495c87cce353ca2da79aa57a3a5336b45b6f1d018Jeff Sharkey        std::string& fsUuid, std::string& fsLabel) {
23595c87cce353ca2da79aa57a3a5336b45b6f1d018Jeff Sharkey    return readMetadata(path, fsType, fsUuid, fsLabel, false);
23695c87cce353ca2da79aa57a3a5336b45b6f1d018Jeff Sharkey}
23795c87cce353ca2da79aa57a3a5336b45b6f1d018Jeff Sharkey
23895c87cce353ca2da79aa57a3a5336b45b6f1d018Jeff Sharkeystatus_t ReadMetadataUntrusted(const std::string& path, std::string& fsType,
23995c87cce353ca2da79aa57a3a5336b45b6f1d018Jeff Sharkey        std::string& fsUuid, std::string& fsLabel) {
24095c87cce353ca2da79aa57a3a5336b45b6f1d018Jeff Sharkey    return readMetadata(path, fsType, fsUuid, fsLabel, true);
24195c87cce353ca2da79aa57a3a5336b45b6f1d018Jeff Sharkey}
24295c87cce353ca2da79aa57a3a5336b45b6f1d018Jeff Sharkey
243ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkeystatus_t ForkExecvp(const std::vector<std::string>& args) {
244ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey    return ForkExecvp(args, nullptr);
245ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey}
246ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey
247ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkeystatus_t ForkExecvp(const std::vector<std::string>& args, security_context_t context) {
248ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey    size_t argc = args.size();
2499c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    char** argv = (char**) calloc(argc, sizeof(char*));
250ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey    for (size_t i = 0; i < argc; i++) {
2519c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        argv[i] = (char*) args[i].c_str();
2529c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        if (i == 0) {
2539c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey            LOG(VERBOSE) << args[i];
2549c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        } else {
2559c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey            LOG(VERBOSE) << "    " << args[i];
2569c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        }
2579c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    }
258ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey
2591d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    if (setexeccon(context)) {
2601d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        LOG(ERROR) << "Failed to setexeccon";
2611d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        abort();
2621d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    }
2631d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    status_t res = android_fork_execvp(argc, argv, NULL, false, true);
2641d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    if (setexeccon(nullptr)) {
2651d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        LOG(ERROR) << "Failed to setexeccon";
2661d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        abort();
267ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey    }
2681d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
2699c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    free(argv);
2709c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    return res;
2719c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey}
2729c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey
273ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkeystatus_t ForkExecvp(const std::vector<std::string>& args,
274ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey        std::vector<std::string>& output) {
275ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey    return ForkExecvp(args, output, nullptr);
276ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey}
277ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey
278ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkeystatus_t ForkExecvp(const std::vector<std::string>& args,
279ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey        std::vector<std::string>& output, security_context_t context) {
280ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey    std::string cmd;
281ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey    for (size_t i = 0; i < args.size(); i++) {
282ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey        cmd += args[i] + " ";
283ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey        if (i == 0) {
284ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey            LOG(VERBOSE) << args[i];
285ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey        } else {
286ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey            LOG(VERBOSE) << "    " << args[i];
287ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey        }
288ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey    }
289ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey    output.clear();
290ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey
2911d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    if (setexeccon(context)) {
2921d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        LOG(ERROR) << "Failed to setexeccon";
2931d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        abort();
2941d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    }
2951d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    FILE* fp = popen(cmd.c_str(), "r");
2961d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    if (setexeccon(nullptr)) {
2971d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        LOG(ERROR) << "Failed to setexeccon";
2981d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        abort();
299ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey    }
300ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey
301ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey    if (!fp) {
302ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey        PLOG(ERROR) << "Failed to popen " << cmd;
303ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey        return -errno;
304ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey    }
305ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey    char line[1024];
306ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey    while (fgets(line, sizeof(line), fp) != nullptr) {
307ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey        LOG(VERBOSE) << line;
308ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey        output.push_back(std::string(line));
309ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey    }
310ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey    if (pclose(fp) != 0) {
311ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey        PLOG(ERROR) << "Failed to pclose " << cmd;
312ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey        return -errno;
313ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey    }
314ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey
315ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey    return OK;
316ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey}
317ce6a913aeac7db94a41362c63bab74092767bb3eJeff Sharkey
3181d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkeypid_t ForkExecvpAsync(const std::vector<std::string>& args) {
3191d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    size_t argc = args.size();
3201d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    char** argv = (char**) calloc(argc + 1, sizeof(char*));
3211d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    for (size_t i = 0; i < argc; i++) {
3221d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        argv[i] = (char*) args[i].c_str();
3231d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        if (i == 0) {
3241d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey            LOG(VERBOSE) << args[i];
3251d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        } else {
3261d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey            LOG(VERBOSE) << "    " << args[i];
3271d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        }
3281d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    }
3291d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
3301d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    pid_t pid = fork();
3311d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    if (pid == 0) {
3321d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        close(STDIN_FILENO);
3331d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        close(STDOUT_FILENO);
3341d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        close(STDERR_FILENO);
3351d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
3361d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        if (execvp(argv[0], argv)) {
3371d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey            PLOG(ERROR) << "Failed to exec";
3381d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        }
3391d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
3401d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        _exit(1);
3411d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    }
3421d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
3431d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    if (pid == -1) {
3441d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        PLOG(ERROR) << "Failed to exec";
3451d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    }
3461d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
3471d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    free(argv);
3481d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    return pid;
3491d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey}
3501d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
3519c48498f4529f623650c56d03e63324c8d813032Jeff Sharkeystatus_t ReadRandomBytes(size_t bytes, std::string& out) {
3529c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    out.clear();
3539c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey
3549c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    int fd = TEMP_FAILURE_RETRY(open("/dev/urandom", O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
3559c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    if (fd == -1) {
3569c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        return -errno;
3579c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    }
3589c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey
3599c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    char buf[BUFSIZ];
3609c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    size_t n;
3619c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    while ((n = TEMP_FAILURE_RETRY(read(fd, &buf[0], std::min(sizeof(buf), bytes)))) > 0) {
3629c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        out.append(buf, n);
3639c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        bytes -= n;
3649c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    }
365a623108ef40143e04e3e765a057981a439ff3cd2Elliott Hughes    close(fd);
3669c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey
3679c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    if (bytes == 0) {
3689c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        return OK;
3699c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    } else {
3709c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        return -EIO;
3719c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    }
3729c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey}
3739c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey
3749c48498f4529f623650c56d03e63324c8d813032Jeff Sharkeystatus_t HexToStr(const std::string& hex, std::string& str) {
3759c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    str.clear();
3769c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    bool even = true;
3779c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    char cur = 0;
3789c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    for (size_t i = 0; i < hex.size(); i++) {
3799c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        int val = 0;
3809c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        switch (hex[i]) {
3819c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        case ' ': case '-': case ':': continue;
3829c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        case 'f': case 'F': val = 15; break;
3839c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        case 'e': case 'E': val = 14; break;
3849c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        case 'd': case 'D': val = 13; break;
3859c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        case 'c': case 'C': val = 12; break;
3869c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        case 'b': case 'B': val = 11; break;
3879c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        case 'a': case 'A': val = 10; break;
3889c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        case '9': val = 9; break;
3899c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        case '8': val = 8; break;
3909c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        case '7': val = 7; break;
3919c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        case '6': val = 6; break;
3929c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        case '5': val = 5; break;
3939c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        case '4': val = 4; break;
3949c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        case '3': val = 3; break;
3959c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        case '2': val = 2; break;
3969c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        case '1': val = 1; break;
3979c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        case '0': val = 0; break;
3989c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        default: return -EINVAL;
3999c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        }
4009c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey
4019c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        if (even) {
4029c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey            cur = val << 4;
4039c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        } else {
4049c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey            cur += val;
4059c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey            str.push_back(cur);
4069c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey            cur = 0;
4079c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        }
4089c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        even = !even;
4099c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    }
4109c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    return even ? OK : -EINVAL;
4119c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey}
4129c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey
4139c48498f4529f623650c56d03e63324c8d813032Jeff Sharkeystatic const char* kLookup = "0123456789abcdef";
4149c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey
4159c48498f4529f623650c56d03e63324c8d813032Jeff Sharkeystatus_t StrToHex(const std::string& str, std::string& hex) {
4169c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    hex.clear();
4179c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    for (size_t i = 0; i < str.size(); i++) {
418ef3697545bc7fadec43001fa3c8376426510b9eaJeff Sharkey        hex.push_back(kLookup[(str[i] & 0xF0) >> 4]);
4199c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey        hex.push_back(kLookup[str[i] & 0x0F]);
4209c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    }
4219c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey    return OK;
4229c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey}
4239c48498f4529f623650c56d03e63324c8d813032Jeff Sharkey
424bc40cc8f07f69e0e26fc41516e2a83f0a8becbe0Jeff Sharkeystatus_t NormalizeHex(const std::string& in, std::string& out) {
425bc40cc8f07f69e0e26fc41516e2a83f0a8becbe0Jeff Sharkey    std::string tmp;
426bc40cc8f07f69e0e26fc41516e2a83f0a8becbe0Jeff Sharkey    if (HexToStr(in, tmp)) {
427bc40cc8f07f69e0e26fc41516e2a83f0a8becbe0Jeff Sharkey        return -EINVAL;
428bc40cc8f07f69e0e26fc41516e2a83f0a8becbe0Jeff Sharkey    }
429bc40cc8f07f69e0e26fc41516e2a83f0a8becbe0Jeff Sharkey    return StrToHex(tmp, out);
430bc40cc8f07f69e0e26fc41516e2a83f0a8becbe0Jeff Sharkey}
431bc40cc8f07f69e0e26fc41516e2a83f0a8becbe0Jeff Sharkey
4321d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkeyuint64_t GetFreeBytes(const std::string& path) {
4331d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    struct statvfs sb;
4341d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    if (statvfs(path.c_str(), &sb) == 0) {
435a0220a5bd410d4b342ee1ca84e8381d6bc5f468eJeff Sharkey        return (uint64_t) sb.f_bavail * sb.f_frsize;
4361d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    } else {
4371d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        return -1;
4381d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    }
4391d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey}
4401d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
4411d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey// TODO: borrowed from frameworks/native/libs/diskusage/ which should
4421d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey// eventually be migrated into system/
4431d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkeystatic int64_t stat_size(struct stat *s) {
4441d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    int64_t blksize = s->st_blksize;
4451d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    // count actual blocks used instead of nominal file size
4461d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    int64_t size = s->st_blocks * 512;
4471d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
4481d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    if (blksize) {
4491d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        /* round up to filesystem block size */
4501d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        size = (size + blksize - 1) & (~(blksize - 1));
4511d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    }
4521d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
4531d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    return size;
4541d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey}
4551d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
4561d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey// TODO: borrowed from frameworks/native/libs/diskusage/ which should
4571d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey// eventually be migrated into system/
4581d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkeyint64_t calculate_dir_size(int dfd) {
4591d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    int64_t size = 0;
4601d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    struct stat s;
4611d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    DIR *d;
4621d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    struct dirent *de;
4631d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
4641d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    d = fdopendir(dfd);
4651d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    if (d == NULL) {
4661d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        close(dfd);
4671d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        return 0;
4681d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    }
4691d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
4701d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    while ((de = readdir(d))) {
4711d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        const char *name = de->d_name;
4721d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
4731d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey            size += stat_size(&s);
4741d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        }
4751d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        if (de->d_type == DT_DIR) {
4761d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey            int subfd;
4771d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
4781d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey            /* always skip "." and ".." */
4791d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey            if (name[0] == '.') {
4801d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey                if (name[1] == 0)
4811d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey                    continue;
4821d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey                if ((name[1] == '.') && (name[2] == 0))
4831d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey                    continue;
4841d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey            }
4851d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
486fd3dc3c076f30e19e7ac902ba0531c6bcfe2e042Jeff Sharkey            subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY | O_CLOEXEC);
4871d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey            if (subfd >= 0) {
4881d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey                size += calculate_dir_size(subfd);
4891d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey            }
4901d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        }
4911d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    }
4921d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    closedir(d);
4931d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    return size;
4941d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey}
4951d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
4961d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkeyuint64_t GetTreeBytes(const std::string& path) {
497fd3dc3c076f30e19e7ac902ba0531c6bcfe2e042Jeff Sharkey    int dirfd = open(path.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC);
4981d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    if (dirfd < 0) {
4991d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        PLOG(WARNING) << "Failed to open " << path;
5001d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        return -1;
5011d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    } else {
5021d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        uint64_t res = calculate_dir_size(dirfd);
5031d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        close(dirfd);
5041d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey        return res;
5051d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey    }
5061d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey}
5071d6fbcc389ecb9f418076e8ab5f4c93a5d911de9Jeff Sharkey
508d0640f6358041f7e2657167560b357078db73526Jeff Sharkeybool IsFilesystemSupported(const std::string& fsType) {
509d0640f6358041f7e2657167560b357078db73526Jeff Sharkey    std::string supported;
510d0640f6358041f7e2657167560b357078db73526Jeff Sharkey    if (!ReadFileToString(kProcFilesystems, &supported)) {
511d0640f6358041f7e2657167560b357078db73526Jeff Sharkey        PLOG(ERROR) << "Failed to read supported filesystems";
512d0640f6358041f7e2657167560b357078db73526Jeff Sharkey        return false;
513d0640f6358041f7e2657167560b357078db73526Jeff Sharkey    }
514d0640f6358041f7e2657167560b357078db73526Jeff Sharkey    return supported.find(fsType + "\n") != std::string::npos;
515d0640f6358041f7e2657167560b357078db73526Jeff Sharkey}
516d0640f6358041f7e2657167560b357078db73526Jeff Sharkey
517d0640f6358041f7e2657167560b357078db73526Jeff Sharkeystatus_t WipeBlockDevice(const std::string& path) {
518d0640f6358041f7e2657167560b357078db73526Jeff Sharkey    status_t res = -1;
519d0640f6358041f7e2657167560b357078db73526Jeff Sharkey    const char* c_path = path.c_str();
520d0640f6358041f7e2657167560b357078db73526Jeff Sharkey    unsigned long nr_sec = 0;
521d0640f6358041f7e2657167560b357078db73526Jeff Sharkey    unsigned long long range[2];
522d0640f6358041f7e2657167560b357078db73526Jeff Sharkey
523d0640f6358041f7e2657167560b357078db73526Jeff Sharkey    int fd = TEMP_FAILURE_RETRY(open(c_path, O_RDWR | O_CLOEXEC));
524d0640f6358041f7e2657167560b357078db73526Jeff Sharkey    if (fd == -1) {
525d0640f6358041f7e2657167560b357078db73526Jeff Sharkey        PLOG(ERROR) << "Failed to open " << path;
526d0640f6358041f7e2657167560b357078db73526Jeff Sharkey        goto done;
527d0640f6358041f7e2657167560b357078db73526Jeff Sharkey    }
528d0640f6358041f7e2657167560b357078db73526Jeff Sharkey
5299102b0b1757cea7abe1217efda6943d23292fed8caozhiyuan    if ((ioctl(fd, BLKGETSIZE, &nr_sec)) == -1) {
530d0640f6358041f7e2657167560b357078db73526Jeff Sharkey        PLOG(ERROR) << "Failed to determine size of " << path;
531d0640f6358041f7e2657167560b357078db73526Jeff Sharkey        goto done;
532d0640f6358041f7e2657167560b357078db73526Jeff Sharkey    }
533d0640f6358041f7e2657167560b357078db73526Jeff Sharkey
534d0640f6358041f7e2657167560b357078db73526Jeff Sharkey    range[0] = 0;
535d0640f6358041f7e2657167560b357078db73526Jeff Sharkey    range[1] = (unsigned long long) nr_sec * 512;
536d0640f6358041f7e2657167560b357078db73526Jeff Sharkey
537d0640f6358041f7e2657167560b357078db73526Jeff Sharkey    LOG(INFO) << "About to discard " << range[1] << " on " << path;
538d0640f6358041f7e2657167560b357078db73526Jeff Sharkey    if (ioctl(fd, BLKDISCARD, &range) == 0) {
539d0640f6358041f7e2657167560b357078db73526Jeff Sharkey        LOG(INFO) << "Discard success on " << path;
540d0640f6358041f7e2657167560b357078db73526Jeff Sharkey        res = 0;
541d0640f6358041f7e2657167560b357078db73526Jeff Sharkey    } else {
542d0640f6358041f7e2657167560b357078db73526Jeff Sharkey        PLOG(ERROR) << "Discard failure on " << path;
543d0640f6358041f7e2657167560b357078db73526Jeff Sharkey    }
544d0640f6358041f7e2657167560b357078db73526Jeff Sharkey
545d0640f6358041f7e2657167560b357078db73526Jeff Sharkeydone:
546d0640f6358041f7e2657167560b357078db73526Jeff Sharkey    close(fd);
547d0640f6358041f7e2657167560b357078db73526Jeff Sharkey    return res;
548d0640f6358041f7e2657167560b357078db73526Jeff Sharkey}
549d0640f6358041f7e2657167560b357078db73526Jeff Sharkey
550d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkeystatic bool isValidFilename(const std::string& name) {
551d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey    if (name.empty() || (name == ".") || (name == "..")
552d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey            || (name.find('/') != std::string::npos)) {
553d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey        return false;
554d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey    } else {
555d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey        return true;
556d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey    }
557d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey}
558d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey
559bc40cc8f07f69e0e26fc41516e2a83f0a8becbe0Jeff Sharkeystd::string BuildKeyPath(const std::string& partGuid) {
560bc40cc8f07f69e0e26fc41516e2a83f0a8becbe0Jeff Sharkey    return StringPrintf("%s/expand_%s.key", kKeyPath, partGuid.c_str());
561bc40cc8f07f69e0e26fc41516e2a83f0a8becbe0Jeff Sharkey}
562bc40cc8f07f69e0e26fc41516e2a83f0a8becbe0Jeff Sharkey
563be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkeystd::string BuildDataSystemLegacyPath(userid_t userId) {
564be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey    return StringPrintf("%s/system/users/%u", BuildDataPath(nullptr).c_str(), userId);
565be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey}
566be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey
567d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkeystd::string BuildDataSystemCePath(userid_t userId) {
56847695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey    return StringPrintf("%s/system_ce/%u", BuildDataPath(nullptr).c_str(), userId);
56947695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey}
57047695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey
57147695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkeystd::string BuildDataSystemDePath(userid_t userId) {
57247695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey    return StringPrintf("%s/system_de/%u", BuildDataPath(nullptr).c_str(), userId);
57347695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey}
57447695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey
575be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkeystd::string BuildDataMiscLegacyPath(userid_t userId) {
576be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey    return StringPrintf("%s/misc/user/%u", BuildDataPath(nullptr).c_str(), userId);
577be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey}
578be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkey
57947695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkeystd::string BuildDataMiscCePath(userid_t userId) {
58047695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey    return StringPrintf("%s/misc_ce/%u", BuildDataPath(nullptr).c_str(), userId);
58147695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey}
58247695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey
58347695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkeystd::string BuildDataMiscDePath(userid_t userId) {
58447695b29af0467dd8e18f5534e3b62e39326d7e1Jeff Sharkey    return StringPrintf("%s/misc_de/%u", BuildDataPath(nullptr).c_str(), userId);
585d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey}
586d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey
58779f55a461f1edf90b769824c6a69dcb520614d83Calin Juravle// Keep in sync with installd (frameworks/native/cmds/installd/utils.h)
58879f55a461f1edf90b769824c6a69dcb520614d83Calin Juravlestd::string BuildDataProfilesDePath(userid_t userId) {
58979f55a461f1edf90b769824c6a69dcb520614d83Calin Juravle    return StringPrintf("%s/misc/profiles/cur/%u", BuildDataPath(nullptr).c_str(), userId);
59079f55a461f1edf90b769824c6a69dcb520614d83Calin Juravle}
59179f55a461f1edf90b769824c6a69dcb520614d83Calin Juravle
592d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkeystd::string BuildDataPath(const char* volumeUuid) {
593d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey    // TODO: unify with installd path generation logic
594d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey    if (volumeUuid == nullptr) {
595d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey        return "/data";
596d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey    } else {
597d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey        CHECK(isValidFilename(volumeUuid));
598d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey        return StringPrintf("/mnt/expand/%s", volumeUuid);
599d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey    }
600d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey}
601d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey
602be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkeystd::string BuildDataMediaCePath(const char* volumeUuid, userid_t userId) {
603fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey    // TODO: unify with installd path generation logic
604fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey    std::string data(BuildDataPath(volumeUuid));
605fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey    return StringPrintf("%s/media/%u", data.c_str(), userId);
606fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey}
607fc505c3ff6c1ba3a061e7e8b3f2236be90712a80Jeff Sharkey
608be70c9ae2251ac8f3bfbbe75146f8c533d64e01bJeff Sharkeystd::string BuildDataUserCePath(const char* volumeUuid, userid_t userId) {
609d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey    // TODO: unify with installd path generation logic
610d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey    std::string data(BuildDataPath(volumeUuid));
611d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey    if (volumeUuid == nullptr) {
612d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey        if (userId == 0) {
613d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey            return StringPrintf("%s/data", data.c_str());
614d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey        } else {
615d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey            return StringPrintf("%s/user/%u", data.c_str(), userId);
616d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey        }
617d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey    } else {
618d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey        return StringPrintf("%s/user/%u", data.c_str(), userId);
619d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey    }
620d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey}
621d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey
622d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkeystd::string BuildDataUserDePath(const char* volumeUuid, userid_t userId) {
623d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey    // TODO: unify with installd path generation logic
624d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey    std::string data(BuildDataPath(volumeUuid));
625d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey    return StringPrintf("%s/user_de/%u", data.c_str(), userId);
626d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey}
627d2c96e788381a6c8dd87cbf9ecd7e8a6bc7337c2Jeff Sharkey
62866270a21df1058434e4d63691221f11ff5387a0fJeff Sharkeydev_t GetDevice(const std::string& path) {
62966270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey    struct stat sb;
63066270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey    if (stat(path.c_str(), &sb)) {
63166270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey        PLOG(WARNING) << "Failed to stat " << path;
63266270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey        return 0;
63366270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey    } else {
63466270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey        return sb.st_dev;
63566270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey    }
63666270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey}
63766270a21df1058434e4d63691221f11ff5387a0fJeff Sharkey
638d24aeda425196a7ab0a19c00bc9a4ced6383432bJeff Sharkeystatus_t RestoreconRecursive(const std::string& path) {
639d24aeda425196a7ab0a19c00bc9a4ced6383432bJeff Sharkey    LOG(VERBOSE) << "Starting restorecon of " << path;
640d24aeda425196a7ab0a19c00bc9a4ced6383432bJeff Sharkey
641d24aeda425196a7ab0a19c00bc9a4ced6383432bJeff Sharkey    // TODO: find a cleaner way of waiting for restorecon to finish
642d24aeda425196a7ab0a19c00bc9a4ced6383432bJeff Sharkey    const char* cpath = path.c_str();
643d24aeda425196a7ab0a19c00bc9a4ced6383432bJeff Sharkey    property_set("selinux.restorecon_recursive", "");
644d24aeda425196a7ab0a19c00bc9a4ced6383432bJeff Sharkey    property_set("selinux.restorecon_recursive", cpath);
645d24aeda425196a7ab0a19c00bc9a4ced6383432bJeff Sharkey
646d24aeda425196a7ab0a19c00bc9a4ced6383432bJeff Sharkey    char value[PROPERTY_VALUE_MAX];
647d24aeda425196a7ab0a19c00bc9a4ced6383432bJeff Sharkey    while (true) {
648d24aeda425196a7ab0a19c00bc9a4ced6383432bJeff Sharkey        property_get("selinux.restorecon_recursive", value, "");
649d24aeda425196a7ab0a19c00bc9a4ced6383432bJeff Sharkey        if (strcmp(cpath, value) == 0) {
650d24aeda425196a7ab0a19c00bc9a4ced6383432bJeff Sharkey            break;
651d24aeda425196a7ab0a19c00bc9a4ced6383432bJeff Sharkey        }
652d24aeda425196a7ab0a19c00bc9a4ced6383432bJeff Sharkey        usleep(100000); // 100ms
653d24aeda425196a7ab0a19c00bc9a4ced6383432bJeff Sharkey    }
654d24aeda425196a7ab0a19c00bc9a4ced6383432bJeff Sharkey
655d24aeda425196a7ab0a19c00bc9a4ced6383432bJeff Sharkey    LOG(VERBOSE) << "Finished restorecon of " << path;
656d24aeda425196a7ab0a19c00bc9a4ced6383432bJeff Sharkey    return OK;
657d24aeda425196a7ab0a19c00bc9a4ced6383432bJeff Sharkey}
658d24aeda425196a7ab0a19c00bc9a4ced6383432bJeff Sharkey
65910d34887b3e00e603604e0301487f9b8222c66f4Daichi Hironostatus_t SaneReadLinkAt(int dirfd, const char* path, char* buf, size_t bufsiz) {
66010d34887b3e00e603604e0301487f9b8222c66f4Daichi Hirono    ssize_t len = readlinkat(dirfd, path, buf, bufsiz);
66110d34887b3e00e603604e0301487f9b8222c66f4Daichi Hirono    if (len < 0) {
66210d34887b3e00e603604e0301487f9b8222c66f4Daichi Hirono        return -1;
66310d34887b3e00e603604e0301487f9b8222c66f4Daichi Hirono    } else if (len == (ssize_t) bufsiz) {
66410d34887b3e00e603604e0301487f9b8222c66f4Daichi Hirono        return -1;
66510d34887b3e00e603604e0301487f9b8222c66f4Daichi Hirono    } else {
66610d34887b3e00e603604e0301487f9b8222c66f4Daichi Hirono        buf[len] = '\0';
66710d34887b3e00e603604e0301487f9b8222c66f4Daichi Hirono        return 0;
66810d34887b3e00e603604e0301487f9b8222c66f4Daichi Hirono    }
66910d34887b3e00e603604e0301487f9b8222c66f4Daichi Hirono}
67010d34887b3e00e603604e0301487f9b8222c66f4Daichi Hirono
671942d4e830b2057177fd2d47c51b788edd6e94398Yu Ningbool IsRunningInEmulator() {
672942d4e830b2057177fd2d47c51b788edd6e94398Yu Ning    return property_get_bool("ro.kernel.qemu", 0);
673942d4e830b2057177fd2d47c51b788edd6e94398Yu Ning}
674942d4e830b2057177fd2d47c51b788edd6e94398Yu Ning
675deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey}  // namespace vold
676deb240573754daf36fa8ea10a05240f9f31e7b2cJeff Sharkey}  // namespace android
677