xref: /OK3568_Linux_fs/external/recovery/mtdutils/rk29.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * Copyright (C) 2023 Rockchip Electronics Co., Ltd.
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 #define _GNU_SOURCE
18 
19 #include <dirent.h>
20 #include <libgen.h>
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include <sys/stat.h>
26 #include <sys/types.h>
27 #include <sys/wait.h>
28 #include <sys/mount.h>
29 #include <errno.h>
30 #include "mtdutils.h"
31 #include "rk29.h"
32 #include "common.h"
33 
run(const char * filename,char * const argv[])34 int run(const char *filename, char *const argv[])
35 {
36     struct stat s;
37     int status;
38     pid_t pid;
39 
40     if (stat(filename, &s) != 0) {
41         LOGE("cannot find '%s'", filename);
42         return -1;
43     }
44 
45     LOGI("executing '%s'\n", filename);
46 
47     pid = fork();
48 
49     if (pid == 0) {
50         setpgid(0, getpid());
51         /* execute */
52         execv(filename, argv);
53         LOGE("can't run %s (%s)\n", filename, strerror(errno));
54         /* exit */
55         _exit(0);
56     }
57 
58     if (pid < 0) {
59         LOGE("failed to fork and start '%s'\n", filename);
60         return -1;
61     }
62 
63     if (-1 == waitpid(pid, &status, WCONTINUED | WUNTRACED)) {
64         LOGE("wait for child error\n");
65         return -1;
66     }
67 
68     if (WIFEXITED(status)) {
69         LOGI("executed '%s' done\n", filename);
70     }
71 
72     LOGI("executed '%s' return %d\n", filename, WEXITSTATUS(status));
73     return 0;
74 }
75 
rk_check_and_resizefs(const char * filename)76 int rk_check_and_resizefs(const char *filename)
77 {
78     int result;
79 
80     const char *const e2fsck_argv[] = { "/sbin/e2fsck", "-fy", filename, NULL };
81     const char *const resizefs_argv[] = { "/sbin/resize2fs", filename, NULL  };
82 
83     result = run(e2fsck_argv[0], (char **) e2fsck_argv);
84     if (result) {
85         LOGI("e2fsck check '%s' failed!\n", filename);
86         return result;
87     }
88 
89     result = run(resizefs_argv[0], (char **) resizefs_argv);
90     if (result) {
91         LOGI("resizefs '%s' failed!\n", filename);
92     }
93 
94     return result;
95 }
96 
rk_check_and_resizefs_f2fs(const char * filename)97 int rk_check_and_resizefs_f2fs(const char *filename)
98 {
99     int result;
100 
101     const char *const e2fsck_argv[] = { "fsck_f2fs", filename, NULL };
102     const char *const resizefs_argv[] = { "resize.f2fs", filename, NULL  };
103 
104     result = run(e2fsck_argv[0], (char **) e2fsck_argv);
105     if (result) {
106         LOGI("fsck_f2fs check '%s' failed!\n", filename);
107         return result;
108     }
109 
110     result = run(resizefs_argv[0], (char **) resizefs_argv);
111     if (result) {
112         LOGI("resize.f2fs '%s' failed!\n", filename);
113     }
114 
115     return result;
116 }
117 
make_extfs(const char * path,const char * label,const char * type)118 static int make_extfs(const char *path, const char *label, const char *type)
119 {
120     const char *const mke2fs[] = {
121         "/sbin/mke2fs", "-t", type, "-q", path, NULL,
122     };
123 
124     // max-mount-counts(0) + time-dependent checking(0) + fslabel
125     const char *const tune2fs[] = {
126         "/sbin/tune2fs", "-c", "0", "-i", "0", "-L", label, path, NULL,
127     };
128     int result;
129 
130     LOGI("format '%s' to %s filesystem\n", path, type);
131     result = run(mke2fs[0], (char **) mke2fs);
132     if (result) {
133         LOGI("failed!\n");
134         return result;
135     }
136 
137     result = run(tune2fs[0], (char **) tune2fs);
138     if (result) {
139         LOGI("failed!\n");
140         return result;
141     }
142 
143     return result;
144 }
145 
make_ext2(const char * path,const char * label)146 int make_ext2(const char *path, const char *label)
147 {
148     return make_extfs(path, label, "ext2");
149 }
150 
make_ext4(const char * path,const char * label)151 int make_ext4(const char *path, const char *label)
152 {
153     return make_extfs(path, label, "ext4");
154 }
155 
make_vfat(const char * path,const char * label)156 int make_vfat(const char *path, const char *label)
157 {
158     // fat32
159     const char *const mkdosfs[] = {
160         "/sbin/mkdosfs", "-F", "32", "-n", label, path, NULL,
161     };
162 
163     LOGI("format '%s' to vfat filesystem\n", path);
164     return run(mkdosfs[0], (char **) mkdosfs);
165 }
166 
make_ntfs(const char * path,const char * label)167 int make_ntfs(const char *path, const char *label)
168 {
169     // compression
170     const char *const mkntfs[] = {
171         "mkntfs", "-F", "C", "Q", "-L", label, path, NULL,
172     };
173 
174     LOGI("format '%s' to ntfs filesystem\n", path);
175     return run(mkntfs[0], (char **) mkntfs);
176 }
177 
178 #ifndef min
179 #define min(a,b) ((a)<(b)?(a):(b))
180 #endif
181 
rk29_fread(void * ptr,size_t size,size_t nmemb,FILE * stream)182 size_t rk29_fread(void *ptr, size_t size, size_t nmemb, FILE *stream)
183 {
184     char buf[READ_SIZE];
185     int fd;
186     long begin, end;
187     off_t offset;
188     ssize_t sz;
189     size_t count = 0, total;
190     char *p = ptr;
191 
192     if (!ptr)
193         return 0;
194     if (!size || !nmemb)
195         return 0;
196     if (!stream)
197         return 0;
198     fd = fileno(stream);
199     if (fd < 0)
200         return 0;
201 
202     begin = ftell(stream);
203     if (begin < 0)
204         begin = 0;
205 
206     total = size * nmemb;
207     if (!total)
208         return 0;
209 
210     end = begin + total;
211     offset = begin & ~READ_MASK;
212 
213     if (begin & READ_MASK) {
214         sz = pread(fd, buf, READ_SIZE, offset);
215         if (sz < READ_SIZE)
216             goto out;
217         count = min(end, offset + READ_SIZE) - begin;
218         memcpy(p, buf + (begin & READ_MASK), count);
219         p += count;
220         offset += READ_SIZE;
221     }
222 
223     for (; offset < (end & ~READ_MASK); offset += READ_SIZE) {
224         sz = pread(fd, buf, READ_SIZE, offset);
225         if (sz < READ_SIZE)
226             goto out;
227         count += READ_SIZE;
228         memcpy(p, buf, READ_SIZE);
229         p += READ_SIZE;
230     }
231 
232     if (count < total && (end & READ_MASK)) {
233         offset = end & ~READ_MASK;
234         sz = pread(fd, buf, READ_SIZE, offset);
235         if (sz < READ_SIZE)
236             goto out;
237         memcpy(p, buf, end - offset);
238         count += end - offset;
239     }
240 out:
241     count /= size;
242     fseek(stream, begin + count * size, SEEK_SET);
243     return count;
244 }
245 
rk29_fwrite(const void * ptr,size_t size,size_t nmemb,FILE * stream)246 size_t rk29_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
247 {
248     char buf[WRITE_SIZE];
249     int fd;
250     long begin, end;
251     off_t offset;
252     ssize_t sz;
253     size_t count = 0, total;
254     char *p = (char *)ptr;
255 
256     if (!ptr)
257         return 0;
258     if (!size || !nmemb)
259         return 0;
260     if (!stream)
261         return 0;
262     fd = fileno(stream);
263     if (fd < 0)
264         return 0;
265 
266     begin = ftell(stream);
267     if (begin < 0)
268         begin = 0;
269 
270     total = size * nmemb;
271     if (!total)
272         return 0;
273 
274     end = begin + total;
275     offset = begin & ~WRITE_MASK;
276 
277     if (begin & WRITE_MASK) {
278         sz = pread(fd, buf, WRITE_SIZE, offset);
279         if (sz < WRITE_SIZE)
280             goto out;
281         count = min(end, offset + WRITE_SIZE) - begin;
282         memcpy(buf + (begin & WRITE_MASK), p, count);
283         sz = pwrite(fd, buf, WRITE_SIZE, offset);
284         if (sz < WRITE_SIZE)
285             goto out;
286         p += count;
287         offset += WRITE_SIZE;
288     }
289 
290     for (; offset < (end & ~WRITE_MASK); offset += WRITE_SIZE) {
291         sz = pwrite(fd, p, WRITE_SIZE, offset);
292         if (sz < WRITE_SIZE)
293             goto out;
294         count += WRITE_SIZE;
295         p += WRITE_SIZE;
296     }
297 
298     if (count < total && (end & WRITE_MASK)) {
299         offset = end & ~WRITE_MASK;
300         sz = pread(fd, buf, WRITE_SIZE, offset);
301         if (sz < WRITE_SIZE)
302             goto out;
303         memcpy(buf, p, end - offset);
304         sz = pwrite(fd, buf, WRITE_SIZE, offset);
305         if (sz < WRITE_SIZE)
306             goto out;
307         count += end - offset;
308     }
309 out:
310     count /= size;
311     fseek(stream, begin + count * size, SEEK_SET);
312     return count;
313 }
314 
315