Index: usr.bin/mkimg/mkimg.1 =================================================================== --- usr.bin/mkimg/mkimg.1 +++ usr.bin/mkimg/mkimg.1 @@ -348,6 +348,18 @@ 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 +The +.Nm +utility also support flexible size partition if a maximum disk capacity +have been provided. Flexible sizes are given in percentage and the resulting +size is calculated from the whole disk capacity. +.Dl % mkimg --capacity 1G -s gpt -p freebsd-swap::10% -p freebsd-ufs/ping::45% \ +-p freebsd-ufs/pong::45% -o pingpong.img +You can also use ~ as size for specifying that one partition should take all +the available size. +.Dl % mkimg --capacity 1G -s gpt -p freebsd-swap::10% -p freebsd-ufs::~ -o fill.img +Note that you cannot use fill partition with cascaded ones. .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 @@ -171,7 +171,8 @@ fputc('\n', stderr); fprintf(stderr, " partition specification:\n"); fprintf(stderr, "\t[/]::\t- empty partition of given " - "size\n"); + "size (see the\n" + "\t\t\t\t manpage for flexible size example)\n"); fprintf(stderr, "\t[/]:=\t- partition content and size " "are determined\n\t\t\t\t by the named file\n"); fprintf(stderr, "\t[/]:-\t- partition content and size " @@ -400,16 +401,75 @@ mkimg(void) { FILE *fp; - struct part *part; - lba_t block; - off_t bytesize; - int error, fd; + struct part *part, *fillpart = NULL; + struct stat sb; + lba_t block, metablock, diskblock, partblock = 0; + off_t bytesize, percent; + char *percntptr; + int num_parts = 0, error, fd, have_pipe_part = 0; + + TAILQ_FOREACH(part, &partlist, link) { + num_parts++; + } + + /* + * Calculate the number of usable blocks on the disk, without + * the scheme metadata. + * Since the block after a partition can be rounded up, we add + * one block per partition that exists. + * It may not be the best calculation but seems to work with any + * sector size. + */ + if (max_capacity != 0) { + metablock = scheme_metadata(SCHEME_META_IMG_START, 0) + + scheme_metadata(SCHEME_META_IMG_END, 0) + num_parts + 1; + diskblock = max_capacity - (metablock * secsz); + } /* First check partition information */ TAILQ_FOREACH(part, &partlist, link) { error = scheme_check_part(part); if (error) errc(EX_DATAERR, error, "partition %d", part->index+1); + switch (part->kind) { + case PART_KIND_SIZE: + percntptr = strchr(part->contents, '%'); + if (percntptr != NULL && max_capacity != 0) { + *percntptr = '\0'; + if (expand_number(part->contents, &percent) == -1) { + error = errno; + break; + } + part->size = diskblock * percent / 100; + } else if (strcmp(part->contents, "~") == 0) { + if (fillpart) + usage("cannot have two fill partition"); + fillpart = part; + } else { + if (expand_number(part->contents, &part->size) == -1) + error = errno; + } + break; + case PART_KIND_FILE: + if (stat(part->contents, &sb) == -1) + errc(EX_DATAERR, errno, "partition %d", part->index+1); + part->size = sb.st_size; + break; + case PART_KIND_PIPE: + have_pipe_part = 1; + break; + } + partblock += part->size; + } + + if (fillpart) { + if (max_capacity == 0) + usage("cannot fill partition without a capacity"); + if (have_pipe_part == 1) + usage("cannot fill partition with cascade partition"); + fillpart->size = diskblock - partblock; + if (fillpart->size <= 0) + usage("no more room for fill partition"); } block = scheme_metadata(SCHEME_META_IMG_START, 0); @@ -421,8 +481,7 @@ part->block = block; switch (part->kind) { case PART_KIND_SIZE: - if (expand_number(part->contents, &bytesize) == -1) - error = errno; + bytesize = part->size; break; case PART_KIND_FILE: fd = open(part->contents, O_RDONLY, 0);