---
daemon/daemon.h | 1 +
daemon/ext2.c | 62 +++++++++++++++++++++++++++++++++++++++++++++-------
daemon/fs-min-size.c | 3 +++
generator/actions.ml | 20 ++++-------------
src/MAX_PROC_NR | 2 +-
5 files changed, 63 insertions(+), 25 deletions(-)
diff --git a/daemon/daemon.h b/daemon/daemon.h
index 3b0266d..8bcc9bd 100644
--- a/daemon/daemon.h
+++ b/daemon/daemon.h
@@ -224,6 +224,7 @@ extern int sync_disks (void);
#define EXT2_LABEL_MAX 16
extern int fstype_is_extfs (const char *fstype);
extern int ext_set_uuid_random (const char *device);
+extern int64_t ext_minimum_size (const char *device);
/*-- in blkid.c --*/
extern char *get_blkid_tag (const char *device, const char *tag);
diff --git a/daemon/ext2.c b/daemon/ext2.c
index 0cd6a66..01f934b 100644
--- a/daemon/ext2.c
+++ b/daemon/ext2.c
@@ -29,6 +29,7 @@
#include "daemon.h"
#include "c-ctype.h"
#include "actions.h"
+#include "xstrtol.h"
#define MAX_ARGS 128
@@ -279,15 +280,41 @@ do_resize2fs_M (const char *device)
return 0;
}
+static long
+get_block_size (const char *device)
+{
+ CLEANUP_FREE_STRING_LIST char **params = NULL;
+ const char *block_pattern = "Block size";
+ size_t i;
+ long block_size;
+
+ params = do_tune2fs_l (device);
+ if (params == NULL)
+ return -1;
+
+ for (i = 0; params[i] != NULL; i += 2) {
+ if (STREQ (params[i], block_pattern)) {
+ if (xstrtol (params[i + 1], NULL, 10, &block_size, NULL) != LONGINT_OK) {
+ reply_with_error ("Cannot parse block size");
+ return -1;
+ }
+ return block_size;
+ }
+ }
+
+ reply_with_error ("Missing 'Block size' in tune2fs_l output");
+ return -1;
+}
+
int64_t
-do_resize2fs_P (const char *device)
+ext_minimum_size (const char *device)
{
CLEANUP_FREE char *err = NULL, *out = NULL;
CLEANUP_FREE_STRING_LIST char **lines = NULL;
int r;
size_t i;
- char *p;
int64_t ret;
+ long block_size;
const char *pattern = "Estimated minimum size of the filesystem: ";
r = command (&out, &err, str_resize2fs, "-P", device, NULL);
@@ -300,17 +327,36 @@ do_resize2fs_P (const char *device)
if (lines == NULL)
return -1;
- for (i = 0; lines[i] != NULL; ++i) {
- if (verbose)
- fprintf (stderr, "resize2fs_P: lines[%zu] = \"%s\"\n", i,
lines[i]);
+#if __WORDSIZE == 64
+#define XSTRTOD64 xstrtol
+#else
+#define XSTRTOD64 xstrtoll
+#endif
- if ((p = strstr (lines[i], pattern))) {
- if (sscanf (p + strlen(pattern), "%" SCNd64, &ret) != 1)
+ for (i = 0; lines[i] != NULL; ++i) {
+ if (STRPREFIX (lines[i], pattern)) {
+ if (XSTRTOD64 (lines[i] + strlen (pattern),
+ NULL, 20, &ret, NULL) != LONGINT_OK) {
+ reply_with_error ("Cannot parse minimum size");
+ return -1;
+ }
+ if ((block_size = get_block_size (device)) == -1)
+ return -1;
+ if (verbose) {
+ fprintf (stderr, "Minimum size in blocks: %" SCNd64 \
+ "\nBlock count: %ld\n", ret, block_size);
+ }
+ if (INT64_MAX / block_size < ret) {
+ reply_with_error ("Filesystem size too big: overflow");
return -1;
- return ret;
+ }
+ return ret * block_size;
}
}
+#undef XSTRTOD64
+
+ reply_with_error ("Minimum size not found. Check output format:\n%s", out);
return -1;
}
diff --git a/daemon/fs-min-size.c b/daemon/fs-min-size.c
index 652eb0e..4f93f8c 100644
--- a/daemon/fs-min-size.c
+++ b/daemon/fs-min-size.c
@@ -35,6 +35,9 @@ do_vfs_minimum_size (const mountable_t *mountable)
if (vfs_type == NULL)
return -1;
+ else if (fstype_is_extfs (vfs_type))
+ r = ext_minimum_size (mountable->device);
+
else if (STREQ (vfs_type, "ntfs"))
r = ntfs_minimum_size (mountable->device);
diff --git a/generator/actions.ml b/generator/actions.ml
index e0459c0..10acb7c 100644
--- a/generator/actions.ml
+++ b/generator/actions.ml
@@ -12752,24 +12752,12 @@ Only some filesystem types support setting UUIDs.
To read the UUID on a filesystem, call C<guestfs_vfs_uuid>." };
{ defaults with
- name = "resize2fs_P"; added = (1, 31, 17);
- style = RInt64 "sizeinblocks", [Device "device"], [];
- proc_nr = Some 457;
- tests = [
- InitBasicFS, Always, TestRun (
- [["resize2fs_P"; "/dev/sda1"]]), [];
- ];
- shortdesc = "get minimum filesystem size in blocks";
- longdesc = "\
-Get the estimated minimum filesystem size of an ext2/3/4 filesystem in blocks.
-
-See also L<resize2fs(8)>." };
-
- { defaults with
name = "vfs_minimum_size"; added = (1, 31, 18);
style = RInt64 "sizeinbytes", [Mountable "mountable"], [];
- proc_nr = Some 458;
+ proc_nr = Some 457;
tests = [
+ InitBasicFS, Always, TestRun (
+ [["vfs_minimum_size"; "/dev/sda1"]]), [];
InitPartition, IfAvailable "ntfsprogs", TestRun(
[["mkfs"; "ntfs"; "/dev/sda1"; "";
"NOARG"; ""; ""; "NOARG"];
["vfs_minimum_size"; "/dev/sda1"]]), [];
@@ -12782,7 +12770,7 @@ This is the minimum possible size for filesystem shrinking.
If getting minimum size of specified filesystem is not supported,
this will fail and set errno as ENOTSUP.
-See also L<ntfsresize(8)>." };
+See also L<ntfsresize(8)>, L<resize2fs(8)>." };
]
diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR
index c92ddb6..de2a00c 100644
--- a/src/MAX_PROC_NR
+++ b/src/MAX_PROC_NR
@@ -1 +1 @@
-458
+457
--
1.8.3.1