blob: aa1b63f7f1b5ff875add45d5305e8aa84f7e43c4 [file] [log] [blame]
San Mehatbf041852010-01-04 10:09:16 -08001/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <stdio.h>
Olivier Bailly37dcda62010-11-16 10:41:53 -080018#include <stdlib.h>
San Mehatbf041852010-01-04 10:09:16 -080019#include <fcntl.h>
20#include <unistd.h>
21#include <errno.h>
22#include <string.h>
23#include <dirent.h>
24#include <errno.h>
25#include <fcntl.h>
26
27#include <sys/types.h>
28#include <sys/stat.h>
29#include <sys/types.h>
30#include <sys/mman.h>
31#include <sys/mount.h>
Rom Lemarchand2ba45aa2013-01-16 12:29:28 -080032#include <sys/wait.h>
Ken Sumrall9caab762013-06-11 19:10:20 -070033#include <linux/fs.h>
34#include <sys/ioctl.h>
San Mehatbf041852010-01-04 10:09:16 -080035
36#include <linux/kdev_t.h>
37
Elliott Hughes7e128fb2015-12-04 15:50:53 -080038#include <android-base/logging.h>
39#include <android-base/stringprintf.h>
Jeff Sharkey95c87cc2015-04-01 11:54:32 -070040#include <selinux/selinux.h>
San Mehatbf041852010-01-04 10:09:16 -080041
Rom Lemarchand2ba45aa2013-01-16 12:29:28 -080042#include <logwrap/logwrap.h>
43
Jeff Sharkeyd0640f62015-05-21 22:35:42 -070044#include "Vfat.h"
Jeff Sharkey95c87cc2015-04-01 11:54:32 -070045#include "Utils.h"
Rom Lemarchand5593c852012-12-21 12:41:43 -080046#include "VoldUtil.h"
San Mehatbf041852010-01-04 10:09:16 -080047
Jeff Sharkeyce6a9132015-04-08 21:07:21 -070048using android::base::StringPrintf;
49
Jeff Sharkeyd0640f62015-05-21 22:35:42 -070050namespace android {
51namespace vold {
52namespace vfat {
53
Jeff Sharkeyce6a9132015-04-08 21:07:21 -070054static const char* kMkfsPath = "/system/bin/newfs_msdos";
55static const char* kFsckPath = "/system/bin/fsck_msdos";
San Mehatbf041852010-01-04 10:09:16 -080056
Jeff Sharkeyd0640f62015-05-21 22:35:42 -070057bool IsSupported() {
58 return access(kMkfsPath, X_OK) == 0
59 && access(kFsckPath, X_OK) == 0
60 && IsFilesystemSupported("vfat");
61}
62
63status_t Check(const std::string& source) {
Jeff Sharkeyce6a9132015-04-08 21:07:21 -070064 if (access(kFsckPath, X_OK)) {
Logan Chienbf319c42018-06-25 10:18:42 +080065 LOG(WARNING) << "Skipping fs checks";
San Mehatbf041852010-01-04 10:09:16 -080066 return 0;
67 }
68
69 int pass = 1;
70 int rc = 0;
71 do {
Jeff Sharkeyce6a9132015-04-08 21:07:21 -070072 std::vector<std::string> cmd;
73 cmd.push_back(kFsckPath);
74 cmd.push_back("-p");
75 cmd.push_back("-f");
Jeff Sharkeyd0640f62015-05-21 22:35:42 -070076 cmd.push_back(source);
San Mehatbf041852010-01-04 10:09:16 -080077
Jeff Sharkey95c87cc2015-04-01 11:54:32 -070078 // Fat devices are currently always untrusted
Jeff Sharkeyd0640f62015-05-21 22:35:42 -070079 rc = ForkExecvp(cmd, sFsckUntrustedContext);
Jeff Sharkey95c87cc2015-04-01 11:54:32 -070080
Jeff Sharkeyce6a9132015-04-08 21:07:21 -070081 if (rc < 0) {
Logan Chienbf319c42018-06-25 10:18:42 +080082 LOG(ERROR) << "Filesystem check failed due to logwrap error";
Rom Lemarchand2ba45aa2013-01-16 12:29:28 -080083 errno = EIO;
84 return -1;
85 }
San Mehatbf041852010-01-04 10:09:16 -080086
Jeff Sharkeyce6a9132015-04-08 21:07:21 -070087 switch(rc) {
San Mehatbf041852010-01-04 10:09:16 -080088 case 0:
Logan Chienbf319c42018-06-25 10:18:42 +080089 LOG(INFO) << "Filesystem check completed OK";
San Mehatbf041852010-01-04 10:09:16 -080090 return 0;
91
92 case 2:
Logan Chienbf319c42018-06-25 10:18:42 +080093 LOG(ERROR) << "Filesystem check failed (not a FAT filesystem)";
San Mehatbf041852010-01-04 10:09:16 -080094 errno = ENODATA;
95 return -1;
96
97 case 4:
98 if (pass++ <= 3) {
Logan Chienbf319c42018-06-25 10:18:42 +080099 LOG(WARNING) << "Filesystem modified - rechecking (pass " << pass << ")";
San Mehatbf041852010-01-04 10:09:16 -0800100 continue;
101 }
Logan Chienbf319c42018-06-25 10:18:42 +0800102 LOG(ERROR) << "Failing check after too many rechecks";
San Mehatbf041852010-01-04 10:09:16 -0800103 errno = EIO;
104 return -1;
105
Mateusz Nowak3dd39302015-08-03 15:48:52 +0200106 case 8:
Logan Chienbf319c42018-06-25 10:18:42 +0800107 LOG(ERROR) << "Filesystem check failed (no filesystem)";
Mateusz Nowak3dd39302015-08-03 15:48:52 +0200108 errno = ENODATA;
109 return -1;
110
San Mehatbf041852010-01-04 10:09:16 -0800111 default:
Logan Chienbf319c42018-06-25 10:18:42 +0800112 LOG(ERROR) << "Filesystem check failed (unknown exit code " << rc << ")";
San Mehatbf041852010-01-04 10:09:16 -0800113 errno = EIO;
114 return -1;
115 }
116 } while (0);
117
118 return 0;
119}
120
Jeff Sharkeyd0640f62015-05-21 22:35:42 -0700121status_t Mount(const std::string& source, const std::string& target, bool ro,
122 bool remount, bool executable, int ownerUid, int ownerGid, int permMask,
123 bool createLost) {
San Mehatbf041852010-01-04 10:09:16 -0800124 int rc;
125 unsigned long flags;
San Mehatfff0b472010-01-06 19:19:46 -0800126 char mountData[255];
San Mehatbf041852010-01-04 10:09:16 -0800127
Jeff Sharkeyd0640f62015-05-21 22:35:42 -0700128 const char* c_source = source.c_str();
129 const char* c_target = target.c_str();
130
Ravisankar Reddy4cc6baf2017-07-03 11:25:33 +0900131 flags = MS_NODEV | MS_NOSUID | MS_DIRSYNC | MS_NOATIME;
San Mehatbf041852010-01-04 10:09:16 -0800132
Kenny Roota3e06082010-08-27 08:31:35 -0700133 flags |= (executable ? 0 : MS_NOEXEC);
San Mehata19b2502010-01-06 10:33:53 -0800134 flags |= (ro ? MS_RDONLY : 0);
135 flags |= (remount ? MS_REMOUNT : 0);
136
George Burgess IV605d7ae2016-02-29 13:39:17 -0800137 snprintf(mountData, sizeof(mountData),
San Mehatfff0b472010-01-06 19:19:46 -0800138 "utf8,uid=%d,gid=%d,fmask=%o,dmask=%o,shortname=mixed",
139 ownerUid, ownerGid, permMask, permMask);
140
Jeff Sharkeyd0640f62015-05-21 22:35:42 -0700141 rc = mount(c_source, c_target, "vfat", flags, mountData);
San Mehatfff0b472010-01-06 19:19:46 -0800142
San Mehatbf041852010-01-04 10:09:16 -0800143 if (rc && errno == EROFS) {
Logan Chienbf319c42018-06-25 10:18:42 +0800144 LOG(ERROR) << source << " appears to be a read only filesystem - retrying mount RO";
San Mehatbf041852010-01-04 10:09:16 -0800145 flags |= MS_RDONLY;
Jeff Sharkeyd0640f62015-05-21 22:35:42 -0700146 rc = mount(c_source, c_target, "vfat", flags, mountData);
San Mehatbf041852010-01-04 10:09:16 -0800147 }
148
San Mehatfff0b472010-01-06 19:19:46 -0800149 if (rc == 0 && createLost) {
San Mehatbf041852010-01-04 10:09:16 -0800150 char *lost_path;
Jeff Sharkeyd0640f62015-05-21 22:35:42 -0700151 asprintf(&lost_path, "%s/LOST.DIR", c_target);
San Mehatbf041852010-01-04 10:09:16 -0800152 if (access(lost_path, F_OK)) {
153 /*
154 * Create a LOST.DIR in the root so we have somewhere to put
155 * lost cluster chains (fsck_msdos doesn't currently do this)
156 */
157 if (mkdir(lost_path, 0755)) {
Logan Chienbf319c42018-06-25 10:18:42 +0800158 PLOG(ERROR) << "Unable to create LOST.DIR";
San Mehatbf041852010-01-04 10:09:16 -0800159 }
160 }
161 free(lost_path);
162 }
163
164 return rc;
165}
166
Mateusz Nowaka4f48d02015-08-03 18:06:39 +0200167status_t Format(const std::string& source, unsigned long numSectors) {
Jeff Sharkeyce6a9132015-04-08 21:07:21 -0700168 std::vector<std::string> cmd;
169 cmd.push_back(kMkfsPath);
Jeff Sharkeyce6a9132015-04-08 21:07:21 -0700170 cmd.push_back("-O");
171 cmd.push_back("android");
Jeff Sharkeyce6a9132015-04-08 21:07:21 -0700172 cmd.push_back("-A");
San Mehatfcf24fe2010-03-03 12:37:32 -0800173
174 if (numSectors) {
Jeff Sharkeyce6a9132015-04-08 21:07:21 -0700175 cmd.push_back("-s");
Mateusz Nowaka4f48d02015-08-03 18:06:39 +0200176 cmd.push_back(StringPrintf("%lu", numSectors));
San Mehatfcf24fe2010-03-03 12:37:32 -0800177 }
San Mehatbf041852010-01-04 10:09:16 -0800178
Jeff Sharkeyd0640f62015-05-21 22:35:42 -0700179 cmd.push_back(source);
Jeff Sharkeyce6a9132015-04-08 21:07:21 -0700180
Jeff Sharkeyd0640f62015-05-21 22:35:42 -0700181 int rc = ForkExecvp(cmd);
Jeff Sharkeyce6a9132015-04-08 21:07:21 -0700182 if (rc < 0) {
Logan Chienbf319c42018-06-25 10:18:42 +0800183 LOG(ERROR) << "Filesystem format failed due to logwrap error";
Rom Lemarchand2ba45aa2013-01-16 12:29:28 -0800184 errno = EIO;
185 return -1;
186 }
187
Jeff Sharkeyce6a9132015-04-08 21:07:21 -0700188 if (rc == 0) {
Logan Chienbf319c42018-06-25 10:18:42 +0800189 LOG(INFO) << "Filesystem formatted OK";
San Mehatbf041852010-01-04 10:09:16 -0800190 return 0;
191 } else {
Logan Chienbf319c42018-06-25 10:18:42 +0800192 LOG(ERROR) << "Format failed (unknown exit code " << rc << ")";
San Mehatbf041852010-01-04 10:09:16 -0800193 errno = EIO;
194 return -1;
195 }
196 return 0;
197}
Ken Sumrall9caab762013-06-11 19:10:20 -0700198
Jeff Sharkeyd0640f62015-05-21 22:35:42 -0700199} // namespace vfat
200} // namespace vold
201} // namespace android