• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
17 #include <stdio.h>
18 #include <fcntl.h>
19 #include <unistd.h>
20 #include <errno.h>
21 #include <string.h>
22 #include <dirent.h>
23 #include <errno.h>
24 #include <fcntl.h>
25 
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <sys/types.h>
29 #include <sys/mman.h>
30 #include <sys/mount.h>
31 
32 #include <linux/kdev_t.h>
33 
34 #define LOG_TAG "Vold"
35 
36 #include <cutils/log.h>
37 #include <cutils/properties.h>
38 
39 #include "Fat.h"
40 
41 static char FSCK_MSDOS_PATH[] = "/system/bin/fsck_msdos";
42 static char MKDOSFS_PATH[] = "/system/bin/newfs_msdos";
43 extern "C" int logwrap(int argc, const char **argv, int background);
44 extern "C" int mount(const char *, const char *, const char *, unsigned long, const void *);
45 
check(const char * fsPath)46 int Fat::check(const char *fsPath) {
47     bool rw = true;
48     if (access(FSCK_MSDOS_PATH, X_OK)) {
49         SLOGW("Skipping fs checks\n");
50         return 0;
51     }
52 
53     int pass = 1;
54     int rc = 0;
55     do {
56         const char *args[5];
57         args[0] = FSCK_MSDOS_PATH;
58         args[1] = "-p";
59         args[2] = "-f";
60         args[3] = fsPath;
61         args[4] = NULL;
62 
63         rc = logwrap(4, args, 1);
64 
65         switch(rc) {
66         case 0:
67             SLOGI("Filesystem check completed OK");
68             return 0;
69 
70         case 2:
71             SLOGE("Filesystem check failed (not a FAT filesystem)");
72             errno = ENODATA;
73             return -1;
74 
75         case 4:
76             if (pass++ <= 3) {
77                 SLOGW("Filesystem modified - rechecking (pass %d)",
78                         pass);
79                 continue;
80             }
81             SLOGE("Failing check after too many rechecks");
82             errno = EIO;
83             return -1;
84 
85         default:
86             SLOGE("Filesystem check failed (unknown exit code %d)", rc);
87             errno = EIO;
88             return -1;
89         }
90     } while (0);
91 
92     return 0;
93 }
94 
doMount(const char * fsPath,const char * mountPoint,bool ro,bool remount,bool executable,int ownerUid,int ownerGid,int permMask,bool createLost)95 int Fat::doMount(const char *fsPath, const char *mountPoint,
96                  bool ro, bool remount, bool executable,
97                  int ownerUid, int ownerGid, int permMask, bool createLost) {
98     int rc;
99     unsigned long flags;
100     char mountData[255];
101 
102     flags = MS_NODEV | MS_NOSUID | MS_DIRSYNC;
103 
104     flags |= (executable ? 0 : MS_NOEXEC);
105     flags |= (ro ? MS_RDONLY : 0);
106     flags |= (remount ? MS_REMOUNT : 0);
107 
108     /*
109      * Note: This is a temporary hack. If the sampling profiler is enabled,
110      * we make the SD card world-writable so any process can write snapshots.
111      *
112      * TODO: Remove this code once we have a drop box in system_server.
113      */
114     char value[PROPERTY_VALUE_MAX];
115     property_get("persist.sampling_profiler", value, "");
116     if (value[0] == '1') {
117         SLOGW("The SD card is world-writable because the"
118             " 'persist.sampling_profiler' system property is set to '1'.");
119         permMask = 0;
120     }
121 
122     sprintf(mountData,
123             "utf8,uid=%d,gid=%d,fmask=%o,dmask=%o,shortname=mixed",
124             ownerUid, ownerGid, permMask, permMask);
125 
126     rc = mount(fsPath, mountPoint, "vfat", flags, mountData);
127 
128     if (rc && errno == EROFS) {
129         SLOGE("%s appears to be a read only filesystem - retrying mount RO", fsPath);
130         flags |= MS_RDONLY;
131         rc = mount(fsPath, mountPoint, "vfat", flags, mountData);
132     }
133 
134     if (rc == 0 && createLost) {
135         char *lost_path;
136         asprintf(&lost_path, "%s/LOST.DIR", mountPoint);
137         if (access(lost_path, F_OK)) {
138             /*
139              * Create a LOST.DIR in the root so we have somewhere to put
140              * lost cluster chains (fsck_msdos doesn't currently do this)
141              */
142             if (mkdir(lost_path, 0755)) {
143                 SLOGE("Unable to create LOST.DIR (%s)", strerror(errno));
144             }
145         }
146         free(lost_path);
147     }
148 
149     return rc;
150 }
151 
format(const char * fsPath,unsigned int numSectors)152 int Fat::format(const char *fsPath, unsigned int numSectors) {
153     int fd;
154     const char *args[11];
155     int rc;
156 
157     args[0] = MKDOSFS_PATH;
158     args[1] = "-F";
159     args[2] = "32";
160     args[3] = "-O";
161     args[4] = "android";
162     args[5] = "-c";
163     args[6] = "8";
164 
165     if (numSectors) {
166         char tmp[32];
167         snprintf(tmp, sizeof(tmp), "%u", numSectors);
168         const char *size = tmp;
169         args[7] = "-s";
170         args[8] = size;
171         args[9] = fsPath;
172         args[10] = NULL;
173         rc = logwrap(11, args, 1);
174     } else {
175         args[7] = fsPath;
176         args[8] = NULL;
177         rc = logwrap(9, args, 1);
178     }
179 
180     if (rc == 0) {
181         SLOGI("Filesystem formatted OK");
182         return 0;
183     } else {
184         SLOGE("Format failed (unknown exit code %d)", rc);
185         errno = EIO;
186         return -1;
187     }
188     return 0;
189 }
190