[Libguestfs] [PATCH] New API: ntfsresize_info

Maxim Perevedentsev mperevedentsev at virtuozzo.com
Fri Oct 16 12:55:44 UTC 2015


Get minimum size of NTFS filesystem in bytes. This is used primarily for shrinking images.

In case of a full images ntfsresize returns error code and does not print minimum size.
So we calculate it manually by rounding 'volume size' up to 'cluster size'.

---
 daemon/ntfs.c        | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 generator/actions.ml | 17 +++++++++++++
 src/MAX_PROC_NR      |  2 +-
 3 files changed, 86 insertions(+), 1 deletion(-)

diff --git a/daemon/ntfs.c b/daemon/ntfs.c
index 1ead159..f0a8c3b 100644
--- a/daemon/ntfs.c
+++ b/daemon/ntfs.c
@@ -153,6 +153,74 @@ do_ntfsresize_size (const char *device, int64_t size)
   return do_ntfsresize (device, size, 0);
 }

+int64_t
+do_ntfsresize_info (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, volume_size = 0;
+  const char *size_pattern = "You might resize at ",
+             *full_pattern = "Volume is full",
+             *cluster_size_pattern = "Cluster size",
+             *volume_size_pattern = "Current volume size:";
+  int is_full = 0;
+  int32_t cluster_size = 0;
+
+  /* FS may be marked for check, so force ntfsresize */
+  r = command (&out, &err, str_ntfsresize, "--info", "-ff", device, NULL);
+
+  lines = split_lines (out);
+  if (lines == NULL)
+    return -1;
+
+  if (verbose) {
+    for (i = 0; lines[i] != NULL; ++i)
+      fprintf (stderr, "ntfsresize_info: lines[%zu] = \"%s\"\n", i, lines[i]);
+  }
+
+  if (r == -1) {
+    /* If volume is full, ntfsresize returns error. */
+    for (i = 0; lines[i] != NULL; ++i) {
+      if (strstr (lines[i], full_pattern))
+        is_full = 1;
+      else if ((p = strstr (lines[i], cluster_size_pattern))) {
+        if (sscanf (p + strlen(cluster_size_pattern),
+                    "%*[ ]:%" SCNd32, &cluster_size) != 1)
+          return -1;
+      }
+      else if ((p = strstr (lines[i], volume_size_pattern))) {
+        if (sscanf (p + strlen(volume_size_pattern),
+                    "%" SCNd64, &volume_size) != 1)
+          return -1;
+      }
+    }
+    if (is_full) {
+      /* Ceil to cluster size */
+      if (cluster_size == 0) {
+        reply_with_error("%s", "Bad cluster size");
+        return -1;
+      }
+      return (volume_size + cluster_size - 1) / cluster_size * cluster_size;
+    }
+
+    reply_with_error ("%s", err);
+    return -1;
+  }
+
+  for (i = 0; lines[i] != NULL; ++i) {
+    if ((p = strstr (lines[i], size_pattern))) {
+      if (sscanf (p + strlen(size_pattern), "%" SCNd64, &ret) != 1)
+        return -1;
+      return ret;
+    }
+  }
+
+  return -1;
+}
+
 /* Takes optional arguments, consult optargs_bitmask. */
 int
 do_ntfsfix (const char *device, int clearbadsectors)
diff --git a/generator/actions.ml b/generator/actions.ml
index 274ef3f..ede6278 100644
--- a/generator/actions.ml
+++ b/generator/actions.ml
@@ -12765,6 +12765,23 @@ Get the estimated minimum filesystem size of an ext2/3/4 filesystem in blocks.

 See also L<resize2fs(8)>." };

+  { defaults with
+    name = "ntfsresize_info"; added = (1, 31, 17);
+    style = RInt64 "sizeinbytes", [Device "device"], [];
+    proc_nr = Some 458;
+    tests = [
+      InitPartition, Always, TestRun(
+        [["mkfs"; "ntfs"; "/dev/sda1"; ""; "NOARG"; ""; ""; "NOARG"];
+         ["ntfsresize_info"; "/dev/sda1"]]), [];
+    ];
+    shortdesc = "get minimum NTFS filesystem size";
+    longdesc = "\
+Get the minimum size of NTFS filesystem in bytes.
+
+This number is expected to be safely passed as C<guestfs_ntfsresize> command parameter.
+
+See also L<ntfsresize(8)>." };
+
 ]

 (* Non-API meta-commands available only in guestfish.
diff --git a/src/MAX_PROC_NR b/src/MAX_PROC_NR
index de2a00c..c92ddb6 100644
--- a/src/MAX_PROC_NR
+++ b/src/MAX_PROC_NR
@@ -1 +1 @@
-457
+458
--
1.8.3.1




More information about the Libguestfs mailing list