plover/razor.c
author J. Ali Harlow <ali@juiblex.co.uk>
Sat Jul 16 11:07:18 2016 +0100 (2016-07-16)
changeset 61 31fb35727621
parent 59 296eac3183bc
child 62 5c3ef7363959
permissions -rw-r--r--
Support parallel installations. The idea is that for CAD screener, we want
to be able to install this on the same machine as a standard AVOT setup
(most notably for John's laptop). To allow for the possibility of a second
application that might have the same requirements, we add the concept of
vendor-specific distributions. Thus we can have one distribution for CAD
screener and one for The Next Big Thing. It doesn't seem trivial to have
both CAD screener and AVOT under the same vendor tag so we'll have to have
AVOT under "City Occupational" and CAD screener under "City Occupational Ltd"
or some such kludge.

Most of this is done although we are very short of test cases (in particular
we don't test that it's actually possible to install CAD screener in parallel
with AVOT or to update either of them once installed, which is fundamental).

We also have a lot of baggage left over, including an intercept of razor_set.
The problem that this was introduced to debug has been fixed but it looks
like there are a number of memory leaks which it might be useful to help
track down so it has been left in place for now.

There is still a lot of confusion in plover between path-based and URI-based
API. We should review the API, decide what we want and have a general clear up.

There is also confusion as to the purpose of RAZOR_ROOT (and meaning; path or
URI). This is not used at all in librazor (although it is used in razor.exe).
Ideally we shouldn't use it in plover or plover-gtk either although again, we
might want to support it or an equivalent in (some of) the various executables.

Work that would still to nice to do for CAD screener:

- uninstall (ideally as an installed program that hooks into Add/Remove programs
but even re-running the installer would be acceptable).
- xz support (smaller packages).
- repomd.xml and xml:base (would be needed for an Internet installer).
- graphical installer.
ali@0
     1
/*
ali@0
     2
 * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
ali@0
     3
 * Copyright (C) 2008  Red Hat, Inc
ali@24
     4
 * Copyright (C) 2009, 2011, 2012, 2014  J. Ali Harlow <ali@juiblex.co.uk>
ali@0
     5
 *
ali@0
     6
 * This program is free software; you can redistribute it and/or modify
ali@0
     7
 * it under the terms of the GNU General Public License as published by
ali@0
     8
 * the Free Software Foundation; either version 2 of the License, or
ali@0
     9
 * (at your option) any later version.
ali@0
    10
 *
ali@0
    11
 * This program is distributed in the hope that it will be useful,
ali@0
    12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
ali@0
    13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
ali@0
    14
 * GNU General Public License for more details.
ali@0
    15
 *
ali@0
    16
 * You should have received a copy of the GNU General Public License along
ali@0
    17
 * with this program; if not, write to the Free Software Foundation, Inc.,
ali@0
    18
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
ali@0
    19
 */
ali@0
    20
ali@61
    21
#define _GNU_SOURCE
ali@0
    22
#include <stdlib.h>
ali@0
    23
#include <stdio.h>
ali@0
    24
#include <stdarg.h>
ali@0
    25
#include <string.h>
ali@24
    26
#include <errno.h>
ali@0
    27
#include <unistd.h>
ali@0
    28
#include <razor.h>
ali@24
    29
#include <glib.h>
ali@24
    30
#include <gio/gio.h>
ali@0
    31
#include "config.h"
ali@0
    32
#include "plover/plover.h"
ali@24
    33
#include "plover/transaction.h"
ali@44
    34
#include "plover/uri-handler.h"
ali@0
    35
ali@0
    36
static char *rpm_filename(const char *name,const char *version,const char *arch)
ali@0
    37
{
ali@0
    38
    const char *v;
ali@0
    39
    v=strchr(version,':');	      /* Skip epoch */
ali@0
    40
    if (v)
ali@0
    41
	v++;
ali@0
    42
    else
ali@0
    43
	v=version;
ali@24
    44
    return g_strconcat(name,"-",v,".",arch,".rpm",NULL);
ali@0
    45
}
ali@0
    46
ali@19
    47
/*
ali@19
    48
 * Returns 0 on success, -1 on failure and 1 if a RAZOR_INSTALL_ACTION_COMMIT
ali@19
    49
 * is met (in which case the action is consumed).
ali@19
    50
 */
ali@13
    51
int plover_run_transaction(struct razor_transaction *trans,
ali@61
    52
  struct razor_install_iterator *ii,const char *root_uri,
ali@24
    53
  struct razor_set *system,PloverPackageSet *next,PloverRepository *upstream,
ali@24
    54
  struct razor_atomic *atomic,struct razor_relocations *relocations,
ali@24
    55
  enum razor_stage_type stage,GCancellable *cancellable)
ali@0
    56
{
ali@24
    57
    struct razor_package *pkg;
ali@0
    58
    enum razor_install_action action;
ali@0
    59
    struct razor_rpm *rpm;
ali@19
    60
    struct razor_error *error=NULL;
ali@0
    61
    const char *name,*version,*arch;
ali@24
    62
    gchar *t;
ali@19
    63
    int r,count;
ali@24
    64
    GError *tmp_error=NULL;
ali@24
    65
    PloverPackage *package;
ali@44
    66
    plover__uri_handler_init();
ali@61
    67
    if (!*root_uri)
ali@61
    68
	root_uri="file:/";
ali@13
    69
    switch(stage)
ali@13
    70
    {
ali@13
    71
	case RAZOR_STAGE_SCRIPTS_PRE:
ali@13
    72
	    printf("Running pre-transaction scripts\n");
ali@13
    73
	    break;
ali@13
    74
	case RAZOR_STAGE_FILES:
ali@13
    75
	    printf("Running Transaction\n");
ali@13
    76
	    break;
ali@13
    77
	case RAZOR_STAGE_SCRIPTS_POST:
ali@13
    78
	    printf("Running post-transaction scripts\n");
ali@13
    79
	    break;
ali@13
    80
	default:
ali@13
    81
	    /* Keep the compiler happy */
ali@13
    82
	    break;
ali@13
    83
    }
ali@24
    84
    while (razor_install_iterator_next(ii,&pkg,&action,&count))
ali@0
    85
    {
ali@24
    86
	if (g_cancellable_is_cancelled(cancellable))
ali@24
    87
	{
ali@24
    88
	    razor_atomic_abort(atomic,PLOVER_GENERAL_ERROR,
ali@24
    89
	      PLOVER_GENERAL_ERROR_CANCELLED,"Operation was cancelled");
ali@24
    90
	    return -1;
ali@24
    91
	}
ali@0
    92
	if (action==RAZOR_INSTALL_ACTION_REMOVE)
ali@0
    93
	{
ali@24
    94
	    razor_package_get_details(system,pkg,RAZOR_DETAIL_NAME,&name,
ali@0
    95
	      RAZOR_DETAIL_LAST);
ali@13
    96
	    if (stage==RAZOR_STAGE_FILES)
ali@13
    97
		printf("  Removing : %s ",name);
ali@24
    98
	    r=razor_package_remove(system,plover_package_set_get_razor(next),
ali@61
    99
	      atomic,pkg,root_uri,count,stage);
ali@13
   100
	    if (stage==RAZOR_STAGE_FILES)
ali@13
   101
		printf("\n");
ali@0
   102
	}
ali@19
   103
	else if (action==RAZOR_INSTALL_ACTION_ADD)
ali@0
   104
	{
ali@24
   105
	    package=plover_package_set_lookup(next,pkg);
ali@24
   106
	    rpm=plover_repository_open_rpm(upstream,package,&tmp_error);
ali@0
   107
	    if (!rpm)
ali@19
   108
	    {
ali@24
   109
		plover_propagate_g_error(&error,tmp_error);
ali@24
   110
		razor_atomic_propagate_error(atomic,error,NULL);
ali@0
   111
		return -1;
ali@19
   112
	    }
ali@13
   113
	    if (stage==RAZOR_STAGE_FILES)
ali@24
   114
		printf("  Installing : %s ",plover_package_get_name(package));
ali@0
   115
	    if (relocations)
ali@0
   116
		razor_rpm_set_relocations(rpm,relocations);
ali@24
   117
	    razor_transaction_fixup_package(trans,pkg,rpm);
ali@61
   118
	    r=razor_rpm_install(rpm,atomic,root_uri,1,stage);
ali@0
   119
	    razor_rpm_close(rpm);
ali@13
   120
	    if (stage==RAZOR_STAGE_FILES)
ali@13
   121
		printf("\n");
ali@0
   122
	}
ali@61
   123
	else if (action==RAZOR_INSTALL_ACTION_COMMIT)
ali@19
   124
	    return 1;
ali@19
   125
	else
ali@19
   126
	    r=0;
ali@13
   127
	if (razor_atomic_in_error_state(atomic))
ali@13
   128
	    return -1;
ali@19
   129
	else if (r)
ali@19
   130
	{
ali@29
   131
	    if (action==RAZOR_INSTALL_ACTION_REMOVE)
ali@29
   132
	    {
ali@29
   133
		razor_package_get_details(system,pkg,RAZOR_DETAIL_NAME,&name,
ali@29
   134
		  RAZOR_DETAIL_VERSION,&version,RAZOR_DETAIL_ARCH,&arch,
ali@29
   135
		  RAZOR_DETAIL_LAST);
ali@29
   136
	    }
ali@29
   137
	    else
ali@29
   138
	    {
ali@29
   139
		package=plover_package_set_lookup(next,pkg);
ali@29
   140
		name=plover_package_get_name(package);
ali@29
   141
		version=plover_package_get_version(package);
ali@29
   142
		arch=plover_package_get_arch(package);
ali@29
   143
	    }
ali@19
   144
	    /*
ali@19
   145
	     * If a pre or preun script fails, then we should
ali@19
   146
	     * treat that as a fatal error. post and postun
ali@19
   147
	     * script failures are treated as warnings. Be
ali@19
   148
	     * nice and tell the user _which_ script failed.
ali@19
   149
	     */
ali@19
   150
	    if (stage==RAZOR_STAGE_SCRIPTS_PRE)
ali@22
   151
	    {
ali@24
   152
		t=g_strconcat(action==RAZOR_INSTALL_ACTION_ADD?
ali@24
   153
		  "%pre":"%preun","(",name,"-",version,".",arch,
ali@24
   154
		  ") scriptlet failed",NULL);
ali@24
   155
		fprintf(stderr,"error: %s, exit status %d\n",t,r);
ali@24
   156
		razor_atomic_abort(atomic,PLOVER_SCRIPTLET_ERROR,r,t);
ali@24
   157
		g_free(t);
ali@19
   158
		return -1;
ali@22
   159
	    }
ali@22
   160
	    else
ali@22
   161
		fprintf(stderr,
ali@22
   162
		  "warning: %s(%s-%s.%s) scriptlet failed, exit status %d\n",
ali@22
   163
		  action==RAZOR_INSTALL_ACTION_ADD?"%post":"%postun",
ali@22
   164
		  name,version,arch,r);
ali@19
   165
	}
ali@0
   166
    }
ali@13
   167
    return 0;
ali@13
   168
}
ali@13
   169
ali@43
   170
gboolean plover_install_uri(const char *base_uri,const char *prefix,char **pkgs,
ali@43
   171
  GError **error)
ali@43
   172
{
ali@43
   173
    gboolean retval;
ali@43
   174
    PloverTransaction *transaction;
ali@43
   175
    transaction=plover_transaction_new_install_uri(base_uri,prefix,pkgs,error);
ali@43
   176
    if (!transaction)
ali@43
   177
	return FALSE;
ali@43
   178
    retval=plover_transaction_commit(transaction,NULL,error);
ali@43
   179
    g_object_unref(transaction);
ali@43
   180
    return retval;
ali@43
   181
}
ali@43
   182
ali@24
   183
gboolean plover_install(const char *base,const char *prefix,char **pkgs,
ali@24
   184
  GError **error)
ali@13
   185
{
ali@24
   186
    gboolean retval;
ali@43
   187
    GFile *file;
ali@43
   188
    gchar *base_uri;
ali@43
   189
    file=g_file_new_for_path(base);
ali@43
   190
    base_uri=g_file_get_uri(file);
ali@43
   191
    g_object_unref(file);
ali@43
   192
    retval=plover_install_uri(base_uri,prefix,pkgs,error);
ali@43
   193
    g_free(base_uri);
ali@13
   194
    return retval;
ali@0
   195
}
ali@0
   196
ali@59
   197
gboolean plover_update_uri(const char *base_uri,const char *prefix,char **pkgs,
ali@59
   198
  GError **error)
ali@59
   199
{
ali@59
   200
    gboolean retval;
ali@59
   201
    PloverTransaction *transaction;
ali@61
   202
    transaction=plover_transaction_new_update_uri(base_uri,prefix,pkgs,error);
ali@59
   203
    if (!transaction)
ali@61
   204
	return FALSE;
ali@61
   205
    retval=plover_transaction_commit(transaction,NULL,error);
ali@61
   206
    g_object_unref(transaction);
ali@59
   207
    return retval;
ali@59
   208
}
ali@59
   209
ali@24
   210
gboolean plover_update(const char *base,const char *prefix,char **pkgs,
ali@24
   211
  GError **error)
ali@0
   212
{
ali@24
   213
    gboolean retval;
ali@24
   214
    PloverTransaction *transaction;
ali@61
   215
    transaction=plover_transaction_new_update(base,prefix,pkgs,error);
ali@24
   216
    if (!transaction)
ali@61
   217
	return FALSE;
ali@61
   218
    retval=plover_transaction_commit(transaction,NULL,error);
ali@61
   219
    g_object_unref(transaction);
ali@0
   220
    return retval;
ali@0
   221
}
ali@0
   222
ali@24
   223
gboolean plover_remove(char **pkgs,GError **error)
ali@0
   224
{
ali@24
   225
    gboolean retval;
ali@24
   226
    GError *tmp_error=NULL;
ali@24
   227
    PloverTransaction *transaction;
ali@24
   228
    transaction=plover_transaction_new_remove(pkgs,&tmp_error);
ali@24
   229
    if (!transaction)
ali@0
   230
    {
ali@24
   231
	retval=g_error_matches(tmp_error,PLOVER_POSIX_ERROR,ENOENT);
ali@24
   232
	if (retval)
ali@24
   233
	{
ali@24
   234
	    g_error_free(tmp_error);
ali@24
   235
	    if (pkgs)
ali@24
   236
	    {
ali@24
   237
		g_set_error(error,PLOVER_GENERAL_ERROR,
ali@24
   238
		  PLOVER_GENERAL_ERROR_NO_SUCH_PACKAGE,"%s: %s",pkgs[0],
ali@24
   239
		  "Package not found");
ali@24
   240
		retval=FALSE;
ali@24
   241
	    }
ali@24
   242
	}
ali@19
   243
	else
ali@24
   244
	    g_propagate_error(error,tmp_error);
ali@13
   245
    }
ali@13
   246
    else
ali@19
   247
    {
ali@24
   248
	retval=plover_transaction_commit(transaction,NULL,error);
ali@24
   249
	g_object_unref(transaction);
ali@19
   250
    }
ali@13
   251
    return retval;
ali@13
   252
}
ali@13
   253
ali@13
   254
/*
ali@61
   255
 * Returns:
ali@61
   256
 *	 0 if there are any installed files that don't match prefix, or
ali@61
   257
 *	-1 if there are no installed files at all, or
ali@61
   258
 * 	 1 if there are installed files and they all match prefix.
ali@13
   259
 */
ali@13
   260
ali@13
   261
int plover_installed_files_match_prefix(const char *prefix)
ali@13
   262
{
ali@61
   263
    int len,matches=-1;
ali@13
   264
    const char *name;
ali@42
   265
    const char *install_root;
ali@13
   266
    struct razor_set *set;
ali@13
   267
    struct razor_package *package;
ali@13
   268
    struct razor_package_iterator *pi;
ali@13
   269
    struct razor_file_iterator *fi;
ali@44
   270
    plover__uri_handler_init();
ali@13
   271
    len=strlen(prefix);
ali@13
   272
    while(len && prefix[len-1]=='/')
ali@13
   273
	len--;
ali@42
   274
    install_root=g_getenv("RAZOR_ROOT");
ali@13
   275
    if (!install_root)
ali@42
   276
	install_root="file:///";
ali@42
   277
    set=razor_root_open_read_only(install_root,NULL);
ali@13
   278
    if (set)
ali@13
   279
    {
ali@13
   280
	pi=razor_package_iterator_create(set);
ali@13
   281
	while (matches &&
ali@13
   282
	  razor_package_iterator_next(pi,&package,RAZOR_DETAIL_LAST))
ali@13
   283
	{
ali@13
   284
	    fi=razor_file_iterator_create(set,package,0);
ali@13
   285
	    while (matches && razor_file_iterator_next(fi,&name))
ali@13
   286
	    {
ali@13
   287
		if (strncmp(name,prefix,len) ||
ali@13
   288
		  name[len]!='\0' && name[len]!='/')
ali@13
   289
		    matches=0;
ali@61
   290
		else
ali@61
   291
		    matches=1;
ali@13
   292
	    }
ali@13
   293
	    razor_file_iterator_destroy(fi);
ali@13
   294
	}
ali@13
   295
	razor_package_iterator_destroy(pi);
ali@13
   296
	razor_set_unref(set);
ali@0
   297
    }
ali@13
   298
    return matches;
ali@0
   299
}
ali@61
   300
ali@61
   301
#include <fcntl.h>
ali@61
   302
#include <dlfcn.h>
ali@61
   303
ali@61
   304
struct razor_set_counter
ali@61
   305
{
ali@61
   306
    struct razor_set *set;
ali@61
   307
    int count;
ali@61
   308
};
ali@61
   309
ali@61
   310
static GList *counters;
ali@61
   311
ali@61
   312
static struct razor_set_counter *get_razor_set_counter(struct razor_set *set)
ali@61
   313
{
ali@61
   314
    GList *lnk;
ali@61
   315
    struct razor_set_counter *counter;
ali@61
   316
    for(lnk=counters;lnk;lnk=lnk->next)
ali@61
   317
    {
ali@61
   318
	counter=lnk->data;
ali@61
   319
	if (counter->set==set)
ali@61
   320
	    return counter;
ali@61
   321
    }
ali@61
   322
    counter=g_new(struct razor_set_counter,1);
ali@61
   323
    counter->set=set;
ali@61
   324
    counter->count=0;
ali@61
   325
    counters=g_list_prepend(counters,counter);
ali@61
   326
    return counter;
ali@61
   327
}
ali@61
   328
ali@61
   329
static void dump_razor_set_ref(struct razor_set *set)
ali@61
   330
{
ali@61
   331
    FILE *fp;
ali@61
   332
    gchar *filename;
ali@61
   333
    void *bt[16];
ali@61
   334
    size_t len;
ali@61
   335
    struct razor_set_counter *counter;
ali@61
   336
    filename=g_strdup_printf("razor-set-%p",set);
ali@61
   337
    fp=fopen(filename,"a");
ali@61
   338
    g_free(filename);
ali@61
   339
    counter=get_razor_set_counter(set);
ali@61
   340
    counter->count++;
ali@61
   341
    fprintf(fp,"Ref %p (%d refs)\n",set,counter->count);
ali@61
   342
    fflush(fp);
ali@61
   343
    len=backtrace(bt,G_N_ELEMENTS(bt));
ali@61
   344
    backtrace_symbols_fd(bt,len,fileno(fp));
ali@61
   345
    fprintf(fp,"\n");
ali@61
   346
    fclose(fp);
ali@61
   347
}
ali@61
   348
ali@61
   349
static void dump_razor_set_unref(struct razor_set *set)
ali@61
   350
{
ali@61
   351
    FILE *fp;
ali@61
   352
    gchar *filename;
ali@61
   353
    void *bt[16];
ali@61
   354
    size_t len;
ali@61
   355
    struct razor_set_counter *counter;
ali@61
   356
    filename=g_strdup_printf("razor-set-%p",set);
ali@61
   357
    fp=fopen(filename,"a");
ali@61
   358
    g_free(filename);
ali@61
   359
    counter=get_razor_set_counter(set);
ali@61
   360
    --counter->count;
ali@61
   361
    fprintf(fp,"Unref %p (%d refs)\n",set,counter->count);
ali@61
   362
    fflush(fp);
ali@61
   363
    len=backtrace(bt,G_N_ELEMENTS(bt));
ali@61
   364
    backtrace_symbols_fd(bt,len,fileno(fp));
ali@61
   365
    fprintf(fp,"\n");
ali@61
   366
    fclose(fp);
ali@61
   367
}
ali@61
   368
ali@61
   369
static void dump_razor_set_peek(struct razor_set *set)
ali@61
   370
{
ali@61
   371
    FILE *fp;
ali@61
   372
    gchar *filename;
ali@61
   373
    void *bt[16];
ali@61
   374
    size_t len;
ali@61
   375
    struct razor_set_counter *counter;
ali@61
   376
    filename=g_strdup_printf("razor-set-%p",set);
ali@61
   377
    fp=fopen(filename,"a");
ali@61
   378
    g_free(filename);
ali@61
   379
    counter=get_razor_set_counter(set);
ali@61
   380
    fprintf(fp,"Peek %p (%d refs)\n",set,counter->count);
ali@61
   381
    fflush(fp);
ali@61
   382
    len=backtrace(bt,G_N_ELEMENTS(bt));
ali@61
   383
    backtrace_symbols_fd(bt,len,fileno(fp));
ali@61
   384
    fprintf(fp,"\n");
ali@61
   385
    fclose(fp);
ali@61
   386
}
ali@61
   387
ali@61
   388
struct razor_set *razor_set_create_without_root(void)
ali@61
   389
{
ali@61
   390
    static struct razor_set *(*next)(void);
ali@61
   391
    struct razor_set *set;
ali@61
   392
    if (!next)
ali@61
   393
	next=dlsym(RTLD_NEXT,"razor_set_create_without_root");
ali@61
   394
    set=(*next)();
ali@61
   395
    dump_razor_set_ref(set);
ali@61
   396
    return set;
ali@61
   397
}
ali@61
   398
ali@61
   399
struct razor_set *razor_set_create(void)
ali@61
   400
{
ali@61
   401
    static struct razor_set *(*next)(void);
ali@61
   402
    struct razor_set *set;
ali@61
   403
    if (!next)
ali@61
   404
	next=dlsym(RTLD_NEXT,"razor_set_create");
ali@61
   405
    set=(*next)();
ali@61
   406
    dump_razor_set_ref(set);
ali@61
   407
    return set;
ali@61
   408
}
ali@61
   409
ali@61
   410
struct razor_set *razor_set_open(const char *uri,enum razor_set_flags flags,
ali@61
   411
  struct razor_error **error)
ali@61
   412
{
ali@61
   413
    static struct razor_set *(*next)(const char *uri,enum razor_set_flags flags,
ali@61
   414
      struct razor_error **error);
ali@61
   415
    struct razor_set *set;
ali@61
   416
    if (!next)
ali@61
   417
	next=dlsym(RTLD_NEXT,"razor_set_open");
ali@61
   418
    set=(*next)(uri,flags,error);
ali@61
   419
    dump_razor_set_ref(set);
ali@61
   420
    return set;
ali@61
   421
}
ali@61
   422
ali@61
   423
void razor_set_unref(struct razor_set *set)
ali@61
   424
{
ali@61
   425
    static void (*next)(struct razor_set *set);
ali@61
   426
    if (!next)
ali@61
   427
	next=dlsym(RTLD_NEXT,"razor_set_unref");
ali@61
   428
    if (!set)
ali@61
   429
	abort();
ali@61
   430
    dump_razor_set_unref(set);
ali@61
   431
    (*next)(set);
ali@61
   432
}
ali@61
   433
ali@61
   434
struct razor_set *razor_set_ref(struct razor_set *set)
ali@61
   435
{
ali@61
   436
    static struct razor_set *(*next)(struct razor_set *set);
ali@61
   437
    if (!next)
ali@61
   438
	next=dlsym(RTLD_NEXT,"razor_set_ref");
ali@61
   439
    (*next)(set);
ali@61
   440
    dump_razor_set_ref(set);
ali@61
   441
    return set;
ali@61
   442
}
ali@61
   443
ali@61
   444
struct razor_set *
ali@61
   445
  razor_install_iterator_commit_set(struct razor_install_iterator *ii)
ali@61
   446
{
ali@61
   447
    static struct razor_set *(*next)(struct razor_install_iterator *ii);
ali@61
   448
    struct razor_set *set;
ali@61
   449
    if (!next)
ali@61
   450
	next=dlsym(RTLD_NEXT,"razor_install_iterator_commit_set");
ali@61
   451
    set=(*next)(ii);
ali@61
   452
    dump_razor_set_ref(set);
ali@61
   453
    return set;
ali@61
   454
}
ali@61
   455
ali@61
   456
struct razor_set *razor_transaction_commit(struct razor_transaction *trans)
ali@61
   457
{
ali@61
   458
    static struct razor_set *(*next)(struct razor_transaction *trans);
ali@61
   459
    struct razor_set *set;
ali@61
   460
    if (!next)
ali@61
   461
	next=dlsym(RTLD_NEXT,"razor_transaction_commit");
ali@61
   462
    set=(*next)(trans);
ali@61
   463
    dump_razor_set_ref(set);
ali@61
   464
    return set;
ali@61
   465
}
ali@61
   466
ali@61
   467
struct razor_set *razor_importer_finish(struct razor_importer *importer)
ali@61
   468
{
ali@61
   469
    static struct razor_set *(*next)(struct razor_importer *importer);
ali@61
   470
    struct razor_set *set;
ali@61
   471
    if (!next)
ali@61
   472
	next=dlsym(RTLD_NEXT,"razor_importer_finish");
ali@61
   473
    set=(*next)(importer);
ali@61
   474
    dump_razor_set_ref(set);
ali@61
   475
    return set;
ali@61
   476
}
ali@61
   477
ali@61
   478
struct razor_set *razor_root_open_read_only(const char *root_uri,
ali@61
   479
  struct razor_error **error)
ali@61
   480
{
ali@61
   481
    static struct razor_set *(*next)(const char *root_uri,
ali@61
   482
      struct razor_error **error);
ali@61
   483
    struct razor_set *set;
ali@61
   484
    if (!next)
ali@61
   485
	next=dlsym(RTLD_NEXT,"razor_root_open_read_only");
ali@61
   486
    set=(*next)(root_uri,error);
ali@61
   487
    dump_razor_set_ref(set);
ali@61
   488
    return set;
ali@61
   489
}
ali@61
   490
ali@61
   491
struct razor_set *razor_root_get_system_set(struct razor_root *root)
ali@61
   492
{
ali@61
   493
    static struct razor_set *(*next)(struct razor_root *root);
ali@61
   494
    struct razor_set *set;
ali@61
   495
    if (!next)
ali@61
   496
	next=dlsym(RTLD_NEXT,"razor_root_get_system_set");
ali@61
   497
    set=(*next)(root);
ali@61
   498
    dump_razor_set_peek(set);
ali@61
   499
    return set;
ali@61
   500
}