mirror of
git://sourceware.org/git/lvm2.git
synced 2024-12-22 17:35:59 +03:00
155 lines
2.5 KiB
C
155 lines
2.5 KiB
C
/*
|
|
* Copyright (C) 2002 Sistina Software
|
|
*
|
|
* This file is released under the LGPL.
|
|
*/
|
|
|
|
#include "label.h"
|
|
#include "list.h"
|
|
#include "dbg_malloc.h"
|
|
#include "log.h"
|
|
|
|
/*
|
|
* Internal labeller struct.
|
|
*/
|
|
struct labeller_i {
|
|
struct list list;
|
|
|
|
struct labeller *l;
|
|
char name[0];
|
|
};
|
|
|
|
static struct list _labellers;
|
|
|
|
|
|
static struct labeller_i *_alloc_li(const char *name, struct labeller *l)
|
|
{
|
|
struct labeller_i *li;
|
|
size_t len;
|
|
|
|
len = sizeof(*li) + strlen(name) + 1;
|
|
|
|
if (!(li = dbg_malloc(len))) {
|
|
log_error("Couldn't allocate memory for labeller list object.");
|
|
return NULL;
|
|
}
|
|
|
|
li->l = l;
|
|
strcpy(li->name, name);
|
|
|
|
return li;
|
|
}
|
|
|
|
static void _free_li(struct labeller_i *li)
|
|
{
|
|
dbg_free(li);
|
|
}
|
|
|
|
|
|
int label_init(void)
|
|
{
|
|
list_init(&_labellers);
|
|
return 1;
|
|
}
|
|
|
|
void label_exit(void)
|
|
{
|
|
struct list *c, *n;
|
|
struct labeller_i *li;
|
|
|
|
for (c = _labellers.n; c != &_labellers; c = n) {
|
|
n = c->n;
|
|
li = list_item(c, struct labeller_i);
|
|
_free_li(li);
|
|
}
|
|
}
|
|
|
|
int label_register_handler(const char *name, struct labeller *handler)
|
|
{
|
|
struct labeller_i *li;
|
|
|
|
if (!(li = _alloc_li(name, handler))) {
|
|
stack;
|
|
return 0;
|
|
}
|
|
|
|
list_add(&_labellers, &li->list);
|
|
return 1;
|
|
}
|
|
|
|
struct labeller *label_get_handler(const char *name)
|
|
{
|
|
struct list *lih;
|
|
struct labeller_i *li;
|
|
|
|
list_iterate (lih, &_labellers) {
|
|
li = list_item(lih, struct labeller_i);
|
|
if (!strcmp(li->name, name))
|
|
return li->l;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static struct labeller *_find_labeller(struct device *dev)
|
|
{
|
|
struct list *lih;
|
|
struct labeller_i *li;
|
|
|
|
list_iterate (lih, &_labellers) {
|
|
li = list_item(lih, struct labeller_i);
|
|
if (li->l->ops->can_handle(li->l, dev))
|
|
return li->l;
|
|
}
|
|
|
|
log_debug("No label on device '%s'.", dev_name(dev));
|
|
return NULL;
|
|
}
|
|
|
|
int label_remove(struct device *dev)
|
|
{
|
|
struct labeller *l;
|
|
|
|
if (!(l = _find_labeller(dev))) {
|
|
stack;
|
|
return 0;
|
|
}
|
|
|
|
return l->ops->remove(l, dev);
|
|
}
|
|
|
|
int label_read(struct device *dev, struct label **result)
|
|
{
|
|
int r;
|
|
struct list *lih;
|
|
struct labeller_i *li;
|
|
|
|
list_iterate (lih, &_labellers) {
|
|
li = list_item(lih, struct labeller_i);
|
|
if ((r = li->l->ops->read(li->l, dev, result))) {
|
|
(*result)->labeller = li->l;
|
|
return r;
|
|
}
|
|
}
|
|
|
|
log_debug("No label on device '%s'.", dev_name(dev));
|
|
return 0;
|
|
}
|
|
|
|
int label_verify(struct device *dev)
|
|
{
|
|
struct labeller *l;
|
|
|
|
if (!(l = _find_labeller(dev))) {
|
|
stack;
|
|
return 0;
|
|
}
|
|
|
|
return l->ops->verify(l, dev);
|
|
}
|
|
|
|
void label_destroy(struct label *lab)
|
|
{
|
|
lab->labeller->ops->destroy_label(lab->labeller, lab);
|
|
}
|