1 /* 2 * Copyright (C) 2018 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 <sys/mount.h> 18 19 #include <android-base/logging.h> 20 #include <android-base/stringprintf.h> 21 22 #include <logwrap/logwrap.h> 23 24 #include "Exfat.h" 25 #include "Utils.h" 26 27 using android::base::StringPrintf; 28 29 namespace android { 30 namespace vold { 31 namespace exfat { 32 33 static const char* kMkfsPath = "/system/bin/mkfs.exfat"; 34 static const char* kFsckPath = "/system/bin/fsck.exfat"; 35 36 bool IsSupported() { 37 return access(kMkfsPath, X_OK) == 0 && access(kFsckPath, X_OK) == 0 && 38 IsFilesystemSupported("exfat"); 39 } 40 41 status_t Check(const std::string& source) { 42 std::vector<std::string> cmd; 43 cmd.push_back(kFsckPath); 44 cmd.push_back("-y"); 45 cmd.push_back(source); 46 47 int rc = ForkExecvp(cmd, nullptr, sFsckUntrustedContext); 48 if (rc == 0) { 49 LOG(INFO) << "Check OK"; 50 return 0; 51 } else { 52 LOG(ERROR) << "Check failed (code " << rc << ")"; 53 errno = EIO; 54 return -1; 55 } 56 } 57 58 status_t Mount(const std::string& source, const std::string& target, int ownerUid, int ownerGid, 59 int permMask) { 60 int mountFlags = MS_NODEV | MS_NOSUID | MS_DIRSYNC | MS_NOATIME | MS_NOEXEC; 61 auto mountData = android::base::StringPrintf("uid=%d,gid=%d,fmask=%o,dmask=%o", ownerUid, 62 ownerGid, permMask, permMask); 63 64 if (mount(source.c_str(), target.c_str(), "exfat", mountFlags, mountData.c_str()) == 0) { 65 return 0; 66 } 67 68 PLOG(ERROR) << "Mount failed; attempting read-only"; 69 mountFlags |= MS_RDONLY; 70 if (mount(source.c_str(), target.c_str(), "exfat", mountFlags, mountData.c_str()) == 0) { 71 return 0; 72 } 73 74 return -1; 75 } 76 77 status_t Format(const std::string& source) { 78 std::vector<std::string> cmd; 79 cmd.push_back(kMkfsPath); 80 cmd.push_back("-n"); 81 cmd.push_back("android"); 82 cmd.push_back(source); 83 84 int rc = ForkExecvp(cmd); 85 if (rc == 0) { 86 LOG(INFO) << "Format OK"; 87 return 0; 88 } else { 89 LOG(ERROR) << "Format failed (code " << rc << ")"; 90 errno = EIO; 91 return -1; 92 } 93 return 0; 94 } 95 96 } // namespace exfat 97 } // namespace vold 98 } // namespace android 99