From: Karel Zak Date: Wed, 15 Oct 2014 12:10:25 +0000 (+0200) Subject: libfdisk: cleanup parttype API X-Git-Tag: v2.26-rc1~302 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=dfc6db2a3558d2a2cedbeb381e2cc8feda41a214;p=thirdparty%2Futil-linux.git libfdisk: cleanup parttype API * add reference counting * add functions to set allocated types Signed-off-by: Karel Zak --- diff --git a/disk-utils/sfdisk.c b/disk-utils/sfdisk.c index 821b5ed15d..ad0e17e212 100644 --- a/disk-utils/sfdisk.c +++ b/disk-utils/sfdisk.c @@ -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); } diff --git a/libfdisk/src/dos.c b/libfdisk/src/dos.c index bcfacfc7d4..5f928a7adb 100644 --- a/libfdisk/src/dos.c +++ b/libfdisk/src/dos.c @@ -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); } diff --git a/libfdisk/src/fdiskP.h b/libfdisk/src/fdiskP.h index 7915e5cf02..b9955fafb1 100644 --- a/libfdisk/src/fdiskP.h +++ b/libfdisk/src/fdiskP.h @@ -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 { diff --git a/libfdisk/src/gpt.c b/libfdisk/src/gpt.c index ec6dbd6644..422c461a3c 100644 --- a/libfdisk/src/gpt.c +++ b/libfdisk/src/gpt.c @@ -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; diff --git a/libfdisk/src/libfdisk.h b/libfdisk/src/libfdisk.h index 92f6416785..cb40ecf01e 100644 --- a/libfdisk/src/libfdisk.h +++ b/libfdisk/src/libfdisk.h @@ -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); diff --git a/libfdisk/src/partition.c b/libfdisk/src/partition.c index d63dae03e6..ee33d7bdf1 100644 --- a/libfdisk/src/partition.c +++ b/libfdisk/src/partition.c @@ -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; } diff --git a/libfdisk/src/parttype.c b/libfdisk/src/parttype.c index 8c4ac61ef1..2bcf69d6f5 100644 --- a/libfdisk/src/parttype.c +++ b/libfdisk/src/parttype.c @@ -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); diff --git a/libfdisk/src/script.c b/libfdisk/src/script.c index 97b5e4d26a..144f421382 100644 --- a/libfdisk/src/script.c +++ b/libfdisk/src/script.c @@ -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; }