libfdisk: cleanup parttype API

* add reference counting
 * add functions to set allocated types

Signed-off-by: Karel Zak <kzak@redhat.com>
This commit is contained in:
Karel Zak 2014-10-15 14:10:25 +02:00
parent 0123bd1a87
commit dfc6db2a35
8 changed files with 209 additions and 67 deletions

View File

@ -725,7 +725,7 @@ static int command_parttype(struct sfdisk *sf, int argc, char **argv)
else if (fdisk_set_partition_type(sf->cxt, partno - 1, type) != 0)
errx(EXIT_FAILURE, _("%s: partition %zu: failed to set partition type"),
devname, partno);
fdisk_free_parttype(type);
fdisk_unref_parttype(type);
return write_changes(sf);
}

View File

@ -1165,7 +1165,7 @@ static int add_partition(struct fdisk_context *cxt, size_t n,
struct fdisk_parttype *t =
fdisk_label_get_parttype_from_code(cxt->label, sys);
fdisk_info_new_partition(cxt, n + 1, start, stop, t);
fdisk_free_parttype(t);
fdisk_unref_parttype(t);
}

View File

@ -96,10 +96,11 @@ struct fdisk_iter {
*/
struct fdisk_parttype {
unsigned int code; /* type as number or zero */
const char *name; /* description */
char *name; /* description */
char *typestr; /* type as string or NULL */
unsigned int flags; /* FDISK_PARTTYPE_* flags */
int refcount; /* reference counter for allocated types */
};
enum {

View File

@ -2093,7 +2093,7 @@ static int gpt_add_partition(
t = gpt_partition_parttype(cxt, &ents[partnum]);
fdisk_info_new_partition(cxt, partnum + 1, user_f, user_l, t);
fdisk_free_parttype(t);
fdisk_unref_parttype(t);
}
rc = 0;

View File

@ -137,26 +137,27 @@ sector_t fdisk_get_geom_cylinders(struct fdisk_context *cxt);
/* parttype.c */
const struct fdisk_parttype *fdisk_label_get_parttype(const struct fdisk_label *lb, size_t n);
struct fdisk_parttype *fdisk_new_parttype(void);
void fdisk_ref_parttype(struct fdisk_parttype *t);
void fdisk_unref_parttype(struct fdisk_parttype *t);
int fdisk_parttype_set_name(struct fdisk_parttype *t, const char *str);
int fdisk_parttype_set_typestr(struct fdisk_parttype *t, const char *str);
int fdisk_parttype_set_code(struct fdisk_parttype *t, int code);
size_t fdisk_label_get_nparttypes(const struct fdisk_label *lb);
struct fdisk_parttype *fdisk_label_get_parttype(const struct fdisk_label *lb, size_t n);
int fdisk_label_has_code_parttypes(const struct fdisk_label *lb);
struct fdisk_parttype *fdisk_label_get_parttype_from_code(
const struct fdisk_label *lb,
unsigned int code);
struct fdisk_parttype *fdisk_label_get_parttype_from_string(
const struct fdisk_label *lb,
const char *str);
struct fdisk_parttype *fdisk_new_unknown_parttype(unsigned int code,
const char *typestr);
struct fdisk_parttype *fdisk_copy_parttype(const struct fdisk_parttype *type);
struct fdisk_parttype *fdisk_label_parse_parttype(
const struct fdisk_label *lb,
const char *str);
struct fdisk_parttype *fdisk_copy_parttype(const struct fdisk_parttype *type);
void fdisk_free_parttype(struct fdisk_parttype *t); /* TODO: use refcount */
const char *fdisk_parttype_get_string(const struct fdisk_parttype *t);
unsigned int fdisk_parttype_get_code(const struct fdisk_parttype *t);
const char *fdisk_parttype_get_name(const struct fdisk_parttype *t);
@ -271,8 +272,8 @@ int fdisk_partition_cmp_partno(struct fdisk_partition *a,
int fdisk_partition_partno_follow_default(struct fdisk_partition *pa, int enable);
extern int fdisk_partition_set_type(struct fdisk_partition *pa, const struct fdisk_parttype *type);
extern const struct fdisk_parttype *fdisk_partition_get_type(struct fdisk_partition *pa);
extern int fdisk_partition_set_type(struct fdisk_partition *pa, struct fdisk_parttype *type);
extern struct fdisk_parttype *fdisk_partition_get_type(struct fdisk_partition *pa);
extern int fdisk_partition_set_name(struct fdisk_partition *pa, const char *name);
extern const char *fdisk_partition_get_name(struct fdisk_partition *pa);
extern int fdisk_partition_set_uuid(struct fdisk_partition *pa, const char *uuid);

View File

@ -48,7 +48,7 @@ void fdisk_reset_partition(struct fdisk_partition *pa)
DBG(PART, ul_debugobj(pa, "reset"));
ref = pa->refcount;
fdisk_free_parttype(pa->type);
fdisk_unref_parttype(pa->type);
free(pa->name);
free(pa->uuid);
free(pa->attrs);
@ -383,17 +383,35 @@ int fdisk_partition_partno_follow_default(struct fdisk_partition *pa, int enable
return 0;
}
/**
* fdisk_partition_set_type:
* @pa: partition
* @type: partition type
*
* Sets parition type.
*
* Returns: 0 on success, <0 on error.
*/
int fdisk_partition_set_type(struct fdisk_partition *pa,
const struct fdisk_parttype *type)
struct fdisk_parttype *type)
{
if (!pa)
return -EINVAL;
fdisk_free_parttype(pa->type);
pa->type = fdisk_copy_parttype(type);
fdisk_ref_parttype(type);
fdisk_unref_parttype(pa->type);
pa->type = type;
return 0;
}
const struct fdisk_parttype *fdisk_partition_get_type(struct fdisk_partition *pa)
/**
* fdisk_partition_get_type:
* @pa: partition
*
* Returns: pointer to partition type.
*/
struct fdisk_parttype *fdisk_partition_get_type(struct fdisk_partition *pa)
{
return pa ? pa->type : NULL;
}

View File

@ -6,6 +6,131 @@
#include "fdiskP.h"
/**
* fdisk_new_parttype:
*
* It's recommended to use fdisk_label_get_parttype_from_code() or
* fdisk_label_get_parttype_from_string() for well known types rather
* than allocate a new instance.
*
* Returns: new instance.
*/
struct fdisk_parttype *fdisk_new_parttype(void)
{
struct fdisk_parttype *t = calloc(1, sizeof(*t));
t->refcount = 1;
t->flags = FDISK_PARTTYPE_ALLOCATED;
DBG(PARTTYPE, ul_debugobj(t, "alloc"));
return t;
}
/**
* fdisk_ref_parttype:
* @t: partition type
*
* Incremparts reference counter for allocated types
*/
void fdisk_ref_parttype(struct fdisk_parttype *t)
{
if (fdisk_parttype_is_allocated(t))
t->refcount++;
}
/**
* fdisk_unref_parttype
* @t: partition pointer
*
* De-incremparts reference counter, on zero the @t is automatically
* deallocated.
*/
void fdisk_unref_parttype(struct fdisk_parttype *t)
{
if (!fdisk_parttype_is_allocated(t))
return;
t->refcount--;
if (t->refcount <= 0) {
DBG(PARTTYPE, ul_debugobj(t, "free"));
free(t->typestr);
free(t->name);
free(t);
}
}
/**
* fdisk_parttype_set_name:
* @t: partition type
* @str: type name
*
* Sets type name to allocated partition type, for static types
* it returns -EINVAL.
*
* Return: 0 on success, <0 on error
*/
int fdisk_parttype_set_name(struct fdisk_parttype *t, const char *str)
{
char *p = NULL;
if (!t || !fdisk_parttype_is_allocated(t))
return -EINVAL;
if (str) {
p = strdup(str);
if (!p)
return -ENOMEM;
}
free(t->name);
t->name = p;
return 0;
}
/**
* fdisk_parttype_set_typestr:
* @t: partition type
* @str: type identificator (e.g. GUID for GPT)
*
* Sets type string to allocated partition type, for static types
* it returns -EINVAL. Don't use this function for MBR, see
* fdisk_parttype_set_code().
*
* Return: 0 on success, <0 on error
*/
int fdisk_parttype_set_typestr(struct fdisk_parttype *t, const char *str)
{
char *p = NULL;
if (!t || !fdisk_parttype_is_allocated(t))
return -EINVAL;
if (str) {
p = strdup(str);
if (!p)
return -ENOMEM;
}
free(t->typestr);
t->typestr = p;
return 0;
}
/**
* fdisk_parttype_set_code:
* @t: partition type
* @int: type identificator (e.g. MBR type codes)
*
* Sets type code to allocated partition type, for static types it returns
* -EINVAL. Don't use this function for GPT, see fdisk_parttype_set_typestr().
*
* Return: 0 on success, <0 on error
*/
int fdisk_parttype_set_code(struct fdisk_parttype *t, int code)
{
if (!t || !fdisk_parttype_is_allocated(t))
return -EINVAL;
t->code = code;
return 0;
}
/**
* fdisk_label_get_nparttypes:
* @lb: label
@ -26,7 +151,7 @@ size_t fdisk_label_get_nparttypes(const struct fdisk_label *lb)
*
* Returns: return parttype
*/
const struct fdisk_parttype *fdisk_label_get_parttype(const struct fdisk_label *lb, size_t n)
struct fdisk_parttype *fdisk_label_get_parttype(const struct fdisk_label *lb, size_t n)
{
if (!lb || n >= lb->nparttypes)
return NULL;
@ -55,7 +180,8 @@ int fdisk_label_has_code_parttypes(const struct fdisk_label *lb)
* @lb: label
* @code: code to search for
*
* Search in lable-specific table of supported partition types by code.
* Search for partition type in label-specific table. The result
* is pointer to static array of label types.
*
* Returns: partition type or NULL upon failure or invalid @code.
*/
@ -73,7 +199,6 @@ struct fdisk_parttype *fdisk_label_get_parttype_from_code(
for (i = 0; i < lb->nparttypes; i++)
if (lb->parttypes[i].code == code)
return &lb->parttypes[i];
return NULL;
}
@ -82,7 +207,8 @@ struct fdisk_parttype *fdisk_label_get_parttype_from_code(
* @lb: label
* @str: string to search for
*
* Search in lable-specific table of supported partition types by typestr.
* Search for partition type in label-specific table. The result
* is pointer to static array of label types.
*
* Returns: partition type or NULL upon failure or invalid @str.
*/
@ -105,35 +231,12 @@ struct fdisk_parttype *fdisk_label_get_parttype_from_string(
return NULL;
}
static struct fdisk_parttype *new_parttype(unsigned int code,
const char *typestr,
const char *name)
{
struct fdisk_parttype *t= calloc(1, sizeof(*t));
if (!t)
return NULL;
if (typestr) {
t->typestr = strdup(typestr);
if (!t->typestr) {
free(t);
return NULL;
}
}
t->name = name;
t->code = code;
t->flags |= FDISK_PARTTYPE_ALLOCATED;
DBG(PARTTYPE, ul_debugobj(t, "allocated new %s type", name));
return t;
}
/**
* fdisk_new_unknown_parttype:
* @code: type as number
* @typestr: type as string
* Allocates new 'unknown' partition type. Use fdisk_free_parttype() to
* Allocates new 'unknown' partition type. Use fdisk_unref_parttype() to
* deallocate.
*
* Returns: newly allocated partition type, or NULL upon failure.
@ -141,11 +244,16 @@ static struct fdisk_parttype *new_parttype(unsigned int code,
struct fdisk_parttype *fdisk_new_unknown_parttype(unsigned int code,
const char *typestr)
{
struct fdisk_parttype *t = new_parttype(code, typestr, _("unknown"));
struct fdisk_parttype *t = fdisk_new_parttype();
if (!t)
return NULL;
fdisk_parttype_set_name(t, _("unknown"));
fdisk_parttype_set_code(t, code);
fdisk_parttype_set_typestr(t, typestr);
t->flags |= FDISK_PARTTYPE_UNKNOWN;
return t;
}
@ -153,13 +261,22 @@ struct fdisk_parttype *fdisk_new_unknown_parttype(unsigned int code,
* fdisk_copy_parttype:
* @type: type to copy
*
* Use fdisk_free_parttype() to deallocate.
* Use fdisk_unref_parttype() to deallocate.
*
* Returns: newly allocated partition type, or NULL upon failure.
*/
struct fdisk_parttype *fdisk_copy_parttype(const struct fdisk_parttype *type)
{
return new_parttype(type->code, type->typestr, type->name);
struct fdisk_parttype *t = fdisk_new_parttype();
if (!t)
return NULL;
fdisk_parttype_set_name(t, type->name);
fdisk_parttype_set_code(t, type->code);
fdisk_parttype_set_typestr(t, type->typestr);
return t;
}
/**
@ -167,9 +284,12 @@ struct fdisk_parttype *fdisk_copy_parttype(const struct fdisk_parttype *type)
* @lb: label
* @str: string to parse from
*
* Returns: pointer to static table of the partition types, or newly allocated
* partition type for unknown types. It's safe to call fdisk_free_parttype()
* for all results.
* Parses partition type from @str according to the label. Thefunction returns
* a pointer to static table of the partition types, or newly allocated
* partition type for unknown types (see fdisk_parttype_is_unknown(). It's
* safe to call fdisk_unref_parttype() for all results.
*
* Returns: pointer to type or NULL on error.
*/
struct fdisk_parttype *fdisk_label_parse_parttype(
const struct fdisk_label *lb,
@ -186,7 +306,6 @@ struct fdisk_parttype *fdisk_label_parse_parttype(
DBG(LABEL, ul_debugobj((void *) lb, "parsing '%s' (%s) partition type",
str, lb->name));
types = lb->parttypes;
if (types[0].typestr == NULL && isxdigit(*str)) {
@ -226,32 +345,35 @@ done:
}
/**
* fdisk_free_parttype:
* @t: new type
* fdisk_parttype_get_string:
* @t: type
*
* Free the @type.
* Returns: partition type string (e.g. GUID for GPT)
*/
void fdisk_free_parttype(struct fdisk_parttype *t)
{
if (t && (t->flags & FDISK_PARTTYPE_ALLOCATED)) {
DBG(PARTTYPE, ul_debugobj(t, "free"));
free(t->typestr);
free(t);
}
}
const char *fdisk_parttype_get_string(const struct fdisk_parttype *t)
{
assert(t);
return t->typestr && *t->typestr ? t->typestr : NULL;
}
/**
* fdisk_parttype_get_code:
* @t: type
*
* Returns: partition type code (e.g. for MBR)
*/
unsigned int fdisk_parttype_get_code(const struct fdisk_parttype *t)
{
assert(t);
return t->code;
}
/**
* fdisk_parttype_get_name:
* @t: type
*
* Returns: partition type human readable name
*/
const char *fdisk_parttype_get_name(const struct fdisk_parttype *t)
{
assert(t);

View File

@ -668,7 +668,7 @@ static int parse_script_line(struct fdisk_script *dp, char *s)
if (!pa->type || fdisk_parttype_is_unknown(pa->type)) {
rc = -EINVAL;
fdisk_free_parttype(pa->type);
fdisk_unref_parttype(pa->type);
pa->type = NULL;
break;
}
@ -810,7 +810,7 @@ static int parse_commas_line(struct fdisk_script *dp, char *s)
if (!pa->type || fdisk_parttype_is_unknown(pa->type)) {
rc = -EINVAL;
fdisk_free_parttype(pa->type);
fdisk_unref_parttype(pa->type);
pa->type = NULL;
break;
}