xref: /OK3568_Linux_fs/external/recovery/roots.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright (C) 2007 The Android Open Source Project
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Licensed under the Apache License, Version 2.0 (the "License");
5*4882a593Smuzhiyun  * you may not use this file except in compliance with the License.
6*4882a593Smuzhiyun  * You may obtain a copy of the License at
7*4882a593Smuzhiyun  *
8*4882a593Smuzhiyun  *      http://www.apache.org/licenses/LICENSE-2.0
9*4882a593Smuzhiyun  *
10*4882a593Smuzhiyun  * Unless required by applicable law or agreed to in writing, software
11*4882a593Smuzhiyun  * distributed under the License is distributed on an "AS IS" BASIS,
12*4882a593Smuzhiyun  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*4882a593Smuzhiyun  * See the License for the specific language governing permissions and
14*4882a593Smuzhiyun  * limitations under the License.
15*4882a593Smuzhiyun  */
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun #include <errno.h>
18*4882a593Smuzhiyun #include <stdlib.h>
19*4882a593Smuzhiyun #include <string.h>
20*4882a593Smuzhiyun #include <sys/mount.h>
21*4882a593Smuzhiyun #include <sys/stat.h>
22*4882a593Smuzhiyun #include <sys/types.h>
23*4882a593Smuzhiyun #include <unistd.h>
24*4882a593Smuzhiyun #include <ctype.h>
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun #include "mtdutils/mtdutils.h"
27*4882a593Smuzhiyun #include "mtdutils/mounts.h"
28*4882a593Smuzhiyun #include "roots.h"
29*4882a593Smuzhiyun #include "common.h"
30*4882a593Smuzhiyun #include "rktools.h"
31*4882a593Smuzhiyun #include "mtdutils/rk29.h"
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun static int num_volumes = 0;
34*4882a593Smuzhiyun static Volume* device_volumes = NULL;
35*4882a593Smuzhiyun static char mount_point[256] = {0};
36*4882a593Smuzhiyun 
37*4882a593Smuzhiyun #define VOLUME_TO_LABEL(v) ((strrchr(v->mount_point, '/') ? : "/unknown") + 1)
38*4882a593Smuzhiyun 
get_link_path(const char * linkpath,char * buf,int count)39*4882a593Smuzhiyun char * get_link_path(const char* linkpath, char * buf, int count)
40*4882a593Smuzhiyun {
41*4882a593Smuzhiyun     int i;
42*4882a593Smuzhiyun     int rslt;
43*4882a593Smuzhiyun     char path[256];
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun     memset(path, 0, sizeof(path));
46*4882a593Smuzhiyun     strcpy(path, linkpath);
47*4882a593Smuzhiyun     for (i = strlen(linkpath); i > 0; i--) {
48*4882a593Smuzhiyun         if (path[i] == '/') {
49*4882a593Smuzhiyun             path[i] = '\0';
50*4882a593Smuzhiyun             break;
51*4882a593Smuzhiyun         }
52*4882a593Smuzhiyun     }
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun     rslt = readlink(path, buf, count - 1);
55*4882a593Smuzhiyun     if (rslt < 0 || (rslt >= count - 1)) {
56*4882a593Smuzhiyun         // printf("No link to path [%s]!!! \n", path);
57*4882a593Smuzhiyun         return NULL;
58*4882a593Smuzhiyun     }
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun     if (buf[0] != '/') {
61*4882a593Smuzhiyun         char tmp[256];
62*4882a593Smuzhiyun         memset(tmp, 0, sizeof(tmp));
63*4882a593Smuzhiyun         memcpy(tmp, buf, strlen(buf));
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun         memset(buf, 0, sizeof(buf));
66*4882a593Smuzhiyun         memcpy(buf + 1, tmp, strlen(tmp));
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun         buf[0] = '/';
69*4882a593Smuzhiyun     }
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun     // printf("buf = %s \n", buf);
72*4882a593Smuzhiyun     return buf;
73*4882a593Smuzhiyun }
74*4882a593Smuzhiyun 
get_mounted_device_from_path(const char * path)75*4882a593Smuzhiyun const char* get_mounted_device_from_path(const char* path)
76*4882a593Smuzhiyun {
77*4882a593Smuzhiyun     const MountedVolume *volume;
78*4882a593Smuzhiyun 
79*4882a593Smuzhiyun     int result = scan_mounted_volumes();
80*4882a593Smuzhiyun     if (result < 0) {
81*4882a593Smuzhiyun         LOGE("failed to scan mounted volumes\n");
82*4882a593Smuzhiyun         return NULL;
83*4882a593Smuzhiyun     }
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun     volume = find_mounted_volume_by_mount_point(path);
86*4882a593Smuzhiyun     if (!volume) {
87*4882a593Smuzhiyun         LOGE("failed to get volume from %s\n", path);
88*4882a593Smuzhiyun         return NULL;
89*4882a593Smuzhiyun     }
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun     return volume->device;
92*4882a593Smuzhiyun }
93*4882a593Smuzhiyun 
load_volume_table()94*4882a593Smuzhiyun void load_volume_table()
95*4882a593Smuzhiyun {
96*4882a593Smuzhiyun     int alloc = 2;
97*4882a593Smuzhiyun     device_volumes = malloc(alloc * sizeof(Volume));
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun     // Insert an entry for /tmp, which is the ramdisk and is always mounted.
100*4882a593Smuzhiyun     device_volumes[0].mount_point = "/tmp";
101*4882a593Smuzhiyun     device_volumes[0].fs_type = "ramdisk";
102*4882a593Smuzhiyun     device_volumes[0].device = NULL;
103*4882a593Smuzhiyun     device_volumes[0].device2 = NULL;
104*4882a593Smuzhiyun     device_volumes[0].option = NULL;
105*4882a593Smuzhiyun     device_volumes[0].dump = NULL;
106*4882a593Smuzhiyun     device_volumes[0].pass = NULL;
107*4882a593Smuzhiyun     num_volumes = 1;
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun     FILE* fstab = fopen("/etc/fstab", "r");
110*4882a593Smuzhiyun     if (fstab == NULL) {
111*4882a593Smuzhiyun         LOGE("failed to open /etc/fstab (%d)\n", errno);
112*4882a593Smuzhiyun         return;
113*4882a593Smuzhiyun     }
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun     char buffer[1024];
116*4882a593Smuzhiyun     char file_system[1024];
117*4882a593Smuzhiyun     char mount_point[1024];
118*4882a593Smuzhiyun     char fs_type[1024];
119*4882a593Smuzhiyun     char option[1024];
120*4882a593Smuzhiyun     char dump[1024];
121*4882a593Smuzhiyun     char pass[1024];
122*4882a593Smuzhiyun     char device[1024];
123*4882a593Smuzhiyun     int i;
124*4882a593Smuzhiyun     while (fgets(buffer, sizeof(buffer) - 1, fstab)) {
125*4882a593Smuzhiyun         i = sscanf(buffer, "%s %s %s %s %s %s", file_system,
126*4882a593Smuzhiyun                    mount_point, fs_type, option, dump, pass);
127*4882a593Smuzhiyun         if (file_system[0] == '#') continue;
128*4882a593Smuzhiyun         //printf("load_volume_table file_system:%s, mount_point:%s, fs_type:%s, option:%s, dump:%s, pass:%s\n", file_system, mount_point, fs_type, option, dump, pass);
129*4882a593Smuzhiyun         /* HACK: Convert *LABEL to "by-name" symlink */
130*4882a593Smuzhiyun         if (strstr(file_system, "LABEL="))
131*4882a593Smuzhiyun             snprintf(device, sizeof(device), "/dev/block/by-name/%s",
132*4882a593Smuzhiyun                      strstr(file_system, "LABEL=") + strlen("LABEL="));
133*4882a593Smuzhiyun         else
134*4882a593Smuzhiyun             strcpy(device, file_system);
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun         if (i == 6) {
137*4882a593Smuzhiyun             while (num_volumes >= alloc) {
138*4882a593Smuzhiyun                 alloc *= 2;
139*4882a593Smuzhiyun                 device_volumes = realloc(device_volumes, alloc * sizeof(Volume));
140*4882a593Smuzhiyun             }
141*4882a593Smuzhiyun             device_volumes[num_volumes].mount_point = strdup(mount_point);
142*4882a593Smuzhiyun             device_volumes[num_volumes].fs_type = strdup(fs_type);
143*4882a593Smuzhiyun             device_volumes[num_volumes].option = strdup(option);
144*4882a593Smuzhiyun             device_volumes[num_volumes].dump = strdup(dump);
145*4882a593Smuzhiyun             device_volumes[num_volumes].pass = strdup(pass);
146*4882a593Smuzhiyun             device_volumes[num_volumes].device = strdup(device);;
147*4882a593Smuzhiyun             device_volumes[num_volumes].device2 = NULL;
148*4882a593Smuzhiyun             ++num_volumes;
149*4882a593Smuzhiyun         } else {
150*4882a593Smuzhiyun             LOGE("skipping malformed recovery.fstab line: %s\n", buffer);
151*4882a593Smuzhiyun         }
152*4882a593Smuzhiyun     }
153*4882a593Smuzhiyun 
154*4882a593Smuzhiyun     fclose(fstab);
155*4882a593Smuzhiyun 
156*4882a593Smuzhiyun     printf("recovery filesystem table\n");
157*4882a593Smuzhiyun     printf("=========================\n");
158*4882a593Smuzhiyun     for (i = 0; i < num_volumes; ++i) {
159*4882a593Smuzhiyun         Volume* v = &device_volumes[i];
160*4882a593Smuzhiyun         printf("  %d %s %s %s %s %s %s\n", i, v->device, v->mount_point, v->fs_type, v->option, v->dump, v->pass);
161*4882a593Smuzhiyun     }
162*4882a593Smuzhiyun     printf("\n");
163*4882a593Smuzhiyun }
164*4882a593Smuzhiyun 
volume_for_path(const char * path)165*4882a593Smuzhiyun Volume* volume_for_path(const char* path)
166*4882a593Smuzhiyun {
167*4882a593Smuzhiyun     int i;
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun     memset(mount_point, 0, sizeof(mount_point));
170*4882a593Smuzhiyun     char* tmp = get_link_path(path, mount_point, 1024);
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun     // if ( tmp != NULL)
173*4882a593Smuzhiyun     //  printf(" ### get mount_ponit = %s ### \n", mount_point);
174*4882a593Smuzhiyun 
175*4882a593Smuzhiyun     for (i = 0; i < num_volumes; ++i) {
176*4882a593Smuzhiyun         Volume* v = device_volumes + i;
177*4882a593Smuzhiyun         int len = strlen(v->mount_point);
178*4882a593Smuzhiyun         if (strncmp(path, v->mount_point, len) == 0 &&
179*4882a593Smuzhiyun             (path[len] == '\0' || path[len] == '/')) {
180*4882a593Smuzhiyun             //printf(" ===path = %s, v-mount_point = %s ===\n",path, v->mount_point);
181*4882a593Smuzhiyun             return v;
182*4882a593Smuzhiyun         } else {
183*4882a593Smuzhiyun             //add by chad.ma for symbol link file. eg. sdcard/ --->mnt/sdcard
184*4882a593Smuzhiyun             if (!tmp)
185*4882a593Smuzhiyun                 continue;
186*4882a593Smuzhiyun 
187*4882a593Smuzhiyun             //printf(" # v->mount_point = %s\n", v->mount_point);
188*4882a593Smuzhiyun             if (strncmp(mount_point, v->mount_point, len) == 0 &&
189*4882a593Smuzhiyun                 (path[len] == '\0' || path[len] == '/')) {
190*4882a593Smuzhiyun                 return v;
191*4882a593Smuzhiyun             }
192*4882a593Smuzhiyun         }
193*4882a593Smuzhiyun     }
194*4882a593Smuzhiyun     return NULL;
195*4882a593Smuzhiyun }
196*4882a593Smuzhiyun 
ensure_path_mounted(const char * path)197*4882a593Smuzhiyun int ensure_path_mounted(const char* path)
198*4882a593Smuzhiyun {
199*4882a593Smuzhiyun     if (access(path, F_OK) == 0)
200*4882a593Smuzhiyun         return 0;
201*4882a593Smuzhiyun 
202*4882a593Smuzhiyun     Volume* v = volume_for_path(path);
203*4882a593Smuzhiyun     if (v == NULL) {
204*4882a593Smuzhiyun         if (mount_point[0] != 0) {
205*4882a593Smuzhiyun             int result = scan_mounted_volumes();
206*4882a593Smuzhiyun             if (result < 0) {
207*4882a593Smuzhiyun                 LOGE("failed to scan mounted volumes\n");
208*4882a593Smuzhiyun                 return -1;
209*4882a593Smuzhiyun             }
210*4882a593Smuzhiyun 
211*4882a593Smuzhiyun             const MountedVolume* mv =
212*4882a593Smuzhiyun                 find_mounted_volume_by_mount_point(mount_point);
213*4882a593Smuzhiyun             if (mv) {
214*4882a593Smuzhiyun                 // volume is already mounted
215*4882a593Smuzhiyun                 LOGI("%s already mounted \n", path);
216*4882a593Smuzhiyun                 return 0;
217*4882a593Smuzhiyun             }
218*4882a593Smuzhiyun         }
219*4882a593Smuzhiyun 
220*4882a593Smuzhiyun         LOGE("unknown volume for path [%s]\n", path);
221*4882a593Smuzhiyun         return -1;
222*4882a593Smuzhiyun     }
223*4882a593Smuzhiyun     if (strcmp(v->fs_type, "ramdisk") == 0) {
224*4882a593Smuzhiyun         // the ramdisk is always mounted.
225*4882a593Smuzhiyun         return 0;
226*4882a593Smuzhiyun     }
227*4882a593Smuzhiyun 
228*4882a593Smuzhiyun     int result;
229*4882a593Smuzhiyun     result = scan_mounted_volumes();
230*4882a593Smuzhiyun     if (result < 0) {
231*4882a593Smuzhiyun         LOGE("failed to scan mounted volumes\n");
232*4882a593Smuzhiyun         return -1;
233*4882a593Smuzhiyun     }
234*4882a593Smuzhiyun 
235*4882a593Smuzhiyun     const MountedVolume* mv =
236*4882a593Smuzhiyun         find_mounted_volume_by_mount_point(v->mount_point);
237*4882a593Smuzhiyun     if (mv) {
238*4882a593Smuzhiyun         // volume is already mounted
239*4882a593Smuzhiyun         return 0;
240*4882a593Smuzhiyun     }
241*4882a593Smuzhiyun 
242*4882a593Smuzhiyun     mkdir(v->mount_point, 0755);  // in case it doesn't already exist
243*4882a593Smuzhiyun 
244*4882a593Smuzhiyun     if (strcmp(v->fs_type, "yaffs2") == 0) {
245*4882a593Smuzhiyun         // mount an MTD partition as a YAFFS2 filesystem.
246*4882a593Smuzhiyun         mtd_scan_partitions();
247*4882a593Smuzhiyun         const MtdPartition* partition;
248*4882a593Smuzhiyun         partition = mtd_find_partition_by_name(v->device);
249*4882a593Smuzhiyun         if (partition == NULL) {
250*4882a593Smuzhiyun             LOGE("failed to find \"%s\" partition to mount at \"%s\"\n",
251*4882a593Smuzhiyun                  v->device, v->mount_point);
252*4882a593Smuzhiyun             return -1;
253*4882a593Smuzhiyun         }
254*4882a593Smuzhiyun         return mtd_mount_partition(partition, v->mount_point, v->fs_type, 0);
255*4882a593Smuzhiyun     } else if (strcmp(v->fs_type, "ext4") == 0 ||
256*4882a593Smuzhiyun                strcmp(v->fs_type, "vfat") == 0 ||
257*4882a593Smuzhiyun                strcmp(v->fs_type, "ext2") == 0) {
258*4882a593Smuzhiyun         char *blk_device;
259*4882a593Smuzhiyun         blk_device = (char*)v->device;
260*4882a593Smuzhiyun         if (strcmp("/mnt/sdcard", v->mount_point) == 0) {
261*4882a593Smuzhiyun             blk_device = getenv(SD_POINT_NAME);
262*4882a593Smuzhiyun             if (blk_device == NULL) {
263*4882a593Smuzhiyun                 setFlashPoint();
264*4882a593Smuzhiyun                 blk_device = getenv(SD_POINT_NAME);
265*4882a593Smuzhiyun             }
266*4882a593Smuzhiyun             result = mount(blk_device, v->mount_point, v->fs_type,
267*4882a593Smuzhiyun                            MS_NOATIME | MS_NODEV | MS_NODIRATIME, "");
268*4882a593Smuzhiyun             if (result == 0) return 0;
269*4882a593Smuzhiyun         }
270*4882a593Smuzhiyun         result = mount(v->device, v->mount_point, v->fs_type,
271*4882a593Smuzhiyun                        MS_NOATIME | MS_NODEV | MS_NODIRATIME, "");
272*4882a593Smuzhiyun         if (result == 0) return 0;
273*4882a593Smuzhiyun 
274*4882a593Smuzhiyun         if (v->device2) {
275*4882a593Smuzhiyun             LOGW("failed to mount %s (%s); trying %s\n",
276*4882a593Smuzhiyun                  v->device, strerror(errno), v->device2);
277*4882a593Smuzhiyun             result = mount(v->device2, v->mount_point, v->fs_type,
278*4882a593Smuzhiyun                            MS_NOATIME | MS_NODEV | MS_NODIRATIME, "");
279*4882a593Smuzhiyun             if (result == 0) return 0;
280*4882a593Smuzhiyun         }
281*4882a593Smuzhiyun         LOGE("failed to mount %s (%s)\n", v->mount_point, strerror(errno));
282*4882a593Smuzhiyun         return -1;
283*4882a593Smuzhiyun     }
284*4882a593Smuzhiyun 
285*4882a593Smuzhiyun     LOGE("unknown fs_type \"%s\" for %s\n", v->fs_type, v->mount_point);
286*4882a593Smuzhiyun     return -1;
287*4882a593Smuzhiyun }
288*4882a593Smuzhiyun 
ensure_ex_path_unmounted(const char * path)289*4882a593Smuzhiyun int ensure_ex_path_unmounted(const char* path)
290*4882a593Smuzhiyun {
291*4882a593Smuzhiyun     int result;
292*4882a593Smuzhiyun 
293*4882a593Smuzhiyun     result = scan_mounted_volumes();
294*4882a593Smuzhiyun     if (result < 0) {
295*4882a593Smuzhiyun         LOGE("unknown volume for path [%s]\n", path);
296*4882a593Smuzhiyun         return -1;
297*4882a593Smuzhiyun     }
298*4882a593Smuzhiyun 
299*4882a593Smuzhiyun     const MountedVolume* mv =
300*4882a593Smuzhiyun         find_mounted_volume_by_mount_point(path);
301*4882a593Smuzhiyun     if (mv == NULL) {
302*4882a593Smuzhiyun         LOGE("path: %s is already unmounted or not existed\n");
303*4882a593Smuzhiyun         return 0;
304*4882a593Smuzhiyun     }
305*4882a593Smuzhiyun 
306*4882a593Smuzhiyun     return unmount_mounted_volume(mv);
307*4882a593Smuzhiyun }
308*4882a593Smuzhiyun 
ensure_path_unmounted(const char * path)309*4882a593Smuzhiyun int ensure_path_unmounted(const char* path)
310*4882a593Smuzhiyun {
311*4882a593Smuzhiyun     Volume* v = volume_for_path(path);
312*4882a593Smuzhiyun     if (v == NULL) {
313*4882a593Smuzhiyun         LOGE("unknown volume for path [%s]\n", path);
314*4882a593Smuzhiyun         return -1;
315*4882a593Smuzhiyun     }
316*4882a593Smuzhiyun     if (strcmp(v->fs_type, "ramdisk") == 0) {
317*4882a593Smuzhiyun         // the ramdisk is always mounted; you can't unmount it.
318*4882a593Smuzhiyun         return -1;
319*4882a593Smuzhiyun     }
320*4882a593Smuzhiyun 
321*4882a593Smuzhiyun     int result;
322*4882a593Smuzhiyun     result = scan_mounted_volumes();
323*4882a593Smuzhiyun     if (result < 0) {
324*4882a593Smuzhiyun         LOGE("failed to scan mounted volumes\n");
325*4882a593Smuzhiyun         return -1;
326*4882a593Smuzhiyun     }
327*4882a593Smuzhiyun 
328*4882a593Smuzhiyun     const MountedVolume* mv =
329*4882a593Smuzhiyun         find_mounted_volume_by_mount_point(v->mount_point);
330*4882a593Smuzhiyun     if (mv == NULL) {
331*4882a593Smuzhiyun         // volume is already unmounted
332*4882a593Smuzhiyun         return 0;
333*4882a593Smuzhiyun     }
334*4882a593Smuzhiyun 
335*4882a593Smuzhiyun     return unmount_mounted_volume(mv);
336*4882a593Smuzhiyun }
337*4882a593Smuzhiyun 
format_volume(const char * volume)338*4882a593Smuzhiyun int format_volume(const char* volume)
339*4882a593Smuzhiyun {
340*4882a593Smuzhiyun     Volume* v = volume_for_path(volume);
341*4882a593Smuzhiyun     const char *label;
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun     if (v == NULL) {
344*4882a593Smuzhiyun         LOGE("unknown volume \"%s\"\n", volume);
345*4882a593Smuzhiyun         return -1;
346*4882a593Smuzhiyun     }
347*4882a593Smuzhiyun     if (strcmp(v->fs_type, "ramdisk") == 0) {
348*4882a593Smuzhiyun         // you can't format the ramdisk.
349*4882a593Smuzhiyun         LOGE("can't format_volume \"%s\"", volume);
350*4882a593Smuzhiyun         return -1;
351*4882a593Smuzhiyun     }
352*4882a593Smuzhiyun     if (strcmp(v->mount_point, volume) != 0) {
353*4882a593Smuzhiyun         LOGE("can't give path \"%s\" to format_volume\n", volume);
354*4882a593Smuzhiyun         return -1;
355*4882a593Smuzhiyun     }
356*4882a593Smuzhiyun 
357*4882a593Smuzhiyun     if (ensure_path_unmounted(volume) != 0) {
358*4882a593Smuzhiyun         LOGE("format_volume failed to unmount \"%s\"\n", v->mount_point);
359*4882a593Smuzhiyun         return -1;
360*4882a593Smuzhiyun     }
361*4882a593Smuzhiyun 
362*4882a593Smuzhiyun     label = VOLUME_TO_LABEL(v);
363*4882a593Smuzhiyun 
364*4882a593Smuzhiyun     if (strcmp(v->fs_type, "yaffs2") == 0 || strcmp(v->fs_type, "mtd") == 0 || strcmp(v->fs_type, "ubifs") == 0 ) {
365*4882a593Smuzhiyun         mtd_scan_partitions();
366*4882a593Smuzhiyun         char filepath[20];
367*4882a593Smuzhiyun         if (strstr(v->device, "userdata") != NULL) {
368*4882a593Smuzhiyun             strcpy(filepath, "userdata");
369*4882a593Smuzhiyun             LOGW("change v->device from %s to %s.\n", v->device, filepath);
370*4882a593Smuzhiyun         } else {
371*4882a593Smuzhiyun             strcpy(filepath, v->device);
372*4882a593Smuzhiyun         }
373*4882a593Smuzhiyun 
374*4882a593Smuzhiyun         const MtdPartition* partition = mtd_find_partition_by_name(filepath);
375*4882a593Smuzhiyun         if (partition == NULL) {
376*4882a593Smuzhiyun             LOGE("format_volume: no MTD partition \"%s\"\n", v->device);
377*4882a593Smuzhiyun             return -1;
378*4882a593Smuzhiyun         }
379*4882a593Smuzhiyun 
380*4882a593Smuzhiyun         MtdWriteContext *write = mtd_write_partition(partition);
381*4882a593Smuzhiyun         if (write == NULL) {
382*4882a593Smuzhiyun             LOGW("format_volume: can't open MTD \"%s\"\n", v->device);
383*4882a593Smuzhiyun             return -1;
384*4882a593Smuzhiyun         } else if (mtd_erase_blocks(write, -1) == (off_t) -1) {
385*4882a593Smuzhiyun             LOGW("format_volume: can't erase MTD \"%s\"\n", v->device);
386*4882a593Smuzhiyun             mtd_write_close(write);
387*4882a593Smuzhiyun             return -1;
388*4882a593Smuzhiyun         } else if (mtd_write_close(write)) {
389*4882a593Smuzhiyun             LOGW("format_volume: can't close MTD \"%s\"\n", v->device);
390*4882a593Smuzhiyun             return -1;
391*4882a593Smuzhiyun         }
392*4882a593Smuzhiyun         return 0;
393*4882a593Smuzhiyun     }
394*4882a593Smuzhiyun 
395*4882a593Smuzhiyun     if (strcmp(v->fs_type, "ext4") == 0) {
396*4882a593Smuzhiyun         int result = make_ext4(v->device, label);
397*4882a593Smuzhiyun         if (result != 0) {
398*4882a593Smuzhiyun             LOGE("format_volume: make_extf4 failed on %s\n", v->device);
399*4882a593Smuzhiyun             return -1;
400*4882a593Smuzhiyun         }
401*4882a593Smuzhiyun         return 0;
402*4882a593Smuzhiyun     }
403*4882a593Smuzhiyun 
404*4882a593Smuzhiyun     if (strcmp(v->fs_type, "ext2") == 0) {
405*4882a593Smuzhiyun         int result = make_ext2(v->device, label);
406*4882a593Smuzhiyun         if (result != 0) {
407*4882a593Smuzhiyun             LOGE("format_volume: make_extf2 failed on %s\n", v->device);
408*4882a593Smuzhiyun             return -1;
409*4882a593Smuzhiyun         }
410*4882a593Smuzhiyun         return 0;
411*4882a593Smuzhiyun     }
412*4882a593Smuzhiyun     if (strcmp(v->fs_type, "vfat") == 0) {
413*4882a593Smuzhiyun         int result = make_vfat(v->device, label);
414*4882a593Smuzhiyun         if (result != 0) {
415*4882a593Smuzhiyun             LOGE("format_volume: make_vfat failed on %s\n", v->device);
416*4882a593Smuzhiyun             return -1;
417*4882a593Smuzhiyun         }
418*4882a593Smuzhiyun         return 0;
419*4882a593Smuzhiyun     }
420*4882a593Smuzhiyun 
421*4882a593Smuzhiyun     if (strcmp(v->fs_type, "ntfs") == 0) {
422*4882a593Smuzhiyun         int result = make_ntfs(v->device, label);
423*4882a593Smuzhiyun         if (result != 0) {
424*4882a593Smuzhiyun             LOGE("format_volume: make_ntfs failed on %s\n", v->device);
425*4882a593Smuzhiyun             return -1;
426*4882a593Smuzhiyun         }
427*4882a593Smuzhiyun         return 0;
428*4882a593Smuzhiyun     }
429*4882a593Smuzhiyun 
430*4882a593Smuzhiyun     LOGE("format_volume: fs_type \"%s\" unsupported\n", v->fs_type);
431*4882a593Smuzhiyun     return -1;
432*4882a593Smuzhiyun }
433*4882a593Smuzhiyun 
resize_volume(const char * volume)434*4882a593Smuzhiyun int resize_volume(const char* volume)
435*4882a593Smuzhiyun {
436*4882a593Smuzhiyun     Volume* v = volume_for_path(volume);
437*4882a593Smuzhiyun     if (v == NULL) {
438*4882a593Smuzhiyun         LOGE("unknown volume \"%s\"\n", volume);
439*4882a593Smuzhiyun         return -1;
440*4882a593Smuzhiyun     }
441*4882a593Smuzhiyun     if (strcmp(v->fs_type, "ramdisk") == 0) {
442*4882a593Smuzhiyun         // you can't format the ramdisk.
443*4882a593Smuzhiyun         LOGE("can't format_volume \"%s\"", volume);
444*4882a593Smuzhiyun         return -1;
445*4882a593Smuzhiyun     }
446*4882a593Smuzhiyun     if (strcmp(v->mount_point, volume) != 0) {
447*4882a593Smuzhiyun         LOGE("can't give path \"%s\" to format_volume\n", volume);
448*4882a593Smuzhiyun         return -1;
449*4882a593Smuzhiyun     }
450*4882a593Smuzhiyun 
451*4882a593Smuzhiyun     if (ensure_path_unmounted(volume) != 0) {
452*4882a593Smuzhiyun         LOGE("format_volume failed to unmount \"%s\"\n", v->mount_point);
453*4882a593Smuzhiyun         return -1;
454*4882a593Smuzhiyun     }
455*4882a593Smuzhiyun 
456*4882a593Smuzhiyun     if ((strcmp(v->fs_type, "ext4") == 0) || (strcmp(v->fs_type, "ext2") == 0)) {
457*4882a593Smuzhiyun         int result = rk_check_and_resizefs(v->device);
458*4882a593Smuzhiyun         if (result != 0) {
459*4882a593Smuzhiyun             LOGE("resize_volume: resizefs failed on %s\n", v->device);
460*4882a593Smuzhiyun             return -1;
461*4882a593Smuzhiyun         }
462*4882a593Smuzhiyun         return 0;
463*4882a593Smuzhiyun     }
464*4882a593Smuzhiyun 
465*4882a593Smuzhiyun     LOGE("format_volume: fs_type \"%s\" unsupported\n", v->fs_type);
466*4882a593Smuzhiyun     return -1;
467*4882a593Smuzhiyun }
468*4882a593Smuzhiyun 
469