From: Nick Bowler Date: Tue, 15 May 2012 02:15:01 +0000 (-0400) Subject: libuobject: Store hierarchical object names for UObjects. X-Git-Url: http://git.draconx.ca/gitweb/upkg.git/commitdiff_plain/aa72d53735c595550e417882b9aa8d1473b9b57c libuobject: Store hierarchical object names for UObjects. Such names are useful for logging and, in general, displaying object references in a human-readable manner. This is only a partial implementation, as package names are not yet available to the deserialize method. --- diff --git a/src/uobject/uobject.c b/src/uobject/uobject.c index fa93ec0..4778292 100644 --- a/src/uobject/uobject.c +++ b/src/uobject/uobject.c @@ -311,10 +311,47 @@ static int deserialize(UObject *uo) return 0; } +/* + * Get the full hierarchical object name for an export, used for diagnostics. + * Currently, this does not include the package name (which is actually + * required for this to be a "full" name) as it's not yet passed to the + * deserialize method. + * + * Returns a buffer allocated by malloc on success, or NULL on failure. + */ +static char *get_obj_fullname(const struct upkg_export *e) +{ + size_t total_len = 0, len; + char *fullname; + + for (const struct upkg_export *c = e; c; c = c->parent) { + len = strlen(c->name) + 1; + if (total_len > SIZE_MAX - len) + return NULL; + total_len += len; + } + + fullname = malloc(total_len); + if (!fullname) + return NULL; + + for (const struct upkg_export *c = e; c; c = c->parent) { + len = strlen(c->name); + assert(total_len > len); + + total_len -= len + 1; + memcpy(fullname + total_len, c->name, len); + fullname[total_len + len] = c == e ? '\0' : '.'; + } + + return fullname; +} + int u_object_deserialize(GObject *obj, struct upkg *pkg, unsigned long idx) { g_return_val_if_fail(IS_U_OBJECT(obj), -1); UObject *uo = U_OBJECT(obj); + const struct upkg_export *e; struct upkg_file *f; int rc; @@ -327,6 +364,13 @@ int u_object_deserialize(GObject *obj, struct upkg *pkg, unsigned long idx) uo->pkg = pkg; uo->pkg_file = f; + e = upkg_get_export(pkg, idx); + if (!e) + return -1; + uo->pkg_name = get_obj_fullname(e); + if (!uo->pkg_name) + return -1; + rc = U_OBJECT_GET_CLASS(obj)->deserialize(uo); if (rc != 0) { upkg_export_close(f); @@ -371,6 +415,8 @@ static void u_object_finalize(GObject *o) upkg_export_close(uo->pkg_file); } + free(uo->pkg_name); + G_OBJECT_CLASS(u_object_parent_class)->finalize(o); } @@ -427,12 +473,8 @@ void u_vlog_full(GObject *o, GLogLevelFlags level, const char *fmt, va_list ap) UObject *uo = U_OBJECT(o); char *new_fmt = NULL; - if (uo->pkg_file) { - /* XXX: Currently, there's no way to get the full object name - * here because the object path information is discarded - * after opening it. In principle, there's no reason why - * we couldn't keep it around to improve log messages. */ - new_fmt = prepend_fmt(uo->pkg_file->name, fmt); + if (uo->pkg_name) { + new_fmt = prepend_fmt(uo->pkg_name, fmt); if (!new_fmt) { g_log(G_OBJECT_TYPE_NAME(o), level, "%s", uo->pkg_file->name); diff --git a/src/uobject/uobject.h b/src/uobject/uobject.h index e91bf5b..e0b2256 100644 --- a/src/uobject/uobject.h +++ b/src/uobject/uobject.h @@ -43,6 +43,7 @@ struct UObject { struct upkg *pkg; struct upkg_file *pkg_file; + char *pkg_name; }; struct UObjectClass { diff --git a/src/upkg.c b/src/upkg.c index e174c21..5a51c2e 100644 --- a/src/upkg.c +++ b/src/upkg.c @@ -312,8 +312,8 @@ static int object_info(GTypeModule *pkg, unsigned long idx) UObject *obj = g_value_get_object(&val); /* TODO: Display full object names here. */ - if (obj->pkg_file) { - printf(" %s", obj->pkg_file->name); + if (obj->pkg_name) { + printf(" %s", obj->pkg_name); } }