1
0
mirror of git://sourceware.org/git/lvm2.git synced 2024-12-22 17:35:59 +03:00
lvm2/device_mapper/vdo/status.c

239 lines
4.8 KiB
C
Raw Normal View History

#include "configure.h"
#include "target.h"
// For DM_ARRAY_SIZE!
#include "device_mapper/all.h"
2018-05-02 13:15:35 +03:00
#include <ctype.h>
#include <stdlib.h>
2018-05-02 13:15:35 +03:00
#include <string.h>
//----------------------------------------------------------------
static bool _tok_eq(const char *b, const char *e, const char *str)
{
while (b != e) {
if (!*str || *b != *str)
return false;
b++;
str++;
}
return !*str;
}
2018-05-02 13:15:35 +03:00
static bool _parse_operating_mode(const char *b, const char *e, void *context)
{
static const struct {
const char str[12];
enum vdo_operating_mode mode;
} _table[] = {
{"recovering", VDO_MODE_RECOVERING},
{"read-only", VDO_MODE_READ_ONLY},
{"normal", VDO_MODE_NORMAL}
};
enum vdo_operating_mode *r = context;
unsigned i;
for (i = 0; i < DM_ARRAY_SIZE(_table); i++) {
if (_tok_eq(b, e, _table[i].str)) {
*r = _table[i].mode;
return true;
}
}
return false;
}
2018-05-02 13:15:35 +03:00
static bool _parse_compression_state(const char *b, const char *e, void *context)
{
static const struct {
const char str[8];
enum vdo_compression_state state;
} _table[] = {
{"online", VDO_COMPRESSION_ONLINE},
{"offline", VDO_COMPRESSION_OFFLINE}
};
enum vdo_compression_state *r = context;
unsigned i;
for (i = 0; i < DM_ARRAY_SIZE(_table); i++) {
if (_tok_eq(b, e, _table[i].str)) {
*r = _table[i].state;
return true;
}
}
return false;
}
2018-05-02 13:15:35 +03:00
static bool _parse_recovering(const char *b, const char *e, void *context)
{
bool *r = context;
2018-05-02 13:15:35 +03:00
if (_tok_eq(b, e, "recovering"))
*r = true;
else if (_tok_eq(b, e, "-"))
*r = false;
else
return false;
return true;
}
2018-05-02 13:15:35 +03:00
static bool _parse_index_state(const char *b, const char *e, void *context)
{
static const struct {
const char str[8];
enum vdo_index_state state;
} _table[] = {
{"error", VDO_INDEX_ERROR},
{"closed", VDO_INDEX_CLOSED},
{"opening", VDO_INDEX_OPENING},
{"closing", VDO_INDEX_CLOSING},
{"offline", VDO_INDEX_OFFLINE},
{"online", VDO_INDEX_ONLINE},
{"unknown", VDO_INDEX_UNKNOWN}
};
enum vdo_index_state *r = context;
unsigned i;
for (i = 0; i < DM_ARRAY_SIZE(_table); i++) {
if (_tok_eq(b, e, _table[i].str)) {
*r = _table[i].state;
return true;
}
}
return false;
}
2018-05-02 13:15:35 +03:00
static bool _parse_uint64(const char *b, const char *e, void *context)
{
uint64_t *r = context, n;
2018-05-02 13:15:35 +03:00
n = 0;
while (b != e) {
if (!isdigit(*b))
return false;
2018-05-02 13:15:35 +03:00
2018-05-10 15:01:26 +03:00
n = (n * 10) + (*b - '0');
2018-05-02 13:15:35 +03:00
b++;
}
*r = n;
return true;
}
static const char *_eat_space(const char *b, const char *e)
{
while (b != e && isspace(*b))
b++;
return b;
}
static const char *_next_tok(const char *b, const char *e)
{
const char *te = b;
2018-05-10 15:01:26 +03:00
while (te != e && !isspace(*te))
te++;
return te == b ? NULL : te;
}
2018-05-10 15:01:26 +03:00
static void _set_error(struct vdo_status_parse_result *result, const char *fmt, ...)
__attribute__ ((format(printf, 2, 3)));
2018-05-02 13:15:35 +03:00
2018-05-10 15:01:26 +03:00
static void _set_error(struct vdo_status_parse_result *result, const char *fmt, ...)
2018-05-02 13:15:35 +03:00
{
va_list ap;
2018-05-02 13:15:35 +03:00
va_start(ap, fmt);
2018-05-02 13:15:35 +03:00
vsnprintf(result->error, sizeof(result->error), fmt, ap);
va_end(ap);
2018-05-02 13:15:35 +03:00
}
static bool _parse_field(const char **b, const char *e,
bool (*p_fn)(const char *, const char *, void *),
void *field, const char *field_name,
struct vdo_status_parse_result *result)
{
const char *te;
te = _next_tok(*b, e);
if (!te) {
_set_error(result, "couldn't get token for '%s'", field_name);
return false;
}
if (!p_fn(*b, te, field)) {
_set_error(result, "couldn't parse '%s'", field_name);
return false;
}
2018-05-02 13:15:35 +03:00
*b = _eat_space(te, e);
return true;
}
bool vdo_status_parse(struct dm_pool *mem, const char *input,
struct vdo_status_parse_result *result)
{
2018-05-02 13:15:35 +03:00
const char *b = b = input;
const char *e = input + strlen(input);
const char *te;
struct vdo_status *s;
s = (!mem) ? malloc(sizeof(*s)) : dm_pool_zalloc(mem, sizeof(*s));
if (!s) {
_set_error(result, "out of memory");
return false;
}
2018-05-02 13:15:35 +03:00
b = _eat_space(b, e);
te = _next_tok(b, e);
if (!te) {
_set_error(result, "couldn't get token for device");
goto bad;
}
if (!(s->device = (!mem) ? malloc((e - b) + 1) : dm_pool_alloc(mem, (e - b) + 1))) {
2018-05-02 13:15:35 +03:00
_set_error(result, "out of memory");
goto bad;
}
dm_strncpy(s->device, b, te - b);
2018-05-02 13:15:35 +03:00
b = _eat_space(te, e);
#define XX(p, f, fn) if (!_parse_field(&b, e, p, f, fn, result)) goto bad;
2018-05-02 13:15:35 +03:00
XX(_parse_operating_mode, &s->operating_mode, "operating mode");
XX(_parse_recovering, &s->recovering, "recovering");
2018-05-02 13:15:35 +03:00
XX(_parse_index_state, &s->index_state, "index state");
XX(_parse_compression_state, &s->compression_state, "compression state");
XX(_parse_uint64, &s->used_blocks, "used blocks");
XX(_parse_uint64, &s->total_blocks, "total blocks");
#undef XX
2018-05-10 15:01:26 +03:00
if (b != e) {
_set_error(result, "too many tokens");
goto bad;
}
result->status = s;
return true;
bad:
if (s && !mem) {
free(s->device);
free(s);
}
return false;
}
//----------------------------------------------------------------