(root)/
util-linux-2.39/
libfdisk/
samples/
mkpart.c
       1  /*
       2   * Copyright (C) 2017 Karel Zak <kzak@redhat.com>
       3   *
       4   * This file may be redistributed under the terms of the
       5   * GNU Lesser General Public License.
       6   *
       7   *
       8   * Libfdisk sample to create partitions by specify size, for example:
       9   *
      10   *	mkpart --label dos --device /dev/sdc 2M 2M 2M 10M 1M -
      11   *
      12    * creates 6 partitions:
      13    *	- 3 primary  (3x 2M)
      14    *	- 1 extended (1x 10M)
      15    *	- 2 logical  (1x 1M, 1x remaining-space-in-extended-partition)
      16    *
      17    * Notes:
      18    *     The sample specifies size and partno for MBR, and size only for another
      19    *     labels (e.g. GPT).
      20    *
      21    *     The Ask-API does not use anything else than warning/info. The
      22    *     partitionning has to be done non-interactive.
      23    */
      24  #include <stdlib.h>
      25  #include <unistd.h>
      26  #include <string.h>
      27  #include <errno.h>
      28  #include <sys/types.h>
      29  #include <sys/stat.h>
      30  #include <dirent.h>
      31  #include <getopt.h>
      32  
      33  #include "c.h"
      34  #include "nls.h"
      35  #include "strutils.h"
      36  #include "xalloc.h"
      37  
      38  #include "libfdisk.h"
      39  
      40  static int ask_callback(struct fdisk_context *cxt __attribute__((__unused__)),
      41  			struct fdisk_ask *ask,
      42  			void *data)
      43  {
      44  	switch(fdisk_ask_get_type(ask)) {
      45  	case FDISK_ASKTYPE_INFO:
      46  		fputs(fdisk_ask_print_get_mesg(ask), stdout);
      47  		fputc('\n', stdout);
      48  		break;
      49  	case FDISK_ASKTYPE_WARNX:
      50  		fflush(stdout);
      51  		fputs(fdisk_ask_print_get_mesg(ask), stderr);
      52  		fputc('\n', stderr);
      53  		break;
      54  	case FDISK_ASKTYPE_WARN:
      55  		fflush(stdout);
      56  		fputs(fdisk_ask_print_get_mesg(ask), stderr);
      57  		errno = fdisk_ask_print_get_errno(ask);
      58  		fprintf(stderr, ": %m\n");
      59  		break;
      60  	default:
      61  		break;
      62  	}
      63  	return 0;
      64  }
      65  
      66  int main(int argc, char *argv[])
      67  {
      68  	struct fdisk_context *cxt;
      69  	struct fdisk_partition *pa;
      70  	const char *label = NULL, *device = NULL;
      71  	int n = 0, c, nopartno = 0;
      72  	unsigned int sectorsize;
      73  	uint64_t grain = 0;
      74  
      75  	static const struct option longopts[] = {
      76  		{ "label",  required_argument, NULL, 'x' },
      77  		{ "device", required_argument, NULL, 'd' },
      78  		{ "nopartno", no_argument, NULL, 'p' },
      79  		{ "grain", required_argument, NULL, 'g' },
      80  		{ "help",   no_argument, NULL, 'h' },
      81  		{ NULL, 0, NULL, 0 },
      82  	};
      83  
      84  	setlocale(LC_ALL, "");	/* just to have enable UTF8 chars */
      85  
      86  	fdisk_init_debug(0);
      87  
      88  	while((c = getopt_long(argc, argv, "g:x:d:h", longopts, NULL)) != -1) {
      89  		switch(c) {
      90  		case 'x':
      91  			label = optarg;
      92  			break;
      93  		case 'd':
      94  			device = optarg;
      95  			break;
      96  		case 'p':
      97  			nopartno = 1;
      98  			break;
      99  		case 'g':
     100  			grain = strtosize_or_err(optarg, "failed to parse grain");
     101  			break;
     102  		case 'h':
     103  			printf("%s [options] <size> ...", program_invocation_short_name);
     104  			fputs(USAGE_SEPARATOR, stdout);
     105  			fputs("Make disklabel and partitions.\n", stdout);
     106  			fputs(USAGE_OPTIONS, stdout);
     107  			fputs(" -x, --label <dos,gpt,...>    disk label type\n", stdout);
     108  			fputs(" -d, --device <path>          block device\n", stdout);
     109  			fputs(" -p, --nopartno               don't set partno (use default)\n", stdout);
     110  			fputs(" -h, --help                   this help\n", stdout);
     111  			fputs(USAGE_SEPARATOR, stdout);
     112  			return EXIT_SUCCESS;
     113  		}
     114  	}
     115  
     116  	if (!device)
     117  		errx(EXIT_FAILURE, "no device specified");
     118  	if (!label)
     119  		label = "dos";
     120  
     121  	cxt = fdisk_new_context();
     122  	if (!cxt)
     123  		err_oom();
     124  	fdisk_set_ask(cxt, ask_callback, NULL);
     125  
     126  	if (grain)
     127  		fdisk_save_user_grain(cxt, grain);
     128  
     129  	pa = fdisk_new_partition();
     130  	if (!pa)
     131  		err_oom();
     132  
     133  	if (fdisk_assign_device(cxt, device, 0))
     134  		err(EXIT_FAILURE, "failed to assign device");
     135  	if (fdisk_create_disklabel(cxt, label))
     136  		err(EXIT_FAILURE, "failed to create disk label");
     137  
     138  	sectorsize = fdisk_get_sector_size(cxt);
     139  
     140  	fdisk_disable_dialogs(cxt, 1);
     141  
     142  	while (optind < argc) {
     143  		int rc;
     144  		uint64_t size;
     145  		const char *str = argv[optind];
     146  
     147  		/* defaults */
     148  		fdisk_partition_start_follow_default(pa, 1);
     149  		fdisk_partition_end_follow_default(pa, 1);
     150  		fdisk_partition_partno_follow_default(pa, 1);
     151  
     152  		/* set size */
     153  		if (isdigit(*str)) {
     154  			size = strtosize_or_err(argv[optind], "failed to parse partition size");
     155  			fdisk_partition_set_size(pa, size / sectorsize);
     156  			fdisk_partition_end_follow_default(pa, 0);
     157  
     158  		} else if (*str == '-') {
     159  			fdisk_partition_end_follow_default(pa, 1);
     160  		}
     161  
     162  		if (fdisk_is_label(cxt, DOS)) {
     163  			/* For MBR we want to avoid primary/logical dialog.
     164  			 * This is possible by explicitly specified partition
     165  			 * number, <4 means primary, >=4 means logical.
     166  			 */
     167  			if (!nopartno) {
     168  				fdisk_partition_partno_follow_default(pa, 0);
     169  				fdisk_partition_set_partno(pa, n);
     170  			}
     171  
     172  			/* Make sure last primary partition is extended if user
     173  			 * wants more than 4 partitions.
     174  			 */
     175  			if (n == 3 && optind + 1 < argc) {
     176  				struct fdisk_parttype *type =
     177  					fdisk_label_parse_parttype(
     178  							fdisk_get_label(cxt, NULL), "05");
     179  				if (!type)
     180  					err_oom();
     181  				fdisk_partition_set_type(pa, type);
     182  				fdisk_unref_parttype(type);
     183  			}
     184  		}
     185  
     186  		rc = fdisk_add_partition(cxt, pa, NULL);
     187  		if (rc) {
     188  			errno = -rc;
     189  			errx(EXIT_FAILURE, "failed to add #%d partition", n + 1);
     190  		}
     191  
     192  		fdisk_reset_partition(pa);
     193  		optind++;
     194  		n++;
     195  	}
     196  
     197  	if (fdisk_write_disklabel(cxt))
     198  		err(EXIT_FAILURE, "failed to write disk label");
     199  
     200  	fdisk_deassign_device(cxt, 1);
     201  	fdisk_unref_context(cxt);
     202  	fdisk_unref_partition(pa);
     203  
     204  	return EXIT_SUCCESS;
     205  }