1*33b1fccfSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0+
2*33b1fccfSAndroid Build Coastguard Worker /*
3*33b1fccfSAndroid Build Coastguard Worker * Copyright (C) 2018-2019 HUAWEI, Inc.
4*33b1fccfSAndroid Build Coastguard Worker * http://www.huawei.com/
5*33b1fccfSAndroid Build Coastguard Worker * Created by Li Guifu <[email protected]>
6*33b1fccfSAndroid Build Coastguard Worker */
7*33b1fccfSAndroid Build Coastguard Worker #define _GNU_SOURCE
8*33b1fccfSAndroid Build Coastguard Worker #include <ctype.h>
9*33b1fccfSAndroid Build Coastguard Worker #include <time.h>
10*33b1fccfSAndroid Build Coastguard Worker #include <sys/time.h>
11*33b1fccfSAndroid Build Coastguard Worker #include <stdlib.h>
12*33b1fccfSAndroid Build Coastguard Worker #include <limits.h>
13*33b1fccfSAndroid Build Coastguard Worker #include <libgen.h>
14*33b1fccfSAndroid Build Coastguard Worker #include <sys/stat.h>
15*33b1fccfSAndroid Build Coastguard Worker #include <getopt.h>
16*33b1fccfSAndroid Build Coastguard Worker #include "erofs/config.h"
17*33b1fccfSAndroid Build Coastguard Worker #include "erofs/print.h"
18*33b1fccfSAndroid Build Coastguard Worker #include "erofs/cache.h"
19*33b1fccfSAndroid Build Coastguard Worker #include "erofs/diskbuf.h"
20*33b1fccfSAndroid Build Coastguard Worker #include "erofs/inode.h"
21*33b1fccfSAndroid Build Coastguard Worker #include "erofs/tar.h"
22*33b1fccfSAndroid Build Coastguard Worker #include "erofs/compress.h"
23*33b1fccfSAndroid Build Coastguard Worker #include "erofs/dedupe.h"
24*33b1fccfSAndroid Build Coastguard Worker #include "erofs/xattr.h"
25*33b1fccfSAndroid Build Coastguard Worker #include "erofs/exclude.h"
26*33b1fccfSAndroid Build Coastguard Worker #include "erofs/block_list.h"
27*33b1fccfSAndroid Build Coastguard Worker #include "erofs/compress_hints.h"
28*33b1fccfSAndroid Build Coastguard Worker #include "erofs/blobchunk.h"
29*33b1fccfSAndroid Build Coastguard Worker #include "erofs/fragments.h"
30*33b1fccfSAndroid Build Coastguard Worker #include "erofs/rebuild.h"
31*33b1fccfSAndroid Build Coastguard Worker #include "../lib/liberofs_private.h"
32*33b1fccfSAndroid Build Coastguard Worker #include "../lib/liberofs_uuid.h"
33*33b1fccfSAndroid Build Coastguard Worker #include "../lib/compressor.h"
34*33b1fccfSAndroid Build Coastguard Worker
35*33b1fccfSAndroid Build Coastguard Worker static struct option long_options[] = {
36*33b1fccfSAndroid Build Coastguard Worker {"version", no_argument, 0, 'V'},
37*33b1fccfSAndroid Build Coastguard Worker {"help", no_argument, 0, 'h'},
38*33b1fccfSAndroid Build Coastguard Worker {"exclude-path", required_argument, NULL, 2},
39*33b1fccfSAndroid Build Coastguard Worker {"exclude-regex", required_argument, NULL, 3},
40*33b1fccfSAndroid Build Coastguard Worker #ifdef HAVE_LIBSELINUX
41*33b1fccfSAndroid Build Coastguard Worker {"file-contexts", required_argument, NULL, 4},
42*33b1fccfSAndroid Build Coastguard Worker #endif
43*33b1fccfSAndroid Build Coastguard Worker {"force-uid", required_argument, NULL, 5},
44*33b1fccfSAndroid Build Coastguard Worker {"force-gid", required_argument, NULL, 6},
45*33b1fccfSAndroid Build Coastguard Worker {"all-root", no_argument, NULL, 7},
46*33b1fccfSAndroid Build Coastguard Worker #ifndef NDEBUG
47*33b1fccfSAndroid Build Coastguard Worker {"random-pclusterblks", no_argument, NULL, 8},
48*33b1fccfSAndroid Build Coastguard Worker {"random-algorithms", no_argument, NULL, 18},
49*33b1fccfSAndroid Build Coastguard Worker #endif
50*33b1fccfSAndroid Build Coastguard Worker {"max-extent-bytes", required_argument, NULL, 9},
51*33b1fccfSAndroid Build Coastguard Worker {"compress-hints", required_argument, NULL, 10},
52*33b1fccfSAndroid Build Coastguard Worker {"chunksize", required_argument, NULL, 11},
53*33b1fccfSAndroid Build Coastguard Worker {"quiet", no_argument, 0, 12},
54*33b1fccfSAndroid Build Coastguard Worker {"blobdev", required_argument, NULL, 13},
55*33b1fccfSAndroid Build Coastguard Worker {"ignore-mtime", no_argument, NULL, 14},
56*33b1fccfSAndroid Build Coastguard Worker {"preserve-mtime", no_argument, NULL, 15},
57*33b1fccfSAndroid Build Coastguard Worker {"uid-offset", required_argument, NULL, 16},
58*33b1fccfSAndroid Build Coastguard Worker {"gid-offset", required_argument, NULL, 17},
59*33b1fccfSAndroid Build Coastguard Worker {"tar", optional_argument, NULL, 20},
60*33b1fccfSAndroid Build Coastguard Worker {"aufs", no_argument, NULL, 21},
61*33b1fccfSAndroid Build Coastguard Worker {"mount-point", required_argument, NULL, 512},
62*33b1fccfSAndroid Build Coastguard Worker {"xattr-prefix", required_argument, NULL, 19},
63*33b1fccfSAndroid Build Coastguard Worker #ifdef WITH_ANDROID
64*33b1fccfSAndroid Build Coastguard Worker {"product-out", required_argument, NULL, 513},
65*33b1fccfSAndroid Build Coastguard Worker {"fs-config-file", required_argument, NULL, 514},
66*33b1fccfSAndroid Build Coastguard Worker {"block-list-file", required_argument, NULL, 515},
67*33b1fccfSAndroid Build Coastguard Worker #endif
68*33b1fccfSAndroid Build Coastguard Worker {"ovlfs-strip", optional_argument, NULL, 516},
69*33b1fccfSAndroid Build Coastguard Worker {"offset", required_argument, NULL, 517},
70*33b1fccfSAndroid Build Coastguard Worker #ifdef HAVE_ZLIB
71*33b1fccfSAndroid Build Coastguard Worker {"gzip", no_argument, NULL, 518},
72*33b1fccfSAndroid Build Coastguard Worker {"ungzip", optional_argument, NULL, 518},
73*33b1fccfSAndroid Build Coastguard Worker #endif
74*33b1fccfSAndroid Build Coastguard Worker #ifdef HAVE_LIBLZMA
75*33b1fccfSAndroid Build Coastguard Worker {"unlzma", optional_argument, NULL, 519},
76*33b1fccfSAndroid Build Coastguard Worker {"unxz", optional_argument, NULL, 519},
77*33b1fccfSAndroid Build Coastguard Worker #endif
78*33b1fccfSAndroid Build Coastguard Worker #ifdef EROFS_MT_ENABLED
79*33b1fccfSAndroid Build Coastguard Worker {"workers", required_argument, NULL, 520},
80*33b1fccfSAndroid Build Coastguard Worker #endif
81*33b1fccfSAndroid Build Coastguard Worker {"zfeature-bits", required_argument, NULL, 521},
82*33b1fccfSAndroid Build Coastguard Worker {"clean", optional_argument, NULL, 522},
83*33b1fccfSAndroid Build Coastguard Worker {"incremental", optional_argument, NULL, 523},
84*33b1fccfSAndroid Build Coastguard Worker {"root-xattr-isize", required_argument, NULL, 524},
85*33b1fccfSAndroid Build Coastguard Worker {"mkfs-time", no_argument, NULL, 525},
86*33b1fccfSAndroid Build Coastguard Worker {"all-time", no_argument, NULL, 526},
87*33b1fccfSAndroid Build Coastguard Worker {0, 0, 0, 0},
88*33b1fccfSAndroid Build Coastguard Worker };
89*33b1fccfSAndroid Build Coastguard Worker
print_available_compressors(FILE * f,const char * delim)90*33b1fccfSAndroid Build Coastguard Worker static void print_available_compressors(FILE *f, const char *delim)
91*33b1fccfSAndroid Build Coastguard Worker {
92*33b1fccfSAndroid Build Coastguard Worker int i = 0;
93*33b1fccfSAndroid Build Coastguard Worker bool comma = false;
94*33b1fccfSAndroid Build Coastguard Worker const struct erofs_algorithm *s;
95*33b1fccfSAndroid Build Coastguard Worker
96*33b1fccfSAndroid Build Coastguard Worker while ((s = z_erofs_list_available_compressors(&i)) != NULL) {
97*33b1fccfSAndroid Build Coastguard Worker if (comma)
98*33b1fccfSAndroid Build Coastguard Worker fputs(delim, f);
99*33b1fccfSAndroid Build Coastguard Worker fputs(s->name, f);
100*33b1fccfSAndroid Build Coastguard Worker comma = true;
101*33b1fccfSAndroid Build Coastguard Worker }
102*33b1fccfSAndroid Build Coastguard Worker fputc('\n', f);
103*33b1fccfSAndroid Build Coastguard Worker }
104*33b1fccfSAndroid Build Coastguard Worker
usage(int argc,char ** argv)105*33b1fccfSAndroid Build Coastguard Worker static void usage(int argc, char **argv)
106*33b1fccfSAndroid Build Coastguard Worker {
107*33b1fccfSAndroid Build Coastguard Worker int i = 0;
108*33b1fccfSAndroid Build Coastguard Worker const struct erofs_algorithm *s;
109*33b1fccfSAndroid Build Coastguard Worker
110*33b1fccfSAndroid Build Coastguard Worker // " 1 2 3 4 5 6 7 8 "
111*33b1fccfSAndroid Build Coastguard Worker // "12345678901234567890123456789012345678901234567890123456789012345678901234567890\n"
112*33b1fccfSAndroid Build Coastguard Worker printf(
113*33b1fccfSAndroid Build Coastguard Worker "Usage: %s [OPTIONS] FILE SOURCE(s)\n"
114*33b1fccfSAndroid Build Coastguard Worker "Generate EROFS image (FILE) from SOURCE(s).\n"
115*33b1fccfSAndroid Build Coastguard Worker "\n"
116*33b1fccfSAndroid Build Coastguard Worker "General options:\n"
117*33b1fccfSAndroid Build Coastguard Worker " -V, --version print the version number of mkfs.erofs and exit\n"
118*33b1fccfSAndroid Build Coastguard Worker " -h, --help display this help and exit\n"
119*33b1fccfSAndroid Build Coastguard Worker "\n"
120*33b1fccfSAndroid Build Coastguard Worker " -b# set block size to # (# = page size by default)\n"
121*33b1fccfSAndroid Build Coastguard Worker " -d<0-9> set output verbosity; 0=quiet, 9=verbose (default=%i)\n"
122*33b1fccfSAndroid Build Coastguard Worker " -x# set xattr tolerance to # (< 0, disable xattrs; default 2)\n"
123*33b1fccfSAndroid Build Coastguard Worker " -zX[,level=Y] X=compressor (Y=compression level, Z=dictionary size, optional)\n"
124*33b1fccfSAndroid Build Coastguard Worker " [,dictsize=Z] alternative compressors can be separated by colons(:)\n"
125*33b1fccfSAndroid Build Coastguard Worker " [:...] supported compressors and their option ranges are:\n",
126*33b1fccfSAndroid Build Coastguard Worker argv[0], EROFS_WARN);
127*33b1fccfSAndroid Build Coastguard Worker while ((s = z_erofs_list_available_compressors(&i)) != NULL) {
128*33b1fccfSAndroid Build Coastguard Worker const char spaces[] = " ";
129*33b1fccfSAndroid Build Coastguard Worker
130*33b1fccfSAndroid Build Coastguard Worker printf("%s%s\n", spaces, s->name);
131*33b1fccfSAndroid Build Coastguard Worker if (s->c->setlevel) {
132*33b1fccfSAndroid Build Coastguard Worker if (!strcmp(s->name, "lzma"))
133*33b1fccfSAndroid Build Coastguard Worker /* A little kludge to show the range as disjointed
134*33b1fccfSAndroid Build Coastguard Worker * "0-9,100-109" instead of a continuous "0-109", and to
135*33b1fccfSAndroid Build Coastguard Worker * state what those two subranges respectively mean. */
136*33b1fccfSAndroid Build Coastguard Worker printf("%s [,level=<0-9,100-109>]\t0-9=normal, 100-109=extreme (default=%i)\n",
137*33b1fccfSAndroid Build Coastguard Worker spaces, s->c->default_level);
138*33b1fccfSAndroid Build Coastguard Worker else
139*33b1fccfSAndroid Build Coastguard Worker printf("%s [,level=<0-%i>]\t\t(default=%i)\n",
140*33b1fccfSAndroid Build Coastguard Worker spaces, s->c->best_level, s->c->default_level);
141*33b1fccfSAndroid Build Coastguard Worker }
142*33b1fccfSAndroid Build Coastguard Worker if (s->c->setdictsize) {
143*33b1fccfSAndroid Build Coastguard Worker if (s->c->default_dictsize)
144*33b1fccfSAndroid Build Coastguard Worker printf("%s [,dictsize=<dictsize>]\t(default=%u, max=%u)\n",
145*33b1fccfSAndroid Build Coastguard Worker spaces, s->c->default_dictsize, s->c->max_dictsize);
146*33b1fccfSAndroid Build Coastguard Worker else
147*33b1fccfSAndroid Build Coastguard Worker printf("%s [,dictsize=<dictsize>]\t(default=<auto>, max=%u)\n",
148*33b1fccfSAndroid Build Coastguard Worker spaces, s->c->max_dictsize);
149*33b1fccfSAndroid Build Coastguard Worker }
150*33b1fccfSAndroid Build Coastguard Worker }
151*33b1fccfSAndroid Build Coastguard Worker printf(
152*33b1fccfSAndroid Build Coastguard Worker " -C# specify the size of compress physical cluster in bytes\n"
153*33b1fccfSAndroid Build Coastguard Worker " -EX[,...] X=extended options\n"
154*33b1fccfSAndroid Build Coastguard Worker " -L volume-label set the volume label (maximum 16)\n"
155*33b1fccfSAndroid Build Coastguard Worker " -T# specify a fixed UNIX timestamp # as build time\n"
156*33b1fccfSAndroid Build Coastguard Worker " --all-time the timestamp is also applied to all files (default)\n"
157*33b1fccfSAndroid Build Coastguard Worker " --mkfs-time the timestamp is applied as build time only\n"
158*33b1fccfSAndroid Build Coastguard Worker " -UX use a given filesystem UUID\n"
159*33b1fccfSAndroid Build Coastguard Worker " --all-root make all files owned by root\n"
160*33b1fccfSAndroid Build Coastguard Worker " --blobdev=X specify an extra device X to store chunked data\n"
161*33b1fccfSAndroid Build Coastguard Worker " --chunksize=# generate chunk-based files with #-byte chunks\n"
162*33b1fccfSAndroid Build Coastguard Worker " --clean=X run full clean build (default) or:\n"
163*33b1fccfSAndroid Build Coastguard Worker " --incremental=X run incremental build\n"
164*33b1fccfSAndroid Build Coastguard Worker " (X = data|rvsp; data=full data, rvsp=space is allocated\n"
165*33b1fccfSAndroid Build Coastguard Worker " and filled with zeroes)\n"
166*33b1fccfSAndroid Build Coastguard Worker " --compress-hints=X specify a file to configure per-file compression strategy\n"
167*33b1fccfSAndroid Build Coastguard Worker " --exclude-path=X avoid including file X (X = exact literal path)\n"
168*33b1fccfSAndroid Build Coastguard Worker " --exclude-regex=X avoid including files that match X (X = regular expression)\n"
169*33b1fccfSAndroid Build Coastguard Worker #ifdef HAVE_LIBSELINUX
170*33b1fccfSAndroid Build Coastguard Worker " --file-contexts=X specify a file contexts file to setup selinux labels\n"
171*33b1fccfSAndroid Build Coastguard Worker #endif
172*33b1fccfSAndroid Build Coastguard Worker " --force-uid=# set all file uids to # (# = UID)\n"
173*33b1fccfSAndroid Build Coastguard Worker " --force-gid=# set all file gids to # (# = GID)\n"
174*33b1fccfSAndroid Build Coastguard Worker " --uid-offset=# add offset # to all file uids (# = id offset)\n"
175*33b1fccfSAndroid Build Coastguard Worker " --gid-offset=# add offset # to all file gids (# = id offset)\n"
176*33b1fccfSAndroid Build Coastguard Worker " --ignore-mtime use build time instead of strict per-file modification time\n"
177*33b1fccfSAndroid Build Coastguard Worker " --max-extent-bytes=# set maximum decompressed extent size # in bytes\n"
178*33b1fccfSAndroid Build Coastguard Worker " --mount-point=X X=prefix of target fs path (default: /)\n"
179*33b1fccfSAndroid Build Coastguard Worker " --preserve-mtime keep per-file modification time strictly\n"
180*33b1fccfSAndroid Build Coastguard Worker " --offset=# skip # bytes at the beginning of IMAGE.\n"
181*33b1fccfSAndroid Build Coastguard Worker " --root-xattr-isize=# ensure the inline xattr size of the root directory is # bytes at least\n"
182*33b1fccfSAndroid Build Coastguard Worker " --aufs replace aufs special files with overlayfs metadata\n"
183*33b1fccfSAndroid Build Coastguard Worker " --tar=X generate a full or index-only image from a tarball(-ish) source\n"
184*33b1fccfSAndroid Build Coastguard Worker " (X = f|i|headerball; f=full mode, i=index mode,\n"
185*33b1fccfSAndroid Build Coastguard Worker " headerball=file data is omited in the source stream)\n"
186*33b1fccfSAndroid Build Coastguard Worker " --ovlfs-strip=<0,1> strip overlayfs metadata in the target image (e.g. whiteouts)\n"
187*33b1fccfSAndroid Build Coastguard Worker " --quiet quiet execution (do not write anything to standard output.)\n"
188*33b1fccfSAndroid Build Coastguard Worker #ifndef NDEBUG
189*33b1fccfSAndroid Build Coastguard Worker " --random-pclusterblks randomize pclusterblks for big pcluster (debugging only)\n"
190*33b1fccfSAndroid Build Coastguard Worker " --random-algorithms randomize per-file algorithms (debugging only)\n"
191*33b1fccfSAndroid Build Coastguard Worker #endif
192*33b1fccfSAndroid Build Coastguard Worker #ifdef HAVE_ZLIB
193*33b1fccfSAndroid Build Coastguard Worker " --ungzip[=X] try to filter the tarball stream through gzip\n"
194*33b1fccfSAndroid Build Coastguard Worker " (and optionally dump the raw stream to X together)\n"
195*33b1fccfSAndroid Build Coastguard Worker #endif
196*33b1fccfSAndroid Build Coastguard Worker #ifdef HAVE_LIBLZMA
197*33b1fccfSAndroid Build Coastguard Worker " --unxz[=X] try to filter the tarball stream through xz/lzma/lzip\n"
198*33b1fccfSAndroid Build Coastguard Worker " (and optionally dump the raw stream to X together)\n"
199*33b1fccfSAndroid Build Coastguard Worker #endif
200*33b1fccfSAndroid Build Coastguard Worker #ifdef EROFS_MT_ENABLED
201*33b1fccfSAndroid Build Coastguard Worker " --workers=# set the number of worker threads to # (default: %u)\n"
202*33b1fccfSAndroid Build Coastguard Worker #endif
203*33b1fccfSAndroid Build Coastguard Worker " --xattr-prefix=X X=extra xattr name prefix\n"
204*33b1fccfSAndroid Build Coastguard Worker " --zfeature-bits=# toggle filesystem compression features according to given bits #\n"
205*33b1fccfSAndroid Build Coastguard Worker #ifdef WITH_ANDROID
206*33b1fccfSAndroid Build Coastguard Worker "\n"
207*33b1fccfSAndroid Build Coastguard Worker "Android-specific options:\n"
208*33b1fccfSAndroid Build Coastguard Worker " --product-out=X X=product_out directory\n"
209*33b1fccfSAndroid Build Coastguard Worker " --fs-config-file=X X=fs_config file\n"
210*33b1fccfSAndroid Build Coastguard Worker " --block-list-file=X X=block_list file\n"
211*33b1fccfSAndroid Build Coastguard Worker #endif
212*33b1fccfSAndroid Build Coastguard Worker #ifdef EROFS_MT_ENABLED
213*33b1fccfSAndroid Build Coastguard Worker , erofs_get_available_processors() /* --workers= */
214*33b1fccfSAndroid Build Coastguard Worker #endif
215*33b1fccfSAndroid Build Coastguard Worker );
216*33b1fccfSAndroid Build Coastguard Worker }
217*33b1fccfSAndroid Build Coastguard Worker
version(void)218*33b1fccfSAndroid Build Coastguard Worker static void version(void)
219*33b1fccfSAndroid Build Coastguard Worker {
220*33b1fccfSAndroid Build Coastguard Worker printf("mkfs.erofs (erofs-utils) %s\navailable compressors: ",
221*33b1fccfSAndroid Build Coastguard Worker cfg.c_version);
222*33b1fccfSAndroid Build Coastguard Worker print_available_compressors(stdout, ", ");
223*33b1fccfSAndroid Build Coastguard Worker }
224*33b1fccfSAndroid Build Coastguard Worker
225*33b1fccfSAndroid Build Coastguard Worker static unsigned int pclustersize_packed, pclustersize_max;
226*33b1fccfSAndroid Build Coastguard Worker static struct erofs_tarfile erofstar = {
227*33b1fccfSAndroid Build Coastguard Worker .global.xattrs = LIST_HEAD_INIT(erofstar.global.xattrs)
228*33b1fccfSAndroid Build Coastguard Worker };
229*33b1fccfSAndroid Build Coastguard Worker static bool tar_mode, rebuild_mode, incremental_mode;
230*33b1fccfSAndroid Build Coastguard Worker
231*33b1fccfSAndroid Build Coastguard Worker enum {
232*33b1fccfSAndroid Build Coastguard Worker EROFS_MKFS_DATA_IMPORT_DEFAULT,
233*33b1fccfSAndroid Build Coastguard Worker EROFS_MKFS_DATA_IMPORT_FULLDATA,
234*33b1fccfSAndroid Build Coastguard Worker EROFS_MKFS_DATA_IMPORT_RVSP,
235*33b1fccfSAndroid Build Coastguard Worker EROFS_MKFS_DATA_IMPORT_SPARSE,
236*33b1fccfSAndroid Build Coastguard Worker } dataimport_mode;
237*33b1fccfSAndroid Build Coastguard Worker
238*33b1fccfSAndroid Build Coastguard Worker static unsigned int rebuild_src_count;
239*33b1fccfSAndroid Build Coastguard Worker static LIST_HEAD(rebuild_src_list);
240*33b1fccfSAndroid Build Coastguard Worker static u8 fixeduuid[16];
241*33b1fccfSAndroid Build Coastguard Worker static bool valid_fixeduuid;
242*33b1fccfSAndroid Build Coastguard Worker
erofs_mkfs_feat_set_legacy_compress(bool en,const char * val,unsigned int vallen)243*33b1fccfSAndroid Build Coastguard Worker static int erofs_mkfs_feat_set_legacy_compress(bool en, const char *val,
244*33b1fccfSAndroid Build Coastguard Worker unsigned int vallen)
245*33b1fccfSAndroid Build Coastguard Worker {
246*33b1fccfSAndroid Build Coastguard Worker if (vallen)
247*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
248*33b1fccfSAndroid Build Coastguard Worker /* disable compacted indexes and 0padding */
249*33b1fccfSAndroid Build Coastguard Worker cfg.c_legacy_compress = en;
250*33b1fccfSAndroid Build Coastguard Worker return 0;
251*33b1fccfSAndroid Build Coastguard Worker }
252*33b1fccfSAndroid Build Coastguard Worker
erofs_mkfs_feat_set_ztailpacking(bool en,const char * val,unsigned int vallen)253*33b1fccfSAndroid Build Coastguard Worker static int erofs_mkfs_feat_set_ztailpacking(bool en, const char *val,
254*33b1fccfSAndroid Build Coastguard Worker unsigned int vallen)
255*33b1fccfSAndroid Build Coastguard Worker {
256*33b1fccfSAndroid Build Coastguard Worker if (vallen)
257*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
258*33b1fccfSAndroid Build Coastguard Worker cfg.c_ztailpacking = en;
259*33b1fccfSAndroid Build Coastguard Worker return 0;
260*33b1fccfSAndroid Build Coastguard Worker }
261*33b1fccfSAndroid Build Coastguard Worker
erofs_mkfs_feat_set_fragments(bool en,const char * val,unsigned int vallen)262*33b1fccfSAndroid Build Coastguard Worker static int erofs_mkfs_feat_set_fragments(bool en, const char *val,
263*33b1fccfSAndroid Build Coastguard Worker unsigned int vallen)
264*33b1fccfSAndroid Build Coastguard Worker {
265*33b1fccfSAndroid Build Coastguard Worker if (!en) {
266*33b1fccfSAndroid Build Coastguard Worker if (vallen)
267*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
268*33b1fccfSAndroid Build Coastguard Worker cfg.c_fragments = false;
269*33b1fccfSAndroid Build Coastguard Worker return 0;
270*33b1fccfSAndroid Build Coastguard Worker }
271*33b1fccfSAndroid Build Coastguard Worker
272*33b1fccfSAndroid Build Coastguard Worker if (vallen) {
273*33b1fccfSAndroid Build Coastguard Worker char *endptr;
274*33b1fccfSAndroid Build Coastguard Worker u64 i = strtoull(val, &endptr, 0);
275*33b1fccfSAndroid Build Coastguard Worker
276*33b1fccfSAndroid Build Coastguard Worker if (endptr - val != vallen) {
277*33b1fccfSAndroid Build Coastguard Worker erofs_err("invalid pcluster size %s for the packed file %s", val);
278*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
279*33b1fccfSAndroid Build Coastguard Worker }
280*33b1fccfSAndroid Build Coastguard Worker pclustersize_packed = i;
281*33b1fccfSAndroid Build Coastguard Worker }
282*33b1fccfSAndroid Build Coastguard Worker cfg.c_fragments = true;
283*33b1fccfSAndroid Build Coastguard Worker return 0;
284*33b1fccfSAndroid Build Coastguard Worker }
285*33b1fccfSAndroid Build Coastguard Worker
erofs_mkfs_feat_set_all_fragments(bool en,const char * val,unsigned int vallen)286*33b1fccfSAndroid Build Coastguard Worker static int erofs_mkfs_feat_set_all_fragments(bool en, const char *val,
287*33b1fccfSAndroid Build Coastguard Worker unsigned int vallen)
288*33b1fccfSAndroid Build Coastguard Worker {
289*33b1fccfSAndroid Build Coastguard Worker cfg.c_all_fragments = en;
290*33b1fccfSAndroid Build Coastguard Worker return erofs_mkfs_feat_set_fragments(en, val, vallen);
291*33b1fccfSAndroid Build Coastguard Worker }
292*33b1fccfSAndroid Build Coastguard Worker
erofs_mkfs_feat_set_dedupe(bool en,const char * val,unsigned int vallen)293*33b1fccfSAndroid Build Coastguard Worker static int erofs_mkfs_feat_set_dedupe(bool en, const char *val,
294*33b1fccfSAndroid Build Coastguard Worker unsigned int vallen)
295*33b1fccfSAndroid Build Coastguard Worker {
296*33b1fccfSAndroid Build Coastguard Worker if (vallen)
297*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
298*33b1fccfSAndroid Build Coastguard Worker cfg.c_dedupe = en;
299*33b1fccfSAndroid Build Coastguard Worker return 0;
300*33b1fccfSAndroid Build Coastguard Worker }
301*33b1fccfSAndroid Build Coastguard Worker
302*33b1fccfSAndroid Build Coastguard Worker static struct {
303*33b1fccfSAndroid Build Coastguard Worker char *feat;
304*33b1fccfSAndroid Build Coastguard Worker int (*set)(bool en, const char *val, unsigned int len);
305*33b1fccfSAndroid Build Coastguard Worker } z_erofs_mkfs_features[] = {
306*33b1fccfSAndroid Build Coastguard Worker {"legacy-compress", erofs_mkfs_feat_set_legacy_compress},
307*33b1fccfSAndroid Build Coastguard Worker {"ztailpacking", erofs_mkfs_feat_set_ztailpacking},
308*33b1fccfSAndroid Build Coastguard Worker {"fragments", erofs_mkfs_feat_set_fragments},
309*33b1fccfSAndroid Build Coastguard Worker {"all-fragments", erofs_mkfs_feat_set_all_fragments},
310*33b1fccfSAndroid Build Coastguard Worker {"dedupe", erofs_mkfs_feat_set_dedupe},
311*33b1fccfSAndroid Build Coastguard Worker {NULL, NULL},
312*33b1fccfSAndroid Build Coastguard Worker };
313*33b1fccfSAndroid Build Coastguard Worker
parse_extended_opts(const char * opts)314*33b1fccfSAndroid Build Coastguard Worker static int parse_extended_opts(const char *opts)
315*33b1fccfSAndroid Build Coastguard Worker {
316*33b1fccfSAndroid Build Coastguard Worker #define MATCH_EXTENTED_OPT(opt, token, keylen) \
317*33b1fccfSAndroid Build Coastguard Worker (keylen == strlen(opt) && !memcmp(token, opt, keylen))
318*33b1fccfSAndroid Build Coastguard Worker
319*33b1fccfSAndroid Build Coastguard Worker const char *token, *next, *tokenend, *value __maybe_unused;
320*33b1fccfSAndroid Build Coastguard Worker unsigned int keylen, vallen;
321*33b1fccfSAndroid Build Coastguard Worker
322*33b1fccfSAndroid Build Coastguard Worker value = NULL;
323*33b1fccfSAndroid Build Coastguard Worker for (token = opts; *token != '\0'; token = next) {
324*33b1fccfSAndroid Build Coastguard Worker bool clear = false;
325*33b1fccfSAndroid Build Coastguard Worker const char *p = strchr(token, ',');
326*33b1fccfSAndroid Build Coastguard Worker
327*33b1fccfSAndroid Build Coastguard Worker next = NULL;
328*33b1fccfSAndroid Build Coastguard Worker if (p) {
329*33b1fccfSAndroid Build Coastguard Worker next = p + 1;
330*33b1fccfSAndroid Build Coastguard Worker } else {
331*33b1fccfSAndroid Build Coastguard Worker p = token + strlen(token);
332*33b1fccfSAndroid Build Coastguard Worker next = p;
333*33b1fccfSAndroid Build Coastguard Worker }
334*33b1fccfSAndroid Build Coastguard Worker
335*33b1fccfSAndroid Build Coastguard Worker tokenend = memchr(token, '=', p - token);
336*33b1fccfSAndroid Build Coastguard Worker if (tokenend) {
337*33b1fccfSAndroid Build Coastguard Worker keylen = tokenend - token;
338*33b1fccfSAndroid Build Coastguard Worker vallen = p - tokenend - 1;
339*33b1fccfSAndroid Build Coastguard Worker if (!vallen)
340*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
341*33b1fccfSAndroid Build Coastguard Worker
342*33b1fccfSAndroid Build Coastguard Worker value = tokenend + 1;
343*33b1fccfSAndroid Build Coastguard Worker } else {
344*33b1fccfSAndroid Build Coastguard Worker keylen = p - token;
345*33b1fccfSAndroid Build Coastguard Worker vallen = 0;
346*33b1fccfSAndroid Build Coastguard Worker }
347*33b1fccfSAndroid Build Coastguard Worker
348*33b1fccfSAndroid Build Coastguard Worker if (token[0] == '^') {
349*33b1fccfSAndroid Build Coastguard Worker if (keylen < 2)
350*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
351*33b1fccfSAndroid Build Coastguard Worker ++token;
352*33b1fccfSAndroid Build Coastguard Worker --keylen;
353*33b1fccfSAndroid Build Coastguard Worker clear = true;
354*33b1fccfSAndroid Build Coastguard Worker }
355*33b1fccfSAndroid Build Coastguard Worker
356*33b1fccfSAndroid Build Coastguard Worker if (MATCH_EXTENTED_OPT("force-inode-compact", token, keylen)) {
357*33b1fccfSAndroid Build Coastguard Worker if (vallen)
358*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
359*33b1fccfSAndroid Build Coastguard Worker cfg.c_force_inodeversion = FORCE_INODE_COMPACT;
360*33b1fccfSAndroid Build Coastguard Worker cfg.c_ignore_mtime = true;
361*33b1fccfSAndroid Build Coastguard Worker } else if (MATCH_EXTENTED_OPT("force-inode-extended", token, keylen)) {
362*33b1fccfSAndroid Build Coastguard Worker if (vallen)
363*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
364*33b1fccfSAndroid Build Coastguard Worker cfg.c_force_inodeversion = FORCE_INODE_EXTENDED;
365*33b1fccfSAndroid Build Coastguard Worker } else if (MATCH_EXTENTED_OPT("nosbcrc", token, keylen)) {
366*33b1fccfSAndroid Build Coastguard Worker if (vallen)
367*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
368*33b1fccfSAndroid Build Coastguard Worker erofs_sb_clear_sb_chksum(&g_sbi);
369*33b1fccfSAndroid Build Coastguard Worker } else if (MATCH_EXTENTED_OPT("noinline_data", token, keylen)) {
370*33b1fccfSAndroid Build Coastguard Worker if (vallen)
371*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
372*33b1fccfSAndroid Build Coastguard Worker cfg.c_inline_data = false;
373*33b1fccfSAndroid Build Coastguard Worker } else if (MATCH_EXTENTED_OPT("inline_data", token, keylen)) {
374*33b1fccfSAndroid Build Coastguard Worker if (vallen)
375*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
376*33b1fccfSAndroid Build Coastguard Worker cfg.c_inline_data = !clear;
377*33b1fccfSAndroid Build Coastguard Worker } else if (MATCH_EXTENTED_OPT("force-inode-blockmap", token, keylen)) {
378*33b1fccfSAndroid Build Coastguard Worker if (vallen)
379*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
380*33b1fccfSAndroid Build Coastguard Worker cfg.c_force_chunkformat = FORCE_INODE_BLOCK_MAP;
381*33b1fccfSAndroid Build Coastguard Worker } else if (MATCH_EXTENTED_OPT("force-chunk-indexes", token, keylen)) {
382*33b1fccfSAndroid Build Coastguard Worker if (vallen)
383*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
384*33b1fccfSAndroid Build Coastguard Worker cfg.c_force_chunkformat = FORCE_INODE_CHUNK_INDEXES;
385*33b1fccfSAndroid Build Coastguard Worker } else if (MATCH_EXTENTED_OPT("xattr-name-filter", token, keylen)) {
386*33b1fccfSAndroid Build Coastguard Worker if (vallen)
387*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
388*33b1fccfSAndroid Build Coastguard Worker cfg.c_xattr_name_filter = !clear;
389*33b1fccfSAndroid Build Coastguard Worker } else {
390*33b1fccfSAndroid Build Coastguard Worker int i, err;
391*33b1fccfSAndroid Build Coastguard Worker
392*33b1fccfSAndroid Build Coastguard Worker for (i = 0; z_erofs_mkfs_features[i].feat; ++i) {
393*33b1fccfSAndroid Build Coastguard Worker if (!MATCH_EXTENTED_OPT(z_erofs_mkfs_features[i].feat,
394*33b1fccfSAndroid Build Coastguard Worker token, keylen))
395*33b1fccfSAndroid Build Coastguard Worker continue;
396*33b1fccfSAndroid Build Coastguard Worker err = z_erofs_mkfs_features[i].set(!clear, value, vallen);
397*33b1fccfSAndroid Build Coastguard Worker if (err)
398*33b1fccfSAndroid Build Coastguard Worker return err;
399*33b1fccfSAndroid Build Coastguard Worker break;
400*33b1fccfSAndroid Build Coastguard Worker }
401*33b1fccfSAndroid Build Coastguard Worker
402*33b1fccfSAndroid Build Coastguard Worker if (!z_erofs_mkfs_features[i].feat) {
403*33b1fccfSAndroid Build Coastguard Worker erofs_err("unknown extended option %.*s",
404*33b1fccfSAndroid Build Coastguard Worker (int)(p - token), token);
405*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
406*33b1fccfSAndroid Build Coastguard Worker }
407*33b1fccfSAndroid Build Coastguard Worker }
408*33b1fccfSAndroid Build Coastguard Worker }
409*33b1fccfSAndroid Build Coastguard Worker return 0;
410*33b1fccfSAndroid Build Coastguard Worker }
411*33b1fccfSAndroid Build Coastguard Worker
mkfs_apply_zfeature_bits(uintmax_t bits)412*33b1fccfSAndroid Build Coastguard Worker static int mkfs_apply_zfeature_bits(uintmax_t bits)
413*33b1fccfSAndroid Build Coastguard Worker {
414*33b1fccfSAndroid Build Coastguard Worker int i;
415*33b1fccfSAndroid Build Coastguard Worker
416*33b1fccfSAndroid Build Coastguard Worker for (i = 0; bits; ++i) {
417*33b1fccfSAndroid Build Coastguard Worker int err;
418*33b1fccfSAndroid Build Coastguard Worker
419*33b1fccfSAndroid Build Coastguard Worker if (!z_erofs_mkfs_features[i].feat) {
420*33b1fccfSAndroid Build Coastguard Worker erofs_err("unsupported zfeature bit %u", i);
421*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
422*33b1fccfSAndroid Build Coastguard Worker }
423*33b1fccfSAndroid Build Coastguard Worker err = z_erofs_mkfs_features[i].set(bits & 1, NULL, 0);
424*33b1fccfSAndroid Build Coastguard Worker if (err) {
425*33b1fccfSAndroid Build Coastguard Worker erofs_err("failed to apply zfeature %s",
426*33b1fccfSAndroid Build Coastguard Worker z_erofs_mkfs_features[i].feat);
427*33b1fccfSAndroid Build Coastguard Worker return err;
428*33b1fccfSAndroid Build Coastguard Worker }
429*33b1fccfSAndroid Build Coastguard Worker bits >>= 1;
430*33b1fccfSAndroid Build Coastguard Worker }
431*33b1fccfSAndroid Build Coastguard Worker return 0;
432*33b1fccfSAndroid Build Coastguard Worker }
433*33b1fccfSAndroid Build Coastguard Worker
mkfs_parse_tar_cfg(char * cfg)434*33b1fccfSAndroid Build Coastguard Worker static void mkfs_parse_tar_cfg(char *cfg)
435*33b1fccfSAndroid Build Coastguard Worker {
436*33b1fccfSAndroid Build Coastguard Worker char *p;
437*33b1fccfSAndroid Build Coastguard Worker
438*33b1fccfSAndroid Build Coastguard Worker tar_mode = true;
439*33b1fccfSAndroid Build Coastguard Worker if (!cfg)
440*33b1fccfSAndroid Build Coastguard Worker return;
441*33b1fccfSAndroid Build Coastguard Worker p = strchr(cfg, ',');
442*33b1fccfSAndroid Build Coastguard Worker if (p) {
443*33b1fccfSAndroid Build Coastguard Worker *p = '\0';
444*33b1fccfSAndroid Build Coastguard Worker if ((*++p) != '\0')
445*33b1fccfSAndroid Build Coastguard Worker erofstar.mapfile = strdup(p);
446*33b1fccfSAndroid Build Coastguard Worker }
447*33b1fccfSAndroid Build Coastguard Worker if (!strcmp(cfg, "headerball"))
448*33b1fccfSAndroid Build Coastguard Worker erofstar.headeronly_mode = true;
449*33b1fccfSAndroid Build Coastguard Worker
450*33b1fccfSAndroid Build Coastguard Worker if (erofstar.headeronly_mode || !strcmp(optarg, "i") ||
451*33b1fccfSAndroid Build Coastguard Worker !strcmp(optarg, "0"))
452*33b1fccfSAndroid Build Coastguard Worker erofstar.index_mode = true;
453*33b1fccfSAndroid Build Coastguard Worker }
454*33b1fccfSAndroid Build Coastguard Worker
mkfs_parse_one_compress_alg(char * alg,struct erofs_compr_opts * copts)455*33b1fccfSAndroid Build Coastguard Worker static int mkfs_parse_one_compress_alg(char *alg,
456*33b1fccfSAndroid Build Coastguard Worker struct erofs_compr_opts *copts)
457*33b1fccfSAndroid Build Coastguard Worker {
458*33b1fccfSAndroid Build Coastguard Worker char *p, *q, *opt, *endptr;
459*33b1fccfSAndroid Build Coastguard Worker
460*33b1fccfSAndroid Build Coastguard Worker copts->level = -1;
461*33b1fccfSAndroid Build Coastguard Worker copts->dict_size = 0;
462*33b1fccfSAndroid Build Coastguard Worker
463*33b1fccfSAndroid Build Coastguard Worker p = strchr(alg, ',');
464*33b1fccfSAndroid Build Coastguard Worker if (p) {
465*33b1fccfSAndroid Build Coastguard Worker copts->alg = strndup(alg, p - alg);
466*33b1fccfSAndroid Build Coastguard Worker
467*33b1fccfSAndroid Build Coastguard Worker /* support old '-zlzma,9' form */
468*33b1fccfSAndroid Build Coastguard Worker if (isdigit(*(p + 1))) {
469*33b1fccfSAndroid Build Coastguard Worker copts->level = strtol(p + 1, &endptr, 10);
470*33b1fccfSAndroid Build Coastguard Worker if (*endptr && *endptr != ',') {
471*33b1fccfSAndroid Build Coastguard Worker erofs_err("invalid compression level %s",
472*33b1fccfSAndroid Build Coastguard Worker p + 1);
473*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
474*33b1fccfSAndroid Build Coastguard Worker }
475*33b1fccfSAndroid Build Coastguard Worker return 0;
476*33b1fccfSAndroid Build Coastguard Worker }
477*33b1fccfSAndroid Build Coastguard Worker } else {
478*33b1fccfSAndroid Build Coastguard Worker copts->alg = strdup(alg);
479*33b1fccfSAndroid Build Coastguard Worker return 0;
480*33b1fccfSAndroid Build Coastguard Worker }
481*33b1fccfSAndroid Build Coastguard Worker
482*33b1fccfSAndroid Build Coastguard Worker opt = p + 1;
483*33b1fccfSAndroid Build Coastguard Worker while (opt) {
484*33b1fccfSAndroid Build Coastguard Worker q = strchr(opt, ',');
485*33b1fccfSAndroid Build Coastguard Worker if (q)
486*33b1fccfSAndroid Build Coastguard Worker *q = '\0';
487*33b1fccfSAndroid Build Coastguard Worker
488*33b1fccfSAndroid Build Coastguard Worker if ((p = strstr(opt, "level="))) {
489*33b1fccfSAndroid Build Coastguard Worker p += strlen("level=");
490*33b1fccfSAndroid Build Coastguard Worker copts->level = strtol(p, &endptr, 10);
491*33b1fccfSAndroid Build Coastguard Worker if ((endptr == p) || (*endptr && *endptr != ',')) {
492*33b1fccfSAndroid Build Coastguard Worker erofs_err("invalid compression level %s", p);
493*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
494*33b1fccfSAndroid Build Coastguard Worker }
495*33b1fccfSAndroid Build Coastguard Worker } else if ((p = strstr(opt, "dictsize="))) {
496*33b1fccfSAndroid Build Coastguard Worker p += strlen("dictsize=");
497*33b1fccfSAndroid Build Coastguard Worker copts->dict_size = strtoul(p, &endptr, 10);
498*33b1fccfSAndroid Build Coastguard Worker if (*endptr == 'k' || *endptr == 'K')
499*33b1fccfSAndroid Build Coastguard Worker copts->dict_size <<= 10;
500*33b1fccfSAndroid Build Coastguard Worker else if (*endptr == 'm' || *endptr == 'M')
501*33b1fccfSAndroid Build Coastguard Worker copts->dict_size <<= 20;
502*33b1fccfSAndroid Build Coastguard Worker else if ((endptr == p) || (*endptr && *endptr != ',')) {
503*33b1fccfSAndroid Build Coastguard Worker erofs_err("invalid compression dictsize %s", p);
504*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
505*33b1fccfSAndroid Build Coastguard Worker }
506*33b1fccfSAndroid Build Coastguard Worker } else {
507*33b1fccfSAndroid Build Coastguard Worker erofs_err("invalid compression option %s", opt);
508*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
509*33b1fccfSAndroid Build Coastguard Worker }
510*33b1fccfSAndroid Build Coastguard Worker
511*33b1fccfSAndroid Build Coastguard Worker opt = q ? q + 1 : NULL;
512*33b1fccfSAndroid Build Coastguard Worker }
513*33b1fccfSAndroid Build Coastguard Worker
514*33b1fccfSAndroid Build Coastguard Worker return 0;
515*33b1fccfSAndroid Build Coastguard Worker }
516*33b1fccfSAndroid Build Coastguard Worker
mkfs_parse_compress_algs(char * algs)517*33b1fccfSAndroid Build Coastguard Worker static int mkfs_parse_compress_algs(char *algs)
518*33b1fccfSAndroid Build Coastguard Worker {
519*33b1fccfSAndroid Build Coastguard Worker unsigned int i;
520*33b1fccfSAndroid Build Coastguard Worker char *s;
521*33b1fccfSAndroid Build Coastguard Worker int ret;
522*33b1fccfSAndroid Build Coastguard Worker
523*33b1fccfSAndroid Build Coastguard Worker for (s = strtok(algs, ":"), i = 0; s; s = strtok(NULL, ":"), ++i) {
524*33b1fccfSAndroid Build Coastguard Worker if (i >= EROFS_MAX_COMPR_CFGS - 1) {
525*33b1fccfSAndroid Build Coastguard Worker erofs_err("too many algorithm types");
526*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
527*33b1fccfSAndroid Build Coastguard Worker }
528*33b1fccfSAndroid Build Coastguard Worker
529*33b1fccfSAndroid Build Coastguard Worker ret = mkfs_parse_one_compress_alg(s, &cfg.c_compr_opts[i]);
530*33b1fccfSAndroid Build Coastguard Worker if (ret)
531*33b1fccfSAndroid Build Coastguard Worker return ret;
532*33b1fccfSAndroid Build Coastguard Worker }
533*33b1fccfSAndroid Build Coastguard Worker return 0;
534*33b1fccfSAndroid Build Coastguard Worker }
535*33b1fccfSAndroid Build Coastguard Worker
erofs_rebuild_cleanup(void)536*33b1fccfSAndroid Build Coastguard Worker static void erofs_rebuild_cleanup(void)
537*33b1fccfSAndroid Build Coastguard Worker {
538*33b1fccfSAndroid Build Coastguard Worker struct erofs_sb_info *src, *n;
539*33b1fccfSAndroid Build Coastguard Worker
540*33b1fccfSAndroid Build Coastguard Worker list_for_each_entry_safe(src, n, &rebuild_src_list, list) {
541*33b1fccfSAndroid Build Coastguard Worker list_del(&src->list);
542*33b1fccfSAndroid Build Coastguard Worker erofs_put_super(src);
543*33b1fccfSAndroid Build Coastguard Worker erofs_dev_close(src);
544*33b1fccfSAndroid Build Coastguard Worker free(src);
545*33b1fccfSAndroid Build Coastguard Worker }
546*33b1fccfSAndroid Build Coastguard Worker rebuild_src_count = 0;
547*33b1fccfSAndroid Build Coastguard Worker }
548*33b1fccfSAndroid Build Coastguard Worker
mkfs_parse_options_cfg(int argc,char * argv[])549*33b1fccfSAndroid Build Coastguard Worker static int mkfs_parse_options_cfg(int argc, char *argv[])
550*33b1fccfSAndroid Build Coastguard Worker {
551*33b1fccfSAndroid Build Coastguard Worker char *endptr;
552*33b1fccfSAndroid Build Coastguard Worker int opt, i, err;
553*33b1fccfSAndroid Build Coastguard Worker bool quiet = false;
554*33b1fccfSAndroid Build Coastguard Worker int tarerofs_decoder = 0;
555*33b1fccfSAndroid Build Coastguard Worker bool has_timestamp = false;
556*33b1fccfSAndroid Build Coastguard Worker
557*33b1fccfSAndroid Build Coastguard Worker while ((opt = getopt_long(argc, argv, "C:E:L:T:U:b:d:x:z:Vh",
558*33b1fccfSAndroid Build Coastguard Worker long_options, NULL)) != -1) {
559*33b1fccfSAndroid Build Coastguard Worker switch (opt) {
560*33b1fccfSAndroid Build Coastguard Worker case 'z':
561*33b1fccfSAndroid Build Coastguard Worker i = mkfs_parse_compress_algs(optarg);
562*33b1fccfSAndroid Build Coastguard Worker if (i)
563*33b1fccfSAndroid Build Coastguard Worker return i;
564*33b1fccfSAndroid Build Coastguard Worker break;
565*33b1fccfSAndroid Build Coastguard Worker
566*33b1fccfSAndroid Build Coastguard Worker case 'b':
567*33b1fccfSAndroid Build Coastguard Worker i = atoi(optarg);
568*33b1fccfSAndroid Build Coastguard Worker if (i < 512 || i > EROFS_MAX_BLOCK_SIZE) {
569*33b1fccfSAndroid Build Coastguard Worker erofs_err("invalid block size %s", optarg);
570*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
571*33b1fccfSAndroid Build Coastguard Worker }
572*33b1fccfSAndroid Build Coastguard Worker g_sbi.blkszbits = ilog2(i);
573*33b1fccfSAndroid Build Coastguard Worker break;
574*33b1fccfSAndroid Build Coastguard Worker
575*33b1fccfSAndroid Build Coastguard Worker case 'd':
576*33b1fccfSAndroid Build Coastguard Worker i = atoi(optarg);
577*33b1fccfSAndroid Build Coastguard Worker if (i < EROFS_MSG_MIN || i > EROFS_MSG_MAX) {
578*33b1fccfSAndroid Build Coastguard Worker erofs_err("invalid debug level %d", i);
579*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
580*33b1fccfSAndroid Build Coastguard Worker }
581*33b1fccfSAndroid Build Coastguard Worker cfg.c_dbg_lvl = i;
582*33b1fccfSAndroid Build Coastguard Worker break;
583*33b1fccfSAndroid Build Coastguard Worker
584*33b1fccfSAndroid Build Coastguard Worker case 'x':
585*33b1fccfSAndroid Build Coastguard Worker i = strtol(optarg, &endptr, 0);
586*33b1fccfSAndroid Build Coastguard Worker if (*endptr != '\0') {
587*33b1fccfSAndroid Build Coastguard Worker erofs_err("invalid xattr tolerance %s", optarg);
588*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
589*33b1fccfSAndroid Build Coastguard Worker }
590*33b1fccfSAndroid Build Coastguard Worker cfg.c_inline_xattr_tolerance = i;
591*33b1fccfSAndroid Build Coastguard Worker break;
592*33b1fccfSAndroid Build Coastguard Worker
593*33b1fccfSAndroid Build Coastguard Worker case 'E':
594*33b1fccfSAndroid Build Coastguard Worker opt = parse_extended_opts(optarg);
595*33b1fccfSAndroid Build Coastguard Worker if (opt)
596*33b1fccfSAndroid Build Coastguard Worker return opt;
597*33b1fccfSAndroid Build Coastguard Worker break;
598*33b1fccfSAndroid Build Coastguard Worker
599*33b1fccfSAndroid Build Coastguard Worker case 'L':
600*33b1fccfSAndroid Build Coastguard Worker if (optarg == NULL ||
601*33b1fccfSAndroid Build Coastguard Worker strlen(optarg) > sizeof(g_sbi.volume_name)) {
602*33b1fccfSAndroid Build Coastguard Worker erofs_err("invalid volume label");
603*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
604*33b1fccfSAndroid Build Coastguard Worker }
605*33b1fccfSAndroid Build Coastguard Worker strncpy(g_sbi.volume_name, optarg,
606*33b1fccfSAndroid Build Coastguard Worker sizeof(g_sbi.volume_name));
607*33b1fccfSAndroid Build Coastguard Worker break;
608*33b1fccfSAndroid Build Coastguard Worker
609*33b1fccfSAndroid Build Coastguard Worker case 'T':
610*33b1fccfSAndroid Build Coastguard Worker cfg.c_unix_timestamp = strtoull(optarg, &endptr, 0);
611*33b1fccfSAndroid Build Coastguard Worker if (cfg.c_unix_timestamp == -1 || *endptr != '\0') {
612*33b1fccfSAndroid Build Coastguard Worker erofs_err("invalid UNIX timestamp %s", optarg);
613*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
614*33b1fccfSAndroid Build Coastguard Worker }
615*33b1fccfSAndroid Build Coastguard Worker has_timestamp = true;
616*33b1fccfSAndroid Build Coastguard Worker break;
617*33b1fccfSAndroid Build Coastguard Worker case 'U':
618*33b1fccfSAndroid Build Coastguard Worker if (erofs_uuid_parse(optarg, fixeduuid)) {
619*33b1fccfSAndroid Build Coastguard Worker erofs_err("invalid UUID %s", optarg);
620*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
621*33b1fccfSAndroid Build Coastguard Worker }
622*33b1fccfSAndroid Build Coastguard Worker valid_fixeduuid = true;
623*33b1fccfSAndroid Build Coastguard Worker break;
624*33b1fccfSAndroid Build Coastguard Worker case 2:
625*33b1fccfSAndroid Build Coastguard Worker opt = erofs_parse_exclude_path(optarg, false);
626*33b1fccfSAndroid Build Coastguard Worker if (opt) {
627*33b1fccfSAndroid Build Coastguard Worker erofs_err("failed to parse exclude path: %s",
628*33b1fccfSAndroid Build Coastguard Worker erofs_strerror(opt));
629*33b1fccfSAndroid Build Coastguard Worker return opt;
630*33b1fccfSAndroid Build Coastguard Worker }
631*33b1fccfSAndroid Build Coastguard Worker break;
632*33b1fccfSAndroid Build Coastguard Worker case 3:
633*33b1fccfSAndroid Build Coastguard Worker opt = erofs_parse_exclude_path(optarg, true);
634*33b1fccfSAndroid Build Coastguard Worker if (opt) {
635*33b1fccfSAndroid Build Coastguard Worker erofs_err("failed to parse exclude regex: %s",
636*33b1fccfSAndroid Build Coastguard Worker erofs_strerror(opt));
637*33b1fccfSAndroid Build Coastguard Worker return opt;
638*33b1fccfSAndroid Build Coastguard Worker }
639*33b1fccfSAndroid Build Coastguard Worker break;
640*33b1fccfSAndroid Build Coastguard Worker
641*33b1fccfSAndroid Build Coastguard Worker case 4:
642*33b1fccfSAndroid Build Coastguard Worker opt = erofs_selabel_open(optarg);
643*33b1fccfSAndroid Build Coastguard Worker if (opt && opt != -EBUSY)
644*33b1fccfSAndroid Build Coastguard Worker return opt;
645*33b1fccfSAndroid Build Coastguard Worker break;
646*33b1fccfSAndroid Build Coastguard Worker case 5:
647*33b1fccfSAndroid Build Coastguard Worker cfg.c_uid = strtoul(optarg, &endptr, 0);
648*33b1fccfSAndroid Build Coastguard Worker if (cfg.c_uid == -1 || *endptr != '\0') {
649*33b1fccfSAndroid Build Coastguard Worker erofs_err("invalid uid %s", optarg);
650*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
651*33b1fccfSAndroid Build Coastguard Worker }
652*33b1fccfSAndroid Build Coastguard Worker break;
653*33b1fccfSAndroid Build Coastguard Worker case 6:
654*33b1fccfSAndroid Build Coastguard Worker cfg.c_gid = strtoul(optarg, &endptr, 0);
655*33b1fccfSAndroid Build Coastguard Worker if (cfg.c_gid == -1 || *endptr != '\0') {
656*33b1fccfSAndroid Build Coastguard Worker erofs_err("invalid gid %s", optarg);
657*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
658*33b1fccfSAndroid Build Coastguard Worker }
659*33b1fccfSAndroid Build Coastguard Worker break;
660*33b1fccfSAndroid Build Coastguard Worker case 7:
661*33b1fccfSAndroid Build Coastguard Worker cfg.c_uid = cfg.c_gid = 0;
662*33b1fccfSAndroid Build Coastguard Worker break;
663*33b1fccfSAndroid Build Coastguard Worker #ifndef NDEBUG
664*33b1fccfSAndroid Build Coastguard Worker case 8:
665*33b1fccfSAndroid Build Coastguard Worker cfg.c_random_pclusterblks = true;
666*33b1fccfSAndroid Build Coastguard Worker break;
667*33b1fccfSAndroid Build Coastguard Worker case 18:
668*33b1fccfSAndroid Build Coastguard Worker cfg.c_random_algorithms = true;
669*33b1fccfSAndroid Build Coastguard Worker break;
670*33b1fccfSAndroid Build Coastguard Worker #endif
671*33b1fccfSAndroid Build Coastguard Worker case 9:
672*33b1fccfSAndroid Build Coastguard Worker cfg.c_max_decompressed_extent_bytes =
673*33b1fccfSAndroid Build Coastguard Worker strtoul(optarg, &endptr, 0);
674*33b1fccfSAndroid Build Coastguard Worker if (*endptr != '\0') {
675*33b1fccfSAndroid Build Coastguard Worker erofs_err("invalid maximum uncompressed extent size %s",
676*33b1fccfSAndroid Build Coastguard Worker optarg);
677*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
678*33b1fccfSAndroid Build Coastguard Worker }
679*33b1fccfSAndroid Build Coastguard Worker break;
680*33b1fccfSAndroid Build Coastguard Worker case 10:
681*33b1fccfSAndroid Build Coastguard Worker cfg.c_compress_hints_file = optarg;
682*33b1fccfSAndroid Build Coastguard Worker break;
683*33b1fccfSAndroid Build Coastguard Worker case 512:
684*33b1fccfSAndroid Build Coastguard Worker cfg.mount_point = optarg;
685*33b1fccfSAndroid Build Coastguard Worker /* all trailing '/' should be deleted */
686*33b1fccfSAndroid Build Coastguard Worker opt = strlen(cfg.mount_point);
687*33b1fccfSAndroid Build Coastguard Worker if (opt && optarg[opt - 1] == '/')
688*33b1fccfSAndroid Build Coastguard Worker optarg[opt - 1] = '\0';
689*33b1fccfSAndroid Build Coastguard Worker break;
690*33b1fccfSAndroid Build Coastguard Worker #ifdef WITH_ANDROID
691*33b1fccfSAndroid Build Coastguard Worker case 513:
692*33b1fccfSAndroid Build Coastguard Worker cfg.target_out_path = optarg;
693*33b1fccfSAndroid Build Coastguard Worker break;
694*33b1fccfSAndroid Build Coastguard Worker case 514:
695*33b1fccfSAndroid Build Coastguard Worker cfg.fs_config_file = optarg;
696*33b1fccfSAndroid Build Coastguard Worker break;
697*33b1fccfSAndroid Build Coastguard Worker case 515:
698*33b1fccfSAndroid Build Coastguard Worker cfg.block_list_file = optarg;
699*33b1fccfSAndroid Build Coastguard Worker break;
700*33b1fccfSAndroid Build Coastguard Worker #endif
701*33b1fccfSAndroid Build Coastguard Worker case 'C':
702*33b1fccfSAndroid Build Coastguard Worker i = strtoull(optarg, &endptr, 0);
703*33b1fccfSAndroid Build Coastguard Worker if (*endptr != '\0') {
704*33b1fccfSAndroid Build Coastguard Worker erofs_err("invalid physical clustersize %s",
705*33b1fccfSAndroid Build Coastguard Worker optarg);
706*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
707*33b1fccfSAndroid Build Coastguard Worker }
708*33b1fccfSAndroid Build Coastguard Worker pclustersize_max = i;
709*33b1fccfSAndroid Build Coastguard Worker break;
710*33b1fccfSAndroid Build Coastguard Worker case 11:
711*33b1fccfSAndroid Build Coastguard Worker i = strtol(optarg, &endptr, 0);
712*33b1fccfSAndroid Build Coastguard Worker if (*endptr != '\0') {
713*33b1fccfSAndroid Build Coastguard Worker erofs_err("invalid chunksize %s", optarg);
714*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
715*33b1fccfSAndroid Build Coastguard Worker }
716*33b1fccfSAndroid Build Coastguard Worker cfg.c_chunkbits = ilog2(i);
717*33b1fccfSAndroid Build Coastguard Worker if ((1 << cfg.c_chunkbits) != i) {
718*33b1fccfSAndroid Build Coastguard Worker erofs_err("chunksize %s must be a power of two",
719*33b1fccfSAndroid Build Coastguard Worker optarg);
720*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
721*33b1fccfSAndroid Build Coastguard Worker }
722*33b1fccfSAndroid Build Coastguard Worker erofs_sb_set_chunked_file(&g_sbi);
723*33b1fccfSAndroid Build Coastguard Worker break;
724*33b1fccfSAndroid Build Coastguard Worker case 12:
725*33b1fccfSAndroid Build Coastguard Worker quiet = true;
726*33b1fccfSAndroid Build Coastguard Worker break;
727*33b1fccfSAndroid Build Coastguard Worker case 13:
728*33b1fccfSAndroid Build Coastguard Worker cfg.c_blobdev_path = optarg;
729*33b1fccfSAndroid Build Coastguard Worker break;
730*33b1fccfSAndroid Build Coastguard Worker case 14:
731*33b1fccfSAndroid Build Coastguard Worker cfg.c_ignore_mtime = true;
732*33b1fccfSAndroid Build Coastguard Worker break;
733*33b1fccfSAndroid Build Coastguard Worker case 15:
734*33b1fccfSAndroid Build Coastguard Worker cfg.c_ignore_mtime = false;
735*33b1fccfSAndroid Build Coastguard Worker break;
736*33b1fccfSAndroid Build Coastguard Worker case 16:
737*33b1fccfSAndroid Build Coastguard Worker errno = 0;
738*33b1fccfSAndroid Build Coastguard Worker cfg.c_uid_offset = strtoll(optarg, &endptr, 0);
739*33b1fccfSAndroid Build Coastguard Worker if (errno || *endptr != '\0') {
740*33b1fccfSAndroid Build Coastguard Worker erofs_err("invalid uid offset %s", optarg);
741*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
742*33b1fccfSAndroid Build Coastguard Worker }
743*33b1fccfSAndroid Build Coastguard Worker break;
744*33b1fccfSAndroid Build Coastguard Worker case 17:
745*33b1fccfSAndroid Build Coastguard Worker errno = 0;
746*33b1fccfSAndroid Build Coastguard Worker cfg.c_gid_offset = strtoll(optarg, &endptr, 0);
747*33b1fccfSAndroid Build Coastguard Worker if (errno || *endptr != '\0') {
748*33b1fccfSAndroid Build Coastguard Worker erofs_err("invalid gid offset %s", optarg);
749*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
750*33b1fccfSAndroid Build Coastguard Worker }
751*33b1fccfSAndroid Build Coastguard Worker break;
752*33b1fccfSAndroid Build Coastguard Worker case 19:
753*33b1fccfSAndroid Build Coastguard Worker errno = 0;
754*33b1fccfSAndroid Build Coastguard Worker opt = erofs_xattr_insert_name_prefix(optarg);
755*33b1fccfSAndroid Build Coastguard Worker if (opt) {
756*33b1fccfSAndroid Build Coastguard Worker erofs_err("failed to parse xattr name prefix: %s",
757*33b1fccfSAndroid Build Coastguard Worker erofs_strerror(opt));
758*33b1fccfSAndroid Build Coastguard Worker return opt;
759*33b1fccfSAndroid Build Coastguard Worker }
760*33b1fccfSAndroid Build Coastguard Worker cfg.c_extra_ea_name_prefixes = true;
761*33b1fccfSAndroid Build Coastguard Worker break;
762*33b1fccfSAndroid Build Coastguard Worker case 20:
763*33b1fccfSAndroid Build Coastguard Worker mkfs_parse_tar_cfg(optarg);
764*33b1fccfSAndroid Build Coastguard Worker break;
765*33b1fccfSAndroid Build Coastguard Worker case 21:
766*33b1fccfSAndroid Build Coastguard Worker erofstar.aufs = true;
767*33b1fccfSAndroid Build Coastguard Worker break;
768*33b1fccfSAndroid Build Coastguard Worker case 516:
769*33b1fccfSAndroid Build Coastguard Worker if (!optarg || !strcmp(optarg, "1"))
770*33b1fccfSAndroid Build Coastguard Worker cfg.c_ovlfs_strip = true;
771*33b1fccfSAndroid Build Coastguard Worker else
772*33b1fccfSAndroid Build Coastguard Worker cfg.c_ovlfs_strip = false;
773*33b1fccfSAndroid Build Coastguard Worker break;
774*33b1fccfSAndroid Build Coastguard Worker case 517:
775*33b1fccfSAndroid Build Coastguard Worker g_sbi.bdev.offset = strtoull(optarg, &endptr, 0);
776*33b1fccfSAndroid Build Coastguard Worker if (*endptr != '\0') {
777*33b1fccfSAndroid Build Coastguard Worker erofs_err("invalid disk offset %s", optarg);
778*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
779*33b1fccfSAndroid Build Coastguard Worker }
780*33b1fccfSAndroid Build Coastguard Worker break;
781*33b1fccfSAndroid Build Coastguard Worker case 518:
782*33b1fccfSAndroid Build Coastguard Worker case 519:
783*33b1fccfSAndroid Build Coastguard Worker if (optarg)
784*33b1fccfSAndroid Build Coastguard Worker erofstar.dumpfile = strdup(optarg);
785*33b1fccfSAndroid Build Coastguard Worker tarerofs_decoder = EROFS_IOS_DECODER_GZIP + (opt - 518);
786*33b1fccfSAndroid Build Coastguard Worker break;
787*33b1fccfSAndroid Build Coastguard Worker #ifdef EROFS_MT_ENABLED
788*33b1fccfSAndroid Build Coastguard Worker case 520: {
789*33b1fccfSAndroid Build Coastguard Worker unsigned int processors;
790*33b1fccfSAndroid Build Coastguard Worker
791*33b1fccfSAndroid Build Coastguard Worker cfg.c_mt_workers = strtoul(optarg, &endptr, 0);
792*33b1fccfSAndroid Build Coastguard Worker if (errno || *endptr != '\0') {
793*33b1fccfSAndroid Build Coastguard Worker erofs_err("invalid worker number %s", optarg);
794*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
795*33b1fccfSAndroid Build Coastguard Worker }
796*33b1fccfSAndroid Build Coastguard Worker
797*33b1fccfSAndroid Build Coastguard Worker processors = erofs_get_available_processors();
798*33b1fccfSAndroid Build Coastguard Worker if (cfg.c_mt_workers > processors)
799*33b1fccfSAndroid Build Coastguard Worker erofs_warn("%d workers exceed %d processors, potentially impacting performance.",
800*33b1fccfSAndroid Build Coastguard Worker cfg.c_mt_workers, processors);
801*33b1fccfSAndroid Build Coastguard Worker break;
802*33b1fccfSAndroid Build Coastguard Worker }
803*33b1fccfSAndroid Build Coastguard Worker #endif
804*33b1fccfSAndroid Build Coastguard Worker case 521:
805*33b1fccfSAndroid Build Coastguard Worker i = strtol(optarg, &endptr, 0);
806*33b1fccfSAndroid Build Coastguard Worker if (errno || *endptr != '\0') {
807*33b1fccfSAndroid Build Coastguard Worker erofs_err("invalid zfeature bits %s", optarg);
808*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
809*33b1fccfSAndroid Build Coastguard Worker }
810*33b1fccfSAndroid Build Coastguard Worker err = mkfs_apply_zfeature_bits(i);
811*33b1fccfSAndroid Build Coastguard Worker if (err)
812*33b1fccfSAndroid Build Coastguard Worker return err;
813*33b1fccfSAndroid Build Coastguard Worker break;
814*33b1fccfSAndroid Build Coastguard Worker case 522:
815*33b1fccfSAndroid Build Coastguard Worker case 523:
816*33b1fccfSAndroid Build Coastguard Worker if (!optarg || !strcmp(optarg, "data")) {
817*33b1fccfSAndroid Build Coastguard Worker dataimport_mode = EROFS_MKFS_DATA_IMPORT_FULLDATA;
818*33b1fccfSAndroid Build Coastguard Worker } else if (!strcmp(optarg, "rvsp")) {
819*33b1fccfSAndroid Build Coastguard Worker dataimport_mode = EROFS_MKFS_DATA_IMPORT_RVSP;
820*33b1fccfSAndroid Build Coastguard Worker } else {
821*33b1fccfSAndroid Build Coastguard Worker dataimport_mode = strtol(optarg, &endptr, 0);
822*33b1fccfSAndroid Build Coastguard Worker if (errno || *endptr != '\0') {
823*33b1fccfSAndroid Build Coastguard Worker erofs_err("invalid --%s=%s",
824*33b1fccfSAndroid Build Coastguard Worker opt == 523 ? "incremental" : "clean", optarg);
825*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
826*33b1fccfSAndroid Build Coastguard Worker }
827*33b1fccfSAndroid Build Coastguard Worker }
828*33b1fccfSAndroid Build Coastguard Worker incremental_mode = (opt == 523);
829*33b1fccfSAndroid Build Coastguard Worker break;
830*33b1fccfSAndroid Build Coastguard Worker case 524:
831*33b1fccfSAndroid Build Coastguard Worker cfg.c_root_xattr_isize = strtoull(optarg, &endptr, 0);
832*33b1fccfSAndroid Build Coastguard Worker if (*endptr != '\0') {
833*33b1fccfSAndroid Build Coastguard Worker erofs_err("invalid the minimum inline xattr size %s", optarg);
834*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
835*33b1fccfSAndroid Build Coastguard Worker }
836*33b1fccfSAndroid Build Coastguard Worker break;
837*33b1fccfSAndroid Build Coastguard Worker case 525:
838*33b1fccfSAndroid Build Coastguard Worker cfg.c_timeinherit = TIMESTAMP_NONE;
839*33b1fccfSAndroid Build Coastguard Worker break;
840*33b1fccfSAndroid Build Coastguard Worker case 526:
841*33b1fccfSAndroid Build Coastguard Worker cfg.c_timeinherit = TIMESTAMP_FIXED;
842*33b1fccfSAndroid Build Coastguard Worker break;
843*33b1fccfSAndroid Build Coastguard Worker case 'V':
844*33b1fccfSAndroid Build Coastguard Worker version();
845*33b1fccfSAndroid Build Coastguard Worker exit(0);
846*33b1fccfSAndroid Build Coastguard Worker case 'h':
847*33b1fccfSAndroid Build Coastguard Worker usage(argc, argv);
848*33b1fccfSAndroid Build Coastguard Worker exit(0);
849*33b1fccfSAndroid Build Coastguard Worker
850*33b1fccfSAndroid Build Coastguard Worker default: /* '?' */
851*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
852*33b1fccfSAndroid Build Coastguard Worker }
853*33b1fccfSAndroid Build Coastguard Worker }
854*33b1fccfSAndroid Build Coastguard Worker
855*33b1fccfSAndroid Build Coastguard Worker if (cfg.c_blobdev_path && cfg.c_chunkbits < g_sbi.blkszbits) {
856*33b1fccfSAndroid Build Coastguard Worker erofs_err("--blobdev must be used together with --chunksize");
857*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
858*33b1fccfSAndroid Build Coastguard Worker }
859*33b1fccfSAndroid Build Coastguard Worker
860*33b1fccfSAndroid Build Coastguard Worker /* TODO: can be implemented with (deviceslot) mapped_blkaddr */
861*33b1fccfSAndroid Build Coastguard Worker if (cfg.c_blobdev_path &&
862*33b1fccfSAndroid Build Coastguard Worker cfg.c_force_chunkformat == FORCE_INODE_BLOCK_MAP) {
863*33b1fccfSAndroid Build Coastguard Worker erofs_err("--blobdev cannot work with block map currently");
864*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
865*33b1fccfSAndroid Build Coastguard Worker }
866*33b1fccfSAndroid Build Coastguard Worker
867*33b1fccfSAndroid Build Coastguard Worker if (optind >= argc) {
868*33b1fccfSAndroid Build Coastguard Worker erofs_err("missing argument: FILE");
869*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
870*33b1fccfSAndroid Build Coastguard Worker }
871*33b1fccfSAndroid Build Coastguard Worker
872*33b1fccfSAndroid Build Coastguard Worker cfg.c_img_path = strdup(argv[optind++]);
873*33b1fccfSAndroid Build Coastguard Worker if (!cfg.c_img_path)
874*33b1fccfSAndroid Build Coastguard Worker return -ENOMEM;
875*33b1fccfSAndroid Build Coastguard Worker
876*33b1fccfSAndroid Build Coastguard Worker if (optind >= argc) {
877*33b1fccfSAndroid Build Coastguard Worker if (!tar_mode) {
878*33b1fccfSAndroid Build Coastguard Worker erofs_err("missing argument: SOURCE(s)");
879*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
880*33b1fccfSAndroid Build Coastguard Worker } else {
881*33b1fccfSAndroid Build Coastguard Worker int dupfd;
882*33b1fccfSAndroid Build Coastguard Worker
883*33b1fccfSAndroid Build Coastguard Worker dupfd = dup(STDIN_FILENO);
884*33b1fccfSAndroid Build Coastguard Worker if (dupfd < 0) {
885*33b1fccfSAndroid Build Coastguard Worker erofs_err("failed to duplicate STDIN_FILENO: %s",
886*33b1fccfSAndroid Build Coastguard Worker strerror(errno));
887*33b1fccfSAndroid Build Coastguard Worker return -errno;
888*33b1fccfSAndroid Build Coastguard Worker }
889*33b1fccfSAndroid Build Coastguard Worker err = erofs_iostream_open(&erofstar.ios, dupfd,
890*33b1fccfSAndroid Build Coastguard Worker tarerofs_decoder);
891*33b1fccfSAndroid Build Coastguard Worker if (err)
892*33b1fccfSAndroid Build Coastguard Worker return err;
893*33b1fccfSAndroid Build Coastguard Worker }
894*33b1fccfSAndroid Build Coastguard Worker } else {
895*33b1fccfSAndroid Build Coastguard Worker struct stat st;
896*33b1fccfSAndroid Build Coastguard Worker
897*33b1fccfSAndroid Build Coastguard Worker cfg.c_src_path = realpath(argv[optind++], NULL);
898*33b1fccfSAndroid Build Coastguard Worker if (!cfg.c_src_path) {
899*33b1fccfSAndroid Build Coastguard Worker erofs_err("failed to parse source directory: %s",
900*33b1fccfSAndroid Build Coastguard Worker erofs_strerror(-errno));
901*33b1fccfSAndroid Build Coastguard Worker return -ENOENT;
902*33b1fccfSAndroid Build Coastguard Worker }
903*33b1fccfSAndroid Build Coastguard Worker
904*33b1fccfSAndroid Build Coastguard Worker if (tar_mode) {
905*33b1fccfSAndroid Build Coastguard Worker int fd = open(cfg.c_src_path, O_RDONLY);
906*33b1fccfSAndroid Build Coastguard Worker
907*33b1fccfSAndroid Build Coastguard Worker if (fd < 0) {
908*33b1fccfSAndroid Build Coastguard Worker erofs_err("failed to open file: %s", cfg.c_src_path);
909*33b1fccfSAndroid Build Coastguard Worker return -errno;
910*33b1fccfSAndroid Build Coastguard Worker }
911*33b1fccfSAndroid Build Coastguard Worker err = erofs_iostream_open(&erofstar.ios, fd,
912*33b1fccfSAndroid Build Coastguard Worker tarerofs_decoder);
913*33b1fccfSAndroid Build Coastguard Worker if (err)
914*33b1fccfSAndroid Build Coastguard Worker return err;
915*33b1fccfSAndroid Build Coastguard Worker
916*33b1fccfSAndroid Build Coastguard Worker if (erofstar.dumpfile) {
917*33b1fccfSAndroid Build Coastguard Worker fd = open(erofstar.dumpfile,
918*33b1fccfSAndroid Build Coastguard Worker O_WRONLY | O_CREAT | O_TRUNC, 0644);
919*33b1fccfSAndroid Build Coastguard Worker if (fd < 0) {
920*33b1fccfSAndroid Build Coastguard Worker erofs_err("failed to open dumpfile: %s",
921*33b1fccfSAndroid Build Coastguard Worker erofstar.dumpfile);
922*33b1fccfSAndroid Build Coastguard Worker return -errno;
923*33b1fccfSAndroid Build Coastguard Worker }
924*33b1fccfSAndroid Build Coastguard Worker erofstar.ios.dumpfd = fd;
925*33b1fccfSAndroid Build Coastguard Worker }
926*33b1fccfSAndroid Build Coastguard Worker } else {
927*33b1fccfSAndroid Build Coastguard Worker err = lstat(cfg.c_src_path, &st);
928*33b1fccfSAndroid Build Coastguard Worker if (err)
929*33b1fccfSAndroid Build Coastguard Worker return -errno;
930*33b1fccfSAndroid Build Coastguard Worker if (S_ISDIR(st.st_mode))
931*33b1fccfSAndroid Build Coastguard Worker erofs_set_fs_root(cfg.c_src_path);
932*33b1fccfSAndroid Build Coastguard Worker else
933*33b1fccfSAndroid Build Coastguard Worker rebuild_mode = true;
934*33b1fccfSAndroid Build Coastguard Worker }
935*33b1fccfSAndroid Build Coastguard Worker
936*33b1fccfSAndroid Build Coastguard Worker if (rebuild_mode) {
937*33b1fccfSAndroid Build Coastguard Worker char *srcpath = cfg.c_src_path;
938*33b1fccfSAndroid Build Coastguard Worker struct erofs_sb_info *src;
939*33b1fccfSAndroid Build Coastguard Worker
940*33b1fccfSAndroid Build Coastguard Worker do {
941*33b1fccfSAndroid Build Coastguard Worker src = calloc(1, sizeof(struct erofs_sb_info));
942*33b1fccfSAndroid Build Coastguard Worker if (!src) {
943*33b1fccfSAndroid Build Coastguard Worker erofs_rebuild_cleanup();
944*33b1fccfSAndroid Build Coastguard Worker return -ENOMEM;
945*33b1fccfSAndroid Build Coastguard Worker }
946*33b1fccfSAndroid Build Coastguard Worker
947*33b1fccfSAndroid Build Coastguard Worker err = erofs_dev_open(src, srcpath, O_RDONLY);
948*33b1fccfSAndroid Build Coastguard Worker if (err) {
949*33b1fccfSAndroid Build Coastguard Worker free(src);
950*33b1fccfSAndroid Build Coastguard Worker erofs_rebuild_cleanup();
951*33b1fccfSAndroid Build Coastguard Worker return err;
952*33b1fccfSAndroid Build Coastguard Worker }
953*33b1fccfSAndroid Build Coastguard Worker
954*33b1fccfSAndroid Build Coastguard Worker /* extra device index starts from 1 */
955*33b1fccfSAndroid Build Coastguard Worker src->dev = ++rebuild_src_count;
956*33b1fccfSAndroid Build Coastguard Worker list_add(&src->list, &rebuild_src_list);
957*33b1fccfSAndroid Build Coastguard Worker } while (optind < argc && (srcpath = argv[optind++]));
958*33b1fccfSAndroid Build Coastguard Worker } else if (optind < argc) {
959*33b1fccfSAndroid Build Coastguard Worker erofs_err("unexpected argument: %s\n", argv[optind]);
960*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
961*33b1fccfSAndroid Build Coastguard Worker }
962*33b1fccfSAndroid Build Coastguard Worker }
963*33b1fccfSAndroid Build Coastguard Worker if (quiet) {
964*33b1fccfSAndroid Build Coastguard Worker cfg.c_dbg_lvl = EROFS_ERR;
965*33b1fccfSAndroid Build Coastguard Worker cfg.c_showprogress = false;
966*33b1fccfSAndroid Build Coastguard Worker }
967*33b1fccfSAndroid Build Coastguard Worker
968*33b1fccfSAndroid Build Coastguard Worker if (cfg.c_compr_opts[0].alg && erofs_blksiz(&g_sbi) != getpagesize())
969*33b1fccfSAndroid Build Coastguard Worker erofs_warn("Please note that subpage blocksize with compression isn't yet supported in kernel. "
970*33b1fccfSAndroid Build Coastguard Worker "This compressed image will only work with bs = ps = %u bytes",
971*33b1fccfSAndroid Build Coastguard Worker erofs_blksiz(&g_sbi));
972*33b1fccfSAndroid Build Coastguard Worker
973*33b1fccfSAndroid Build Coastguard Worker if (pclustersize_max) {
974*33b1fccfSAndroid Build Coastguard Worker if (pclustersize_max < erofs_blksiz(&g_sbi) ||
975*33b1fccfSAndroid Build Coastguard Worker pclustersize_max % erofs_blksiz(&g_sbi)) {
976*33b1fccfSAndroid Build Coastguard Worker erofs_err("invalid physical clustersize %u",
977*33b1fccfSAndroid Build Coastguard Worker pclustersize_max);
978*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
979*33b1fccfSAndroid Build Coastguard Worker }
980*33b1fccfSAndroid Build Coastguard Worker cfg.c_mkfs_pclustersize_max = pclustersize_max;
981*33b1fccfSAndroid Build Coastguard Worker cfg.c_mkfs_pclustersize_def = cfg.c_mkfs_pclustersize_max;
982*33b1fccfSAndroid Build Coastguard Worker }
983*33b1fccfSAndroid Build Coastguard Worker if (cfg.c_chunkbits && cfg.c_chunkbits < g_sbi.blkszbits) {
984*33b1fccfSAndroid Build Coastguard Worker erofs_err("chunksize %u must be larger than block size",
985*33b1fccfSAndroid Build Coastguard Worker 1u << cfg.c_chunkbits);
986*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
987*33b1fccfSAndroid Build Coastguard Worker }
988*33b1fccfSAndroid Build Coastguard Worker
989*33b1fccfSAndroid Build Coastguard Worker if (pclustersize_packed) {
990*33b1fccfSAndroid Build Coastguard Worker if (pclustersize_packed < erofs_blksiz(&g_sbi) ||
991*33b1fccfSAndroid Build Coastguard Worker pclustersize_packed % erofs_blksiz(&g_sbi)) {
992*33b1fccfSAndroid Build Coastguard Worker erofs_err("invalid pcluster size for the packed file %u",
993*33b1fccfSAndroid Build Coastguard Worker pclustersize_packed);
994*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
995*33b1fccfSAndroid Build Coastguard Worker }
996*33b1fccfSAndroid Build Coastguard Worker cfg.c_mkfs_pclustersize_packed = pclustersize_packed;
997*33b1fccfSAndroid Build Coastguard Worker }
998*33b1fccfSAndroid Build Coastguard Worker
999*33b1fccfSAndroid Build Coastguard Worker if (has_timestamp && cfg.c_timeinherit == TIMESTAMP_UNSPECIFIED)
1000*33b1fccfSAndroid Build Coastguard Worker cfg.c_timeinherit = TIMESTAMP_FIXED;
1001*33b1fccfSAndroid Build Coastguard Worker return 0;
1002*33b1fccfSAndroid Build Coastguard Worker }
1003*33b1fccfSAndroid Build Coastguard Worker
erofs_mkfs_default_options(void)1004*33b1fccfSAndroid Build Coastguard Worker static void erofs_mkfs_default_options(void)
1005*33b1fccfSAndroid Build Coastguard Worker {
1006*33b1fccfSAndroid Build Coastguard Worker cfg.c_showprogress = true;
1007*33b1fccfSAndroid Build Coastguard Worker cfg.c_legacy_compress = false;
1008*33b1fccfSAndroid Build Coastguard Worker cfg.c_inline_data = true;
1009*33b1fccfSAndroid Build Coastguard Worker cfg.c_xattr_name_filter = true;
1010*33b1fccfSAndroid Build Coastguard Worker #ifdef EROFS_MT_ENABLED
1011*33b1fccfSAndroid Build Coastguard Worker cfg.c_mt_workers = erofs_get_available_processors();
1012*33b1fccfSAndroid Build Coastguard Worker cfg.c_mkfs_segment_size = 16ULL * 1024 * 1024;
1013*33b1fccfSAndroid Build Coastguard Worker #endif
1014*33b1fccfSAndroid Build Coastguard Worker g_sbi.blkszbits = ilog2(min_t(u32, getpagesize(), EROFS_MAX_BLOCK_SIZE));
1015*33b1fccfSAndroid Build Coastguard Worker cfg.c_mkfs_pclustersize_max = erofs_blksiz(&g_sbi);
1016*33b1fccfSAndroid Build Coastguard Worker cfg.c_mkfs_pclustersize_def = cfg.c_mkfs_pclustersize_max;
1017*33b1fccfSAndroid Build Coastguard Worker g_sbi.feature_incompat = EROFS_FEATURE_INCOMPAT_ZERO_PADDING;
1018*33b1fccfSAndroid Build Coastguard Worker g_sbi.feature_compat = EROFS_FEATURE_COMPAT_SB_CHKSUM |
1019*33b1fccfSAndroid Build Coastguard Worker EROFS_FEATURE_COMPAT_MTIME;
1020*33b1fccfSAndroid Build Coastguard Worker }
1021*33b1fccfSAndroid Build Coastguard Worker
1022*33b1fccfSAndroid Build Coastguard Worker /* https://reproducible-builds.org/specs/source-date-epoch/ for more details */
parse_source_date_epoch(void)1023*33b1fccfSAndroid Build Coastguard Worker int parse_source_date_epoch(void)
1024*33b1fccfSAndroid Build Coastguard Worker {
1025*33b1fccfSAndroid Build Coastguard Worker char *source_date_epoch;
1026*33b1fccfSAndroid Build Coastguard Worker unsigned long long epoch = -1ULL;
1027*33b1fccfSAndroid Build Coastguard Worker char *endptr;
1028*33b1fccfSAndroid Build Coastguard Worker
1029*33b1fccfSAndroid Build Coastguard Worker source_date_epoch = getenv("SOURCE_DATE_EPOCH");
1030*33b1fccfSAndroid Build Coastguard Worker if (!source_date_epoch)
1031*33b1fccfSAndroid Build Coastguard Worker return 0;
1032*33b1fccfSAndroid Build Coastguard Worker
1033*33b1fccfSAndroid Build Coastguard Worker epoch = strtoull(source_date_epoch, &endptr, 10);
1034*33b1fccfSAndroid Build Coastguard Worker if (epoch == -1ULL || *endptr != '\0') {
1035*33b1fccfSAndroid Build Coastguard Worker erofs_err("environment variable $SOURCE_DATE_EPOCH %s is invalid",
1036*33b1fccfSAndroid Build Coastguard Worker source_date_epoch);
1037*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
1038*33b1fccfSAndroid Build Coastguard Worker }
1039*33b1fccfSAndroid Build Coastguard Worker
1040*33b1fccfSAndroid Build Coastguard Worker if (cfg.c_force_inodeversion != FORCE_INODE_EXTENDED)
1041*33b1fccfSAndroid Build Coastguard Worker erofs_info("SOURCE_DATE_EPOCH is set, forcely generate extended inodes instead");
1042*33b1fccfSAndroid Build Coastguard Worker
1043*33b1fccfSAndroid Build Coastguard Worker cfg.c_force_inodeversion = FORCE_INODE_EXTENDED;
1044*33b1fccfSAndroid Build Coastguard Worker cfg.c_unix_timestamp = epoch;
1045*33b1fccfSAndroid Build Coastguard Worker cfg.c_timeinherit = TIMESTAMP_CLAMPING;
1046*33b1fccfSAndroid Build Coastguard Worker return 0;
1047*33b1fccfSAndroid Build Coastguard Worker }
1048*33b1fccfSAndroid Build Coastguard Worker
erofs_show_progs(int argc,char * argv[])1049*33b1fccfSAndroid Build Coastguard Worker void erofs_show_progs(int argc, char *argv[])
1050*33b1fccfSAndroid Build Coastguard Worker {
1051*33b1fccfSAndroid Build Coastguard Worker if (cfg.c_dbg_lvl >= EROFS_WARN)
1052*33b1fccfSAndroid Build Coastguard Worker printf("%s %s\n", basename(argv[0]), cfg.c_version);
1053*33b1fccfSAndroid Build Coastguard Worker }
1054*33b1fccfSAndroid Build Coastguard Worker
erofs_mkfs_rebuild_load_trees(struct erofs_inode * root)1055*33b1fccfSAndroid Build Coastguard Worker static int erofs_mkfs_rebuild_load_trees(struct erofs_inode *root)
1056*33b1fccfSAndroid Build Coastguard Worker {
1057*33b1fccfSAndroid Build Coastguard Worker struct erofs_sb_info *src;
1058*33b1fccfSAndroid Build Coastguard Worker unsigned int extra_devices = 0;
1059*33b1fccfSAndroid Build Coastguard Worker erofs_blk_t nblocks;
1060*33b1fccfSAndroid Build Coastguard Worker int ret, idx;
1061*33b1fccfSAndroid Build Coastguard Worker enum erofs_rebuild_datamode datamode;
1062*33b1fccfSAndroid Build Coastguard Worker
1063*33b1fccfSAndroid Build Coastguard Worker switch (dataimport_mode) {
1064*33b1fccfSAndroid Build Coastguard Worker case EROFS_MKFS_DATA_IMPORT_DEFAULT:
1065*33b1fccfSAndroid Build Coastguard Worker datamode = EROFS_REBUILD_DATA_BLOB_INDEX;
1066*33b1fccfSAndroid Build Coastguard Worker break;
1067*33b1fccfSAndroid Build Coastguard Worker case EROFS_MKFS_DATA_IMPORT_FULLDATA:
1068*33b1fccfSAndroid Build Coastguard Worker datamode = EROFS_REBUILD_DATA_FULL;
1069*33b1fccfSAndroid Build Coastguard Worker break;
1070*33b1fccfSAndroid Build Coastguard Worker case EROFS_MKFS_DATA_IMPORT_RVSP:
1071*33b1fccfSAndroid Build Coastguard Worker datamode = EROFS_REBUILD_DATA_RESVSP;
1072*33b1fccfSAndroid Build Coastguard Worker break;
1073*33b1fccfSAndroid Build Coastguard Worker default:
1074*33b1fccfSAndroid Build Coastguard Worker return -EINVAL;
1075*33b1fccfSAndroid Build Coastguard Worker }
1076*33b1fccfSAndroid Build Coastguard Worker
1077*33b1fccfSAndroid Build Coastguard Worker list_for_each_entry(src, &rebuild_src_list, list) {
1078*33b1fccfSAndroid Build Coastguard Worker ret = erofs_rebuild_load_tree(root, src, datamode);
1079*33b1fccfSAndroid Build Coastguard Worker if (ret) {
1080*33b1fccfSAndroid Build Coastguard Worker erofs_err("failed to load %s", src->devname);
1081*33b1fccfSAndroid Build Coastguard Worker return ret;
1082*33b1fccfSAndroid Build Coastguard Worker }
1083*33b1fccfSAndroid Build Coastguard Worker if (src->extra_devices > 1) {
1084*33b1fccfSAndroid Build Coastguard Worker erofs_err("%s: unsupported number %u of extra devices",
1085*33b1fccfSAndroid Build Coastguard Worker src->devname, src->extra_devices);
1086*33b1fccfSAndroid Build Coastguard Worker return -EOPNOTSUPP;
1087*33b1fccfSAndroid Build Coastguard Worker }
1088*33b1fccfSAndroid Build Coastguard Worker extra_devices += src->extra_devices;
1089*33b1fccfSAndroid Build Coastguard Worker }
1090*33b1fccfSAndroid Build Coastguard Worker
1091*33b1fccfSAndroid Build Coastguard Worker if (datamode != EROFS_REBUILD_DATA_BLOB_INDEX)
1092*33b1fccfSAndroid Build Coastguard Worker return 0;
1093*33b1fccfSAndroid Build Coastguard Worker
1094*33b1fccfSAndroid Build Coastguard Worker if (extra_devices != rebuild_src_count) {
1095*33b1fccfSAndroid Build Coastguard Worker erofs_err("extra_devices(%u) is mismatched with source images(%u)",
1096*33b1fccfSAndroid Build Coastguard Worker extra_devices, rebuild_src_count);
1097*33b1fccfSAndroid Build Coastguard Worker return -EOPNOTSUPP;
1098*33b1fccfSAndroid Build Coastguard Worker }
1099*33b1fccfSAndroid Build Coastguard Worker
1100*33b1fccfSAndroid Build Coastguard Worker ret = erofs_mkfs_init_devices(&g_sbi, rebuild_src_count);
1101*33b1fccfSAndroid Build Coastguard Worker if (ret)
1102*33b1fccfSAndroid Build Coastguard Worker return ret;
1103*33b1fccfSAndroid Build Coastguard Worker
1104*33b1fccfSAndroid Build Coastguard Worker list_for_each_entry(src, &rebuild_src_list, list) {
1105*33b1fccfSAndroid Build Coastguard Worker u8 *tag = NULL;
1106*33b1fccfSAndroid Build Coastguard Worker
1107*33b1fccfSAndroid Build Coastguard Worker if (extra_devices) {
1108*33b1fccfSAndroid Build Coastguard Worker nblocks = src->devs[0].blocks;
1109*33b1fccfSAndroid Build Coastguard Worker tag = src->devs[0].tag;
1110*33b1fccfSAndroid Build Coastguard Worker } else {
1111*33b1fccfSAndroid Build Coastguard Worker nblocks = src->primarydevice_blocks;
1112*33b1fccfSAndroid Build Coastguard Worker }
1113*33b1fccfSAndroid Build Coastguard Worker DBG_BUGON(src->dev < 1);
1114*33b1fccfSAndroid Build Coastguard Worker idx = src->dev - 1;
1115*33b1fccfSAndroid Build Coastguard Worker g_sbi.devs[idx].blocks = nblocks;
1116*33b1fccfSAndroid Build Coastguard Worker if (tag && *tag)
1117*33b1fccfSAndroid Build Coastguard Worker memcpy(g_sbi.devs[idx].tag, tag, sizeof(g_sbi.devs[0].tag));
1118*33b1fccfSAndroid Build Coastguard Worker else
1119*33b1fccfSAndroid Build Coastguard Worker /* convert UUID of the source image to a hex string */
1120*33b1fccfSAndroid Build Coastguard Worker sprintf((char *)g_sbi.devs[idx].tag,
1121*33b1fccfSAndroid Build Coastguard Worker "%04x%04x%04x%04x%04x%04x%04x%04x",
1122*33b1fccfSAndroid Build Coastguard Worker (src->uuid[0] << 8) | src->uuid[1],
1123*33b1fccfSAndroid Build Coastguard Worker (src->uuid[2] << 8) | src->uuid[3],
1124*33b1fccfSAndroid Build Coastguard Worker (src->uuid[4] << 8) | src->uuid[5],
1125*33b1fccfSAndroid Build Coastguard Worker (src->uuid[6] << 8) | src->uuid[7],
1126*33b1fccfSAndroid Build Coastguard Worker (src->uuid[8] << 8) | src->uuid[9],
1127*33b1fccfSAndroid Build Coastguard Worker (src->uuid[10] << 8) | src->uuid[11],
1128*33b1fccfSAndroid Build Coastguard Worker (src->uuid[12] << 8) | src->uuid[13],
1129*33b1fccfSAndroid Build Coastguard Worker (src->uuid[14] << 8) | src->uuid[15]);
1130*33b1fccfSAndroid Build Coastguard Worker }
1131*33b1fccfSAndroid Build Coastguard Worker return 0;
1132*33b1fccfSAndroid Build Coastguard Worker }
1133*33b1fccfSAndroid Build Coastguard Worker
erofs_mkfs_showsummaries(erofs_blk_t nblocks)1134*33b1fccfSAndroid Build Coastguard Worker static void erofs_mkfs_showsummaries(erofs_blk_t nblocks)
1135*33b1fccfSAndroid Build Coastguard Worker {
1136*33b1fccfSAndroid Build Coastguard Worker char uuid_str[37] = {};
1137*33b1fccfSAndroid Build Coastguard Worker char *incr = incremental_mode ? "new" : "total";
1138*33b1fccfSAndroid Build Coastguard Worker
1139*33b1fccfSAndroid Build Coastguard Worker if (!(cfg.c_dbg_lvl > EROFS_ERR && cfg.c_showprogress))
1140*33b1fccfSAndroid Build Coastguard Worker return;
1141*33b1fccfSAndroid Build Coastguard Worker
1142*33b1fccfSAndroid Build Coastguard Worker erofs_uuid_unparse_lower(g_sbi.uuid, uuid_str);
1143*33b1fccfSAndroid Build Coastguard Worker
1144*33b1fccfSAndroid Build Coastguard Worker fprintf(stdout, "------\nFilesystem UUID: %s\n"
1145*33b1fccfSAndroid Build Coastguard Worker "Filesystem total blocks: %u (of %u-byte blocks)\n"
1146*33b1fccfSAndroid Build Coastguard Worker "Filesystem total inodes: %llu\n"
1147*33b1fccfSAndroid Build Coastguard Worker "Filesystem %s metadata blocks: %u\n"
1148*33b1fccfSAndroid Build Coastguard Worker "Filesystem %s deduplicated bytes (of source files): %llu\n",
1149*33b1fccfSAndroid Build Coastguard Worker uuid_str, nblocks, 1U << g_sbi.blkszbits, g_sbi.inos | 0ULL,
1150*33b1fccfSAndroid Build Coastguard Worker incr, erofs_total_metablocks(g_sbi.bmgr),
1151*33b1fccfSAndroid Build Coastguard Worker incr, g_sbi.saved_by_deduplication | 0ULL);
1152*33b1fccfSAndroid Build Coastguard Worker }
1153*33b1fccfSAndroid Build Coastguard Worker
main(int argc,char ** argv)1154*33b1fccfSAndroid Build Coastguard Worker int main(int argc, char **argv)
1155*33b1fccfSAndroid Build Coastguard Worker {
1156*33b1fccfSAndroid Build Coastguard Worker int err = 0;
1157*33b1fccfSAndroid Build Coastguard Worker struct erofs_buffer_head *sb_bh;
1158*33b1fccfSAndroid Build Coastguard Worker struct erofs_inode *root = NULL;
1159*33b1fccfSAndroid Build Coastguard Worker erofs_blk_t nblocks = 0;
1160*33b1fccfSAndroid Build Coastguard Worker struct timeval t;
1161*33b1fccfSAndroid Build Coastguard Worker FILE *packedfile = NULL;
1162*33b1fccfSAndroid Build Coastguard Worker FILE *blklst = NULL;
1163*33b1fccfSAndroid Build Coastguard Worker u32 crc;
1164*33b1fccfSAndroid Build Coastguard Worker
1165*33b1fccfSAndroid Build Coastguard Worker erofs_init_configure();
1166*33b1fccfSAndroid Build Coastguard Worker erofs_mkfs_default_options();
1167*33b1fccfSAndroid Build Coastguard Worker
1168*33b1fccfSAndroid Build Coastguard Worker err = mkfs_parse_options_cfg(argc, argv);
1169*33b1fccfSAndroid Build Coastguard Worker erofs_show_progs(argc, argv);
1170*33b1fccfSAndroid Build Coastguard Worker if (err) {
1171*33b1fccfSAndroid Build Coastguard Worker if (err == -EINVAL)
1172*33b1fccfSAndroid Build Coastguard Worker fprintf(stderr, "Try '%s --help' for more information.\n", argv[0]);
1173*33b1fccfSAndroid Build Coastguard Worker return 1;
1174*33b1fccfSAndroid Build Coastguard Worker }
1175*33b1fccfSAndroid Build Coastguard Worker
1176*33b1fccfSAndroid Build Coastguard Worker err = parse_source_date_epoch();
1177*33b1fccfSAndroid Build Coastguard Worker if (err) {
1178*33b1fccfSAndroid Build Coastguard Worker fprintf(stderr, "Try '%s --help' for more information.\n", argv[0]);
1179*33b1fccfSAndroid Build Coastguard Worker return 1;
1180*33b1fccfSAndroid Build Coastguard Worker }
1181*33b1fccfSAndroid Build Coastguard Worker
1182*33b1fccfSAndroid Build Coastguard Worker if (cfg.c_unix_timestamp != -1) {
1183*33b1fccfSAndroid Build Coastguard Worker g_sbi.build_time = cfg.c_unix_timestamp;
1184*33b1fccfSAndroid Build Coastguard Worker g_sbi.build_time_nsec = 0;
1185*33b1fccfSAndroid Build Coastguard Worker } else if (!gettimeofday(&t, NULL)) {
1186*33b1fccfSAndroid Build Coastguard Worker g_sbi.build_time = t.tv_sec;
1187*33b1fccfSAndroid Build Coastguard Worker g_sbi.build_time_nsec = t.tv_usec;
1188*33b1fccfSAndroid Build Coastguard Worker }
1189*33b1fccfSAndroid Build Coastguard Worker
1190*33b1fccfSAndroid Build Coastguard Worker err = erofs_dev_open(&g_sbi, cfg.c_img_path, O_RDWR |
1191*33b1fccfSAndroid Build Coastguard Worker (incremental_mode ? 0 : O_TRUNC));
1192*33b1fccfSAndroid Build Coastguard Worker if (err) {
1193*33b1fccfSAndroid Build Coastguard Worker fprintf(stderr, "Try '%s --help' for more information.\n", argv[0]);
1194*33b1fccfSAndroid Build Coastguard Worker return 1;
1195*33b1fccfSAndroid Build Coastguard Worker }
1196*33b1fccfSAndroid Build Coastguard Worker
1197*33b1fccfSAndroid Build Coastguard Worker #ifdef WITH_ANDROID
1198*33b1fccfSAndroid Build Coastguard Worker if (cfg.fs_config_file &&
1199*33b1fccfSAndroid Build Coastguard Worker load_canned_fs_config(cfg.fs_config_file) < 0) {
1200*33b1fccfSAndroid Build Coastguard Worker erofs_err("failed to load fs config %s", cfg.fs_config_file);
1201*33b1fccfSAndroid Build Coastguard Worker return 1;
1202*33b1fccfSAndroid Build Coastguard Worker }
1203*33b1fccfSAndroid Build Coastguard Worker
1204*33b1fccfSAndroid Build Coastguard Worker if (cfg.block_list_file) {
1205*33b1fccfSAndroid Build Coastguard Worker blklst = fopen(cfg.block_list_file, "w");
1206*33b1fccfSAndroid Build Coastguard Worker if (!blklst || erofs_blocklist_open(blklst, false)) {
1207*33b1fccfSAndroid Build Coastguard Worker erofs_err("failed to open %s", cfg.block_list_file);
1208*33b1fccfSAndroid Build Coastguard Worker return 1;
1209*33b1fccfSAndroid Build Coastguard Worker }
1210*33b1fccfSAndroid Build Coastguard Worker }
1211*33b1fccfSAndroid Build Coastguard Worker #endif
1212*33b1fccfSAndroid Build Coastguard Worker erofs_show_config();
1213*33b1fccfSAndroid Build Coastguard Worker if (cfg.c_fragments || cfg.c_extra_ea_name_prefixes) {
1214*33b1fccfSAndroid Build Coastguard Worker if (!cfg.c_mkfs_pclustersize_packed)
1215*33b1fccfSAndroid Build Coastguard Worker cfg.c_mkfs_pclustersize_packed = cfg.c_mkfs_pclustersize_def;
1216*33b1fccfSAndroid Build Coastguard Worker
1217*33b1fccfSAndroid Build Coastguard Worker packedfile = erofs_packedfile_init();
1218*33b1fccfSAndroid Build Coastguard Worker if (IS_ERR(packedfile)) {
1219*33b1fccfSAndroid Build Coastguard Worker erofs_err("failed to initialize packedfile");
1220*33b1fccfSAndroid Build Coastguard Worker return 1;
1221*33b1fccfSAndroid Build Coastguard Worker }
1222*33b1fccfSAndroid Build Coastguard Worker }
1223*33b1fccfSAndroid Build Coastguard Worker
1224*33b1fccfSAndroid Build Coastguard Worker if (cfg.c_fragments) {
1225*33b1fccfSAndroid Build Coastguard Worker err = z_erofs_fragments_init();
1226*33b1fccfSAndroid Build Coastguard Worker if (err) {
1227*33b1fccfSAndroid Build Coastguard Worker erofs_err("failed to initialize fragments");
1228*33b1fccfSAndroid Build Coastguard Worker return 1;
1229*33b1fccfSAndroid Build Coastguard Worker }
1230*33b1fccfSAndroid Build Coastguard Worker }
1231*33b1fccfSAndroid Build Coastguard Worker
1232*33b1fccfSAndroid Build Coastguard Worker #ifndef NDEBUG
1233*33b1fccfSAndroid Build Coastguard Worker if (cfg.c_random_pclusterblks)
1234*33b1fccfSAndroid Build Coastguard Worker srand(time(NULL));
1235*33b1fccfSAndroid Build Coastguard Worker #endif
1236*33b1fccfSAndroid Build Coastguard Worker if (tar_mode) {
1237*33b1fccfSAndroid Build Coastguard Worker if (dataimport_mode == EROFS_MKFS_DATA_IMPORT_RVSP)
1238*33b1fccfSAndroid Build Coastguard Worker erofstar.rvsp_mode = true;
1239*33b1fccfSAndroid Build Coastguard Worker erofstar.dev = rebuild_src_count + 1;
1240*33b1fccfSAndroid Build Coastguard Worker
1241*33b1fccfSAndroid Build Coastguard Worker if (erofstar.mapfile) {
1242*33b1fccfSAndroid Build Coastguard Worker blklst = fopen(erofstar.mapfile, "w");
1243*33b1fccfSAndroid Build Coastguard Worker if (!blklst || erofs_blocklist_open(blklst, true)) {
1244*33b1fccfSAndroid Build Coastguard Worker err = -errno;
1245*33b1fccfSAndroid Build Coastguard Worker erofs_err("failed to open %s", erofstar.mapfile);
1246*33b1fccfSAndroid Build Coastguard Worker goto exit;
1247*33b1fccfSAndroid Build Coastguard Worker }
1248*33b1fccfSAndroid Build Coastguard Worker } else if (erofstar.index_mode) {
1249*33b1fccfSAndroid Build Coastguard Worker /*
1250*33b1fccfSAndroid Build Coastguard Worker * If mapfile is unspecified for tarfs index mode,
1251*33b1fccfSAndroid Build Coastguard Worker * 512-byte block size is enforced here.
1252*33b1fccfSAndroid Build Coastguard Worker */
1253*33b1fccfSAndroid Build Coastguard Worker g_sbi.blkszbits = 9;
1254*33b1fccfSAndroid Build Coastguard Worker }
1255*33b1fccfSAndroid Build Coastguard Worker }
1256*33b1fccfSAndroid Build Coastguard Worker
1257*33b1fccfSAndroid Build Coastguard Worker if (rebuild_mode) {
1258*33b1fccfSAndroid Build Coastguard Worker struct erofs_sb_info *src;
1259*33b1fccfSAndroid Build Coastguard Worker
1260*33b1fccfSAndroid Build Coastguard Worker erofs_warn("EXPERIMENTAL rebuild mode in use. Use at your own risk!");
1261*33b1fccfSAndroid Build Coastguard Worker
1262*33b1fccfSAndroid Build Coastguard Worker src = list_first_entry(&rebuild_src_list, struct erofs_sb_info, list);
1263*33b1fccfSAndroid Build Coastguard Worker if (!src)
1264*33b1fccfSAndroid Build Coastguard Worker goto exit;
1265*33b1fccfSAndroid Build Coastguard Worker err = erofs_read_superblock(src);
1266*33b1fccfSAndroid Build Coastguard Worker if (err) {
1267*33b1fccfSAndroid Build Coastguard Worker erofs_err("failed to read superblock of %s", src->devname);
1268*33b1fccfSAndroid Build Coastguard Worker goto exit;
1269*33b1fccfSAndroid Build Coastguard Worker }
1270*33b1fccfSAndroid Build Coastguard Worker g_sbi.blkszbits = src->blkszbits;
1271*33b1fccfSAndroid Build Coastguard Worker }
1272*33b1fccfSAndroid Build Coastguard Worker
1273*33b1fccfSAndroid Build Coastguard Worker if (!incremental_mode) {
1274*33b1fccfSAndroid Build Coastguard Worker g_sbi.bmgr = erofs_buffer_init(&g_sbi, 0);
1275*33b1fccfSAndroid Build Coastguard Worker if (!g_sbi.bmgr) {
1276*33b1fccfSAndroid Build Coastguard Worker err = -ENOMEM;
1277*33b1fccfSAndroid Build Coastguard Worker goto exit;
1278*33b1fccfSAndroid Build Coastguard Worker }
1279*33b1fccfSAndroid Build Coastguard Worker sb_bh = erofs_reserve_sb(g_sbi.bmgr);
1280*33b1fccfSAndroid Build Coastguard Worker if (IS_ERR(sb_bh)) {
1281*33b1fccfSAndroid Build Coastguard Worker err = PTR_ERR(sb_bh);
1282*33b1fccfSAndroid Build Coastguard Worker goto exit;
1283*33b1fccfSAndroid Build Coastguard Worker }
1284*33b1fccfSAndroid Build Coastguard Worker } else {
1285*33b1fccfSAndroid Build Coastguard Worker union {
1286*33b1fccfSAndroid Build Coastguard Worker struct stat st;
1287*33b1fccfSAndroid Build Coastguard Worker erofs_blk_t startblk;
1288*33b1fccfSAndroid Build Coastguard Worker } u;
1289*33b1fccfSAndroid Build Coastguard Worker
1290*33b1fccfSAndroid Build Coastguard Worker erofs_warn("EXPERIMENTAL incremental build in use. Use at your own risk!");
1291*33b1fccfSAndroid Build Coastguard Worker err = erofs_read_superblock(&g_sbi);
1292*33b1fccfSAndroid Build Coastguard Worker if (err) {
1293*33b1fccfSAndroid Build Coastguard Worker erofs_err("failed to read superblock of %s", g_sbi.devname);
1294*33b1fccfSAndroid Build Coastguard Worker goto exit;
1295*33b1fccfSAndroid Build Coastguard Worker }
1296*33b1fccfSAndroid Build Coastguard Worker
1297*33b1fccfSAndroid Build Coastguard Worker err = erofs_io_fstat(&g_sbi.bdev, &u.st);
1298*33b1fccfSAndroid Build Coastguard Worker if (!err && S_ISREG(u.st.st_mode))
1299*33b1fccfSAndroid Build Coastguard Worker u.startblk = DIV_ROUND_UP(u.st.st_size, erofs_blksiz(&g_sbi));
1300*33b1fccfSAndroid Build Coastguard Worker else
1301*33b1fccfSAndroid Build Coastguard Worker u.startblk = g_sbi.primarydevice_blocks;
1302*33b1fccfSAndroid Build Coastguard Worker g_sbi.bmgr = erofs_buffer_init(&g_sbi, u.startblk);
1303*33b1fccfSAndroid Build Coastguard Worker if (!g_sbi.bmgr) {
1304*33b1fccfSAndroid Build Coastguard Worker err = -ENOMEM;
1305*33b1fccfSAndroid Build Coastguard Worker goto exit;
1306*33b1fccfSAndroid Build Coastguard Worker }
1307*33b1fccfSAndroid Build Coastguard Worker sb_bh = NULL;
1308*33b1fccfSAndroid Build Coastguard Worker }
1309*33b1fccfSAndroid Build Coastguard Worker
1310*33b1fccfSAndroid Build Coastguard Worker /* Use the user-defined UUID or generate one for clean builds */
1311*33b1fccfSAndroid Build Coastguard Worker if (valid_fixeduuid)
1312*33b1fccfSAndroid Build Coastguard Worker memcpy(g_sbi.uuid, fixeduuid, sizeof(g_sbi.uuid));
1313*33b1fccfSAndroid Build Coastguard Worker else if (!incremental_mode)
1314*33b1fccfSAndroid Build Coastguard Worker erofs_uuid_generate(g_sbi.uuid);
1315*33b1fccfSAndroid Build Coastguard Worker
1316*33b1fccfSAndroid Build Coastguard Worker if (tar_mode && !erofstar.index_mode) {
1317*33b1fccfSAndroid Build Coastguard Worker err = erofs_diskbuf_init(1);
1318*33b1fccfSAndroid Build Coastguard Worker if (err) {
1319*33b1fccfSAndroid Build Coastguard Worker erofs_err("failed to initialize diskbuf: %s",
1320*33b1fccfSAndroid Build Coastguard Worker strerror(-err));
1321*33b1fccfSAndroid Build Coastguard Worker goto exit;
1322*33b1fccfSAndroid Build Coastguard Worker }
1323*33b1fccfSAndroid Build Coastguard Worker }
1324*33b1fccfSAndroid Build Coastguard Worker
1325*33b1fccfSAndroid Build Coastguard Worker err = erofs_load_compress_hints(&g_sbi);
1326*33b1fccfSAndroid Build Coastguard Worker if (err) {
1327*33b1fccfSAndroid Build Coastguard Worker erofs_err("failed to load compress hints %s",
1328*33b1fccfSAndroid Build Coastguard Worker cfg.c_compress_hints_file);
1329*33b1fccfSAndroid Build Coastguard Worker goto exit;
1330*33b1fccfSAndroid Build Coastguard Worker }
1331*33b1fccfSAndroid Build Coastguard Worker
1332*33b1fccfSAndroid Build Coastguard Worker err = z_erofs_compress_init(&g_sbi, sb_bh);
1333*33b1fccfSAndroid Build Coastguard Worker if (err) {
1334*33b1fccfSAndroid Build Coastguard Worker erofs_err("failed to initialize compressor: %s",
1335*33b1fccfSAndroid Build Coastguard Worker erofs_strerror(err));
1336*33b1fccfSAndroid Build Coastguard Worker goto exit;
1337*33b1fccfSAndroid Build Coastguard Worker }
1338*33b1fccfSAndroid Build Coastguard Worker
1339*33b1fccfSAndroid Build Coastguard Worker if (cfg.c_dedupe) {
1340*33b1fccfSAndroid Build Coastguard Worker if (!cfg.c_compr_opts[0].alg) {
1341*33b1fccfSAndroid Build Coastguard Worker erofs_err("Compression is not enabled. Turn on chunk-based data deduplication instead.");
1342*33b1fccfSAndroid Build Coastguard Worker cfg.c_chunkbits = g_sbi.blkszbits;
1343*33b1fccfSAndroid Build Coastguard Worker } else {
1344*33b1fccfSAndroid Build Coastguard Worker err = z_erofs_dedupe_init(erofs_blksiz(&g_sbi));
1345*33b1fccfSAndroid Build Coastguard Worker if (err) {
1346*33b1fccfSAndroid Build Coastguard Worker erofs_err("failed to initialize deduplication: %s",
1347*33b1fccfSAndroid Build Coastguard Worker erofs_strerror(err));
1348*33b1fccfSAndroid Build Coastguard Worker goto exit;
1349*33b1fccfSAndroid Build Coastguard Worker }
1350*33b1fccfSAndroid Build Coastguard Worker }
1351*33b1fccfSAndroid Build Coastguard Worker }
1352*33b1fccfSAndroid Build Coastguard Worker
1353*33b1fccfSAndroid Build Coastguard Worker if (cfg.c_chunkbits) {
1354*33b1fccfSAndroid Build Coastguard Worker err = erofs_blob_init(cfg.c_blobdev_path, 1 << cfg.c_chunkbits);
1355*33b1fccfSAndroid Build Coastguard Worker if (err)
1356*33b1fccfSAndroid Build Coastguard Worker return 1;
1357*33b1fccfSAndroid Build Coastguard Worker }
1358*33b1fccfSAndroid Build Coastguard Worker
1359*33b1fccfSAndroid Build Coastguard Worker if (((erofstar.index_mode && !erofstar.headeronly_mode) &&
1360*33b1fccfSAndroid Build Coastguard Worker !erofstar.mapfile) || cfg.c_blobdev_path) {
1361*33b1fccfSAndroid Build Coastguard Worker err = erofs_mkfs_init_devices(&g_sbi, 1);
1362*33b1fccfSAndroid Build Coastguard Worker if (err) {
1363*33b1fccfSAndroid Build Coastguard Worker erofs_err("failed to generate device table: %s",
1364*33b1fccfSAndroid Build Coastguard Worker erofs_strerror(err));
1365*33b1fccfSAndroid Build Coastguard Worker goto exit;
1366*33b1fccfSAndroid Build Coastguard Worker }
1367*33b1fccfSAndroid Build Coastguard Worker }
1368*33b1fccfSAndroid Build Coastguard Worker
1369*33b1fccfSAndroid Build Coastguard Worker erofs_inode_manager_init();
1370*33b1fccfSAndroid Build Coastguard Worker
1371*33b1fccfSAndroid Build Coastguard Worker if (tar_mode) {
1372*33b1fccfSAndroid Build Coastguard Worker root = erofs_rebuild_make_root(&g_sbi);
1373*33b1fccfSAndroid Build Coastguard Worker if (IS_ERR(root)) {
1374*33b1fccfSAndroid Build Coastguard Worker err = PTR_ERR(root);
1375*33b1fccfSAndroid Build Coastguard Worker goto exit;
1376*33b1fccfSAndroid Build Coastguard Worker }
1377*33b1fccfSAndroid Build Coastguard Worker
1378*33b1fccfSAndroid Build Coastguard Worker while (!(err = tarerofs_parse_tar(root, &erofstar)));
1379*33b1fccfSAndroid Build Coastguard Worker
1380*33b1fccfSAndroid Build Coastguard Worker if (err < 0)
1381*33b1fccfSAndroid Build Coastguard Worker goto exit;
1382*33b1fccfSAndroid Build Coastguard Worker
1383*33b1fccfSAndroid Build Coastguard Worker err = erofs_rebuild_dump_tree(root, incremental_mode);
1384*33b1fccfSAndroid Build Coastguard Worker if (err < 0)
1385*33b1fccfSAndroid Build Coastguard Worker goto exit;
1386*33b1fccfSAndroid Build Coastguard Worker } else if (rebuild_mode) {
1387*33b1fccfSAndroid Build Coastguard Worker root = erofs_rebuild_make_root(&g_sbi);
1388*33b1fccfSAndroid Build Coastguard Worker if (IS_ERR(root)) {
1389*33b1fccfSAndroid Build Coastguard Worker err = PTR_ERR(root);
1390*33b1fccfSAndroid Build Coastguard Worker goto exit;
1391*33b1fccfSAndroid Build Coastguard Worker }
1392*33b1fccfSAndroid Build Coastguard Worker
1393*33b1fccfSAndroid Build Coastguard Worker err = erofs_mkfs_rebuild_load_trees(root);
1394*33b1fccfSAndroid Build Coastguard Worker if (err)
1395*33b1fccfSAndroid Build Coastguard Worker goto exit;
1396*33b1fccfSAndroid Build Coastguard Worker err = erofs_rebuild_dump_tree(root, incremental_mode);
1397*33b1fccfSAndroid Build Coastguard Worker if (err)
1398*33b1fccfSAndroid Build Coastguard Worker goto exit;
1399*33b1fccfSAndroid Build Coastguard Worker } else {
1400*33b1fccfSAndroid Build Coastguard Worker err = erofs_build_shared_xattrs_from_path(&g_sbi, cfg.c_src_path);
1401*33b1fccfSAndroid Build Coastguard Worker if (err) {
1402*33b1fccfSAndroid Build Coastguard Worker erofs_err("failed to build shared xattrs: %s",
1403*33b1fccfSAndroid Build Coastguard Worker erofs_strerror(err));
1404*33b1fccfSAndroid Build Coastguard Worker goto exit;
1405*33b1fccfSAndroid Build Coastguard Worker }
1406*33b1fccfSAndroid Build Coastguard Worker
1407*33b1fccfSAndroid Build Coastguard Worker if (cfg.c_extra_ea_name_prefixes)
1408*33b1fccfSAndroid Build Coastguard Worker erofs_xattr_write_name_prefixes(&g_sbi, packedfile);
1409*33b1fccfSAndroid Build Coastguard Worker
1410*33b1fccfSAndroid Build Coastguard Worker root = erofs_mkfs_build_tree_from_path(&g_sbi, cfg.c_src_path);
1411*33b1fccfSAndroid Build Coastguard Worker if (IS_ERR(root)) {
1412*33b1fccfSAndroid Build Coastguard Worker err = PTR_ERR(root);
1413*33b1fccfSAndroid Build Coastguard Worker goto exit;
1414*33b1fccfSAndroid Build Coastguard Worker }
1415*33b1fccfSAndroid Build Coastguard Worker }
1416*33b1fccfSAndroid Build Coastguard Worker
1417*33b1fccfSAndroid Build Coastguard Worker if (erofstar.index_mode && g_sbi.extra_devices && !erofstar.mapfile)
1418*33b1fccfSAndroid Build Coastguard Worker g_sbi.devs[0].blocks = BLK_ROUND_UP(&g_sbi, erofstar.offset);
1419*33b1fccfSAndroid Build Coastguard Worker
1420*33b1fccfSAndroid Build Coastguard Worker if (erofs_sb_has_fragments(&g_sbi)) {
1421*33b1fccfSAndroid Build Coastguard Worker erofs_update_progressinfo("Handling packed data ...");
1422*33b1fccfSAndroid Build Coastguard Worker err = erofs_flush_packed_inode(&g_sbi);
1423*33b1fccfSAndroid Build Coastguard Worker if (err)
1424*33b1fccfSAndroid Build Coastguard Worker goto exit;
1425*33b1fccfSAndroid Build Coastguard Worker }
1426*33b1fccfSAndroid Build Coastguard Worker
1427*33b1fccfSAndroid Build Coastguard Worker if (erofstar.index_mode || cfg.c_chunkbits || g_sbi.extra_devices) {
1428*33b1fccfSAndroid Build Coastguard Worker err = erofs_mkfs_dump_blobs(&g_sbi);
1429*33b1fccfSAndroid Build Coastguard Worker if (err)
1430*33b1fccfSAndroid Build Coastguard Worker goto exit;
1431*33b1fccfSAndroid Build Coastguard Worker }
1432*33b1fccfSAndroid Build Coastguard Worker
1433*33b1fccfSAndroid Build Coastguard Worker /* flush all buffers except for the superblock */
1434*33b1fccfSAndroid Build Coastguard Worker err = erofs_bflush(g_sbi.bmgr, NULL);
1435*33b1fccfSAndroid Build Coastguard Worker if (err)
1436*33b1fccfSAndroid Build Coastguard Worker goto exit;
1437*33b1fccfSAndroid Build Coastguard Worker
1438*33b1fccfSAndroid Build Coastguard Worker erofs_fixup_root_inode(root);
1439*33b1fccfSAndroid Build Coastguard Worker erofs_iput(root);
1440*33b1fccfSAndroid Build Coastguard Worker root = NULL;
1441*33b1fccfSAndroid Build Coastguard Worker
1442*33b1fccfSAndroid Build Coastguard Worker err = erofs_writesb(&g_sbi, sb_bh, &nblocks);
1443*33b1fccfSAndroid Build Coastguard Worker if (err)
1444*33b1fccfSAndroid Build Coastguard Worker goto exit;
1445*33b1fccfSAndroid Build Coastguard Worker
1446*33b1fccfSAndroid Build Coastguard Worker /* flush all remaining buffers */
1447*33b1fccfSAndroid Build Coastguard Worker err = erofs_bflush(g_sbi.bmgr, NULL);
1448*33b1fccfSAndroid Build Coastguard Worker if (err)
1449*33b1fccfSAndroid Build Coastguard Worker goto exit;
1450*33b1fccfSAndroid Build Coastguard Worker
1451*33b1fccfSAndroid Build Coastguard Worker err = erofs_dev_resize(&g_sbi, nblocks);
1452*33b1fccfSAndroid Build Coastguard Worker
1453*33b1fccfSAndroid Build Coastguard Worker if (!err && erofs_sb_has_sb_chksum(&g_sbi)) {
1454*33b1fccfSAndroid Build Coastguard Worker err = erofs_enable_sb_chksum(&g_sbi, &crc);
1455*33b1fccfSAndroid Build Coastguard Worker if (!err)
1456*33b1fccfSAndroid Build Coastguard Worker erofs_info("superblock checksum 0x%08x written", crc);
1457*33b1fccfSAndroid Build Coastguard Worker }
1458*33b1fccfSAndroid Build Coastguard Worker exit:
1459*33b1fccfSAndroid Build Coastguard Worker if (root)
1460*33b1fccfSAndroid Build Coastguard Worker erofs_iput(root);
1461*33b1fccfSAndroid Build Coastguard Worker z_erofs_compress_exit();
1462*33b1fccfSAndroid Build Coastguard Worker z_erofs_dedupe_exit();
1463*33b1fccfSAndroid Build Coastguard Worker blklst = erofs_blocklist_close();
1464*33b1fccfSAndroid Build Coastguard Worker if (blklst)
1465*33b1fccfSAndroid Build Coastguard Worker fclose(blklst);
1466*33b1fccfSAndroid Build Coastguard Worker erofs_dev_close(&g_sbi);
1467*33b1fccfSAndroid Build Coastguard Worker erofs_cleanup_compress_hints();
1468*33b1fccfSAndroid Build Coastguard Worker erofs_cleanup_exclude_rules();
1469*33b1fccfSAndroid Build Coastguard Worker if (cfg.c_chunkbits)
1470*33b1fccfSAndroid Build Coastguard Worker erofs_blob_exit();
1471*33b1fccfSAndroid Build Coastguard Worker if (cfg.c_fragments)
1472*33b1fccfSAndroid Build Coastguard Worker z_erofs_fragments_exit();
1473*33b1fccfSAndroid Build Coastguard Worker erofs_packedfile_exit();
1474*33b1fccfSAndroid Build Coastguard Worker erofs_xattr_cleanup_name_prefixes();
1475*33b1fccfSAndroid Build Coastguard Worker erofs_rebuild_cleanup();
1476*33b1fccfSAndroid Build Coastguard Worker erofs_diskbuf_exit();
1477*33b1fccfSAndroid Build Coastguard Worker erofs_exit_configure();
1478*33b1fccfSAndroid Build Coastguard Worker if (tar_mode) {
1479*33b1fccfSAndroid Build Coastguard Worker erofs_iostream_close(&erofstar.ios);
1480*33b1fccfSAndroid Build Coastguard Worker if (erofstar.ios.dumpfd >= 0)
1481*33b1fccfSAndroid Build Coastguard Worker close(erofstar.ios.dumpfd);
1482*33b1fccfSAndroid Build Coastguard Worker }
1483*33b1fccfSAndroid Build Coastguard Worker
1484*33b1fccfSAndroid Build Coastguard Worker if (err) {
1485*33b1fccfSAndroid Build Coastguard Worker erofs_err("\tCould not format the device : %s\n",
1486*33b1fccfSAndroid Build Coastguard Worker erofs_strerror(err));
1487*33b1fccfSAndroid Build Coastguard Worker return 1;
1488*33b1fccfSAndroid Build Coastguard Worker }
1489*33b1fccfSAndroid Build Coastguard Worker erofs_update_progressinfo("Build completed.\n");
1490*33b1fccfSAndroid Build Coastguard Worker erofs_mkfs_showsummaries(nblocks);
1491*33b1fccfSAndroid Build Coastguard Worker erofs_put_super(&g_sbi);
1492*33b1fccfSAndroid Build Coastguard Worker return 0;
1493*33b1fccfSAndroid Build Coastguard Worker }
1494