| // Copyright 2016 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <errno.h> |
| #include <fcntl.h> |
| #include <getopt.h> |
| #include <lib/fdio/directory.h> |
| #include <lib/fdio/fd.h> |
| #include <lib/fdio/fdio.h> |
| #include <stdarg.h> |
| #include <stdbool.h> |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <sys/stat.h> |
| #include <unistd.h> |
| #include <zircon/compiler.h> |
| #include <zircon/processargs.h> |
| #include <zircon/syscalls.h> |
| |
| #include <fs-management/mount.h> |
| #include <safemath/checked_math.h> |
| |
| namespace { |
| |
| struct { |
| const char* name; |
| disk_format_t df; |
| } FILESYSTEMS[] = { |
| {"blobfs", DISK_FORMAT_BLOBFS}, |
| {"minfs", DISK_FORMAT_MINFS}, |
| {"fat", DISK_FORMAT_FAT}, |
| {"factoryfs", DISK_FORMAT_FACTORYFS}, |
| }; |
| |
| int usage(void) { |
| fprintf(stderr, "usage: mkfs [ <option>* ] devicepath filesystem\n"); |
| fprintf(stderr, " -h|--help Print this message\n"); |
| fprintf(stderr, " -v|--verbose Verbose mode\n"); |
| fprintf(stderr, |
| " -s|--fvm_data_slices SLICES If block device is on top of a FVM,\n" |
| " the filesystem will have at least SLICES slices\n" |
| " allocated for data.\n"); |
| fprintf(stderr, " values for 'filesystem' include:\n"); |
| for (size_t i = 0; i < countof(FILESYSTEMS); i++) { |
| fprintf(stderr, " '%s'\n", FILESYSTEMS[i].name); |
| } |
| return -1; |
| } |
| |
| int parse_args(int argc, char** argv, mkfs_options_t* options, disk_format_t* df, |
| char** devicepath) { |
| static const struct option cmds[] = { |
| {"help", no_argument, NULL, 'h'}, |
| {"verbose", no_argument, NULL, 'v'}, |
| {"fvm_data_slices", required_argument, NULL, 's'}, |
| {0, 0, 0, 0}, |
| }; |
| |
| int opt_index = -1; |
| int c = -1; |
| |
| while ((c = getopt_long(argc, argv, "hvs:", cmds, &opt_index)) >= 0) { |
| switch (c) { |
| case 'v': |
| options->verbose = true; |
| break; |
| case 's': |
| options->fvm_data_slices = safemath::checked_cast<uint32_t>(strtoul(optarg, NULL, 0)); |
| if (options->fvm_data_slices == 0) { |
| fprintf(stderr, "Invalid Args: %s\n", strerror(errno)); |
| return usage(); |
| } |
| break; |
| case 'h': |
| return usage(); |
| default: |
| break; |
| }; |
| }; |
| |
| if (argc - optind < 1) { |
| fprintf(stderr, "Invalid Args: Missing devicepath.\n"); |
| return usage(); |
| } |
| |
| if (argc - optind < 2) { |
| fprintf(stderr, "Invalid Args: Missing filesystem.\n"); |
| return usage(); |
| } |
| |
| for (size_t i = 0; i < countof(FILESYSTEMS); i++) { |
| if (!strcmp(FILESYSTEMS[i].name, argv[argc - 1])) { |
| *df = FILESYSTEMS[i].df; |
| break; |
| } |
| } |
| |
| if (*df == DISK_FORMAT_UNKNOWN) { |
| fprintf(stderr, "fs_mkfs: Cannot format a device with filesystem '%s'\n", argv[2]); |
| return usage(); |
| } |
| |
| size_t device_arg = argc - 2; |
| *devicepath = argv[device_arg]; |
| |
| return 0; |
| } |
| |
| } // namespace |
| int main(int argc, char** argv) { |
| mkfs_options_t options = default_mkfs_options; |
| char* devicepath; |
| disk_format_t df; |
| int r; |
| if ((r = parse_args(argc, argv, &options, &df, &devicepath))) { |
| return r; |
| } |
| if (options.verbose) { |
| printf("fs_mkfs: Formatting device [%s]\n", devicepath); |
| } |
| if ((r = mkfs(devicepath, df, launch_stdio_sync, &options)) < 0) { |
| fprintf(stderr, "fs_mkfs: Failed to format device: %d\n", r); |
| } |
| return r; |
| } |