mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
libdevmapper: add dm_units_to_factor for size unit parsing
Actually moving the existing code from LVM to libdm for reuse.
This commit is contained in:
parent
75d399800a
commit
4360fdf89c
@ -1,5 +1,6 @@
|
|||||||
Version 1.02.88 -
|
Version 1.02.88 -
|
||||||
=================================
|
=================================
|
||||||
|
Add dm_units_to_factor for size unit parsing.
|
||||||
Increase bitset size for minors for thin dmeventd plugin.
|
Increase bitset size for minors for thin dmeventd plugin.
|
||||||
|
|
||||||
Version 1.02.85 - 10th April 2014
|
Version 1.02.85 - 10th April 2014
|
||||||
|
@ -282,8 +282,8 @@ static int _check_config(struct cmd_context *cmd)
|
|||||||
|
|
||||||
int process_profilable_config(struct cmd_context *cmd) {
|
int process_profilable_config(struct cmd_context *cmd) {
|
||||||
if (!(cmd->default_settings.unit_factor =
|
if (!(cmd->default_settings.unit_factor =
|
||||||
units_to_bytes(find_config_tree_str(cmd, global_units_CFG, NULL),
|
dm_units_to_factor(find_config_tree_str(cmd, global_units_CFG, NULL),
|
||||||
&cmd->default_settings.unit_type))) {
|
&cmd->default_settings.unit_type, 1, NULL))) {
|
||||||
log_error("Invalid units specification");
|
log_error("Invalid units specification");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -20,8 +20,6 @@
|
|||||||
#include "toolcontext.h"
|
#include "toolcontext.h"
|
||||||
#include "segtype.h"
|
#include "segtype.h"
|
||||||
#include "defaults.h"
|
#include "defaults.h"
|
||||||
#include <math.h> /* fabs() */
|
|
||||||
#include <float.h> /* DBL_EPSILON */
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
#define SIZE_BUF 128
|
#define SIZE_BUF 128
|
||||||
@ -44,103 +42,6 @@ static const struct {
|
|||||||
|
|
||||||
static const int _num_policies = DM_ARRAY_SIZE(_policies);
|
static const int _num_policies = DM_ARRAY_SIZE(_policies);
|
||||||
|
|
||||||
/* Test if the doubles are close enough to be considered equal */
|
|
||||||
static int _close_enough(double d1, double d2)
|
|
||||||
{
|
|
||||||
return fabs(d1 - d2) < DBL_EPSILON;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t units_to_bytes(const char *units, char *unit_type)
|
|
||||||
{
|
|
||||||
char *ptr = NULL;
|
|
||||||
uint64_t v;
|
|
||||||
double custom_value = 0;
|
|
||||||
uint64_t multiplier;
|
|
||||||
|
|
||||||
if (isdigit(*units)) {
|
|
||||||
custom_value = strtod(units, &ptr);
|
|
||||||
if (ptr == units)
|
|
||||||
return 0;
|
|
||||||
v = (uint64_t) strtoull(units, NULL, 10);
|
|
||||||
if (_close_enough((double) v, custom_value))
|
|
||||||
custom_value = 0; /* Use integer arithmetic */
|
|
||||||
units = ptr;
|
|
||||||
} else
|
|
||||||
v = 1;
|
|
||||||
|
|
||||||
/* Only one units char permitted. */
|
|
||||||
if (units[0] && units[1])
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (v == 1)
|
|
||||||
*unit_type = *units;
|
|
||||||
else
|
|
||||||
*unit_type = 'U';
|
|
||||||
|
|
||||||
switch (*units) {
|
|
||||||
case 'h':
|
|
||||||
case 'H':
|
|
||||||
multiplier = v = UINT64_C(1);
|
|
||||||
*unit_type = *units;
|
|
||||||
break;
|
|
||||||
case 'b':
|
|
||||||
case 'B':
|
|
||||||
multiplier = UINT64_C(1);
|
|
||||||
break;
|
|
||||||
#define KILO UINT64_C(1024)
|
|
||||||
case 's':
|
|
||||||
case 'S':
|
|
||||||
multiplier = (KILO/2);
|
|
||||||
break;
|
|
||||||
case 'k':
|
|
||||||
multiplier = KILO;
|
|
||||||
break;
|
|
||||||
case 'm':
|
|
||||||
multiplier = KILO * KILO;
|
|
||||||
break;
|
|
||||||
case 'g':
|
|
||||||
multiplier = KILO * KILO * KILO;
|
|
||||||
break;
|
|
||||||
case 't':
|
|
||||||
multiplier = KILO * KILO * KILO * KILO;
|
|
||||||
break;
|
|
||||||
case 'p':
|
|
||||||
multiplier = KILO * KILO * KILO * KILO * KILO;
|
|
||||||
break;
|
|
||||||
case 'e':
|
|
||||||
multiplier = KILO * KILO * KILO * KILO * KILO * KILO;
|
|
||||||
break;
|
|
||||||
#undef KILO
|
|
||||||
#define KILO UINT64_C(1000)
|
|
||||||
case 'K':
|
|
||||||
multiplier = KILO;
|
|
||||||
break;
|
|
||||||
case 'M':
|
|
||||||
multiplier = KILO * KILO;
|
|
||||||
break;
|
|
||||||
case 'G':
|
|
||||||
multiplier = KILO * KILO * KILO;
|
|
||||||
break;
|
|
||||||
case 'T':
|
|
||||||
multiplier = KILO * KILO * KILO * KILO;
|
|
||||||
break;
|
|
||||||
case 'P':
|
|
||||||
multiplier = KILO * KILO * KILO * KILO * KILO;
|
|
||||||
break;
|
|
||||||
case 'E':
|
|
||||||
multiplier = KILO * KILO * KILO * KILO * KILO * KILO;
|
|
||||||
break;
|
|
||||||
#undef KILO
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_close_enough(custom_value, 0.))
|
|
||||||
return v * multiplier; /* Use integer arithmetic */
|
|
||||||
else
|
|
||||||
return (uint64_t) (custom_value * multiplier);
|
|
||||||
}
|
|
||||||
|
|
||||||
char alloc_policy_char(alloc_policy_t alloc)
|
char alloc_policy_char(alloc_policy_t alloc)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -22,8 +22,6 @@
|
|||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
uint64_t units_to_bytes(const char *units, char *unit_type);
|
|
||||||
|
|
||||||
/* Specify size in KB */
|
/* Specify size in KB */
|
||||||
const char *display_size(const struct cmd_context *cmd, uint64_t size);
|
const char *display_size(const struct cmd_context *cmd, uint64_t size);
|
||||||
const char *display_size_long(const struct cmd_context *cmd, uint64_t size);
|
const char *display_size_long(const struct cmd_context *cmd, uint64_t size);
|
||||||
|
@ -1454,6 +1454,50 @@ void dm_unescape_colons_and_at_signs(char *src,
|
|||||||
*/
|
*/
|
||||||
int dm_strncpy(char *dest, const char *src, size_t n);
|
int dm_strncpy(char *dest, const char *src, size_t n);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Recognize unit specifier in the 'units' arg and return a factor
|
||||||
|
* representing that unit. If the 'units' contains a prefix with digits,
|
||||||
|
* the 'units' is considered to be a custom unit.
|
||||||
|
*
|
||||||
|
* Also, set 'unit_type' output arg to the character that represents
|
||||||
|
* the unit specified. The 'unit_type' character equals to the unit
|
||||||
|
* character itself recognized in the 'units' arg for canonical units.
|
||||||
|
* Otherwise, the 'unit_type' character is set to 'U' for custom unit.
|
||||||
|
*
|
||||||
|
* An example for k/K canonical units and 8k/8K custom units:
|
||||||
|
*
|
||||||
|
* units unit_type return value (factor)
|
||||||
|
* k k 1024
|
||||||
|
* K K 1000
|
||||||
|
* 8k U 1024*8
|
||||||
|
* 8K U 1000*8
|
||||||
|
* etc...
|
||||||
|
*
|
||||||
|
* Recognized units:
|
||||||
|
*
|
||||||
|
* h/H - human readable (returns 1 for both)
|
||||||
|
* b/B - byte (returns 1 for both)
|
||||||
|
* s/S - sector (returns 512 for both)
|
||||||
|
* k/K - kilo (returns 1024/1000 respectively)
|
||||||
|
* m/M - mega (returns 1024^2/1000^2 respectively)
|
||||||
|
* g/G - giga (returns 1024^3/1000^3 respectively)
|
||||||
|
* t/T - tera (returns 1024^4/1000^4 respectively)
|
||||||
|
* p/P - peta (returns 1024^5/1000^5 respectively)
|
||||||
|
* e/E - exa (returns 1024^6/1000^6 respectively)
|
||||||
|
*
|
||||||
|
* Only one units character is allowed in the 'units' arg
|
||||||
|
* if strict mode is enabled by 'strict' arg.
|
||||||
|
*
|
||||||
|
* The 'endptr' output arg, if not NULL, saves the pointer
|
||||||
|
* in the 'units' string which follows the unit specifier
|
||||||
|
* recognized (IOW the position where the parsing of the
|
||||||
|
* unit specifier stopped).
|
||||||
|
*
|
||||||
|
* Returns the unit factor or 0 if no unit is recognized.
|
||||||
|
*/
|
||||||
|
uint64_t dm_units_to_factor(const char *units, char *unit_type,
|
||||||
|
int strict, char **endptr);
|
||||||
|
|
||||||
/**************************
|
/**************************
|
||||||
* file/stream manipulation
|
* file/stream manipulation
|
||||||
**************************/
|
**************************/
|
||||||
|
@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
#include <math.h> /* fabs() */
|
||||||
|
#include <float.h> /* DBL_EPSILON */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* consume characters while they match the predicate function.
|
* consume characters while they match the predicate function.
|
||||||
@ -434,3 +436,107 @@ int dm_strncpy(char *dest, const char *src, size_t n)
|
|||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Test if the doubles are close enough to be considered equal */
|
||||||
|
static int _close_enough(double d1, double d2)
|
||||||
|
{
|
||||||
|
return fabs(d1 - d2) < DBL_EPSILON;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t dm_units_to_factor(const char *units, char *unit_type,
|
||||||
|
int strict, char **endptr)
|
||||||
|
{
|
||||||
|
char *ptr = NULL;
|
||||||
|
uint64_t v;
|
||||||
|
double custom_value = 0;
|
||||||
|
uint64_t multiplier;
|
||||||
|
|
||||||
|
if (endptr)
|
||||||
|
*endptr = (char *) units;
|
||||||
|
|
||||||
|
if (isdigit(*units)) {
|
||||||
|
custom_value = strtod(units, &ptr);
|
||||||
|
if (ptr == units)
|
||||||
|
return 0;
|
||||||
|
v = (uint64_t) strtoull(units, NULL, 10);
|
||||||
|
if (_close_enough((double) v, custom_value))
|
||||||
|
custom_value = 0; /* Use integer arithmetic */
|
||||||
|
units = ptr;
|
||||||
|
} else
|
||||||
|
v = 1;
|
||||||
|
|
||||||
|
/* Only one units char permitted in strict mode. */
|
||||||
|
if (strict && units[0] && units[1])
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (v == 1)
|
||||||
|
*unit_type = *units;
|
||||||
|
else
|
||||||
|
*unit_type = 'U';
|
||||||
|
|
||||||
|
switch (*units) {
|
||||||
|
case 'h':
|
||||||
|
case 'H':
|
||||||
|
multiplier = v = UINT64_C(1);
|
||||||
|
*unit_type = *units;
|
||||||
|
break;
|
||||||
|
case 'b':
|
||||||
|
case 'B':
|
||||||
|
multiplier = UINT64_C(1);
|
||||||
|
break;
|
||||||
|
#define KILO UINT64_C(1024)
|
||||||
|
case 's':
|
||||||
|
case 'S':
|
||||||
|
multiplier = (KILO/2);
|
||||||
|
break;
|
||||||
|
case 'k':
|
||||||
|
multiplier = KILO;
|
||||||
|
break;
|
||||||
|
case 'm':
|
||||||
|
multiplier = KILO * KILO;
|
||||||
|
break;
|
||||||
|
case 'g':
|
||||||
|
multiplier = KILO * KILO * KILO;
|
||||||
|
break;
|
||||||
|
case 't':
|
||||||
|
multiplier = KILO * KILO * KILO * KILO;
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
multiplier = KILO * KILO * KILO * KILO * KILO;
|
||||||
|
break;
|
||||||
|
case 'e':
|
||||||
|
multiplier = KILO * KILO * KILO * KILO * KILO * KILO;
|
||||||
|
break;
|
||||||
|
#undef KILO
|
||||||
|
#define KILO UINT64_C(1000)
|
||||||
|
case 'K':
|
||||||
|
multiplier = KILO;
|
||||||
|
break;
|
||||||
|
case 'M':
|
||||||
|
multiplier = KILO * KILO;
|
||||||
|
break;
|
||||||
|
case 'G':
|
||||||
|
multiplier = KILO * KILO * KILO;
|
||||||
|
break;
|
||||||
|
case 'T':
|
||||||
|
multiplier = KILO * KILO * KILO * KILO;
|
||||||
|
break;
|
||||||
|
case 'P':
|
||||||
|
multiplier = KILO * KILO * KILO * KILO * KILO;
|
||||||
|
break;
|
||||||
|
case 'E':
|
||||||
|
multiplier = KILO * KILO * KILO * KILO * KILO * KILO;
|
||||||
|
break;
|
||||||
|
#undef KILO
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (endptr)
|
||||||
|
*endptr = (char *) units + 1;
|
||||||
|
|
||||||
|
if (_close_enough(custom_value, 0.))
|
||||||
|
return v * multiplier; /* Use integer arithmetic */
|
||||||
|
else
|
||||||
|
return (uint64_t) (custom_value * multiplier);
|
||||||
|
}
|
||||||
|
@ -923,8 +923,8 @@ static int _get_settings(struct cmd_context *cmd)
|
|||||||
|
|
||||||
if (arg_count(cmd, units_ARG))
|
if (arg_count(cmd, units_ARG))
|
||||||
if (!(cmd->current_settings.unit_factor =
|
if (!(cmd->current_settings.unit_factor =
|
||||||
units_to_bytes(arg_str_value(cmd, units_ARG, ""),
|
dm_units_to_factor(arg_str_value(cmd, units_ARG, ""),
|
||||||
&cmd->current_settings.unit_type))) {
|
&cmd->current_settings.unit_type, 1, NULL))) {
|
||||||
log_error("Invalid units specification");
|
log_error("Invalid units specification");
|
||||||
return EINVALID_CMD_LINE;
|
return EINVALID_CMD_LINE;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user