summaryrefslogtreecommitdiffstats
path: root/disk-utils/resizepart.c
diff options
context:
space:
mode:
Diffstat (limited to 'disk-utils/resizepart.c')
-rw-r--r--disk-utils/resizepart.c119
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;
+}