Creating a common interface
You can pass a function that gets the correct object from tagdb.
AKA Service Locator pattern

typedef HashTable* (*ITEM_GETTER)(tagdb*);

HashTable* getTag(tagdb *db)  { return db-&gt;reverse;}
HashTable* getFile(tagdb *db) { return db-&gt;forward;}

GHashTable *tagdb_get_item_files (tagdb *db, int itemId, ITEM_GETTER getter)
{
    return g_hash_table_lookup(getter(db), GINT_TO_POINTER(itemId));
}

void tagdb_remove_item (tagdb *db, int id, ITEM_GETTER getter)
{
    GHashTable *its_files = g_hash_table_lookup(getter(db), GINT_TO_POINTER(id));
    if (its_files == NULL)
    {
        return;
    }

    GHashTableIter it;
    gpointer key, value;
    g_hash_table_iter_init(&amp;it, its_files);
    if (g_hash_table_iter_next(&amp;it, &amp;key, &amp;value))
    {
        tagdb_remove_tag_from_file(db, id, key);
    }
    g_hash_table_remove(getter(db), GINT_TO_POINTER(id));
}


Edit for clarity:

The old functions can now be implanted like this:

GHashTable *tagdb_get_tag_files (tagdb *db, int tag_code)
{
    return tagdb_get_item_files(db, tag_code, getTag);
}

GHashTable *tagdb_get_file_tags (tagdb *db, int file_id)
{
    return return tagdb_get_item_files(db, file_id, getFile);
}

void tagdb_remove_tag (tagdb *db, int id)
{
    tagdb_remove_item(db, id, getTag);
}

void tagdb_remove_file(tagdb *db, int id)
{
    tagdb_remove_item(db, id, getFile);
}