1*00c7fec1SAndroid Build Coastguard Worker // Copyright (C) 2016 The Android Open Source Project
2*00c7fec1SAndroid Build Coastguard Worker //
3*00c7fec1SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*00c7fec1SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*00c7fec1SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*00c7fec1SAndroid Build Coastguard Worker //
7*00c7fec1SAndroid Build Coastguard Worker // http://www.apache.org/licenses/LICENSE-2.0
8*00c7fec1SAndroid Build Coastguard Worker //
9*00c7fec1SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*00c7fec1SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*00c7fec1SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*00c7fec1SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*00c7fec1SAndroid Build Coastguard Worker // limitations under the License.
14*00c7fec1SAndroid Build Coastguard Worker
15*00c7fec1SAndroid Build Coastguard Worker #define LOG_TAG "sdcard"
16*00c7fec1SAndroid Build Coastguard Worker
17*00c7fec1SAndroid Build Coastguard Worker #include <dirent.h>
18*00c7fec1SAndroid Build Coastguard Worker #include <errno.h>
19*00c7fec1SAndroid Build Coastguard Worker #include <fcntl.h>
20*00c7fec1SAndroid Build Coastguard Worker #include <linux/fuse.h>
21*00c7fec1SAndroid Build Coastguard Worker #include <pthread.h>
22*00c7fec1SAndroid Build Coastguard Worker #include <stdlib.h>
23*00c7fec1SAndroid Build Coastguard Worker #include <string.h>
24*00c7fec1SAndroid Build Coastguard Worker #include <sys/inotify.h>
25*00c7fec1SAndroid Build Coastguard Worker #include <sys/mount.h>
26*00c7fec1SAndroid Build Coastguard Worker #include <sys/resource.h>
27*00c7fec1SAndroid Build Coastguard Worker #include <sys/stat.h>
28*00c7fec1SAndroid Build Coastguard Worker #include <sys/types.h>
29*00c7fec1SAndroid Build Coastguard Worker #include <unistd.h>
30*00c7fec1SAndroid Build Coastguard Worker #include <vector>
31*00c7fec1SAndroid Build Coastguard Worker
32*00c7fec1SAndroid Build Coastguard Worker #include <android-base/file.h>
33*00c7fec1SAndroid Build Coastguard Worker #include <android-base/logging.h>
34*00c7fec1SAndroid Build Coastguard Worker #include <android-base/macros.h>
35*00c7fec1SAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
36*00c7fec1SAndroid Build Coastguard Worker #include <android-base/strings.h>
37*00c7fec1SAndroid Build Coastguard Worker
38*00c7fec1SAndroid Build Coastguard Worker #include <cutils/fs.h>
39*00c7fec1SAndroid Build Coastguard Worker #include <cutils/multiuser.h>
40*00c7fec1SAndroid Build Coastguard Worker #include <cutils/properties.h>
41*00c7fec1SAndroid Build Coastguard Worker
42*00c7fec1SAndroid Build Coastguard Worker #include <libminijail.h>
43*00c7fec1SAndroid Build Coastguard Worker #include <scoped_minijail.h>
44*00c7fec1SAndroid Build Coastguard Worker
45*00c7fec1SAndroid Build Coastguard Worker #include <private/android_filesystem_config.h>
46*00c7fec1SAndroid Build Coastguard Worker
47*00c7fec1SAndroid Build Coastguard Worker #define PROP_SDCARDFS_DEVICE "ro.sys.sdcardfs"
48*00c7fec1SAndroid Build Coastguard Worker #define PROP_SDCARDFS_USER "persist.sys.sdcardfs"
49*00c7fec1SAndroid Build Coastguard Worker
supports_esdfs(void)50*00c7fec1SAndroid Build Coastguard Worker static bool supports_esdfs(void) {
51*00c7fec1SAndroid Build Coastguard Worker std::string filesystems;
52*00c7fec1SAndroid Build Coastguard Worker if (!android::base::ReadFileToString("/proc/filesystems", &filesystems)) {
53*00c7fec1SAndroid Build Coastguard Worker PLOG(ERROR) << "Could not read /proc/filesystems";
54*00c7fec1SAndroid Build Coastguard Worker return false;
55*00c7fec1SAndroid Build Coastguard Worker }
56*00c7fec1SAndroid Build Coastguard Worker for (const auto& fs : android::base::Split(filesystems, "\n")) {
57*00c7fec1SAndroid Build Coastguard Worker if (fs.find("esdfs") != std::string::npos) return true;
58*00c7fec1SAndroid Build Coastguard Worker }
59*00c7fec1SAndroid Build Coastguard Worker return false;
60*00c7fec1SAndroid Build Coastguard Worker }
61*00c7fec1SAndroid Build Coastguard Worker
should_use_sdcardfs(void)62*00c7fec1SAndroid Build Coastguard Worker static bool should_use_sdcardfs(void) {
63*00c7fec1SAndroid Build Coastguard Worker char property[PROPERTY_VALUE_MAX];
64*00c7fec1SAndroid Build Coastguard Worker
65*00c7fec1SAndroid Build Coastguard Worker // Allow user to have a strong opinion about state
66*00c7fec1SAndroid Build Coastguard Worker property_get(PROP_SDCARDFS_USER, property, "");
67*00c7fec1SAndroid Build Coastguard Worker if (!strcmp(property, "force_on")) {
68*00c7fec1SAndroid Build Coastguard Worker LOG(WARNING) << "User explicitly enabled sdcardfs";
69*00c7fec1SAndroid Build Coastguard Worker return true;
70*00c7fec1SAndroid Build Coastguard Worker } else if (!strcmp(property, "force_off")) {
71*00c7fec1SAndroid Build Coastguard Worker LOG(WARNING) << "User explicitly disabled sdcardfs";
72*00c7fec1SAndroid Build Coastguard Worker return !supports_esdfs();
73*00c7fec1SAndroid Build Coastguard Worker }
74*00c7fec1SAndroid Build Coastguard Worker
75*00c7fec1SAndroid Build Coastguard Worker // Fall back to device opinion about state
76*00c7fec1SAndroid Build Coastguard Worker if (property_get_bool(PROP_SDCARDFS_DEVICE, true)) {
77*00c7fec1SAndroid Build Coastguard Worker LOG(WARNING) << "Device explicitly enabled sdcardfs";
78*00c7fec1SAndroid Build Coastguard Worker return true;
79*00c7fec1SAndroid Build Coastguard Worker } else {
80*00c7fec1SAndroid Build Coastguard Worker LOG(WARNING) << "Device explicitly disabled sdcardfs";
81*00c7fec1SAndroid Build Coastguard Worker return !supports_esdfs();
82*00c7fec1SAndroid Build Coastguard Worker }
83*00c7fec1SAndroid Build Coastguard Worker }
84*00c7fec1SAndroid Build Coastguard Worker
85*00c7fec1SAndroid Build Coastguard Worker // NOTE: This is a vestigial program that simply exists to mount the in-kernel
86*00c7fec1SAndroid Build Coastguard Worker // sdcardfs filesystem. The older FUSE-based design that used to live here has
87*00c7fec1SAndroid Build Coastguard Worker // been completely removed to avoid confusion.
88*00c7fec1SAndroid Build Coastguard Worker
89*00c7fec1SAndroid Build Coastguard Worker /* Supplementary groups to execute with. */
90*00c7fec1SAndroid Build Coastguard Worker static const gid_t kGroups[1] = { AID_PACKAGE_INFO };
91*00c7fec1SAndroid Build Coastguard Worker
drop_privs(uid_t uid,gid_t gid)92*00c7fec1SAndroid Build Coastguard Worker static void drop_privs(uid_t uid, gid_t gid) {
93*00c7fec1SAndroid Build Coastguard Worker ScopedMinijail j(minijail_new());
94*00c7fec1SAndroid Build Coastguard Worker minijail_set_supplementary_gids(j.get(), arraysize(kGroups), kGroups);
95*00c7fec1SAndroid Build Coastguard Worker minijail_change_gid(j.get(), gid);
96*00c7fec1SAndroid Build Coastguard Worker minijail_change_uid(j.get(), uid);
97*00c7fec1SAndroid Build Coastguard Worker /* minijail_enter() will abort if priv-dropping fails. */
98*00c7fec1SAndroid Build Coastguard Worker minijail_enter(j.get());
99*00c7fec1SAndroid Build Coastguard Worker }
100*00c7fec1SAndroid Build Coastguard Worker
sdcardfs_setup(const std::string & source_path,const std::string & dest_path,uid_t fsuid,gid_t fsgid,bool multi_user,userid_t userid,gid_t gid,mode_t mask,bool derive_gid,bool default_normal,bool unshared_obb,bool use_esdfs)101*00c7fec1SAndroid Build Coastguard Worker static bool sdcardfs_setup(const std::string& source_path, const std::string& dest_path,
102*00c7fec1SAndroid Build Coastguard Worker uid_t fsuid, gid_t fsgid, bool multi_user, userid_t userid, gid_t gid,
103*00c7fec1SAndroid Build Coastguard Worker mode_t mask, bool derive_gid, bool default_normal, bool unshared_obb,
104*00c7fec1SAndroid Build Coastguard Worker bool use_esdfs) {
105*00c7fec1SAndroid Build Coastguard Worker // Add new options at the end of the vector.
106*00c7fec1SAndroid Build Coastguard Worker std::vector<std::string> new_opts_list;
107*00c7fec1SAndroid Build Coastguard Worker if (multi_user) new_opts_list.push_back("multiuser,");
108*00c7fec1SAndroid Build Coastguard Worker if (derive_gid) new_opts_list.push_back("derive_gid,");
109*00c7fec1SAndroid Build Coastguard Worker if (default_normal) new_opts_list.push_back("default_normal,");
110*00c7fec1SAndroid Build Coastguard Worker if (unshared_obb) new_opts_list.push_back("unshared_obb,");
111*00c7fec1SAndroid Build Coastguard Worker // Try several attempts, each time with one less option, to gracefully
112*00c7fec1SAndroid Build Coastguard Worker // handle older kernels that aren't updated yet.
113*00c7fec1SAndroid Build Coastguard Worker for (int i = 0; i <= new_opts_list.size(); ++i) {
114*00c7fec1SAndroid Build Coastguard Worker std::string new_opts;
115*00c7fec1SAndroid Build Coastguard Worker for (int j = 0; j < new_opts_list.size() - i; ++j) {
116*00c7fec1SAndroid Build Coastguard Worker new_opts += new_opts_list[j];
117*00c7fec1SAndroid Build Coastguard Worker }
118*00c7fec1SAndroid Build Coastguard Worker
119*00c7fec1SAndroid Build Coastguard Worker auto opts = android::base::StringPrintf("fsuid=%d,fsgid=%d,%smask=%d,userid=%d,gid=%d",
120*00c7fec1SAndroid Build Coastguard Worker fsuid, fsgid, new_opts.c_str(), mask, userid, gid);
121*00c7fec1SAndroid Build Coastguard Worker if (mount(source_path.c_str(), dest_path.c_str(), use_esdfs ? "esdfs" : "sdcardfs",
122*00c7fec1SAndroid Build Coastguard Worker MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_NOATIME, opts.c_str()) == -1) {
123*00c7fec1SAndroid Build Coastguard Worker PLOG(WARNING) << "Failed to mount sdcardfs with options " << opts;
124*00c7fec1SAndroid Build Coastguard Worker } else {
125*00c7fec1SAndroid Build Coastguard Worker return true;
126*00c7fec1SAndroid Build Coastguard Worker }
127*00c7fec1SAndroid Build Coastguard Worker }
128*00c7fec1SAndroid Build Coastguard Worker
129*00c7fec1SAndroid Build Coastguard Worker return false;
130*00c7fec1SAndroid Build Coastguard Worker }
131*00c7fec1SAndroid Build Coastguard Worker
sdcardfs_setup_bind_remount(const std::string & source_path,const std::string & dest_path,gid_t gid,mode_t mask)132*00c7fec1SAndroid Build Coastguard Worker static bool sdcardfs_setup_bind_remount(const std::string& source_path, const std::string& dest_path,
133*00c7fec1SAndroid Build Coastguard Worker gid_t gid, mode_t mask) {
134*00c7fec1SAndroid Build Coastguard Worker std::string opts = android::base::StringPrintf("mask=%d,gid=%d", mask, gid);
135*00c7fec1SAndroid Build Coastguard Worker
136*00c7fec1SAndroid Build Coastguard Worker if (mount(source_path.c_str(), dest_path.c_str(), nullptr,
137*00c7fec1SAndroid Build Coastguard Worker MS_BIND, nullptr) != 0) {
138*00c7fec1SAndroid Build Coastguard Worker PLOG(ERROR) << "failed to bind mount sdcardfs filesystem";
139*00c7fec1SAndroid Build Coastguard Worker return false;
140*00c7fec1SAndroid Build Coastguard Worker }
141*00c7fec1SAndroid Build Coastguard Worker
142*00c7fec1SAndroid Build Coastguard Worker if (mount(source_path.c_str(), dest_path.c_str(), "none",
143*00c7fec1SAndroid Build Coastguard Worker MS_REMOUNT | MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_NOATIME, opts.c_str()) != 0) {
144*00c7fec1SAndroid Build Coastguard Worker PLOG(ERROR) << "failed to mount sdcardfs filesystem";
145*00c7fec1SAndroid Build Coastguard Worker if (umount2(dest_path.c_str(), MNT_DETACH))
146*00c7fec1SAndroid Build Coastguard Worker PLOG(WARNING) << "Failed to unmount bind";
147*00c7fec1SAndroid Build Coastguard Worker return false;
148*00c7fec1SAndroid Build Coastguard Worker }
149*00c7fec1SAndroid Build Coastguard Worker
150*00c7fec1SAndroid Build Coastguard Worker return true;
151*00c7fec1SAndroid Build Coastguard Worker }
152*00c7fec1SAndroid Build Coastguard Worker
sdcardfs_setup_secondary(const std::string & default_path,const std::string & source_path,const std::string & dest_path,uid_t fsuid,gid_t fsgid,bool multi_user,userid_t userid,gid_t gid,mode_t mask,bool derive_gid,bool default_normal,bool unshared_obb,bool use_esdfs)153*00c7fec1SAndroid Build Coastguard Worker static bool sdcardfs_setup_secondary(const std::string& default_path,
154*00c7fec1SAndroid Build Coastguard Worker const std::string& source_path, const std::string& dest_path,
155*00c7fec1SAndroid Build Coastguard Worker uid_t fsuid, gid_t fsgid, bool multi_user, userid_t userid,
156*00c7fec1SAndroid Build Coastguard Worker gid_t gid, mode_t mask, bool derive_gid, bool default_normal,
157*00c7fec1SAndroid Build Coastguard Worker bool unshared_obb, bool use_esdfs) {
158*00c7fec1SAndroid Build Coastguard Worker if (use_esdfs) {
159*00c7fec1SAndroid Build Coastguard Worker return sdcardfs_setup(source_path, dest_path, fsuid, fsgid, multi_user, userid, gid, mask,
160*00c7fec1SAndroid Build Coastguard Worker derive_gid, default_normal, unshared_obb, use_esdfs);
161*00c7fec1SAndroid Build Coastguard Worker } else {
162*00c7fec1SAndroid Build Coastguard Worker return sdcardfs_setup_bind_remount(default_path, dest_path, gid, mask);
163*00c7fec1SAndroid Build Coastguard Worker }
164*00c7fec1SAndroid Build Coastguard Worker }
165*00c7fec1SAndroid Build Coastguard Worker
run_sdcardfs(const std::string & source_path,const std::string & label,uid_t uid,gid_t gid,userid_t userid,bool multi_user,bool full_write,bool derive_gid,bool default_normal,bool unshared_obb,bool use_esdfs)166*00c7fec1SAndroid Build Coastguard Worker static void run_sdcardfs(const std::string& source_path, const std::string& label, uid_t uid,
167*00c7fec1SAndroid Build Coastguard Worker gid_t gid, userid_t userid, bool multi_user, bool full_write,
168*00c7fec1SAndroid Build Coastguard Worker bool derive_gid, bool default_normal, bool unshared_obb, bool use_esdfs) {
169*00c7fec1SAndroid Build Coastguard Worker std::string dest_path_default = "/mnt/runtime/default/" + label;
170*00c7fec1SAndroid Build Coastguard Worker std::string dest_path_read = "/mnt/runtime/read/" + label;
171*00c7fec1SAndroid Build Coastguard Worker std::string dest_path_write = "/mnt/runtime/write/" + label;
172*00c7fec1SAndroid Build Coastguard Worker std::string dest_path_full = "/mnt/runtime/full/" + label;
173*00c7fec1SAndroid Build Coastguard Worker
174*00c7fec1SAndroid Build Coastguard Worker umask(0);
175*00c7fec1SAndroid Build Coastguard Worker if (multi_user) {
176*00c7fec1SAndroid Build Coastguard Worker // Multi-user storage is fully isolated per user, so "other"
177*00c7fec1SAndroid Build Coastguard Worker // permissions are completely masked off.
178*00c7fec1SAndroid Build Coastguard Worker if (!sdcardfs_setup(source_path, dest_path_default, uid, gid, multi_user, userid,
179*00c7fec1SAndroid Build Coastguard Worker AID_SDCARD_RW, 0006, derive_gid, default_normal, unshared_obb,
180*00c7fec1SAndroid Build Coastguard Worker use_esdfs) ||
181*00c7fec1SAndroid Build Coastguard Worker !sdcardfs_setup_secondary(dest_path_default, source_path, dest_path_read, uid, gid,
182*00c7fec1SAndroid Build Coastguard Worker multi_user, userid, AID_EVERYBODY, 0027, derive_gid,
183*00c7fec1SAndroid Build Coastguard Worker default_normal, unshared_obb, use_esdfs) ||
184*00c7fec1SAndroid Build Coastguard Worker !sdcardfs_setup_secondary(dest_path_default, source_path, dest_path_write, uid, gid,
185*00c7fec1SAndroid Build Coastguard Worker multi_user, userid, AID_EVERYBODY, full_write ? 0007 : 0027,
186*00c7fec1SAndroid Build Coastguard Worker derive_gid, default_normal, unshared_obb, use_esdfs) ||
187*00c7fec1SAndroid Build Coastguard Worker !sdcardfs_setup_secondary(dest_path_default, source_path, dest_path_full, uid, gid,
188*00c7fec1SAndroid Build Coastguard Worker multi_user, userid, AID_EVERYBODY, 0007, derive_gid,
189*00c7fec1SAndroid Build Coastguard Worker default_normal, unshared_obb, use_esdfs)) {
190*00c7fec1SAndroid Build Coastguard Worker LOG(FATAL) << "failed to sdcardfs_setup";
191*00c7fec1SAndroid Build Coastguard Worker }
192*00c7fec1SAndroid Build Coastguard Worker } else {
193*00c7fec1SAndroid Build Coastguard Worker // Physical storage is readable by all users on device, but
194*00c7fec1SAndroid Build Coastguard Worker // the Android directories are masked off to a single user
195*00c7fec1SAndroid Build Coastguard Worker // deep inside attr_from_stat().
196*00c7fec1SAndroid Build Coastguard Worker if (!sdcardfs_setup(source_path, dest_path_default, uid, gid, multi_user, userid,
197*00c7fec1SAndroid Build Coastguard Worker AID_SDCARD_RW, 0006, derive_gid, default_normal, unshared_obb,
198*00c7fec1SAndroid Build Coastguard Worker use_esdfs) ||
199*00c7fec1SAndroid Build Coastguard Worker !sdcardfs_setup_secondary(dest_path_default, source_path, dest_path_read, uid, gid,
200*00c7fec1SAndroid Build Coastguard Worker multi_user, userid, AID_EVERYBODY, full_write ? 0027 : 0022,
201*00c7fec1SAndroid Build Coastguard Worker derive_gid, default_normal, unshared_obb, use_esdfs) ||
202*00c7fec1SAndroid Build Coastguard Worker !sdcardfs_setup_secondary(dest_path_default, source_path, dest_path_write, uid, gid,
203*00c7fec1SAndroid Build Coastguard Worker multi_user, userid, AID_EVERYBODY, full_write ? 0007 : 0022,
204*00c7fec1SAndroid Build Coastguard Worker derive_gid, default_normal, unshared_obb, use_esdfs) ||
205*00c7fec1SAndroid Build Coastguard Worker !sdcardfs_setup_secondary(dest_path_default, source_path, dest_path_full, uid, gid,
206*00c7fec1SAndroid Build Coastguard Worker multi_user, userid, AID_EVERYBODY, 0007, derive_gid,
207*00c7fec1SAndroid Build Coastguard Worker default_normal, unshared_obb, use_esdfs)) {
208*00c7fec1SAndroid Build Coastguard Worker LOG(FATAL) << "failed to sdcardfs_setup";
209*00c7fec1SAndroid Build Coastguard Worker }
210*00c7fec1SAndroid Build Coastguard Worker }
211*00c7fec1SAndroid Build Coastguard Worker
212*00c7fec1SAndroid Build Coastguard Worker // Will abort if priv-dropping fails.
213*00c7fec1SAndroid Build Coastguard Worker drop_privs(uid, gid);
214*00c7fec1SAndroid Build Coastguard Worker
215*00c7fec1SAndroid Build Coastguard Worker if (multi_user) {
216*00c7fec1SAndroid Build Coastguard Worker std::string obb_path = source_path + "/obb";
217*00c7fec1SAndroid Build Coastguard Worker fs_prepare_dir(obb_path.c_str(), 0775, uid, gid);
218*00c7fec1SAndroid Build Coastguard Worker }
219*00c7fec1SAndroid Build Coastguard Worker
220*00c7fec1SAndroid Build Coastguard Worker exit(0);
221*00c7fec1SAndroid Build Coastguard Worker }
222*00c7fec1SAndroid Build Coastguard Worker
usage()223*00c7fec1SAndroid Build Coastguard Worker static int usage() {
224*00c7fec1SAndroid Build Coastguard Worker LOG(ERROR) << "usage: sdcard [OPTIONS] <source_path> <label>"
225*00c7fec1SAndroid Build Coastguard Worker << " -u: specify UID to run as"
226*00c7fec1SAndroid Build Coastguard Worker << " -g: specify GID to run as"
227*00c7fec1SAndroid Build Coastguard Worker << " -U: specify user ID that owns device"
228*00c7fec1SAndroid Build Coastguard Worker << " -m: source_path is multi-user"
229*00c7fec1SAndroid Build Coastguard Worker << " -w: runtime write mount has full write access"
230*00c7fec1SAndroid Build Coastguard Worker << " -P: preserve owners on the lower file system"
231*00c7fec1SAndroid Build Coastguard Worker << " -o: obb dir doesn't need to be shared between users";
232*00c7fec1SAndroid Build Coastguard Worker return 1;
233*00c7fec1SAndroid Build Coastguard Worker }
234*00c7fec1SAndroid Build Coastguard Worker
main(int argc,char ** argv)235*00c7fec1SAndroid Build Coastguard Worker int main(int argc, char **argv) {
236*00c7fec1SAndroid Build Coastguard Worker const char *source_path = NULL;
237*00c7fec1SAndroid Build Coastguard Worker const char *label = NULL;
238*00c7fec1SAndroid Build Coastguard Worker uid_t uid = 0;
239*00c7fec1SAndroid Build Coastguard Worker gid_t gid = 0;
240*00c7fec1SAndroid Build Coastguard Worker userid_t userid = 0;
241*00c7fec1SAndroid Build Coastguard Worker bool multi_user = false;
242*00c7fec1SAndroid Build Coastguard Worker bool full_write = false;
243*00c7fec1SAndroid Build Coastguard Worker bool derive_gid = false;
244*00c7fec1SAndroid Build Coastguard Worker bool default_normal = false;
245*00c7fec1SAndroid Build Coastguard Worker bool unshared_obb = false;
246*00c7fec1SAndroid Build Coastguard Worker int i;
247*00c7fec1SAndroid Build Coastguard Worker struct rlimit rlim;
248*00c7fec1SAndroid Build Coastguard Worker int fs_version;
249*00c7fec1SAndroid Build Coastguard Worker
250*00c7fec1SAndroid Build Coastguard Worker setenv("ANDROID_LOG_TAGS", "*:v", 1);
251*00c7fec1SAndroid Build Coastguard Worker android::base::InitLogging(argv, android::base::LogdLogger(android::base::SYSTEM));
252*00c7fec1SAndroid Build Coastguard Worker
253*00c7fec1SAndroid Build Coastguard Worker int opt;
254*00c7fec1SAndroid Build Coastguard Worker while ((opt = getopt(argc, argv, "u:g:U:mwGio")) != -1) {
255*00c7fec1SAndroid Build Coastguard Worker switch (opt) {
256*00c7fec1SAndroid Build Coastguard Worker case 'u':
257*00c7fec1SAndroid Build Coastguard Worker uid = strtoul(optarg, NULL, 10);
258*00c7fec1SAndroid Build Coastguard Worker break;
259*00c7fec1SAndroid Build Coastguard Worker case 'g':
260*00c7fec1SAndroid Build Coastguard Worker gid = strtoul(optarg, NULL, 10);
261*00c7fec1SAndroid Build Coastguard Worker break;
262*00c7fec1SAndroid Build Coastguard Worker case 'U':
263*00c7fec1SAndroid Build Coastguard Worker userid = strtoul(optarg, NULL, 10);
264*00c7fec1SAndroid Build Coastguard Worker break;
265*00c7fec1SAndroid Build Coastguard Worker case 'm':
266*00c7fec1SAndroid Build Coastguard Worker multi_user = true;
267*00c7fec1SAndroid Build Coastguard Worker break;
268*00c7fec1SAndroid Build Coastguard Worker case 'w':
269*00c7fec1SAndroid Build Coastguard Worker full_write = true;
270*00c7fec1SAndroid Build Coastguard Worker break;
271*00c7fec1SAndroid Build Coastguard Worker case 'G':
272*00c7fec1SAndroid Build Coastguard Worker derive_gid = true;
273*00c7fec1SAndroid Build Coastguard Worker break;
274*00c7fec1SAndroid Build Coastguard Worker case 'i':
275*00c7fec1SAndroid Build Coastguard Worker default_normal = true;
276*00c7fec1SAndroid Build Coastguard Worker break;
277*00c7fec1SAndroid Build Coastguard Worker case 'o':
278*00c7fec1SAndroid Build Coastguard Worker unshared_obb = true;
279*00c7fec1SAndroid Build Coastguard Worker break;
280*00c7fec1SAndroid Build Coastguard Worker case '?':
281*00c7fec1SAndroid Build Coastguard Worker default:
282*00c7fec1SAndroid Build Coastguard Worker LOG(ERROR) << "Unknown option: '" << opt << "'";
283*00c7fec1SAndroid Build Coastguard Worker return usage();
284*00c7fec1SAndroid Build Coastguard Worker }
285*00c7fec1SAndroid Build Coastguard Worker }
286*00c7fec1SAndroid Build Coastguard Worker
287*00c7fec1SAndroid Build Coastguard Worker for (i = optind; i < argc; i++) {
288*00c7fec1SAndroid Build Coastguard Worker char* arg = argv[i];
289*00c7fec1SAndroid Build Coastguard Worker if (!source_path) {
290*00c7fec1SAndroid Build Coastguard Worker source_path = arg;
291*00c7fec1SAndroid Build Coastguard Worker } else if (!label) {
292*00c7fec1SAndroid Build Coastguard Worker label = arg;
293*00c7fec1SAndroid Build Coastguard Worker } else {
294*00c7fec1SAndroid Build Coastguard Worker LOG(ERROR) << "too many arguments";
295*00c7fec1SAndroid Build Coastguard Worker return usage();
296*00c7fec1SAndroid Build Coastguard Worker }
297*00c7fec1SAndroid Build Coastguard Worker }
298*00c7fec1SAndroid Build Coastguard Worker
299*00c7fec1SAndroid Build Coastguard Worker if (!source_path) {
300*00c7fec1SAndroid Build Coastguard Worker LOG(ERROR) << "no source path specified";
301*00c7fec1SAndroid Build Coastguard Worker return usage();
302*00c7fec1SAndroid Build Coastguard Worker }
303*00c7fec1SAndroid Build Coastguard Worker if (!label) {
304*00c7fec1SAndroid Build Coastguard Worker LOG(ERROR) << "no label specified";
305*00c7fec1SAndroid Build Coastguard Worker return usage();
306*00c7fec1SAndroid Build Coastguard Worker }
307*00c7fec1SAndroid Build Coastguard Worker if (!uid || !gid) {
308*00c7fec1SAndroid Build Coastguard Worker LOG(ERROR) << "uid and gid must be nonzero";
309*00c7fec1SAndroid Build Coastguard Worker return usage();
310*00c7fec1SAndroid Build Coastguard Worker }
311*00c7fec1SAndroid Build Coastguard Worker
312*00c7fec1SAndroid Build Coastguard Worker rlim.rlim_cur = 8192;
313*00c7fec1SAndroid Build Coastguard Worker rlim.rlim_max = 8192;
314*00c7fec1SAndroid Build Coastguard Worker if (setrlimit(RLIMIT_NOFILE, &rlim) == -1) {
315*00c7fec1SAndroid Build Coastguard Worker PLOG(ERROR) << "setting RLIMIT_NOFILE failed";
316*00c7fec1SAndroid Build Coastguard Worker }
317*00c7fec1SAndroid Build Coastguard Worker
318*00c7fec1SAndroid Build Coastguard Worker while ((fs_read_atomic_int("/data/misc/installd/layout_version", &fs_version) == -1) ||
319*00c7fec1SAndroid Build Coastguard Worker (fs_version < 3)) {
320*00c7fec1SAndroid Build Coastguard Worker LOG(ERROR) << "installd fs upgrade not yet complete; waiting...";
321*00c7fec1SAndroid Build Coastguard Worker sleep(1);
322*00c7fec1SAndroid Build Coastguard Worker }
323*00c7fec1SAndroid Build Coastguard Worker
324*00c7fec1SAndroid Build Coastguard Worker run_sdcardfs(source_path, label, uid, gid, userid, multi_user, full_write, derive_gid,
325*00c7fec1SAndroid Build Coastguard Worker default_normal, unshared_obb, !should_use_sdcardfs());
326*00c7fec1SAndroid Build Coastguard Worker return 1;
327*00c7fec1SAndroid Build Coastguard Worker }
328