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
On Friday 16 October 2015 15:55:44 Maxim Perevedentsev wrote:> 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'.NACK to a separate API per-filesystem. As I said in a previous email, please turn the newly added resize2fs_P into a generic API for getting the minimum size of a filesystem, either bytes or blocks. See for example set_label and set_uuid. Thanks, -- Pino Toscano
Richard W.M. Jones
2015-Oct-16 13:06 UTC
Re: [Libguestfs] [PATCH] New API: ntfsresize_info
On Fri, Oct 16, 2015 at 03:00:15PM +0200, Pino Toscano wrote:> On Friday 16 October 2015 15:55:44 Maxim Perevedentsev wrote: > > 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'. > > NACK to a separate API per-filesystem. > > As I said in a previous email, please turn the newly added resize2fs_P > into a generic API for getting the minimum size of a filesystem, either > bytes or blocks. See for example set_label and set_uuid.For example: https://github.com/libguestfs/libguestfs/blob/master/daemon/labels.c#L61-L93 Rich. -- Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones Read my programming and virtualization blog: http://rwmj.wordpress.com Fedora Windows cross-compiler. Compile Windows programs, test, and build Windows installers. Over 100 libraries supported. http://fedoraproject.org/wiki/MinGW