mirror of
https://github.com/libguestfs/libguestfs.git
synced 2026-03-21 22:53:37 +00:00
New API: vfs_minimum_size
This call provides the way to get minimum size of filesystem. This is needed for shrinking. The return units are bytes.
This commit is contained in:
committed by
Richard W.M. Jones
parent
e9b32e1bad
commit
b8d4ca686b
@@ -116,6 +116,7 @@ guestfsd_SOURCES = \
|
||||
findfs.c \
|
||||
fill.c \
|
||||
find.c \
|
||||
fs-min-size.c \
|
||||
fsck.c \
|
||||
fstrim.c \
|
||||
glob.c \
|
||||
|
||||
@@ -283,6 +283,7 @@ extern int btrfs_set_uuid_random (const char *device);
|
||||
/*-- in ntfs.c --*/
|
||||
extern char *ntfs_get_label (const char *device);
|
||||
extern int ntfs_set_label (const char *device, const char *label);
|
||||
extern int64_t ntfs_minimum_size (const char *device);
|
||||
|
||||
/*-- in swap.c --*/
|
||||
extern int swap_set_uuid (const char *device, const char *uuid);
|
||||
|
||||
46
daemon/fs-min-size.c
Normal file
46
daemon/fs-min-size.c
Normal file
@@ -0,0 +1,46 @@
|
||||
/* libguestfs - the guestfsd daemon
|
||||
* Copyright (C) 2015 Maxim Perevedentsev mperevedentsev@virtuozzo.com
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "daemon.h"
|
||||
#include "actions.h"
|
||||
|
||||
int64_t
|
||||
do_vfs_minimum_size (const mountable_t *mountable)
|
||||
{
|
||||
int64_t r;
|
||||
|
||||
/* How we set the label depends on the filesystem type. */
|
||||
CLEANUP_FREE char *vfs_type = do_vfs_type (mountable);
|
||||
if (vfs_type == NULL)
|
||||
return -1;
|
||||
|
||||
else if (STREQ (vfs_type, "ntfs"))
|
||||
r = ntfs_minimum_size (mountable->device);
|
||||
|
||||
else
|
||||
NOT_SUPPORTED (-1, "don't know how to get minimum size of '%s' filesystems",
|
||||
vfs_type);
|
||||
|
||||
return r;
|
||||
}
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "daemon.h"
|
||||
#include "actions.h"
|
||||
#include "optgroups.h"
|
||||
#include "xstrtol.h"
|
||||
|
||||
#define MAX_ARGS 64
|
||||
|
||||
@@ -153,6 +154,92 @@ do_ntfsresize_size (const char *device, int64_t size)
|
||||
return do_ntfsresize (device, size, 0);
|
||||
}
|
||||
|
||||
int64_t
|
||||
ntfs_minimum_size (const char *device)
|
||||
{
|
||||
CLEANUP_FREE char *err = NULL, *out = NULL;
|
||||
CLEANUP_FREE_STRING_LIST char **lines = NULL;
|
||||
int r;
|
||||
size_t i;
|
||||
int64_t 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, "ntfs_minimum_size: lines[%zu] = \"%s\"\n", i, lines[i]);
|
||||
}
|
||||
|
||||
#if __WORDSIZE == 64
|
||||
#define XSTRTOD64 xstrtol
|
||||
#else
|
||||
#define XSTRTOD64 xstrtoll
|
||||
#endif
|
||||
|
||||
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 (STRPREFIX (lines[i], cluster_size_pattern)) {
|
||||
if (sscanf (lines[i] + strlen (cluster_size_pattern),
|
||||
"%*[ ]:%" SCNd32, &cluster_size) != 1) {
|
||||
reply_with_error ("cannot parse cluster size");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if (STRPREFIX (lines[i], volume_size_pattern)) {
|
||||
if (XSTRTOD64 (lines[i] + strlen (volume_size_pattern),
|
||||
NULL, 20, &volume_size, NULL) != LONGINT_OK) {
|
||||
reply_with_error ("cannot parse volume size");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (is_full) {
|
||||
if (cluster_size == 0) {
|
||||
reply_with_error ("bad cluster size");
|
||||
return -1;
|
||||
}
|
||||
/* In case of a full filesystem, we estimate minimum size
|
||||
* as volume size rounded up to cluster size.
|
||||
*/
|
||||
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 (STRPREFIX (lines[i], size_pattern)) {
|
||||
int64_t ret;
|
||||
if (XSTRTOD64 (lines[i] + strlen (size_pattern),
|
||||
NULL, 20, &ret, NULL) != LONGINT_OK) {
|
||||
reply_with_error ("cannot parse minimum size");
|
||||
return -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
#undef XSTRTOD64
|
||||
|
||||
reply_with_error ("minimum size not found. Check output format:\n%s", out);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Takes optional arguments, consult optargs_bitmask. */
|
||||
int
|
||||
do_ntfsfix (const char *device, int clearbadsectors)
|
||||
|
||||
@@ -12765,6 +12765,25 @@ 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;
|
||||
tests = [
|
||||
InitPartition, IfAvailable "ntfsprogs", TestRun(
|
||||
[["mkfs"; "ntfs"; "/dev/sda1"; ""; "NOARG"; ""; ""; "NOARG"];
|
||||
["vfs_minimum_size"; "/dev/sda1"]]), [];
|
||||
];
|
||||
shortdesc = "get minimum filesystem size";
|
||||
longdesc = "\
|
||||
Get the minimum size of filesystem in bytes.
|
||||
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)>." };
|
||||
|
||||
]
|
||||
|
||||
(* Non-API meta-commands available only in guestfish.
|
||||
|
||||
@@ -49,6 +49,7 @@ daemon/file.c
|
||||
daemon/fill.c
|
||||
daemon/find.c
|
||||
daemon/findfs.c
|
||||
daemon/fs-min-size.c
|
||||
daemon/fsck.c
|
||||
daemon/fstrim.c
|
||||
daemon/glob.c
|
||||
|
||||
@@ -1 +1 @@
|
||||
457
|
||||
458
|
||||
|
||||
Reference in New Issue
Block a user