plover/razor.c
author J. Ali Harlow <ali@juiblex.co.uk>
Thu Jun 16 18:00:21 2016 +0100 (2016-06-16)
changeset 43 6b3034a884dc
parent 42 419a02fa70db
child 44 43ffed8669ce
permissions -rw-r--r--
Add test for non-file URI support
     1 /*
     2  * Copyright (C) 2008  Kristian Høgsberg <krh@redhat.com>
     3  * Copyright (C) 2008  Red Hat, Inc
     4  * Copyright (C) 2009, 2011, 2012, 2014  J. Ali Harlow <ali@juiblex.co.uk>
     5  *
     6  * This program is free software; you can redistribute it and/or modify
     7  * it under the terms of the GNU General Public License as published by
     8  * the Free Software Foundation; either version 2 of the License, or
     9  * (at your option) any later version.
    10  *
    11  * This program is distributed in the hope that it will be useful,
    12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    14  * GNU General Public License for more details.
    15  *
    16  * You should have received a copy of the GNU General Public License along
    17  * with this program; if not, write to the Free Software Foundation, Inc.,
    18  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
    19  */
    20 
    21 #include <stdlib.h>
    22 #include <stdio.h>
    23 #include <stdarg.h>
    24 #include <string.h>
    25 #include <errno.h>
    26 #include <unistd.h>
    27 #include <razor.h>
    28 #include <glib.h>
    29 #include <gio/gio.h>
    30 #include "config.h"
    31 #include "plover/plover.h"
    32 #include "plover/transaction.h"
    33 
    34 static char *rpm_filename(const char *name,const char *version,const char *arch)
    35 {
    36     const char *v;
    37     v=strchr(version,':');	      /* Skip epoch */
    38     if (v)
    39 	v++;
    40     else
    41 	v=version;
    42     return g_strconcat(name,"-",v,".",arch,".rpm",NULL);
    43 }
    44 
    45 /*
    46  * Returns 0 on success, -1 on failure and 1 if a RAZOR_INSTALL_ACTION_COMMIT
    47  * is met (in which case the action is consumed).
    48  */
    49 int plover_run_transaction(struct razor_transaction *trans,
    50   struct razor_install_iterator *ii,const char *install_root,
    51   struct razor_set *system,PloverPackageSet *next,PloverRepository *upstream,
    52   struct razor_atomic *atomic,struct razor_relocations *relocations,
    53   enum razor_stage_type stage,GCancellable *cancellable)
    54 {
    55     struct razor_package *pkg;
    56     enum razor_install_action action;
    57     struct razor_rpm *rpm;
    58     struct razor_error *error=NULL;
    59     const char *name,*version,*arch;
    60     gchar *t;
    61     int r,count;
    62     GError *tmp_error=NULL;
    63     PloverPackage *package;
    64     GFile *file;
    65     gchar *uri;
    66     plover__file_io_init();
    67     file=g_file_new_for_path(*install_root?install_root:"/");
    68     uri=g_file_get_uri(file);
    69     g_object_unref(file);
    70     g_message("Using %s as URI",uri);
    71     switch(stage)
    72     {
    73 	case RAZOR_STAGE_SCRIPTS_PRE:
    74 	    printf("Running pre-transaction scripts\n");
    75 	    break;
    76 	case RAZOR_STAGE_FILES:
    77 	    printf("Running Transaction\n");
    78 	    break;
    79 	case RAZOR_STAGE_SCRIPTS_POST:
    80 	    printf("Running post-transaction scripts\n");
    81 	    break;
    82 	default:
    83 	    /* Keep the compiler happy */
    84 	    break;
    85     }
    86     while (razor_install_iterator_next(ii,&pkg,&action,&count))
    87     {
    88 	if (g_cancellable_is_cancelled(cancellable))
    89 	{
    90 	    razor_atomic_abort(atomic,PLOVER_GENERAL_ERROR,
    91 	      PLOVER_GENERAL_ERROR_CANCELLED,"Operation was cancelled");
    92 	    g_free(uri);
    93 	    return -1;
    94 	}
    95 	if (action==RAZOR_INSTALL_ACTION_REMOVE)
    96 	{
    97 	    razor_package_get_details(system,pkg,RAZOR_DETAIL_NAME,&name,
    98 	      RAZOR_DETAIL_LAST);
    99 	    if (stage==RAZOR_STAGE_FILES)
   100 		printf("  Removing : %s ",name);
   101 	    r=razor_package_remove(system,plover_package_set_get_razor(next),
   102 	      atomic,pkg,uri,count,stage);
   103 	    if (stage==RAZOR_STAGE_FILES)
   104 		printf("\n");
   105 	}
   106 	else if (action==RAZOR_INSTALL_ACTION_ADD)
   107 	{
   108 	    package=plover_package_set_lookup(next,pkg);
   109 	    rpm=plover_repository_open_rpm(upstream,package,&tmp_error);
   110 	    if (!rpm)
   111 	    {
   112 		plover_propagate_g_error(&error,tmp_error);
   113 		razor_atomic_propagate_error(atomic,error,NULL);
   114 		razor_error_free(error);
   115 		g_free(uri);
   116 		return -1;
   117 	    }
   118 	    if (stage==RAZOR_STAGE_FILES)
   119 		printf("  Installing : %s ",plover_package_get_name(package));
   120 	    if (relocations)
   121 		razor_rpm_set_relocations(rpm,relocations);
   122 	    razor_transaction_fixup_package(trans,pkg,rpm);
   123 	    r=razor_rpm_install(rpm,atomic,uri,1,stage);
   124 	    razor_rpm_close(rpm);
   125 	    if (stage==RAZOR_STAGE_FILES)
   126 		printf("\n");
   127 	}
   128 	else if (action==RAZOR_INSTALL_ACTION_COMMIT)
   129 	    return 1;
   130 	else
   131 	    r=0;
   132 	if (razor_atomic_in_error_state(atomic))
   133 	{
   134 	    g_free(uri);
   135 	    return -1;
   136 	}
   137 	else if (r)
   138 	{
   139 	    if (action==RAZOR_INSTALL_ACTION_REMOVE)
   140 	    {
   141 		razor_package_get_details(system,pkg,RAZOR_DETAIL_NAME,&name,
   142 		  RAZOR_DETAIL_VERSION,&version,RAZOR_DETAIL_ARCH,&arch,
   143 		  RAZOR_DETAIL_LAST);
   144 	    }
   145 	    else
   146 	    {
   147 		package=plover_package_set_lookup(next,pkg);
   148 		name=plover_package_get_name(package);
   149 		version=plover_package_get_version(package);
   150 		arch=plover_package_get_arch(package);
   151 	    }
   152 	    /*
   153 	     * If a pre or preun script fails, then we should
   154 	     * treat that as a fatal error. post and postun
   155 	     * script failures are treated as warnings. Be
   156 	     * nice and tell the user _which_ script failed.
   157 	     */
   158 	    if (stage==RAZOR_STAGE_SCRIPTS_PRE)
   159 	    {
   160 		t=g_strconcat(action==RAZOR_INSTALL_ACTION_ADD?
   161 		  "%pre":"%preun","(",name,"-",version,".",arch,
   162 		  ") scriptlet failed",NULL);
   163 		fprintf(stderr,"error: %s, exit status %d\n",t,r);
   164 		razor_atomic_abort(atomic,PLOVER_SCRIPTLET_ERROR,r,t);
   165 		g_free(t);
   166 		g_free(uri);
   167 		return -1;
   168 	    }
   169 	    else
   170 		fprintf(stderr,
   171 		  "warning: %s(%s-%s.%s) scriptlet failed, exit status %d\n",
   172 		  action==RAZOR_INSTALL_ACTION_ADD?"%post":"%postun",
   173 		  name,version,arch,r);
   174 	}
   175     }
   176     g_free(uri);
   177     return 0;
   178 }
   179 
   180 gboolean plover_install_uri(const char *base_uri,const char *prefix,char **pkgs,
   181   GError **error)
   182 {
   183     gboolean retval;
   184     PloverTransaction *transaction;
   185     transaction=plover_transaction_new_install_uri(base_uri,prefix,pkgs,error);
   186     if (!transaction)
   187 	return FALSE;
   188     retval=plover_transaction_commit(transaction,NULL,error);
   189     g_object_unref(transaction);
   190     return retval;
   191 }
   192 
   193 gboolean plover_install(const char *base,const char *prefix,char **pkgs,
   194   GError **error)
   195 {
   196     gboolean retval;
   197     GFile *file;
   198     gchar *base_uri;
   199     file=g_file_new_for_path(base);
   200     base_uri=g_file_get_uri(file);
   201     g_object_unref(file);
   202     retval=plover_install_uri(base_uri,prefix,pkgs,error);
   203     g_free(base_uri);
   204     return retval;
   205 }
   206 
   207 gboolean plover_update(const char *base,const char *prefix,char **pkgs,
   208   GError **error)
   209 {
   210     gboolean retval;
   211     GError *tmp_error=NULL;
   212     PloverTransaction *transaction;
   213     transaction=plover_transaction_new_update(base,prefix,pkgs,&tmp_error);
   214     if (!transaction)
   215     {
   216 	retval=g_error_matches(tmp_error,PLOVER_POSIX_ERROR,ENOENT);
   217 	if (retval)
   218 	    g_error_free(tmp_error);
   219 	else
   220 	    g_propagate_error(error,tmp_error);
   221     }
   222     else
   223     {
   224 	retval=plover_transaction_commit(transaction,NULL,error);
   225 	g_object_unref(transaction);
   226     }
   227     return retval;
   228 }
   229 
   230 gboolean plover_remove(char **pkgs,GError **error)
   231 {
   232     gboolean retval;
   233     GError *tmp_error=NULL;
   234     PloverTransaction *transaction;
   235     transaction=plover_transaction_new_remove(pkgs,&tmp_error);
   236     if (!transaction)
   237     {
   238 	retval=g_error_matches(tmp_error,PLOVER_POSIX_ERROR,ENOENT);
   239 	if (retval)
   240 	{
   241 	    g_error_free(tmp_error);
   242 	    if (pkgs)
   243 	    {
   244 		g_set_error(error,PLOVER_GENERAL_ERROR,
   245 		  PLOVER_GENERAL_ERROR_NO_SUCH_PACKAGE,"%s: %s",pkgs[0],
   246 		  "Package not found");
   247 		retval=FALSE;
   248 	    }
   249 	}
   250 	else
   251 	    g_propagate_error(error,tmp_error);
   252     }
   253     else
   254     {
   255 	retval=plover_transaction_commit(transaction,NULL,error);
   256 	g_object_unref(transaction);
   257     }
   258     return retval;
   259 }
   260 
   261 /*
   262  * Note: If there are no installed files, then any prefix will match.
   263  */
   264 
   265 int plover_installed_files_match_prefix(const char *prefix)
   266 {
   267     int len,matches=1;
   268     const char *name;
   269     const char *install_root;
   270     struct razor_set *set;
   271     struct razor_package *package;
   272     struct razor_package_iterator *pi;
   273     struct razor_file_iterator *fi;
   274     plover__file_io_init();
   275     len=strlen(prefix);
   276     while(len && prefix[len-1]=='/')
   277 	len--;
   278     install_root=g_getenv("RAZOR_ROOT");
   279     if (!install_root)
   280 	install_root="file:///";
   281     set=razor_root_open_read_only(install_root,NULL);
   282     if (!set)
   283 	g_message("Failed to open root");
   284     if (set)
   285     {
   286 	pi=razor_package_iterator_create(set);
   287 	while (matches &&
   288 	  razor_package_iterator_next(pi,&package,RAZOR_DETAIL_LAST))
   289 	{
   290 	    fi=razor_file_iterator_create(set,package,0);
   291 	    while (matches && razor_file_iterator_next(fi,&name))
   292 	    {
   293 		if (strncmp(name,prefix,len) ||
   294 		  name[len]!='\0' && name[len]!='/')
   295 		    matches=0;
   296 	    }
   297 	    razor_file_iterator_destroy(fi);
   298 	}
   299 	razor_package_iterator_destroy(pi);
   300 	razor_set_unref(set);
   301     }
   302     return matches;
   303 }