diff options
Diffstat (limited to 'disk-utils/resizepart.c')
-rw-r--r-- | disk-utils/resizepart.c | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/disk-utils/resizepart.c b/disk-utils/resizepart.c new file mode 100644 index 0000000..527517f --- /dev/null +++ b/disk-utils/resizepart.c @@ -0,0 +1,119 @@ +#include <getopt.h> +#include <stdio.h> +#include <stdlib.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> + +#include "c.h" +#include "nls.h" +#include "partx.h" +#include "sysfs.h" +#include "strutils.h" +#include "closestream.h" + +static void __attribute__((__noreturn__)) usage(void) +{ + FILE *out = stdout; + fputs(USAGE_HEADER, out); + fprintf(out, _(" %s <disk device> <partition number> <length>\n"), + program_invocation_short_name); + + fputs(USAGE_SEPARATOR, out); + fputs(_("Tell the kernel about the new size of a partition.\n"), out); + + fputs(USAGE_OPTIONS, out); + printf(USAGE_HELP_OPTIONS(16)); + printf(USAGE_MAN_TAIL("resizepart(8)")); + exit(EXIT_SUCCESS); +} + +static int get_partition_start(int fd, int partno, uint64_t *start) +{ + struct stat st; + struct path_cxt *disk = NULL, *part = NULL; + dev_t devno = 0; + int rc = -1; + + /* + * wholedisk + */ + if (fstat(fd, &st) || !S_ISBLK(st.st_mode)) + goto done; + devno = st.st_rdev; + disk = ul_new_sysfs_path(devno, NULL, NULL); + if (!disk) + goto done; + /* + * partition + */ + devno = sysfs_blkdev_partno_to_devno(disk, partno); + if (!devno) + goto done; + + part = ul_new_sysfs_path(devno, disk, NULL); + if (!part) + goto done; + if (ul_path_read_u64(part, start, "start")) + goto done; + + rc = 0; +done: + ul_unref_path(part); + ul_unref_path(disk); + return rc; +} + +int main(int argc, char **argv) +{ + int c, fd, partno; + const char *wholedisk; + uint64_t start; + + static const struct option longopts[] = { + {"help", no_argument, NULL, 'h'}, + {"version", no_argument, NULL, 'V'}, + {NULL, 0, NULL, '0'}, + }; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + atexit(close_stdout); + + while ((c = getopt_long(argc, argv, "Vh", longopts, NULL)) != -1) + switch (c) { + case 'V': + printf(UTIL_LINUX_VERSION); + return EXIT_SUCCESS; + case 'h': + usage(); + default: + errtryhelp(EXIT_FAILURE); + } + + if (argc != 4) { + warnx(_("not enough arguments")); + errtryhelp(EXIT_FAILURE); + } + + wholedisk = argv[1]; + partno = strtou32_or_err(argv[2], _("invalid partition number argument")); + + if ((fd = open(wholedisk, O_RDONLY)) < 0) + err(EXIT_FAILURE, _("cannot open %s"), wholedisk); + + if (get_partition_start(fd, partno, &start)) + err(EXIT_FAILURE, _("%s: failed to get start of the partition number %s"), + wholedisk, argv[2]); + + if (partx_resize_partition(fd, partno, start, + strtou64_or_err(argv[3], _("invalid length argument")))) + err(EXIT_FAILURE, _("failed to resize partition")); + + if (close_fd(fd) != 0) + err(EXIT_FAILURE, _("write failed")); + + return 0; +} |