Constructor for a packagetarget struct As many of you know goto is usually signs of code smell. However I thought this could be an appropriate case, and would like confirmation or criticism.

Unnecessary section such as the called functions were removed. Every non-standard function returns an int as status, 0 is "OK"; except linkedlist_open() which returns a pointer which could be NULL if the system runs out of memory.

packagetarget_close() does implement the necessary NULL checks. 

packagetarget *packagetarget_open()
{
    packagetarget *target = (packagetarget*) malloc(sizeof(packagetarget));

    if (!target) return NULL;

    if (packagetarget_setname(target, ""))
        goto disposer;
    if (packagetarget_setsys(target, PACKAGETARGET_SYS))
        goto disposer;
    if (packagetarget_setarch(target, PACKAGETARGET_ARCH))
        goto disposer;
    if (packagetarget_setmin(target, PACKAGETARGET_MIN))
        goto disposer;
    if (packagetarget_setver(target, PACKAGETARGET_VER))
        goto disposer;
    if (packagetarget_setmax(target, PACKAGETARGET_MAX))
        goto disposer;

    linkedlist *comp = linkedlist_open();

    if (!comp) goto disposer;

    target-&gt;comp = comp;

    return target;   

    disposer:
        packagetarget_close(target);
        return NULL;
}



Each setter function follows a simple pattern. Since each setter is identical, I will only put the code for packagetarget_setname.

int packagetarget_setname(packagetarget *target, char *name)
{
    if (!target) return 1;

    if (!name) return 2;

    target-&gt;name = realloc(target-&gt;name, strlen(name) * sizeof(char));

    if (!target-&gt;name) return 3;

    strcpy(target-&gt;name, name);

    return 0;
}


Here is the packagetarget_close function:

void packagetarget_close(packagetarget *target)
{
    if (!target) return;

    if (target-&gt;name) free(target-&gt;name);
    if (target-&gt;sys) free(target-&gt;sys);
    if (target-&gt;arch) free(target-&gt;arch);
    if (target-&gt;min) free(target-&gt;min);
    if (target-&gt;ver) free(target-&gt;ver);
    if (target-&gt;min) free(target-&gt;min);
    if (target-&gt;comp) linkedlist_close(target-&gt;comp);

    free(target);

    return;
}


linkedlist_open is a similar function to the packagetarget_open.

linkedlist *linkedlist_open()
{
    linkedlist *list = (linkedlist*) malloc(sizeof(linkedlist));

    if (!list) return NULL;

    list-&gt;head = NULL;
    list-&gt;length = 0;
    list-&gt;remhook = NULL;

    return list;
}


The one thing most of these functions is they may fail when the system runs out of memory. So I have implemented checks for each step.
packagetarget_close()

First of all, you have a copy-and-paste error in packagetarget_close(), where you attempt to free target-&gt;min twice, but not target-&gt;max.

Next, note that most of the if statements are superfluous.  As per the standard behaviour for free(),


  If ptr is a null pointer, the function does nothing.


packagetarget_open()

You have undefined behaviour due to the way your error-handling works.  The chunk of memory returned by malloc() contains arbitrary junk.  If packagetarget *target = (packagetarget*) malloc(sizeof(packagetarget)) succeeds, but one of the setters fails, then you would call packagetarget_close(), which would then interpret that arbitrary junk as pointers to memory to be freed.  A good way to fix that is to zero the memory before calling any of the setters.  You can either use calloc() instead of malloc(), or memset(), or a struct initializer.

Avoiding malloc()

In C, I prefer the init-cleanup idiom over new-destroy (which you call open-close).  In the init-cleanup idiom, the caller is responsible for providing the chunk of memory to be initialized, which gives the caller the option of providing either stack-based or heap-based memory.

Avoiding goto

While indiscriminate use of goto leads to spaghetti code, there are some circumstances where goto is justifiable, if used in a readily recognizable pattern.

I think that your use of goto isn't horrible, but personally I would prefer to write the if statements as a chain of &amp;&amp; expressions.

Suggested solution

#include &lt;stdlib.h&gt;
#include &lt;string.h&gt;

typedef struct packagetarget {
    char *name;
    char *sys;
    char *arch;
    char *min;
    char *ver;
    char *max;
    linkedlist comp;
} packagetarget;

int packagetarget_setname(packagetarget *target, const char *name) {
    if (!target) return 1;
    if (!name) return 2;
    target-&gt;name = realloc(target-&gt;name, strlen(name) * sizeof(char));
    if (!target-&gt;name) return 3;
    strcpy(target-&gt;name, name);
    return 0;
}

int packagetarget_setsys(packagetarget *target, const char *sys) {
    …
}

int packagetarget_setarch(packagetarget *target, const char *arch) {
    …
}

int packagetarget_setmin(packagetarget *target, const char *min) {
    …
}

int packagetarget_setver(packagetarget *target, const char *ver) {
    …
}

int packagetarget_setmax(packagetarget *target, const char *max) {
    …
}

packagetarget *packagetarget_cleanup(packagetarget *target) {
    if (target) {
        free(target-&gt;name);
        free(target-&gt;sys);
        free(target-&gt;arch);
        free(target-&gt;min);
        free(target-&gt;ver);
        free(target-&gt;max);
        linkedlist_cleanup(&amp;target-&gt;comp);
    }
    return target;
}

packagetarget *packagetarget_init(packagetarget *target) {
    static const packagetarget empty = {};
    if (target) {
        *target = empty;
        if (!(0 == packagetarget_setname(target, "") &amp;&amp;
              0 == packagetarget_setsys(target, PACKAGETARGET_SYS) &amp;&amp;
              0 == packagetarget_setarch(target, PACKAGETARGET_ARCH) &amp;&amp;
              0 == packagetarget_setmin(target, PACKAGETARGET_MIN) &amp;&amp;
              0 == packagetarget_setver(target, PACKAGETARGET_VER) &amp;&amp;
              0 == packagetarget_setmax(target, PACKAGETARGET_MAX) &amp;&amp;
              linkedlist_init(&amp;target-&gt;comp))) {
            packagetarget_cleanup(target);
            return NULL;
        }
    }
    return target;
}

int main() {
    packagetarget t;
    if (packagetarget_init(&amp;t)) {
        …
    }
    packagetarget_cleanup(&amp;t);
}