mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-21 13:34:40 +03:00
libdm: Add dm_size_to_string to libdevmapper.
Moved out from lib/display and a little documentation added. It's tuned to LVM's requirements historically and its behaviour might not always be what you would expect.
This commit is contained in:
parent
fa11ddd7df
commit
af1c7bf0c7
@ -24,10 +24,6 @@
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#define SIZE_BUF 128
|
||||
|
||||
typedef enum { SIZE_LONG = 0, SIZE_SHORT = 1, SIZE_UNIT = 2 } size_len_t;
|
||||
|
||||
static const struct {
|
||||
alloc_policy_t alloc;
|
||||
const char str[14]; /* must be changed when size extends 13 chars */
|
||||
@ -146,164 +142,30 @@ const char *display_lvname(const struct logical_volume *lv)
|
||||
return name;
|
||||
}
|
||||
|
||||
#define BASE_UNKNOWN 0
|
||||
#define BASE_SHARED 1
|
||||
#define BASE_1024 8
|
||||
#define BASE_1000 15
|
||||
#define BASE_SPECIAL 21
|
||||
#define NUM_UNIT_PREFIXES 6
|
||||
#define NUM_SPECIAL 3
|
||||
|
||||
/* Size supplied in sectors */
|
||||
static const char *_display_size(const struct cmd_context *cmd,
|
||||
uint64_t size, size_len_t sl)
|
||||
uint64_t size, dm_size_suffix_t suffix_type)
|
||||
{
|
||||
unsigned base = BASE_UNKNOWN;
|
||||
unsigned s;
|
||||
int suffix, precision;
|
||||
uint64_t byte = UINT64_C(0);
|
||||
uint64_t units = UINT64_C(1024);
|
||||
char *size_buf = NULL;
|
||||
const char * const size_str[][3] = {
|
||||
/* BASE_UNKNOWN */
|
||||
{" ", " ", " "}, /* [0] */
|
||||
|
||||
/* BASE_SHARED - Used if cmd->si_unit_consistency = 0 */
|
||||
{" Exabyte", " EB", "E"}, /* [1] */
|
||||
{" Petabyte", " PB", "P"}, /* [2] */
|
||||
{" Terabyte", " TB", "T"}, /* [3] */
|
||||
{" Gigabyte", " GB", "G"}, /* [4] */
|
||||
{" Megabyte", " MB", "M"}, /* [5] */
|
||||
{" Kilobyte", " KB", "K"}, /* [6] */
|
||||
{" Byte ", " B", "B"}, /* [7] */
|
||||
|
||||
/* BASE_1024 - Used if cmd->si_unit_consistency = 1 */
|
||||
{" Exbibyte", " EiB", "e"}, /* [8] */
|
||||
{" Pebibyte", " PiB", "p"}, /* [9] */
|
||||
{" Tebibyte", " TiB", "t"}, /* [10] */
|
||||
{" Gibibyte", " GiB", "g"}, /* [11] */
|
||||
{" Mebibyte", " MiB", "m"}, /* [12] */
|
||||
{" Kibibyte", " KiB", "k"}, /* [13] */
|
||||
{" Byte ", " B", "b"}, /* [14] */
|
||||
|
||||
/* BASE_1000 - Used if cmd->si_unit_consistency = 1 */
|
||||
{" Exabyte", " EB", "E"}, /* [15] */
|
||||
{" Petabyte", " PB", "P"}, /* [16] */
|
||||
{" Terabyte", " TB", "T"}, /* [17] */
|
||||
{" Gigabyte", " GB", "G"}, /* [18] */
|
||||
{" Megabyte", " MB", "M"}, /* [19] */
|
||||
{" Kilobyte", " kB", "K"}, /* [20] */
|
||||
|
||||
/* BASE_SPECIAL */
|
||||
{" Byte ", " B ", "B"}, /* [21] (shared with BASE_1000) */
|
||||
{" Units ", " Un", "U"}, /* [22] */
|
||||
{" Sectors ", " Se", "S"}, /* [23] */
|
||||
};
|
||||
|
||||
if (!(size_buf = dm_pool_alloc(cmd->mem, SIZE_BUF))) {
|
||||
log_error("no memory for size display buffer");
|
||||
return "";
|
||||
}
|
||||
|
||||
suffix = cmd->current_settings.suffix;
|
||||
|
||||
if (!cmd->si_unit_consistency) {
|
||||
/* Case-independent match */
|
||||
for (s = 0; s < NUM_UNIT_PREFIXES; s++)
|
||||
if (toupper((int) cmd->current_settings.unit_type) ==
|
||||
*size_str[BASE_SHARED + s][2]) {
|
||||
base = BASE_SHARED;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* Case-dependent match for powers of 1000 */
|
||||
for (s = 0; s < NUM_UNIT_PREFIXES; s++)
|
||||
if (cmd->current_settings.unit_type ==
|
||||
*size_str[BASE_1000 + s][2]) {
|
||||
base = BASE_1000;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Case-dependent match for powers of 1024 */
|
||||
if (base == BASE_UNKNOWN)
|
||||
for (s = 0; s < NUM_UNIT_PREFIXES; s++)
|
||||
if (cmd->current_settings.unit_type ==
|
||||
*size_str[BASE_1024 + s][2]) {
|
||||
base = BASE_1024;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (base == BASE_UNKNOWN)
|
||||
/* Check for special units - s, b or u */
|
||||
for (s = 0; s < NUM_SPECIAL; s++)
|
||||
if (toupper((int) cmd->current_settings.unit_type) ==
|
||||
*size_str[BASE_SPECIAL + s][2]) {
|
||||
base = BASE_SPECIAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (size == UINT64_C(0)) {
|
||||
if (base == BASE_UNKNOWN)
|
||||
s = 0;
|
||||
sprintf(size_buf, "0%s", suffix ? size_str[base + s][sl] : "");
|
||||
return size_buf;
|
||||
}
|
||||
|
||||
size *= UINT64_C(512);
|
||||
|
||||
if (base != BASE_UNKNOWN)
|
||||
byte = cmd->current_settings.unit_factor;
|
||||
else {
|
||||
/* Human-readable style */
|
||||
if (cmd->current_settings.unit_type == 'H') {
|
||||
units = UINT64_C(1000);
|
||||
base = BASE_1000;
|
||||
} else {
|
||||
units = UINT64_C(1024);
|
||||
base = BASE_1024;
|
||||
}
|
||||
|
||||
if (!cmd->si_unit_consistency)
|
||||
base = BASE_SHARED;
|
||||
|
||||
byte = units * units * units * units * units * units;
|
||||
|
||||
for (s = 0; s < NUM_UNIT_PREFIXES && size < byte; s++)
|
||||
byte /= units;
|
||||
|
||||
suffix = 1;
|
||||
}
|
||||
|
||||
/* FIXME Make precision configurable */
|
||||
switch (toupper(*size_str[base + s][SIZE_UNIT])) {
|
||||
case 'B':
|
||||
case 'S':
|
||||
precision = 0;
|
||||
break;
|
||||
default:
|
||||
precision = 2;
|
||||
}
|
||||
|
||||
snprintf(size_buf, SIZE_BUF - 1, "%.*f%s", precision,
|
||||
(double) size / byte, suffix ? size_str[base + s][sl] : "");
|
||||
|
||||
return size_buf;
|
||||
return dm_size_to_string(cmd->mem, size, cmd->current_settings.unit_type,
|
||||
cmd->si_unit_consistency,
|
||||
cmd->current_settings.unit_factor,
|
||||
cmd->current_settings.suffix,
|
||||
suffix_type);
|
||||
}
|
||||
|
||||
const char *display_size_long(const struct cmd_context *cmd, uint64_t size)
|
||||
{
|
||||
return _display_size(cmd, size, SIZE_LONG);
|
||||
return _display_size(cmd, size, DM_SIZE_LONG);
|
||||
}
|
||||
|
||||
const char *display_size_units(const struct cmd_context *cmd, uint64_t size)
|
||||
{
|
||||
return _display_size(cmd, size, SIZE_UNIT);
|
||||
return _display_size(cmd, size, DM_SIZE_UNIT);
|
||||
}
|
||||
|
||||
const char *display_size(const struct cmd_context *cmd, uint64_t size)
|
||||
{
|
||||
return _display_size(cmd, size, SIZE_SHORT);
|
||||
return _display_size(cmd, size, DM_SIZE_SHORT);
|
||||
}
|
||||
|
||||
void pvdisplay_colons(const struct physical_volume *pv)
|
||||
|
1
libdm/.exported_symbols.DM_1_02_104
Normal file
1
libdm/.exported_symbols.DM_1_02_104
Normal file
@ -0,0 +1 @@
|
||||
dm_size_to_string
|
@ -1532,6 +1532,32 @@ int dm_strncpy(char *dest, const char *src, size_t n);
|
||||
uint64_t dm_units_to_factor(const char *units, char *unit_type,
|
||||
int strict, const char **endptr);
|
||||
|
||||
/*
|
||||
* Type of unit specifier used by dm_size_to_string().
|
||||
*/
|
||||
typedef enum {
|
||||
DM_SIZE_LONG = 0, /* Megabyte */
|
||||
DM_SIZE_SHORT = 1, /* MB or MiB */
|
||||
DM_SIZE_UNIT = 2 /* M or m */
|
||||
} dm_size_suffix_t;
|
||||
|
||||
/*
|
||||
* Convert a size (in 512-byte sectors) into a printable string using units of unit_type.
|
||||
* An upper-case unit_type indicates output units based on powers of 1000 are
|
||||
* required; a lower-case unit_type indicates powers of 1024.
|
||||
* For correct operation, unit_factor must be one of:
|
||||
* 0 - the correct value will be calculated internally;
|
||||
* or the output from dm_units_to_factor() corresponding to unit_type;
|
||||
* or 'u' or 'U', an arbitrary number of bytes to use as the power base.
|
||||
* Set include_suffix to 1 to include a suffix of suffix_type.
|
||||
* Set use_si_units to 0 for suffixes that don't distinguish between 1000 and 1024.
|
||||
* Set use_si_units to 1 for a suffix that does distinguish.
|
||||
*/
|
||||
const char *dm_size_to_string(struct dm_pool *mem, uint64_t size,
|
||||
char unit_type, int use_si_units,
|
||||
uint64_t unit_factor, int include_suffix,
|
||||
dm_size_suffix_t suffix_type);
|
||||
|
||||
/**************************
|
||||
* file/stream manipulation
|
||||
**************************/
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2006-2012 Red Hat, Inc. All rights reserved.
|
||||
* Copyright (C) 2006-2015 Red Hat, Inc. All rights reserved.
|
||||
*
|
||||
* This file is part of the device-mapper userspace tools.
|
||||
*
|
||||
@ -443,6 +443,161 @@ static int _close_enough(double d1, double d2)
|
||||
return fabs(d1 - d2) < DBL_EPSILON;
|
||||
}
|
||||
|
||||
#define BASE_UNKNOWN 0
|
||||
#define BASE_SHARED 1
|
||||
#define BASE_1024 8
|
||||
#define BASE_1000 15
|
||||
#define BASE_SPECIAL 21
|
||||
#define NUM_UNIT_PREFIXES 6
|
||||
#define NUM_SPECIAL 3
|
||||
|
||||
#define SIZE_BUF 128
|
||||
|
||||
const char *dm_size_to_string(struct dm_pool *mem, uint64_t size,
|
||||
char unit_type, int use_si_units,
|
||||
uint64_t unit_factor, int include_suffix,
|
||||
dm_size_suffix_t suffix_type)
|
||||
{
|
||||
unsigned base = BASE_UNKNOWN;
|
||||
unsigned s;
|
||||
int precision;
|
||||
uint64_t byte = UINT64_C(0);
|
||||
uint64_t units = UINT64_C(1024);
|
||||
char *size_buf = NULL;
|
||||
char new_unit_type = '\0', unit_type_buf[2];
|
||||
const char * const size_str[][3] = {
|
||||
/* BASE_UNKNOWN */
|
||||
{" ", " ", " "}, /* [0] */
|
||||
|
||||
/* BASE_SHARED - Used if use_si_units = 0 */
|
||||
{" Exabyte", " EB", "E"}, /* [1] */
|
||||
{" Petabyte", " PB", "P"}, /* [2] */
|
||||
{" Terabyte", " TB", "T"}, /* [3] */
|
||||
{" Gigabyte", " GB", "G"}, /* [4] */
|
||||
{" Megabyte", " MB", "M"}, /* [5] */
|
||||
{" Kilobyte", " KB", "K"}, /* [6] */
|
||||
{" Byte ", " B", "B"}, /* [7] */
|
||||
|
||||
/* BASE_1024 - Used if use_si_units = 1 */
|
||||
{" Exbibyte", " EiB", "e"}, /* [8] */
|
||||
{" Pebibyte", " PiB", "p"}, /* [9] */
|
||||
{" Tebibyte", " TiB", "t"}, /* [10] */
|
||||
{" Gibibyte", " GiB", "g"}, /* [11] */
|
||||
{" Mebibyte", " MiB", "m"}, /* [12] */
|
||||
{" Kibibyte", " KiB", "k"}, /* [13] */
|
||||
{" Byte ", " B", "b"}, /* [14] */
|
||||
|
||||
/* BASE_1000 - Used if use_si_units = 1 */
|
||||
{" Exabyte", " EB", "E"}, /* [15] */
|
||||
{" Petabyte", " PB", "P"}, /* [16] */
|
||||
{" Terabyte", " TB", "T"}, /* [17] */
|
||||
{" Gigabyte", " GB", "G"}, /* [18] */
|
||||
{" Megabyte", " MB", "M"}, /* [19] */
|
||||
{" Kilobyte", " kB", "K"}, /* [20] */
|
||||
|
||||
/* BASE_SPECIAL */
|
||||
{" Byte ", " B ", "B"}, /* [21] (shared with BASE_1000) */
|
||||
{" Units ", " Un", "U"}, /* [22] */
|
||||
{" Sectors ", " Se", "S"}, /* [23] */
|
||||
};
|
||||
|
||||
if (!(size_buf = dm_pool_alloc(mem, SIZE_BUF))) {
|
||||
log_error("no memory for size display buffer");
|
||||
return "";
|
||||
}
|
||||
|
||||
if (!use_si_units) {
|
||||
/* Case-independent match */
|
||||
for (s = 0; s < NUM_UNIT_PREFIXES; s++)
|
||||
if (toupper((int) unit_type) ==
|
||||
*size_str[BASE_SHARED + s][2]) {
|
||||
base = BASE_SHARED;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
/* Case-dependent match for powers of 1000 */
|
||||
for (s = 0; s < NUM_UNIT_PREFIXES; s++)
|
||||
if (unit_type == *size_str[BASE_1000 + s][2]) {
|
||||
base = BASE_1000;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Case-dependent match for powers of 1024 */
|
||||
if (base == BASE_UNKNOWN)
|
||||
for (s = 0; s < NUM_UNIT_PREFIXES; s++)
|
||||
if (unit_type == *size_str[BASE_1024 + s][2]) {
|
||||
base = BASE_1024;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (base == BASE_UNKNOWN)
|
||||
/* Check for special units - s, b or u */
|
||||
for (s = 0; s < NUM_SPECIAL; s++)
|
||||
if (toupper((int) unit_type) ==
|
||||
*size_str[BASE_SPECIAL + s][2]) {
|
||||
base = BASE_SPECIAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (size == UINT64_C(0)) {
|
||||
if (base == BASE_UNKNOWN)
|
||||
s = 0;
|
||||
sprintf(size_buf, "0%s", include_suffix ? size_str[base + s][suffix_type] : "");
|
||||
return size_buf;
|
||||
}
|
||||
|
||||
size *= UINT64_C(512);
|
||||
|
||||
if (base != BASE_UNKNOWN) {
|
||||
if (!unit_factor) {
|
||||
unit_type_buf[0] = unit_type;
|
||||
unit_type_buf[1] = '\0';
|
||||
if (!(unit_factor = dm_units_to_factor(&unit_type_buf[0], &new_unit_type, 1, NULL)) ||
|
||||
unit_type != new_unit_type) {
|
||||
/* The two functions should match (and unrecognised units get treated like 'h'). */
|
||||
log_error(INTERNAL_ERROR "Inconsistent units: %c and %c.", unit_type, new_unit_type);
|
||||
return "";
|
||||
}
|
||||
}
|
||||
byte = unit_factor;
|
||||
} else {
|
||||
/* Human-readable style */
|
||||
if (unit_type == 'H') {
|
||||
units = UINT64_C(1000);
|
||||
base = BASE_1000;
|
||||
} else {
|
||||
units = UINT64_C(1024);
|
||||
base = BASE_1024;
|
||||
}
|
||||
|
||||
if (!use_si_units)
|
||||
base = BASE_SHARED;
|
||||
|
||||
byte = units * units * units * units * units * units;
|
||||
|
||||
for (s = 0; s < NUM_UNIT_PREFIXES && size < byte; s++)
|
||||
byte /= units;
|
||||
|
||||
include_suffix = 1;
|
||||
}
|
||||
|
||||
/* FIXME Make precision configurable */
|
||||
switch (toupper(*size_str[base + s][DM_SIZE_UNIT])) {
|
||||
case 'B':
|
||||
case 'S':
|
||||
precision = 0;
|
||||
break;
|
||||
default:
|
||||
precision = 2;
|
||||
}
|
||||
|
||||
snprintf(size_buf, SIZE_BUF - 1, "%.*f%s", precision,
|
||||
(double) size / byte, include_suffix ? size_str[base + s][suffix_type] : "");
|
||||
|
||||
return size_buf;
|
||||
}
|
||||
|
||||
uint64_t dm_units_to_factor(const char *units, char *unit_type,
|
||||
int strict, const char **endptr)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user