Vfat.cpp 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. /*
  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. #include <dirent.h>
  17. #include <errno.h>
  18. #include <fcntl.h>
  19. #include <stdio.h>
  20. #include <stdlib.h>
  21. #include <string.h>
  22. #include <unistd.h>
  23. #include <linux/fs.h>
  24. #include <sys/ioctl.h>
  25. #include <sys/mman.h>
  26. #include <sys/mount.h>
  27. #include <sys/stat.h>
  28. #include <sys/types.h>
  29. #include <sys/wait.h>
  30. #include <linux/kdev_t.h>
  31. #include <android-base/logging.h>
  32. #include <android-base/stringprintf.h>
  33. #include <selinux/selinux.h>
  34. #include <logwrap/logwrap.h>
  35. #include "Utils.h"
  36. #include "Vfat.h"
  37. #include "VoldUtil.h"
  38. using android::base::StringPrintf;
  39. namespace android {
  40. namespace vold {
  41. namespace vfat {
  42. static const char* kMkfsPath = "/system/bin/newfs_msdos";
  43. static const char* kFsckPath = "/system/bin/fsck_msdos";
  44. bool IsSupported() {
  45. return access(kMkfsPath, X_OK) == 0 && access(kFsckPath, X_OK) == 0 &&
  46. IsFilesystemSupported("vfat");
  47. }
  48. status_t Check(const std::string& source) {
  49. int pass = 1;
  50. int rc = 0;
  51. do {
  52. std::vector<std::string> cmd;
  53. cmd.push_back(kFsckPath);
  54. cmd.push_back("-p");
  55. cmd.push_back("-f");
  56. cmd.push_back("-y");
  57. cmd.push_back(source);
  58. // Fat devices are currently always untrusted
  59. rc = ForkExecvp(cmd, nullptr, sFsckUntrustedContext);
  60. if (rc < 0) {
  61. LOG(ERROR) << "Filesystem check failed due to logwrap error";
  62. errno = EIO;
  63. return -1;
  64. }
  65. switch (rc) {
  66. case 0:
  67. LOG(INFO) << "Filesystem check completed OK";
  68. return 0;
  69. case 2:
  70. LOG(ERROR) << "Filesystem check failed (not a FAT filesystem)";
  71. errno = ENODATA;
  72. return -1;
  73. case 4:
  74. if (pass++ <= 3) {
  75. LOG(WARNING) << "Filesystem modified - rechecking (pass " << pass << ")";
  76. continue;
  77. }
  78. LOG(ERROR) << "Failing check after too many rechecks";
  79. errno = EIO;
  80. return -1;
  81. case 8:
  82. LOG(ERROR) << "Filesystem check failed (no filesystem)";
  83. errno = ENODATA;
  84. return -1;
  85. default:
  86. LOG(ERROR) << "Filesystem check failed (unknown exit code " << rc << ")";
  87. errno = EIO;
  88. return -1;
  89. }
  90. } while (0);
  91. return 0;
  92. }
  93. status_t Mount(const std::string& source, const std::string& target, bool ro, bool remount,
  94. bool executable, int ownerUid, int ownerGid, int permMask, bool createLost) {
  95. int rc;
  96. unsigned long flags;
  97. const char* c_source = source.c_str();
  98. const char* c_target = target.c_str();
  99. flags = MS_NODEV | MS_NOSUID | MS_DIRSYNC | MS_NOATIME;
  100. flags |= (executable ? 0 : MS_NOEXEC);
  101. flags |= (ro ? MS_RDONLY : 0);
  102. flags |= (remount ? MS_REMOUNT : 0);
  103. auto mountData =
  104. android::base::StringPrintf("utf8,uid=%d,gid=%d,fmask=%o,dmask=%o,shortname=mixed",
  105. ownerUid, ownerGid, permMask, permMask);
  106. rc = mount(c_source, c_target, "vfat", flags, mountData.c_str());
  107. if (rc && errno == EROFS) {
  108. LOG(ERROR) << source << " appears to be a read only filesystem - retrying mount RO";
  109. flags |= MS_RDONLY;
  110. rc = mount(c_source, c_target, "vfat", flags, mountData.c_str());
  111. }
  112. if (rc == 0 && createLost) {
  113. auto lost_path = android::base::StringPrintf("%s/LOST.DIR", target.c_str());
  114. if (access(lost_path.c_str(), F_OK)) {
  115. /*
  116. * Create a LOST.DIR in the root so we have somewhere to put
  117. * lost cluster chains (fsck_msdos doesn't currently do this)
  118. */
  119. if (mkdir(lost_path.c_str(), 0755)) {
  120. PLOG(ERROR) << "Unable to create LOST.DIR";
  121. }
  122. }
  123. }
  124. return rc;
  125. }
  126. status_t Format(const std::string& source, unsigned long numSectors) {
  127. std::vector<std::string> cmd;
  128. cmd.push_back(kMkfsPath);
  129. cmd.push_back("-O");
  130. cmd.push_back("android");
  131. cmd.push_back("-A");
  132. if (numSectors) {
  133. cmd.push_back("-s");
  134. cmd.push_back(StringPrintf("%lu", numSectors));
  135. }
  136. cmd.push_back(source);
  137. int rc = ForkExecvp(cmd);
  138. if (rc < 0) {
  139. LOG(ERROR) << "Filesystem format failed due to logwrap error";
  140. errno = EIO;
  141. return -1;
  142. }
  143. if (rc == 0) {
  144. LOG(INFO) << "Filesystem formatted OK";
  145. return 0;
  146. } else {
  147. LOG(ERROR) << "Format failed (unknown exit code " << rc << ")";
  148. errno = EIO;
  149. return -1;
  150. }
  151. return 0;
  152. }
  153. } // namespace vfat
  154. } // namespace vold
  155. } // namespace android