Index: usr.bin/mkimg/mkimg.1 =================================================================== --- usr.bin/mkimg/mkimg.1 +++ usr.bin/mkimg/mkimg.1 @@ -24,7 +24,7 @@ .\" .\" $FreeBSD$ .\" -.Dd August 7, 2015 +.Dd April 18, 2017 .Dt MKIMG 1 .Os .Sh NAME @@ -37,7 +37,9 @@ .Op Fl S Ar secsz .Op Fl T Ar tracksz .Op Fl b Ar bootcode -.Op Fl c Ar capacity +.Op Fl c Ar minimum capacity +.Op Fl m Ar maximum capacity +.Op Fl C Ar fixed capacity .Op Fl f Ar format .Op Fl o Ar outfile .Op Fl a Ar active @@ -125,6 +127,20 @@ given. .Pp The +.Fl m +option can be used to specify a maximal capacity for the disk image. +If the size of the given partitions exceed it, image creaton will fail. +.Pp +The +.Fl C +option can be used to specify a fixed capacity for the disk image. +This is equivalent of specifying +.Fl c +and +.Fl m +with the same value. +.Pp +The .Fl v option increases the level of output that the .Nm @@ -334,6 +350,16 @@ utility supports assigning labels to the partitions specified. In the following example the file system partition is labeled as 'backup': .Dl % mkimg -s gpt -p freebsd-ufs/backup:=file-system.ufs -o gpt.img +.Pp +If a disk size is given with the +.Fl m +or +.Fl C +argument, the +.Nm +utility supports percentage for the size. The actual size is calculated from +the maximum disk capacity +.Dl % mkimg -C 2G -s gpt -p freebsd-swap::10% -p freebsd-ufs::45% -p freebsd-ufs::45% -o gpt.img .Sh SEE ALSO .Xr dd 1 , .Xr gpart 8 , Index: usr.bin/mkimg/mkimg.c =================================================================== --- usr.bin/mkimg/mkimg.c +++ usr.bin/mkimg/mkimg.c @@ -27,6 +27,7 @@ #include __FBSDID("$FreeBSD$"); +#include #include #include #include @@ -57,7 +58,8 @@ { NULL, 0, NULL, 0 } }; -static uint64_t capacity; +static uint64_t min_capacity = 0; +static uint64_t max_capacity = 0; struct partlisthead partlist = TAILQ_HEAD_INITIALIZER(partlist); u_int nparts = 0; @@ -148,7 +150,8 @@ fputc('\n', stderr); fprintf(stderr, "\t-a \t- mark num'th partion as active\n"); fprintf(stderr, "\t-b \t- file containing boot code\n"); - fprintf(stderr, "\t-c \t- capacity (in bytes) of the disk\n"); + fprintf(stderr, "\t-c \t- minimum capacity (in bytes) of the disk\n"); + fprintf(stderr, "\t-C \t- maximum capacity (in bytes) of the disk\n"); fprintf(stderr, "\t-f \n"); fprintf(stderr, "\t-o \t- file to write image into\n"); fprintf(stderr, "\t-p \n"); @@ -176,6 +179,8 @@ fprintf(stderr, "\t\t\t- scheme neutral partition type\n"); fprintf(stderr, "\t\t\t- optional scheme-dependent partition " "label\n"); + fprintf(stderr, "\t\t\t- size of the partition (SI unit suffixes\n" + "\t\t\t are allowed) or in percentage of the whole disk.\n"); exit(EX_USAGE); } @@ -378,12 +383,17 @@ static int capacity_resize(lba_t end) { - lba_t capsz; + lba_t min_capsz, max_capsz; - capsz = (capacity + secsz - 1) / secsz; - if (end >= capsz) + min_capsz = (min_capacity + secsz - 1) / secsz; + max_capsz = (max_capacity + secsz - 1) / secsz; + + if (max_capsz != 0 && end >= max_capsz) + return (ENOSPC); + if (end >= min_capsz) return (0); - return (image_set_size(capsz)); + + return (image_set_size(MAX(min_capsz, max_capsz))); } static void @@ -391,8 +401,8 @@ { FILE *fp; struct part *part; - lba_t block; - off_t bytesize; + lba_t block, metablock; + off_t bytesize, percent; int error, fd; /* First check partition information */ @@ -411,8 +421,22 @@ part->block = block; switch (part->kind) { case PART_KIND_SIZE: - if (expand_number(part->contents, &bytesize) == -1) - error = errno; + if (strchr(part->contents, '%') != NULL && + max_capacity != 0) { + part->contents[strchr(part->contents, '%') - part->contents] = '\0'; + if (expand_number(part->contents, &percent) == -1) { + error = errno; + break; + } + metablock = scheme_metadata(SCHEME_META_IMG_START, 0); + metablock += scheme_metadata(SCHEME_META_IMG_END, 0) + 1; + bytesize = (max_capacity * percent / 100) - (metablock * secsz); + } else { + if (expand_number(part->contents, &bytesize) == -1) + error = errno; + } + if (bytesize == 0) + error = ENOSPC; break; case PART_KIND_FILE: fd = open(part->contents, O_RDONLY, 0); @@ -470,7 +494,7 @@ bcfd = -1; outfd = 1; /* Write to stdout by default */ - while ((c = getopt_long(argc, argv, "a:b:c:f:o:p:s:vyH:P:S:T:", + while ((c = getopt_long(argc, argv, "a:b:c:m:C:f:o:p:s:vyH:P:S:T:", longopts, NULL)) != -1) { switch (c) { case 'a': /* ACTIVE PARTITION, if supported */ @@ -485,10 +509,28 @@ if (bcfd == -1) err(EX_UNAVAILABLE, "%s", optarg); break; - case 'c': /* CAPACITY */ - error = parse_uint64(&capacity, 1, INT64_MAX, optarg); + case 'c': /* MIN CAPACITY */ + error = parse_uint64(&min_capacity, 1, + INT64_MAX, optarg); + if (error) + errc(EX_DATAERR, error, + "min capacity in bytes"); + break; + case 'm': /* MAX CAPACITY */ + error = parse_uint64(&max_capacity, 1, + INT64_MAX, optarg); + if (error) + errc(EX_DATAERR, error, + "max capacity in bytes"); + break; + case 'C': /* FIXED CAPACITY */ + error = parse_uint64(&min_capacity, 1, + INT64_MAX, optarg); + error = parse_uint64(&max_capacity, 1, + INT64_MAX, optarg); if (error) - errc(EX_DATAERR, error, "capacity in bytes"); + errc(EX_DATAERR, error, + "max capacity in bytes"); break; case 'f': /* OUTPUT FORMAT */ if (format_selected() != NULL) @@ -568,8 +610,10 @@ usage("trailing arguments"); if (scheme_selected() == NULL && nparts > 0) usage("no scheme"); - if (nparts == 0 && capacity == 0) + if (nparts == 0 && min_capacity == 0) usage("no partitions"); + if (min_capacity > max_capacity) + usage("wrong capacity size"); if (secsz > blksz) { if (blksz != 0)