15e5c12b0Sopenharmony_ci/**
25e5c12b0Sopenharmony_ci * f2fs_format.c
35e5c12b0Sopenharmony_ci *
45e5c12b0Sopenharmony_ci * Copyright (c) 2012 Samsung Electronics Co., Ltd.
55e5c12b0Sopenharmony_ci *             http://www.samsung.com/
65e5c12b0Sopenharmony_ci *
75e5c12b0Sopenharmony_ci * Dual licensed under the GPL or LGPL version 2 licenses.
85e5c12b0Sopenharmony_ci */
95e5c12b0Sopenharmony_ci#ifndef _LARGEFILE64_SOURCE
105e5c12b0Sopenharmony_ci#define _LARGEFILE64_SOURCE
115e5c12b0Sopenharmony_ci#endif
125e5c12b0Sopenharmony_ci
135e5c12b0Sopenharmony_ci#include <stdio.h>
145e5c12b0Sopenharmony_ci#include <stdlib.h>
155e5c12b0Sopenharmony_ci#include <fcntl.h>
165e5c12b0Sopenharmony_ci#include <string.h>
175e5c12b0Sopenharmony_ci#include <stdbool.h>
185e5c12b0Sopenharmony_ci#include <unistd.h>
195e5c12b0Sopenharmony_ci#include <sys/stat.h>
205e5c12b0Sopenharmony_ci#ifdef HAVE_SYS_MOUNT_H
215e5c12b0Sopenharmony_ci#include <sys/mount.h>
225e5c12b0Sopenharmony_ci#endif
235e5c12b0Sopenharmony_ci#include <time.h>
245e5c12b0Sopenharmony_ci#include <errno.h>
255e5c12b0Sopenharmony_ci#include <getopt.h>
265e5c12b0Sopenharmony_ci
275e5c12b0Sopenharmony_ci#include <f2fs_fs.h>
285e5c12b0Sopenharmony_ci
295e5c12b0Sopenharmony_ci#ifdef HAVE_LIBBLKID
305e5c12b0Sopenharmony_ci#include <blkid/blkid.h>
315e5c12b0Sopenharmony_ci#endif
325e5c12b0Sopenharmony_ci#ifdef HAVE_UUID_UUID_H
335e5c12b0Sopenharmony_ci#include <uuid.h>
345e5c12b0Sopenharmony_ci#endif
355e5c12b0Sopenharmony_ci
365e5c12b0Sopenharmony_ci#include "quota.h"
375e5c12b0Sopenharmony_ci#include "f2fs_format_utils.h"
385e5c12b0Sopenharmony_ci
395e5c12b0Sopenharmony_ci#ifdef HAVE_SYS_UTSNAME_H
405e5c12b0Sopenharmony_ci#include <sys/utsname.h>
415e5c12b0Sopenharmony_ci#endif
425e5c12b0Sopenharmony_ci#ifdef HAVE_SPARSE_SPARSE_H
435e5c12b0Sopenharmony_ci#include <sparse/sparse.h>
445e5c12b0Sopenharmony_ciextern struct sparse_file *f2fs_sparse_file;
455e5c12b0Sopenharmony_ci#endif
465e5c12b0Sopenharmony_ci
475e5c12b0Sopenharmony_ciextern struct f2fs_configuration c;
485e5c12b0Sopenharmony_cistatic int force_overwrite = 0;
495e5c12b0Sopenharmony_ci
505e5c12b0Sopenharmony_ciINIT_FEATURE_TABLE;
515e5c12b0Sopenharmony_ci
525e5c12b0Sopenharmony_cistatic void mkfs_usage()
535e5c12b0Sopenharmony_ci{
545e5c12b0Sopenharmony_ci	MSG(0, "\nUsage: mkfs.f2fs [options] device [sectors]\n");
555e5c12b0Sopenharmony_ci	MSG(0, "[options]:\n");
565e5c12b0Sopenharmony_ci	MSG(0, "  -a heap-based allocation [default:0]\n");
575e5c12b0Sopenharmony_ci	MSG(0, "  -c device1[,device2,...] up to 7 additional devices, except meta device\n");
585e5c12b0Sopenharmony_ci	MSG(0, "  -d debug level [default:0]\n");
595e5c12b0Sopenharmony_ci	MSG(0, "  -e [cold file ext list] e.g. \"mp3,gif,mov\"\n");
605e5c12b0Sopenharmony_ci	MSG(0, "  -E [hot file ext list] e.g. \"db\"\n");
615e5c12b0Sopenharmony_ci	MSG(0, "  -f force overwrite of the existing filesystem\n");
625e5c12b0Sopenharmony_ci	MSG(0, "  -g add default options\n");
635e5c12b0Sopenharmony_ci	MSG(0, "  -i extended node bitmap, node ratio is 20%% by default\n");
645e5c12b0Sopenharmony_ci	MSG(0, "  -l label\n");
655e5c12b0Sopenharmony_ci	MSG(0, "  -U uuid\n");
665e5c12b0Sopenharmony_ci	MSG(0, "  -m support zoned block device [default:0]\n");
675e5c12b0Sopenharmony_ci	MSG(0, "  -o overprovision percentage [default:auto]\n");
685e5c12b0Sopenharmony_ci	MSG(0, "  -O feature1[,feature2,...] e.g. \"encrypt\"\n");
695e5c12b0Sopenharmony_ci	MSG(0, "  -C [encoding[:flag1,...]] Support casefolding with optional flags\n");
705e5c12b0Sopenharmony_ci	MSG(0, "  -q quiet mode\n");
715e5c12b0Sopenharmony_ci	MSG(0, "  -r set checkpointing seed (srand()) to 0\n");
725e5c12b0Sopenharmony_ci	MSG(0, "  -R root_owner [default: 0:0]\n");
735e5c12b0Sopenharmony_ci	MSG(0, "  -s # of segments per section [default:1]\n");
745e5c12b0Sopenharmony_ci	MSG(0, "  -S sparse mode\n");
755e5c12b0Sopenharmony_ci	MSG(0, "  -t 0: nodiscard, 1: discard [default:1]\n");
765e5c12b0Sopenharmony_ci	MSG(0, "  -T timestamps\n");
775e5c12b0Sopenharmony_ci	MSG(0, "  -w wanted sector size\n");
785e5c12b0Sopenharmony_ci	MSG(0, "  -z # of sections per zone [default:1]\n");
795e5c12b0Sopenharmony_ci	MSG(0, "  -V print the version number and exit\n");
805e5c12b0Sopenharmony_ci	MSG(0, "sectors: number of sectors [default: determined by device size]\n");
815e5c12b0Sopenharmony_ci	exit(1);
825e5c12b0Sopenharmony_ci}
835e5c12b0Sopenharmony_ci
845e5c12b0Sopenharmony_cistatic void f2fs_show_info()
855e5c12b0Sopenharmony_ci{
865e5c12b0Sopenharmony_ci	MSG(0, "\n    F2FS-tools: mkfs.f2fs Ver: %s (%s)\n\n",
875e5c12b0Sopenharmony_ci				F2FS_TOOLS_VERSION,
885e5c12b0Sopenharmony_ci				F2FS_TOOLS_DATE);
895e5c12b0Sopenharmony_ci	if (c.heap == 0)
905e5c12b0Sopenharmony_ci		MSG(0, "Info: Disable heap-based policy\n");
915e5c12b0Sopenharmony_ci
925e5c12b0Sopenharmony_ci	MSG(0, "Info: Debug level = %d\n", c.dbg_lv);
935e5c12b0Sopenharmony_ci	if (c.extension_list[0])
945e5c12b0Sopenharmony_ci		MSG(0, "Info: Add new cold file extension list\n");
955e5c12b0Sopenharmony_ci	if (c.extension_list[1])
965e5c12b0Sopenharmony_ci		MSG(0, "Info: Add new hot file extension list\n");
975e5c12b0Sopenharmony_ci
985e5c12b0Sopenharmony_ci	if (strlen(c.vol_label))
995e5c12b0Sopenharmony_ci		MSG(0, "Info: Label = %s\n", c.vol_label);
1005e5c12b0Sopenharmony_ci	MSG(0, "Info: Trim is %s\n", c.trim ? "enabled": "disabled");
1015e5c12b0Sopenharmony_ci
1025e5c12b0Sopenharmony_ci	if (c.defset == CONF_ANDROID)
1035e5c12b0Sopenharmony_ci		MSG(0, "Info: Set conf for android\n");
1045e5c12b0Sopenharmony_ci
1055e5c12b0Sopenharmony_ci	if (c.feature & le32_to_cpu(F2FS_FEATURE_CASEFOLD))
1065e5c12b0Sopenharmony_ci		MSG(0, "Info: Enable %s with casefolding\n",
1075e5c12b0Sopenharmony_ci					f2fs_encoding2str(c.s_encoding));
1085e5c12b0Sopenharmony_ci	if (c.feature & le32_to_cpu(F2FS_FEATURE_PRJQUOTA))
1095e5c12b0Sopenharmony_ci		MSG(0, "Info: Enable Project quota\n");
1105e5c12b0Sopenharmony_ci
1115e5c12b0Sopenharmony_ci	if (c.feature & le32_to_cpu(F2FS_FEATURE_COMPRESSION))
1125e5c12b0Sopenharmony_ci		MSG(0, "Info: Enable Compression\n");
1135e5c12b0Sopenharmony_ci}
1145e5c12b0Sopenharmony_ci
1155e5c12b0Sopenharmony_ci#if defined(ANDROID_TARGET) && defined(HAVE_SYS_UTSNAME_H)
1165e5c12b0Sopenharmony_cistatic bool kernel_version_over(unsigned int min_major, unsigned int min_minor)
1175e5c12b0Sopenharmony_ci{
1185e5c12b0Sopenharmony_ci	unsigned int major, minor;
1195e5c12b0Sopenharmony_ci	struct utsname uts;
1205e5c12b0Sopenharmony_ci
1215e5c12b0Sopenharmony_ci	if ((uname(&uts) != 0) ||
1225e5c12b0Sopenharmony_ci			(sscanf(uts.release, "%u.%u", &major, &minor) != 2))
1235e5c12b0Sopenharmony_ci		return false;
1245e5c12b0Sopenharmony_ci	if (major > min_major)
1255e5c12b0Sopenharmony_ci		return true;
1265e5c12b0Sopenharmony_ci	if (major == min_major && minor >= min_minor)
1275e5c12b0Sopenharmony_ci		return true;
1285e5c12b0Sopenharmony_ci	return false;
1295e5c12b0Sopenharmony_ci}
1305e5c12b0Sopenharmony_ci#else
1315e5c12b0Sopenharmony_cistatic bool kernel_version_over(unsigned int UNUSED(min_major),
1325e5c12b0Sopenharmony_ci				unsigned int UNUSED(min_minor))
1335e5c12b0Sopenharmony_ci{
1345e5c12b0Sopenharmony_ci	return false;
1355e5c12b0Sopenharmony_ci}
1365e5c12b0Sopenharmony_ci#endif
1375e5c12b0Sopenharmony_ci
1385e5c12b0Sopenharmony_cistatic void add_default_options(void)
1395e5c12b0Sopenharmony_ci{
1405e5c12b0Sopenharmony_ci	switch (c.defset) {
1415e5c12b0Sopenharmony_ci	case CONF_ANDROID:
1425e5c12b0Sopenharmony_ci		/* -d1 -f -w 4096 -R 0:0 */
1435e5c12b0Sopenharmony_ci		c.dbg_lv = 1;
1445e5c12b0Sopenharmony_ci		force_overwrite = 1;
1455e5c12b0Sopenharmony_ci		c.wanted_sector_size = 4096;
1465e5c12b0Sopenharmony_ci		c.root_uid = c.root_gid = 0;
1475e5c12b0Sopenharmony_ci
1485e5c12b0Sopenharmony_ci		/* RO doesn't need any other features */
1495e5c12b0Sopenharmony_ci		if (c.feature & cpu_to_le32(F2FS_FEATURE_RO))
1505e5c12b0Sopenharmony_ci			return;
1515e5c12b0Sopenharmony_ci
1525e5c12b0Sopenharmony_ci		/* -O encrypt -O project_quota,extra_attr,{quota} -O verity */
1535e5c12b0Sopenharmony_ci		c.feature |= cpu_to_le32(F2FS_FEATURE_ENCRYPT);
1545e5c12b0Sopenharmony_ci		if (!kernel_version_over(4, 14))
1555e5c12b0Sopenharmony_ci			c.feature |= cpu_to_le32(F2FS_FEATURE_QUOTA_INO);
1565e5c12b0Sopenharmony_ci		c.feature |= cpu_to_le32(F2FS_FEATURE_PRJQUOTA);
1575e5c12b0Sopenharmony_ci		c.feature |= cpu_to_le32(F2FS_FEATURE_EXTRA_ATTR);
1585e5c12b0Sopenharmony_ci		c.feature |= cpu_to_le32(F2FS_FEATURE_VERITY);
1595e5c12b0Sopenharmony_ci		break;
1605e5c12b0Sopenharmony_ci	}
1615e5c12b0Sopenharmony_ci#ifdef CONF_CASEFOLD
1625e5c12b0Sopenharmony_ci	c.s_encoding = F2FS_ENC_UTF8_12_1;
1635e5c12b0Sopenharmony_ci	c.feature |= cpu_to_le32(F2FS_FEATURE_CASEFOLD);
1645e5c12b0Sopenharmony_ci#endif
1655e5c12b0Sopenharmony_ci#ifdef CONF_PROJID
1665e5c12b0Sopenharmony_ci	c.feature |= cpu_to_le32(F2FS_FEATURE_QUOTA_INO);
1675e5c12b0Sopenharmony_ci	c.feature |= cpu_to_le32(F2FS_FEATURE_PRJQUOTA);
1685e5c12b0Sopenharmony_ci	c.feature |= cpu_to_le32(F2FS_FEATURE_EXTRA_ATTR);
1695e5c12b0Sopenharmony_ci#endif
1705e5c12b0Sopenharmony_ci
1715e5c12b0Sopenharmony_ci	if (c.feature & cpu_to_le32(F2FS_FEATURE_QUOTA_INO))
1725e5c12b0Sopenharmony_ci		c.quota_bits = QUOTA_USR_BIT | QUOTA_GRP_BIT;
1735e5c12b0Sopenharmony_ci	if (c.feature & cpu_to_le32(F2FS_FEATURE_PRJQUOTA)) {
1745e5c12b0Sopenharmony_ci		c.feature |= cpu_to_le32(F2FS_FEATURE_QUOTA_INO);
1755e5c12b0Sopenharmony_ci		c.quota_bits |= QUOTA_PRJ_BIT;
1765e5c12b0Sopenharmony_ci	}
1775e5c12b0Sopenharmony_ci}
1785e5c12b0Sopenharmony_ci
1795e5c12b0Sopenharmony_cistatic void f2fs_parse_options(int argc, char *argv[])
1805e5c12b0Sopenharmony_ci{
1815e5c12b0Sopenharmony_ci	static const char *option_string = "qa:c:C:d:e:E:g:hil:mo:O:rR:s:S:z:t:T:U:Vfw:";
1825e5c12b0Sopenharmony_ci	static const struct option long_opts[] = {
1835e5c12b0Sopenharmony_ci		{ .name = "help", .has_arg = 0, .flag = NULL, .val = 'h' },
1845e5c12b0Sopenharmony_ci		{ .name = NULL, .has_arg = 0, .flag = NULL, .val = 0 }
1855e5c12b0Sopenharmony_ci	};
1865e5c12b0Sopenharmony_ci	int32_t option=0;
1875e5c12b0Sopenharmony_ci	int val;
1885e5c12b0Sopenharmony_ci	char *token;
1895e5c12b0Sopenharmony_ci
1905e5c12b0Sopenharmony_ci	while ((option = getopt_long(argc,argv,option_string,long_opts,NULL)) != EOF) {
1915e5c12b0Sopenharmony_ci		switch (option) {
1925e5c12b0Sopenharmony_ci		case 'q':
1935e5c12b0Sopenharmony_ci			c.dbg_lv = -1;
1945e5c12b0Sopenharmony_ci			break;
1955e5c12b0Sopenharmony_ci		case 'a':
1965e5c12b0Sopenharmony_ci			c.heap = atoi(optarg);
1975e5c12b0Sopenharmony_ci			break;
1985e5c12b0Sopenharmony_ci		case 'c':
1995e5c12b0Sopenharmony_ci			if (c.ndevs >= MAX_DEVICES) {
2005e5c12b0Sopenharmony_ci				MSG(0, "Error: Too many devices\n");
2015e5c12b0Sopenharmony_ci				mkfs_usage();
2025e5c12b0Sopenharmony_ci			}
2035e5c12b0Sopenharmony_ci
2045e5c12b0Sopenharmony_ci			if (strlen(optarg) > MAX_PATH_LEN) {
2055e5c12b0Sopenharmony_ci				MSG(0, "Error: device path should be less than "
2065e5c12b0Sopenharmony_ci					"%d characters\n", MAX_PATH_LEN);
2075e5c12b0Sopenharmony_ci				mkfs_usage();
2085e5c12b0Sopenharmony_ci			}
2095e5c12b0Sopenharmony_ci			c.devices[c.ndevs++].path = strdup(optarg);
2105e5c12b0Sopenharmony_ci			break;
2115e5c12b0Sopenharmony_ci		case 'd':
2125e5c12b0Sopenharmony_ci			c.dbg_lv = atoi(optarg);
2135e5c12b0Sopenharmony_ci			break;
2145e5c12b0Sopenharmony_ci		case 'e':
2155e5c12b0Sopenharmony_ci			c.extension_list[0] = strdup(optarg);
2165e5c12b0Sopenharmony_ci			break;
2175e5c12b0Sopenharmony_ci		case 'E':
2185e5c12b0Sopenharmony_ci			c.extension_list[1] = strdup(optarg);
2195e5c12b0Sopenharmony_ci			break;
2205e5c12b0Sopenharmony_ci		case 'g':
2215e5c12b0Sopenharmony_ci			if (!strcmp(optarg, "android"))
2225e5c12b0Sopenharmony_ci				c.defset = CONF_ANDROID;
2235e5c12b0Sopenharmony_ci			break;
2245e5c12b0Sopenharmony_ci		case 'h':
2255e5c12b0Sopenharmony_ci			mkfs_usage();
2265e5c12b0Sopenharmony_ci			break;
2275e5c12b0Sopenharmony_ci		case 'i':
2285e5c12b0Sopenharmony_ci			c.large_nat_bitmap = 1;
2295e5c12b0Sopenharmony_ci			break;
2305e5c12b0Sopenharmony_ci		case 'l':		/*v: volume label */
2315e5c12b0Sopenharmony_ci			if (strlen(optarg) > 512) {
2325e5c12b0Sopenharmony_ci				MSG(0, "Error: Volume Label should be less than "
2335e5c12b0Sopenharmony_ci						"512 characters\n");
2345e5c12b0Sopenharmony_ci				mkfs_usage();
2355e5c12b0Sopenharmony_ci			}
2365e5c12b0Sopenharmony_ci			c.vol_label = optarg;
2375e5c12b0Sopenharmony_ci			break;
2385e5c12b0Sopenharmony_ci		case 'm':
2395e5c12b0Sopenharmony_ci			c.zoned_mode = 1;
2405e5c12b0Sopenharmony_ci			break;
2415e5c12b0Sopenharmony_ci		case 'o':
2425e5c12b0Sopenharmony_ci			c.overprovision = atof(optarg);
2435e5c12b0Sopenharmony_ci			break;
2445e5c12b0Sopenharmony_ci		case 'O':
2455e5c12b0Sopenharmony_ci			if (parse_feature(feature_table, optarg))
2465e5c12b0Sopenharmony_ci				mkfs_usage();
2475e5c12b0Sopenharmony_ci			break;
2485e5c12b0Sopenharmony_ci		case 'r':
2495e5c12b0Sopenharmony_ci			c.fake_seed = 1;
2505e5c12b0Sopenharmony_ci			break;
2515e5c12b0Sopenharmony_ci		case 'R':
2525e5c12b0Sopenharmony_ci			if (parse_root_owner(optarg, &c.root_uid, &c.root_gid))
2535e5c12b0Sopenharmony_ci				mkfs_usage();
2545e5c12b0Sopenharmony_ci			break;
2555e5c12b0Sopenharmony_ci		case 's':
2565e5c12b0Sopenharmony_ci			c.segs_per_sec = atoi(optarg);
2575e5c12b0Sopenharmony_ci			break;
2585e5c12b0Sopenharmony_ci		case 'S':
2595e5c12b0Sopenharmony_ci			c.device_size = atoll(optarg);
2605e5c12b0Sopenharmony_ci			c.device_size &= (~((uint64_t)(F2FS_BLKSIZE - 1)));
2615e5c12b0Sopenharmony_ci			c.sparse_mode = 1;
2625e5c12b0Sopenharmony_ci			break;
2635e5c12b0Sopenharmony_ci		case 'z':
2645e5c12b0Sopenharmony_ci			c.secs_per_zone = atoi(optarg);
2655e5c12b0Sopenharmony_ci			break;
2665e5c12b0Sopenharmony_ci		case 't':
2675e5c12b0Sopenharmony_ci			c.trim = atoi(optarg);
2685e5c12b0Sopenharmony_ci			break;
2695e5c12b0Sopenharmony_ci		case 'T':
2705e5c12b0Sopenharmony_ci			c.fixed_time = strtoul(optarg, NULL, 0);
2715e5c12b0Sopenharmony_ci			break;
2725e5c12b0Sopenharmony_ci		case 'U':
2735e5c12b0Sopenharmony_ci			c.vol_uuid = strdup(optarg);
2745e5c12b0Sopenharmony_ci			break;
2755e5c12b0Sopenharmony_ci		case 'f':
2765e5c12b0Sopenharmony_ci			force_overwrite = 1;
2775e5c12b0Sopenharmony_ci			break;
2785e5c12b0Sopenharmony_ci		case 'w':
2795e5c12b0Sopenharmony_ci			c.wanted_sector_size = atoi(optarg);
2805e5c12b0Sopenharmony_ci			break;
2815e5c12b0Sopenharmony_ci		case 'V':
2825e5c12b0Sopenharmony_ci			show_version("mkfs.f2fs");
2835e5c12b0Sopenharmony_ci			exit(0);
2845e5c12b0Sopenharmony_ci		case 'C':
2855e5c12b0Sopenharmony_ci			token = strtok(optarg, ":");
2865e5c12b0Sopenharmony_ci			val = f2fs_str2encoding(token);
2875e5c12b0Sopenharmony_ci			if (val < 0) {
2885e5c12b0Sopenharmony_ci				MSG(0, "\tError: Unknown encoding %s\n", token);
2895e5c12b0Sopenharmony_ci				mkfs_usage();
2905e5c12b0Sopenharmony_ci			}
2915e5c12b0Sopenharmony_ci			c.s_encoding = val;
2925e5c12b0Sopenharmony_ci			token = strtok(NULL, "");
2935e5c12b0Sopenharmony_ci			val = f2fs_str2encoding_flags(&token, &c.s_encoding_flags);
2945e5c12b0Sopenharmony_ci			if (val) {
2955e5c12b0Sopenharmony_ci				MSG(0, "\tError: Unknown flag %s\n",token);
2965e5c12b0Sopenharmony_ci				mkfs_usage();
2975e5c12b0Sopenharmony_ci			}
2985e5c12b0Sopenharmony_ci			c.feature |= cpu_to_le32(F2FS_FEATURE_CASEFOLD);
2995e5c12b0Sopenharmony_ci			break;
3005e5c12b0Sopenharmony_ci		default:
3015e5c12b0Sopenharmony_ci			MSG(0, "\tError: Unknown option %c\n",option);
3025e5c12b0Sopenharmony_ci			mkfs_usage();
3035e5c12b0Sopenharmony_ci			break;
3045e5c12b0Sopenharmony_ci		}
3055e5c12b0Sopenharmony_ci	}
3065e5c12b0Sopenharmony_ci
3075e5c12b0Sopenharmony_ci	add_default_options();
3085e5c12b0Sopenharmony_ci
3095e5c12b0Sopenharmony_ci	if (!(c.feature & cpu_to_le32(F2FS_FEATURE_EXTRA_ATTR))) {
3105e5c12b0Sopenharmony_ci		if (c.feature & cpu_to_le32(F2FS_FEATURE_PRJQUOTA)) {
3115e5c12b0Sopenharmony_ci			MSG(0, "\tInfo: project quota feature should always be "
3125e5c12b0Sopenharmony_ci				"enabled with extra attr feature\n");
3135e5c12b0Sopenharmony_ci			exit(1);
3145e5c12b0Sopenharmony_ci		}
3155e5c12b0Sopenharmony_ci		if (c.feature & cpu_to_le32(F2FS_FEATURE_INODE_CHKSUM)) {
3165e5c12b0Sopenharmony_ci			MSG(0, "\tInfo: inode checksum feature should always be "
3175e5c12b0Sopenharmony_ci				"enabled with extra attr feature\n");
3185e5c12b0Sopenharmony_ci			exit(1);
3195e5c12b0Sopenharmony_ci		}
3205e5c12b0Sopenharmony_ci		if (c.feature & cpu_to_le32(F2FS_FEATURE_FLEXIBLE_INLINE_XATTR)) {
3215e5c12b0Sopenharmony_ci			MSG(0, "\tInfo: flexible inline xattr feature should always be "
3225e5c12b0Sopenharmony_ci				"enabled with extra attr feature\n");
3235e5c12b0Sopenharmony_ci			exit(1);
3245e5c12b0Sopenharmony_ci		}
3255e5c12b0Sopenharmony_ci		if (c.feature & cpu_to_le32(F2FS_FEATURE_INODE_CRTIME)) {
3265e5c12b0Sopenharmony_ci			MSG(0, "\tInfo: inode crtime feature should always be "
3275e5c12b0Sopenharmony_ci				"enabled with extra attr feature\n");
3285e5c12b0Sopenharmony_ci			exit(1);
3295e5c12b0Sopenharmony_ci		}
3305e5c12b0Sopenharmony_ci		if (c.feature & cpu_to_le32(F2FS_FEATURE_COMPRESSION)) {
3315e5c12b0Sopenharmony_ci			MSG(0, "\tInfo: compression feature should always be "
3325e5c12b0Sopenharmony_ci				"enabled with extra attr feature\n");
3335e5c12b0Sopenharmony_ci			exit(1);
3345e5c12b0Sopenharmony_ci		}
3355e5c12b0Sopenharmony_ci	}
3365e5c12b0Sopenharmony_ci
3375e5c12b0Sopenharmony_ci	if (optind >= argc) {
3385e5c12b0Sopenharmony_ci		MSG(0, "\tError: Device not specified\n");
3395e5c12b0Sopenharmony_ci		mkfs_usage();
3405e5c12b0Sopenharmony_ci	}
3415e5c12b0Sopenharmony_ci
3425e5c12b0Sopenharmony_ci	/* [0] : META, [1 to MAX_DEVICES - 1] : NODE/DATA */
3435e5c12b0Sopenharmony_ci	c.devices[0].path = strdup(argv[optind]);
3445e5c12b0Sopenharmony_ci
3455e5c12b0Sopenharmony_ci	if ((optind + 1) < argc) {
3465e5c12b0Sopenharmony_ci		if (c.ndevs > 1) {
3475e5c12b0Sopenharmony_ci			MSG(0, "\tError: Not support custom size on multi-devs.\n");
3485e5c12b0Sopenharmony_ci			mkfs_usage();
3495e5c12b0Sopenharmony_ci		}
3505e5c12b0Sopenharmony_ci		c.wanted_total_sectors = atoll(argv[optind+1]);
3515e5c12b0Sopenharmony_ci	}
3525e5c12b0Sopenharmony_ci
3535e5c12b0Sopenharmony_ci	if (c.sparse_mode)
3545e5c12b0Sopenharmony_ci		c.trim = 0;
3555e5c12b0Sopenharmony_ci
3565e5c12b0Sopenharmony_ci	if (c.zoned_mode)
3575e5c12b0Sopenharmony_ci		c.feature |= cpu_to_le32(F2FS_FEATURE_BLKZONED);
3585e5c12b0Sopenharmony_ci}
3595e5c12b0Sopenharmony_ci
3605e5c12b0Sopenharmony_ci#ifdef HAVE_LIBBLKID
3615e5c12b0Sopenharmony_cistatic int f2fs_dev_is_overwrite(const char *device)
3625e5c12b0Sopenharmony_ci{
3635e5c12b0Sopenharmony_ci	const char	*type;
3645e5c12b0Sopenharmony_ci	blkid_probe	pr = NULL;
3655e5c12b0Sopenharmony_ci	int		ret = -1;
3665e5c12b0Sopenharmony_ci
3675e5c12b0Sopenharmony_ci	if (!device || !*device)
3685e5c12b0Sopenharmony_ci		return 0;
3695e5c12b0Sopenharmony_ci
3705e5c12b0Sopenharmony_ci	pr = blkid_new_probe_from_filename(device);
3715e5c12b0Sopenharmony_ci	if (!pr)
3725e5c12b0Sopenharmony_ci		goto out;
3735e5c12b0Sopenharmony_ci
3745e5c12b0Sopenharmony_ci	ret = blkid_probe_enable_partitions(pr, 1);
3755e5c12b0Sopenharmony_ci	if (ret < 0)
3765e5c12b0Sopenharmony_ci		goto out;
3775e5c12b0Sopenharmony_ci
3785e5c12b0Sopenharmony_ci	ret = blkid_do_fullprobe(pr);
3795e5c12b0Sopenharmony_ci	if (ret < 0)
3805e5c12b0Sopenharmony_ci		goto out;
3815e5c12b0Sopenharmony_ci
3825e5c12b0Sopenharmony_ci	/*
3835e5c12b0Sopenharmony_ci	 * Blkid returns 1 for nothing found and 0 when it finds a signature,
3845e5c12b0Sopenharmony_ci	 * but we want the exact opposite, so reverse the return value here.
3855e5c12b0Sopenharmony_ci	 *
3865e5c12b0Sopenharmony_ci	 * In addition print some useful diagnostics about what actually is
3875e5c12b0Sopenharmony_ci	 * on the device.
3885e5c12b0Sopenharmony_ci	 */
3895e5c12b0Sopenharmony_ci	if (ret) {
3905e5c12b0Sopenharmony_ci		ret = 0;
3915e5c12b0Sopenharmony_ci		goto out;
3925e5c12b0Sopenharmony_ci	}
3935e5c12b0Sopenharmony_ci
3945e5c12b0Sopenharmony_ci	if (!blkid_probe_lookup_value(pr, "TYPE", &type, NULL)) {
3955e5c12b0Sopenharmony_ci		MSG(0, "\t%s appears to contain an existing filesystem (%s).\n",
3965e5c12b0Sopenharmony_ci			device, type);
3975e5c12b0Sopenharmony_ci	} else if (!blkid_probe_lookup_value(pr, "PTTYPE", &type, NULL)) {
3985e5c12b0Sopenharmony_ci		MSG(0, "\t%s appears to contain a partition table (%s).\n",
3995e5c12b0Sopenharmony_ci			device, type);
4005e5c12b0Sopenharmony_ci	} else {
4015e5c12b0Sopenharmony_ci		MSG(0, "\t%s appears to contain something weird according to blkid\n",
4025e5c12b0Sopenharmony_ci			device);
4035e5c12b0Sopenharmony_ci	}
4045e5c12b0Sopenharmony_ci	ret = 1;
4055e5c12b0Sopenharmony_ciout:
4065e5c12b0Sopenharmony_ci	if (pr)
4075e5c12b0Sopenharmony_ci		blkid_free_probe(pr);
4085e5c12b0Sopenharmony_ci	if (ret == -1)
4095e5c12b0Sopenharmony_ci		MSG(0, "\tprobe of %s failed, cannot detect existing filesystem.\n",
4105e5c12b0Sopenharmony_ci			device);
4115e5c12b0Sopenharmony_ci	return ret;
4125e5c12b0Sopenharmony_ci}
4135e5c12b0Sopenharmony_ci
4145e5c12b0Sopenharmony_cistatic int f2fs_check_overwrite(void)
4155e5c12b0Sopenharmony_ci{
4165e5c12b0Sopenharmony_ci	int i;
4175e5c12b0Sopenharmony_ci
4185e5c12b0Sopenharmony_ci	for (i = 0; i < c.ndevs; i++)
4195e5c12b0Sopenharmony_ci		if (f2fs_dev_is_overwrite((char *)c.devices[i].path))
4205e5c12b0Sopenharmony_ci			return -1;
4215e5c12b0Sopenharmony_ci	return 0;
4225e5c12b0Sopenharmony_ci}
4235e5c12b0Sopenharmony_ci
4245e5c12b0Sopenharmony_ci#else
4255e5c12b0Sopenharmony_ci
4265e5c12b0Sopenharmony_cistatic int f2fs_check_overwrite(void)
4275e5c12b0Sopenharmony_ci{
4285e5c12b0Sopenharmony_ci	return 0;
4295e5c12b0Sopenharmony_ci}
4305e5c12b0Sopenharmony_ci
4315e5c12b0Sopenharmony_ci#endif /* HAVE_LIBBLKID */
4325e5c12b0Sopenharmony_ci
4335e5c12b0Sopenharmony_ciint main(int argc, char *argv[])
4345e5c12b0Sopenharmony_ci{
4355e5c12b0Sopenharmony_ci	f2fs_init_configuration();
4365e5c12b0Sopenharmony_ci
4375e5c12b0Sopenharmony_ci	f2fs_parse_options(argc, argv);
4385e5c12b0Sopenharmony_ci
4395e5c12b0Sopenharmony_ci	f2fs_show_info();
4405e5c12b0Sopenharmony_ci
4415e5c12b0Sopenharmony_ci	c.func = MKFS;
4425e5c12b0Sopenharmony_ci
4435e5c12b0Sopenharmony_ci	if (f2fs_devs_are_umounted() < 0) {
4445e5c12b0Sopenharmony_ci		if (errno != EBUSY)
4455e5c12b0Sopenharmony_ci			MSG(0, "\tError: Not available on mounted device!\n");
4465e5c12b0Sopenharmony_ci		goto err_format;
4475e5c12b0Sopenharmony_ci	}
4485e5c12b0Sopenharmony_ci
4495e5c12b0Sopenharmony_ci	if (f2fs_get_device_info() < 0)
4505e5c12b0Sopenharmony_ci		return -1;
4515e5c12b0Sopenharmony_ci
4525e5c12b0Sopenharmony_ci	if (f2fs_check_overwrite()) {
4535e5c12b0Sopenharmony_ci		char *zero_buf = NULL;
4545e5c12b0Sopenharmony_ci		int i;
4555e5c12b0Sopenharmony_ci
4565e5c12b0Sopenharmony_ci		if (!force_overwrite) {
4575e5c12b0Sopenharmony_ci			MSG(0, "\tUse the -f option to force overwrite.\n");
4585e5c12b0Sopenharmony_ci			goto err_format;
4595e5c12b0Sopenharmony_ci		}
4605e5c12b0Sopenharmony_ci		zero_buf = calloc(F2FS_BLKSIZE, 1);
4615e5c12b0Sopenharmony_ci		if (!zero_buf) {
4625e5c12b0Sopenharmony_ci			MSG(0, "\tError: Fail to allocate zero buffer.\n");
4635e5c12b0Sopenharmony_ci			goto err_format;
4645e5c12b0Sopenharmony_ci		}
4655e5c12b0Sopenharmony_ci		/* wipe out other FS magics mostly first 4MB space */
4665e5c12b0Sopenharmony_ci		for (i = 0; i < 1024; i++)
4675e5c12b0Sopenharmony_ci			if (dev_fill_block(zero_buf, i))
4685e5c12b0Sopenharmony_ci				break;
4695e5c12b0Sopenharmony_ci		free(zero_buf);
4705e5c12b0Sopenharmony_ci		if (i != 1024) {
4715e5c12b0Sopenharmony_ci			MSG(0, "\tError: Fail to fill zeros till %d.\n", i);
4725e5c12b0Sopenharmony_ci			goto err_format;
4735e5c12b0Sopenharmony_ci		}
4745e5c12b0Sopenharmony_ci		if (f2fs_fsync_device())
4755e5c12b0Sopenharmony_ci			goto err_format;
4765e5c12b0Sopenharmony_ci	}
4775e5c12b0Sopenharmony_ci
4785e5c12b0Sopenharmony_ci	if (f2fs_get_f2fs_info() < 0)
4795e5c12b0Sopenharmony_ci		goto err_format;
4805e5c12b0Sopenharmony_ci
4815e5c12b0Sopenharmony_ci	/*
4825e5c12b0Sopenharmony_ci	 * Some options are mandatory for host-managed
4835e5c12b0Sopenharmony_ci	 * zoned block devices.
4845e5c12b0Sopenharmony_ci	 */
4855e5c12b0Sopenharmony_ci	if (c.zoned_model != F2FS_ZONED_NONE && !c.zoned_mode) {
4865e5c12b0Sopenharmony_ci		MSG(0, "\tError: zoned block device feature is required\n");
4875e5c12b0Sopenharmony_ci		goto err_format;
4885e5c12b0Sopenharmony_ci	}
4895e5c12b0Sopenharmony_ci
4905e5c12b0Sopenharmony_ci	if (c.zoned_mode && !c.trim) {
4915e5c12b0Sopenharmony_ci		MSG(0, "\tError: Trim is required for zoned block devices\n");
4925e5c12b0Sopenharmony_ci		goto err_format;
4935e5c12b0Sopenharmony_ci	}
4945e5c12b0Sopenharmony_ci
4955e5c12b0Sopenharmony_ci	if (f2fs_format_device() < 0)
4965e5c12b0Sopenharmony_ci		goto err_format;
4975e5c12b0Sopenharmony_ci
4985e5c12b0Sopenharmony_ci	if (f2fs_finalize_device() < 0)
4995e5c12b0Sopenharmony_ci		goto err_format;
5005e5c12b0Sopenharmony_ci
5015e5c12b0Sopenharmony_ci	MSG(0, "Info: format successful\n");
5025e5c12b0Sopenharmony_ci
5035e5c12b0Sopenharmony_ci	return 0;
5045e5c12b0Sopenharmony_ci
5055e5c12b0Sopenharmony_cierr_format:
5065e5c12b0Sopenharmony_ci	f2fs_release_sparse_resource();
5075e5c12b0Sopenharmony_ci	return -1;
5085e5c12b0Sopenharmony_ci}
509