/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ /* * Copyright (C) 2000 Eazel, Inc * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. * * Authors: Eskil Heyn Olsen * */ #include #include #include #include "eazel-install-public.h" #include "eazel-install-private.h" #include "eazel-install-query.h" #include "eazel-install-xml-package-list.h" #ifndef EAZEL_INSTALL_NO_CORBA #include #include #include #include "trilobite-eazel-install.h" #include "eazel-install-corba-types.h" #else #include #endif /* EAZEL_INSTALL_NO_CORBA */ #include "eazel-install-metadata.h" #include "eazel-install-protocols.h" #include "eazel-install-rpm-glue.h" #include "eazel-install-types.h" #define DEFAULT_RPM_DB_ROOT "/var/lib/rpm" enum { DOWNLOAD_PROGRESS, PREFLIGHT_CHECK, INSTALL_PROGRESS, DOWNLOAD_FAILED, MD5_CHECK_FAILED, INSTALL_FAILED, UNINSTALL_FAILED, DEPENDENCY_CHECK, DELETE_FILES, DONE, LAST_SIGNAL }; enum { ARG_0, ARG_VERBOSE, ARG_SILENT, ARG_DEBUG, ARG_TEST, ARG_FORCE, ARG_DEPEND, ARG_UPDATE, ARG_UNINSTALL, ARG_DOWNGRADE, ARG_PROTOCOL, ARG_TMP_DIR, ARG_RPMRC_FILE, ARG_SERVER, ARG_PACKAGE_LIST_STORAGE_PATH, ARG_PACKAGE_LIST, ARG_ROOT_DIRS, ARG_PACKAGE_SYSTEM, ARG_SERVER_PORT, ARG_TRANSACTION_DIR, ARG_CGI_PATH }; /* The signal array, used for building the signal bindings */ static guint signals[LAST_SIGNAL] = { 0 }; /* This is the parent class pointer */ #ifdef EAZEL_INSTALL_NO_CORBA static GtkObjectClass *eazel_install_parent_class; #else static BonoboObjectClass *eazel_install_parent_class; #endif /* EAZEL_INSTALL_NO_CORBA */ /* prototypes */ void eazel_install_emit_install_progress_default (EazelInstall *service, const PackageData *pack, int, int, int, int, int, int); void eazel_install_emit_download_progress_default (EazelInstall *service, const char *name, int amount, int total); gboolean eazel_install_emit_preflight_check_default (EazelInstall *service, GList *packages, int total_bytes, int total_packages); void eazel_install_emit_download_failed_default (EazelInstall *service, const char *name); void eazel_install_emit_md5_check_failed_default (EazelInstall *service, const PackageData *pack, const char *actual_md5); void eazel_install_emit_install_failed_default (EazelInstall *service, const PackageData *pack); void eazel_install_emit_uninstall_failed_default (EazelInstall *service, const PackageData *pack); void eazel_install_emit_dependency_check_default (EazelInstall *service, const PackageData *pack, const PackageData *needs); gboolean eazel_install_emit_delete_files_default (EazelInstall *service); void eazel_install_emit_done_default (EazelInstall *service, gboolean result); #ifndef EAZEL_INSTALL_NO_CORBA /***************************************** Corba stuff *****************************************/ static PortableServer_ServantBase__epv base_epv = { NULL, NULL, NULL }; static CORBA_char* xml_from_packagedata (const PackageData *pack) { xmlDocPtr doc; xmlNodePtr node; xmlChar *mem; CORBA_char *result; int size; doc = xmlNewDoc ("1.0"); node = xmlNewDocNode (doc, NULL, "CATEGORIES", NULL); xmlDocSetRootElement (doc, node); node = xmlAddChild (node, xmlNewNode (NULL, "CATEGORY")); xmlSetProp (node, "name", "failed"); node = xmlAddChild (node, xmlNewNode (NULL, "PACKAGES")); xmlAddChild (node, eazel_install_packagedata_to_xml (pack, NULL, NULL)); xmlDocDumpMemory (doc, &mem, &size); result = CORBA_string_dup (mem); free (mem); xmlFreeDoc (doc); return result; } static CORBA_char* xml_from_packagedata_list (const GList *packages) { xmlDocPtr doc; xmlNodePtr node; xmlChar *mem; CORBA_char *result; int size; const GList *iterator; doc = xmlNewDoc ("1.0"); node = xmlNewDocNode (doc, NULL, "CATEGORIES", NULL); xmlDocSetRootElement (doc, node); node = xmlAddChild (node, xmlNewNode (NULL, "CATEGORY")); xmlSetProp (node, "name", "failed"); node = xmlAddChild (node, xmlNewNode (NULL, "PACKAGES")); for (iterator = packages; iterator; glist_step (iterator)) { PackageData *pack = (PackageData*)iterator->data; xmlAddChild (node, eazel_install_packagedata_to_xml (pack, NULL, NULL)); } xmlDocDumpMemory (doc, &mem, &size); result = CORBA_string_dup (mem); free (mem); xmlFreeDoc (doc); return result; } #endif /* EAZEL_INSTALL_NO_CORBA */ /***************************************** GTK+ object stuff *****************************************/ static void eazel_install_finalize (GtkObject *object) { EazelInstall *service; g_return_if_fail (object != NULL); g_return_if_fail (EAZEL_INSTALL (object)); service = EAZEL_INSTALL (object); #ifndef EAZEL_INSTALL_NO_CORBA { CORBA_Environment ev; CORBA_exception_init (&ev); if (service->callback != CORBA_OBJECT_NIL) { CORBA_Object_release (service->callback, &ev); } CORBA_exception_free (&ev); } #endif trilobite_debug ("into eazel_install_finalize"); g_hash_table_destroy (service->private->name_to_package_hash); g_free (service->private->logfilename); g_list_foreach (service->private->downloaded_files, (GFunc)g_free, NULL); g_list_free (service->private->downloaded_files); g_list_foreach (service->private->root_dirs, (GFunc)g_free, NULL); g_list_free (service->private->root_dirs); g_list_free (service->private->transaction); g_free (service->private->transaction_dir); g_free (service->private->cur_root); transferoptions_destroy (service->private->topts); installoptions_destroy (service->private->iopts); switch (service->private->package_system) { case EAZEL_INSTALL_USE_RPM: g_hash_table_destroy (service->private->packsys.rpm.dbs); break; } if (GTK_OBJECT_CLASS (eazel_install_parent_class)->finalize) { GTK_OBJECT_CLASS (eazel_install_parent_class)->finalize (object); } trilobite_debug ("out eazel_install_finalize"); } void eazel_install_unref (GtkObject *object) { g_return_if_fail (object != NULL); g_return_if_fail (EAZEL_INSTALL (object)); #ifndef EAZEL_INSTALL_SLIM bonobo_object_unref (BONOBO_OBJECT (object)); #else eazel_install_finalize (object); #endif } static void eazel_install_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) { EazelInstall *service; g_assert (object != NULL); g_assert (IS_EAZEL_INSTALL (object)); service = EAZEL_INSTALL (object); switch (arg_id) { case ARG_VERBOSE: eazel_install_set_verbose (service, GTK_VALUE_BOOL(*arg)); break; case ARG_SILENT: eazel_install_set_silent (service, GTK_VALUE_BOOL(*arg)); break; case ARG_TEST: eazel_install_set_test (service, GTK_VALUE_BOOL(*arg)); break; case ARG_FORCE: eazel_install_set_force (service, GTK_VALUE_BOOL(*arg)); break; case ARG_DEPEND: eazel_install_set_depend (service, GTK_VALUE_BOOL(*arg)); break; case ARG_UPDATE: eazel_install_set_update (service, GTK_VALUE_BOOL(*arg)); break; case ARG_UNINSTALL: eazel_install_set_uninstall (service, GTK_VALUE_BOOL(*arg)); break; case ARG_DOWNGRADE: eazel_install_set_downgrade (service, GTK_VALUE_BOOL(*arg)); break; case ARG_PROTOCOL: eazel_install_set_protocol (service, GTK_VALUE_ENUM(*arg)); break; case ARG_TMP_DIR: eazel_install_set_tmp_dir (service, (char*)GTK_VALUE_POINTER(*arg)); break; case ARG_RPMRC_FILE: eazel_install_set_rpmrc_file (service, (char*)GTK_VALUE_POINTER(*arg)); break; case ARG_SERVER: eazel_install_set_server (service, (char*)GTK_VALUE_POINTER(*arg)); break; case ARG_PACKAGE_LIST_STORAGE_PATH: eazel_install_set_package_list_storage_path (service, (char*)GTK_VALUE_POINTER(*arg)); break; case ARG_PACKAGE_LIST: eazel_install_set_package_list (service, (char*)GTK_VALUE_POINTER(*arg)); break; case ARG_SERVER_PORT: eazel_install_set_server_port (service, GTK_VALUE_UINT(*arg)); break; case ARG_PACKAGE_SYSTEM: eazel_install_set_package_system (service, GTK_VALUE_ENUM(*arg)); break; case ARG_ROOT_DIRS: eazel_install_set_root_dirs (service, (GList*)GTK_VALUE_POINTER(*arg)); break; case ARG_TRANSACTION_DIR: eazel_install_set_transaction_dir (service, (char*)GTK_VALUE_POINTER(*arg)); break; case ARG_CGI_PATH: eazel_install_set_cgi_path (service, (char*)GTK_VALUE_POINTER(*arg)); break; } } static void eazel_install_class_initialize (EazelInstallClass *klass) { GtkObjectClass *object_class; object_class = (GtkObjectClass*)klass; object_class->finalize = eazel_install_finalize; object_class->set_arg = eazel_install_set_arg; #ifdef EAZEL_INSTALL_NO_CORBA eazel_install_parent_class = gtk_type_class (gtk_object_get_type ()); #else eazel_install_parent_class = gtk_type_class (bonobo_object_get_type ()); klass->servant_vepv = g_new0 (POA_Trilobite_Eazel_Install__vepv,1); ((POA_Trilobite_Eazel_Install__vepv*)klass->servant_vepv)->_base_epv = &base_epv; ((POA_Trilobite_Eazel_Install__vepv*)klass->servant_vepv)->Bonobo_Unknown_epv = bonobo_object_get_epv (); ((POA_Trilobite_Eazel_Install__vepv*)klass->servant_vepv)->Trilobite_Eazel_Install_epv = eazel_install_get_epv (); #endif /* EAZEL_INSTALL_NO_CORBA */ signals[DOWNLOAD_PROGRESS] = gtk_signal_new ("download_progress", GTK_RUN_LAST, object_class->type, GTK_SIGNAL_OFFSET (EazelInstallClass, download_progress), gtk_marshal_NONE__POINTER_INT_INT, GTK_TYPE_NONE, 3, GTK_TYPE_POINTER, GTK_TYPE_INT, GTK_TYPE_INT); signals[PREFLIGHT_CHECK] = gtk_signal_new ("preflight_check", GTK_RUN_LAST, object_class->type, GTK_SIGNAL_OFFSET (EazelInstallClass, preflight_check), gtk_marshal_BOOL__POINTER_INT_INT, GTK_TYPE_BOOL, 3, GTK_TYPE_POINTER, GTK_TYPE_INT, GTK_TYPE_INT); signals[INSTALL_PROGRESS] = gtk_signal_new ("install_progress", GTK_RUN_LAST, object_class->type, GTK_SIGNAL_OFFSET (EazelInstallClass, install_progress), eazel_install_gtk_marshal_NONE__POINTER_INT_INT_INT_INT_INT_INT, GTK_TYPE_NONE, 7, GTK_TYPE_POINTER, GTK_TYPE_INT, GTK_TYPE_INT, GTK_TYPE_INT, GTK_TYPE_INT, GTK_TYPE_INT, GTK_TYPE_INT); signals[DOWNLOAD_FAILED] = gtk_signal_new ("download_failed", GTK_RUN_LAST, object_class->type, GTK_SIGNAL_OFFSET (EazelInstallClass, download_failed), gtk_marshal_NONE__POINTER, GTK_TYPE_NONE, 1, GTK_TYPE_POINTER); signals[MD5_CHECK_FAILED] = gtk_signal_new ("md5_check_failed", GTK_RUN_LAST, object_class->type, GTK_SIGNAL_OFFSET (EazelInstallClass, md5_check_failed), gtk_marshal_NONE__POINTER_POINTER, GTK_TYPE_NONE, 2, GTK_TYPE_POINTER, GTK_TYPE_POINTER); signals[INSTALL_FAILED] = gtk_signal_new ("install_failed", GTK_RUN_LAST, object_class->type, GTK_SIGNAL_OFFSET (EazelInstallClass, install_failed), gtk_marshal_NONE__POINTER, GTK_TYPE_NONE, 1, GTK_TYPE_POINTER); signals[UNINSTALL_FAILED] = gtk_signal_new ("uninstall_failed", GTK_RUN_LAST, object_class->type, GTK_SIGNAL_OFFSET (EazelInstallClass, uninstall_failed), gtk_marshal_NONE__POINTER, GTK_TYPE_NONE, 1, GTK_TYPE_POINTER); signals[DEPENDENCY_CHECK] = gtk_signal_new ("dependency_check", GTK_RUN_LAST, object_class->type, GTK_SIGNAL_OFFSET (EazelInstallClass, dependency_check), gtk_marshal_NONE__POINTER_POINTER, GTK_TYPE_NONE, 2, GTK_TYPE_POINTER, GTK_TYPE_POINTER); signals[DELETE_FILES] = gtk_signal_new ("delete_files", GTK_RUN_LAST, object_class->type, GTK_SIGNAL_OFFSET (EazelInstallClass, delete_files), gtk_marshal_BOOL__NONE, GTK_TYPE_BOOL, 0); signals[DONE] = gtk_signal_new ("done", GTK_RUN_LAST, object_class->type, GTK_SIGNAL_OFFSET (EazelInstallClass, done), gtk_marshal_NONE__BOOL, GTK_TYPE_NONE, 1, GTK_TYPE_BOOL); gtk_object_class_add_signals (object_class, signals, LAST_SIGNAL); klass->install_progress = eazel_install_emit_install_progress_default; klass->download_progress = eazel_install_emit_download_progress_default; klass->preflight_check = eazel_install_emit_preflight_check_default; klass->download_failed = eazel_install_emit_download_failed_default; klass->md5_check_failed = eazel_install_emit_md5_check_failed_default; klass->install_failed = eazel_install_emit_install_failed_default; klass->uninstall_failed = eazel_install_emit_uninstall_failed_default; klass->dependency_check = eazel_install_emit_dependency_check_default; klass->delete_files = eazel_install_emit_delete_files_default; klass->done = eazel_install_emit_done_default; gtk_object_add_arg_type ("EazelInstall::verbose", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_VERBOSE); gtk_object_add_arg_type ("EazelInstall::silent", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_SILENT); gtk_object_add_arg_type ("EazelInstall::debug", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_DEBUG); gtk_object_add_arg_type ("EazelInstall::test", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_TEST); gtk_object_add_arg_type ("EazelInstall::force", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_FORCE); gtk_object_add_arg_type ("EazelInstall::depend", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_DEPEND); gtk_object_add_arg_type ("EazelInstall::update", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_UPDATE); gtk_object_add_arg_type ("EazelInstall::uninstall", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_UNINSTALL); gtk_object_add_arg_type ("EazelInstall::downgrade", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_DOWNGRADE); gtk_object_add_arg_type ("EazelInstall::protocol", GTK_TYPE_ENUM, GTK_ARG_READWRITE, ARG_PROTOCOL); gtk_object_add_arg_type ("EazelInstall::tmp_dir", GTK_TYPE_POINTER, GTK_ARG_READWRITE, ARG_TMP_DIR); gtk_object_add_arg_type ("EazelInstall::rpmrc_file", GTK_TYPE_POINTER, GTK_ARG_READWRITE, ARG_RPMRC_FILE); gtk_object_add_arg_type ("EazelInstall::server", GTK_TYPE_POINTER, GTK_ARG_READWRITE, ARG_SERVER); gtk_object_add_arg_type ("EazelInstall::package_list_storage_path", GTK_TYPE_POINTER, GTK_ARG_READWRITE, ARG_PACKAGE_LIST_STORAGE_PATH); gtk_object_add_arg_type ("EazelInstall::package_list", GTK_TYPE_POINTER, GTK_ARG_READWRITE, ARG_PACKAGE_LIST); gtk_object_add_arg_type ("EazelInstall::root_dir", GTK_TYPE_POINTER, GTK_ARG_READWRITE, ARG_ROOT_DIRS); gtk_object_add_arg_type ("EazelInstall::transaction_dir", GTK_TYPE_POINTER, GTK_ARG_READWRITE, ARG_TRANSACTION_DIR); gtk_object_add_arg_type ("EazelInstall::server_port", GTK_TYPE_UINT, GTK_ARG_READWRITE, ARG_SERVER_PORT); gtk_object_add_arg_type ("EazelInstall::package_system", GTK_TYPE_ENUM, GTK_ARG_READWRITE, ARG_PACKAGE_SYSTEM); gtk_object_add_arg_type ("EazelInstall::cgi_path", GTK_TYPE_POINTER, GTK_ARG_READWRITE, ARG_CGI_PATH); } static void eazel_install_initialize (EazelInstall *service) { #ifndef EAZEL_INSTALL_NO_CORBA Trilobite_Eazel_Install corba_service; #endif /* EAZEL_INSTALL_NO_CORBA */ g_assert (service != NULL); g_assert (IS_EAZEL_INSTALL (service)); #ifndef EAZEL_INSTALL_NO_CORBA corba_service = eazel_install_create_corba_object (BONOBO_OBJECT (service)); /* This sets the bonobo structures in service using the corba object */ if (!bonobo_object_construct (BONOBO_OBJECT (service), corba_service)) { g_error ("bonobo_object_construct failed"); } #endif /* EAZEL_INSTALL_NO_CORBA */ service->private = g_new0 (EazelInstallPrivate,1); service->private->topts = g_new0 (TransferOptions, 1); service->private->iopts = g_new0 (InstallOptions, 1); service->private->root_dirs = NULL; service->private->cur_root = NULL; service->private->transaction_dir = g_strdup_printf ("%s/.nautilus/transactions", g_get_home_dir() ); service->private->packsys.rpm.conflicts = NULL; service->private->packsys.rpm.num_conflicts = 0; service->private->packsys.rpm.dbs = g_hash_table_new (g_str_hash, g_str_equal); service->private->packsys.rpm.set = NULL; service->private->logfile = NULL; service->private->logfilename = NULL; service->private->name_to_package_hash = g_hash_table_new ((GHashFunc)g_str_hash, (GCompareFunc)g_str_equal); service->private->downloaded_files = NULL; service->private->transaction = NULL; eazel_install_set_rpmrc_file (service, "/usr/lib/rpm/rpmrc"); /* Set default root dirs list */ { GList *list = NULL; char *tmp = NULL; #ifndef EAZEL_INSTALL_SLIM /* FIXME bugzilla.eazel.com 2581: RPM specific code */ tmp = g_strdup_printf ("%s/.nautilus/rpmdb/", g_get_home_dir ()); if (g_file_test (tmp, G_FILE_TEST_ISDIR)==0) { g_message ("Creating rpmdb in %s", tmp); addMacro(NULL, "_dbpath", NULL, "/", 0); mkdir (tmp, 0700); rpmdbInit (tmp, 0644); } list = g_list_prepend (list, tmp); #endif list = g_list_prepend (list, DEFAULT_RPM_DB_ROOT); eazel_install_set_root_dirs (service, list); g_free (tmp); g_list_free (list); } } GtkType eazel_install_get_type() { static GtkType service_type = 0; /* First time it's called ? */ if (!service_type) { static const GtkTypeInfo service_info = { "EazelInstall", sizeof (EazelInstall), sizeof (EazelInstallClass), (GtkClassInitFunc) eazel_install_class_initialize, (GtkObjectInitFunc) eazel_install_initialize, /* reserved_1 */ NULL, /* reserved_2 */ NULL, (GtkClassInitFunc) NULL, }; #ifdef EAZEL_INSTALL_NO_CORBA service_type = gtk_type_unique (gtk_object_get_type (), &service_info); #else service_type = gtk_type_unique (bonobo_object_get_type (), &service_info); #endif /* EAZEL_INSTALL_NO_CORBA */ } return service_type; } EazelInstall * eazel_install_new (void) { EazelInstall *service; service = EAZEL_INSTALL (gtk_object_new (TYPE_EAZEL_INSTALL, NULL)); gtk_object_ref (GTK_OBJECT (service)); gtk_object_sink (GTK_OBJECT (service)); return service; } EazelInstall * eazel_install_new_with_config (void) { EazelInstall *service; TransferOptions *topts; InstallOptions *iopts; iopts = init_default_install_configuration (); topts = init_default_transfer_configuration (); if (iopts==NULL || topts==NULL) { return NULL; } service = EAZEL_INSTALL (gtk_object_new (TYPE_EAZEL_INSTALL, "verbose", iopts->mode_verbose, "silent", iopts->mode_silent, "debug", iopts->mode_debug, "test", iopts->mode_test, "force", iopts->mode_force, "depend", iopts->mode_depend, "update", iopts->mode_update, "uninstall", iopts->mode_uninstall, "downgrade", iopts->mode_downgrade, "protocol", iopts->protocol, "tmp_dir", topts->tmp_dir, "transaction_dir", iopts->transaction_dir, "rpmrc_file", topts->rpmrc_file, "server", topts->hostname, "package_list_storage_path", topts->pkg_list_storage_path, "server_port", topts->port_number, "cgi_path", topts->cgi_path, NULL)); gtk_object_ref (GTK_OBJECT (service)); gtk_object_sink (GTK_OBJECT (service)); transferoptions_destroy (topts); installoptions_destroy (iopts); return service; } static void create_temporary_directory (const char* tmpdir) { int retval; g_print (_("Creating temporary download directory ...\n")); retval = mkdir (tmpdir, 0700); if (retval < 0) { if (errno != EEXIST) { g_error (_("Could not create temporary directory!\n")); } } } /* end create_temporary_directory */ gboolean eazel_install_fetch_remote_package_list (EazelInstall *service) { gboolean retval; char *url; char *destination; SANITY_VAL(service, FALSE); g_print (_("Getting package list from remote server ...\n")); url = g_strdup_printf ("http://%s:%d%s%s", eazel_install_get_server (service), eazel_install_get_server_port (service), eazel_install_get_package_list_storage_path (service)[0]=='/'?"":"/", eazel_install_get_package_list_storage_path (service)); #ifdef EAZEL_INSTALL_SLIM destination = g_strdup (eazel_install_get_package_list (service)); #else /* EAZEL_INSTALL_SLIM */ destination = g_strdup_printf ("file://%s", eazel_install_get_package_list (service)); #endif /* EAZEL_INSTALL_SLIM */ retval = eazel_install_fetch_file (service, url, "package list", destination); if (retval == FALSE) { g_warning (_("Unable to retrieve package-list.xml!\n")); } g_free (destination); g_free (url); return retval; } static void eazel_install_log (const char *domain, GLogLevelFlags flags, const char *message, EazelInstall *service) { SANITY (service); if ( flags | G_LOG_LEVEL_MESSAGE) { fprintf (service->private->logfile, " : %s\n", message); } else if (flags | G_LOG_LEVEL_WARNING) { fprintf (service->private->logfile, "w: %s\n", message); } else if (flags | G_LOG_LEVEL_ERROR) { fprintf (service->private->logfile, "E: %s\n", message); } } void eazel_install_open_log (EazelInstall *service, const char *fname) { SANITY (service); if (service->private->logfile) { fclose (service->private->logfile); } service->private->logfile = fopen (fname, "wt"); if (service->private->logfilename) { g_free (service->private->logfilename); } service->private->logfilename = g_strdup (fname); if (service->private->logfile!=NULL) { g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_MESSAGE | G_LOG_LEVEL_WARNING | G_LOG_LEVEL_ERROR, (GLogFunc)eazel_install_log, service); return; } g_warning (_("Cannot write to file %s, using default log handler"), fname); } static gboolean eazel_install_alter_mode_on_temp (EazelInstall *service, mode_t mode) { GList *iterator; gboolean result = TRUE; SANITY_VAL (service, FALSE); trilobite_debug ("locking dir to 0%o", mode); /* First set mode 400 on all files */ if (chmod (eazel_install_get_tmp_dir (service), mode + 0100) != 0) { trilobite_debug ("cannot change %s to 0%o", eazel_install_get_tmp_dir (service), mode + 0100); result = FALSE; } for (iterator = service->private->downloaded_files; iterator; iterator = g_list_next (iterator)) { char *filename = (char*)iterator->data; if (filename) { if (chmod (filename, mode) != 0) { trilobite_debug ("cannot change %s to 0%o", filename, mode); result = FALSE; } } } trilobite_debug ("locking done"); return result; } gboolean eazel_install_lock_tmp_dir (EazelInstall *service) { return eazel_install_alter_mode_on_temp (service, 0400); } gboolean eazel_install_unlock_tmp_dir (EazelInstall *service) { return eazel_install_alter_mode_on_temp (service, 0600); } static void eazel_install_delete_downloads (EazelInstall *service) { SANITY (service); if (service->private->downloaded_files && eazel_install_emit_delete_files (service)) { GList *iterator; PackageData *top_pack, *sub_pack; trilobite_debug ("*** deleting the package files"); for (iterator = g_list_first (service->private->downloaded_files); iterator; iterator = g_list_next (iterator)) { char *filename = (char*)iterator->data; trilobite_debug ("*** file '%s'", filename); if (unlink (filename) != 0) { g_warning ("unable to delete file %s !", filename); } } if (rmdir (eazel_install_get_tmp_dir (service))!=0) { g_warning ("unable to delete directory %s !", eazel_install_get_tmp_dir (service)); } } } void eazel_install_install_packages (EazelInstall *service, GList *categories, const char *root) { EazelInstallStatus result; SANITY (service); if (!g_file_exists (eazel_install_get_tmp_dir (service))) { create_temporary_directory (eazel_install_get_tmp_dir (service)); } if (categories == NULL && eazel_install_get_package_list (service) == NULL) { char *tmp; tmp = g_strdup_printf ("%s/package-list.xml", eazel_install_get_tmp_dir (service)); eazel_install_set_package_list (service, tmp); g_free (tmp); eazel_install_fetch_remote_package_list (service); } g_free (service->private->cur_root); service->private->cur_root = g_strdup (root?root:DEFAULT_RPM_DB_ROOT); eazel_install_prepare_package_system (service); result = install_new_packages (service, categories); if (result == EAZEL_INSTALL_NOTHING) { g_warning (_("Install failed")); } eazel_install_unlock_tmp_dir (service); trilobite_debug ("service->private->downloaded_files = 0x%x", service->private->downloaded_files); eazel_install_delete_downloads (service); g_free (service->private->cur_root); eazel_install_emit_done (service, result & EAZEL_INSTALL_INSTALL_OK); } void eazel_install_uninstall_packages (EazelInstall *service, GList *categories, const char *root) { EazelInstallStatus result; SANITY (service); g_free (service->private->cur_root); service->private->cur_root = g_strdup (root?root:DEFAULT_RPM_DB_ROOT); eazel_install_set_uninstall (service, TRUE); if (categories == NULL && eazel_install_get_package_list (service) == NULL) { eazel_install_set_package_list (service, "/var/eazel/services/package-list.xml"); eazel_install_fetch_remote_package_list (service); } eazel_install_prepare_package_system (service); result = uninstall_packages (service, categories); if (result == EAZEL_INSTALL_NOTHING) { g_warning (_("Uninstall failed")); } eazel_install_emit_done (service, result & EAZEL_INSTALL_UNINSTALL_OK); } void eazel_install_revert_transaction_from_xmlstring (EazelInstall *service, const char *xml, int size, const char *root) { GList *packages; EazelInstallStatus result; g_free (service->private->cur_root); service->private->cur_root = g_strdup (root?root:DEFAULT_RPM_DB_ROOT); packages = parse_memory_transaction_file (xml, size); eazel_install_prepare_package_system (service); result = revert_transaction (service, packages); eazel_install_unlock_tmp_dir (service); eazel_install_delete_downloads (service); eazel_install_emit_done (service, result & EAZEL_INSTALL_REVERSION_OK); } void eazel_install_revert_transaction_from_file (EazelInstall *service, const char *filename, const char *root) { xmlDocPtr doc; xmlChar *mem; int size; doc = xmlParseFile (filename); xmlDocDumpMemory (doc, &mem, &size); eazel_install_revert_transaction_from_xmlstring (service, mem, size, root); g_free (mem); xmlFreeDoc (doc); } GList* eazel_install_query_package_system (EazelInstall *service, const char *query, int flags, const char *root) { GList *result; g_message ("eazel_install_query_package_system (...,%s,...)", query); g_free (service->private->cur_root); service->private->cur_root = g_strdup (root); eazel_install_prepare_package_system (service); result = eazel_install_simple_query (service, query, flags, 0, NULL); return result; } /************************************************ Signal emitters and default handlers. The default handlers check for the existance of a corba callback, and if true, do the callback **************************************************/ void eazel_install_emit_install_progress (EazelInstall *service, const PackageData *pack, int package_num, int num_packages, int package_size_completed, int package_size_total, int total_size_completed, int total_size) { SANITY(service); gtk_signal_emit (GTK_OBJECT (service), signals[INSTALL_PROGRESS], pack, package_num, num_packages, package_size_completed, package_size_total, total_size_completed, total_size); } void eazel_install_emit_install_progress_default (EazelInstall *service, const PackageData *pack, int package_num, int num_packages, int package_size_completed, int package_size_total, int total_size_completed, int total_size) { #ifndef EAZEL_INSTALL_NO_CORBA CORBA_Environment ev; CORBA_exception_init (&ev); SANITY(service); if (service->callback != CORBA_OBJECT_NIL) { Trilobite_Eazel_PackageDataStruct *package; package = corba_packagedatastruct_from_packagedata (pack); Trilobite_Eazel_InstallCallback_install_progress (service->callback, package, package_num, num_packages, package_size_completed, package_size_total, total_size_completed, total_size, &ev); CORBA_free (package); } CORBA_exception_free (&ev); #endif /* EAZEL_INSTALL_NO_CORBA */ } void eazel_install_emit_download_progress (EazelInstall *service, const char *name, int amount, int total) { SANITY(service); gtk_signal_emit (GTK_OBJECT (service), signals[DOWNLOAD_PROGRESS], name, amount, total); } void eazel_install_emit_download_progress_default (EazelInstall *service, const char *name, int amount, int total) { #ifndef EAZEL_INSTALL_NO_CORBA CORBA_Environment ev; CORBA_exception_init (&ev); SANITY(service); if (service->callback != CORBA_OBJECT_NIL) { Trilobite_Eazel_InstallCallback_download_progress (service->callback, name, amount, total, &ev); } CORBA_exception_free (&ev); #endif /* EAZEL_INSTALL_NO_CORBA */ } gboolean eazel_install_emit_preflight_check (EazelInstall *service, GList *packages) { GList *packages_in_signal = NULL; GList *iterator; unsigned long size_packages, num_packages; gboolean result; SANITY(service); size_packages = eazel_install_get_total_size_of_packages (service, packages); num_packages = g_list_length (packages); for (iterator = packages; iterator; glist_step (iterator)) { PackageData *pack = (PackageData*)iterator->data; if (pack->toplevel) { packages_in_signal = g_list_prepend (packages_in_signal, pack); } } gtk_signal_emit (GTK_OBJECT (service), signals[PREFLIGHT_CHECK], packages_in_signal, size_packages, num_packages, &result); g_list_free (packages_in_signal); return result; } gboolean eazel_install_emit_preflight_check_default (EazelInstall *service, GList *packages, int total_bytes, int total_packages) { #ifndef EAZEL_INSTALL_NO_CORBA CORBA_Environment ev; CORBA_boolean result = FALSE; CORBA_exception_init (&ev); SANITY(service); if (service->callback != CORBA_OBJECT_NIL) { CORBA_char *corbapackages; corbapackages = xml_from_packagedata_list (packages); result = Trilobite_Eazel_InstallCallback_preflight_check (service->callback, corbapackages, total_bytes, total_packages, &ev); CORBA_free (corbapackages); } CORBA_exception_free (&ev); return (gboolean)result; #else /* EAZEL_INSTALL_NO_CORBA */ return TRUE; #endif /* EAZEL_INSTALL_NO_CORBA */ } void eazel_install_emit_download_failed (EazelInstall *service, const char *name) { SANITY(service); gtk_signal_emit (GTK_OBJECT (service), signals[DOWNLOAD_FAILED], name); } void eazel_install_emit_download_failed_default (EazelInstall *service, const char *name) { #ifndef EAZEL_INSTALL_NO_CORBA CORBA_Environment ev; CORBA_exception_init (&ev); SANITY(service); if (service->callback != CORBA_OBJECT_NIL) { Trilobite_Eazel_InstallCallback_download_failed (service->callback, name, &ev); } CORBA_exception_free (&ev); #endif /* EAZEL_INSTALL_NO_CORBA */ } void eazel_install_emit_md5_check_failed (EazelInstall *service, const PackageData *pd, const char *actual_md5) { SANITY(service); gtk_signal_emit (GTK_OBJECT (service), signals[MD5_CHECK_FAILED], pd, actual_md5); } void eazel_install_emit_md5_check_failed_default (EazelInstall *service, const PackageData *pack, const char *actual_md5) { #ifndef EAZEL_INSTALL_NO_CORBA CORBA_Environment ev; CORBA_exception_init (&ev); SANITY(service); if (service->callback != CORBA_OBJECT_NIL) { Trilobite_Eazel_PackageDataStruct *corbapack; corbapack = corba_packagedatastruct_from_packagedata (pack); Trilobite_Eazel_InstallCallback_md5_check_failed (service->callback, corbapack, actual_md5, &ev); CORBA_free (corbapack); } CORBA_exception_free (&ev); #endif /* EAZEL_INSTALL_NO_CORBA */ } void eazel_install_emit_install_failed (EazelInstall *service, const PackageData *pd) { SANITY(service); gtk_signal_emit (GTK_OBJECT (service), signals[INSTALL_FAILED], pd); } void eazel_install_emit_install_failed_default (EazelInstall *service, const PackageData *pack) { #ifndef EAZEL_INSTALL_NO_CORBA CORBA_Environment ev; CORBA_exception_init (&ev); SANITY(service); if (service->callback != CORBA_OBJECT_NIL) { CORBA_char *package; package = xml_from_packagedata (pack); Trilobite_Eazel_InstallCallback_install_failed (service->callback, package, &ev); CORBA_free (package); } CORBA_exception_free (&ev); #endif /* EAZEL_INSTALL_NO_CORBA */ } void eazel_install_emit_uninstall_failed (EazelInstall *service, const PackageData *pd) { SANITY(service); gtk_signal_emit (GTK_OBJECT (service), signals[UNINSTALL_FAILED], pd); } void eazel_install_emit_uninstall_failed_default (EazelInstall *service, const PackageData *pack) { #ifndef EAZEL_INSTALL_NO_CORBA CORBA_Environment ev; CORBA_exception_init (&ev); SANITY(service); if (service->callback != CORBA_OBJECT_NIL) { CORBA_char *package; package = xml_from_packagedata (pack); Trilobite_Eazel_InstallCallback_uninstall_failed (service->callback, package, &ev); /* CORBA_free (package); */ } CORBA_exception_free (&ev); #endif /* EAZEL_INSTALL_NO_CORBA */ } void eazel_install_emit_dependency_check (EazelInstall *service, const PackageData *package, const PackageData *needs) { SANITY(service); gtk_signal_emit (GTK_OBJECT (service), signals[DEPENDENCY_CHECK], package, needs); } void eazel_install_emit_dependency_check_default (EazelInstall *service, const PackageData *pack, const PackageData *needs) { #ifndef EAZEL_INSTALL_NO_CORBA CORBA_Environment ev; CORBA_exception_init (&ev); SANITY(service); if (service->callback != CORBA_OBJECT_NIL) { Trilobite_Eazel_PackageDataStruct *corbapack; Trilobite_Eazel_PackageDataStruct *corbaneeds; corbapack = corba_packagedatastruct_from_packagedata (pack); corbaneeds = corba_packagedatastruct_from_packagedata (needs); Trilobite_Eazel_InstallCallback_dependency_check (service->callback, corbapack, corbaneeds, &ev); CORBA_free (corbapack); CORBA_free (corbaneeds); } CORBA_exception_free (&ev); #endif /* EAZEL_INSTALL_NO_CORBA */ } gboolean eazel_install_emit_delete_files (EazelInstall *service) { gboolean result; SANITY(service); gtk_signal_emit (GTK_OBJECT (service), signals[DELETE_FILES], &result); return result; } gboolean eazel_install_emit_delete_files_default (EazelInstall *service) { #ifndef EAZEL_INSTALL_NO_CORBA CORBA_Environment ev; CORBA_boolean result = FALSE; CORBA_exception_init (&ev); SANITY(service); if (service->callback != CORBA_OBJECT_NIL) { result = Trilobite_Eazel_InstallCallback_delete_files (service->callback, &ev); } CORBA_exception_free (&ev); return (gboolean)result; #else return TRUE; #endif } void eazel_install_emit_done (EazelInstall *service, gboolean result) { SANITY(service); trilobite_debug ("emit_done (result = %s)", result ? "TRUE" : "FALSE"); gtk_signal_emit (GTK_OBJECT (service), signals[DONE], result); } void eazel_install_emit_done_default (EazelInstall *service, gboolean result) { #ifndef EAZEL_INSTALL_NO_CORBA CORBA_Environment ev; CORBA_exception_init (&ev); SANITY(service); if (service->callback != CORBA_OBJECT_NIL) { Trilobite_Eazel_InstallCallback_done (service->callback, result, &ev); } CORBA_exception_free (&ev); #endif /* EAZEL_INSTALL_NO_CORBA */ } /* Welcome to define madness. These are all the get/set methods. There is nothing of interest beyond this point, except for a fucking big dragon*/ void string_list_copy (GList **in, const GList *strings) { GList *result = NULL; GList *iterator; const GList *iterator_c; for (iterator = *in; iterator; iterator=iterator->next) { g_free (iterator->data); } g_list_free (*in); for (iterator_c = strings; iterator_c; iterator_c = iterator_c->next) { (*in) = g_list_prepend (*in, g_strdup ((char*)iterator_c->data)); } } ei_mutator_impl (verbose, gboolean, iopts->mode_verbose); ei_mutator_impl (silent, gboolean, iopts->mode_silent); ei_mutator_impl (debug, gboolean, iopts->mode_debug); ei_mutator_impl (test, gboolean, iopts->mode_test); ei_mutator_impl (force, gboolean, iopts->mode_force); ei_mutator_impl (depend, gboolean, iopts->mode_depend); ei_mutator_impl (update, gboolean, iopts->mode_update); ei_mutator_impl (uninstall, gboolean, iopts->mode_uninstall); ei_mutator_impl (downgrade, gboolean, iopts->mode_downgrade); ei_mutator_impl (protocol, URLType, iopts->protocol); ei_mutator_impl_copy (tmp_dir, char*, topts->tmp_dir, g_strdup); ei_mutator_impl_copy (rpmrc_file, char*, topts->rpmrc_file, g_strdup); ei_mutator_impl_copy (server, char*, topts->hostname, g_strdup); ei_mutator_impl_copy (package_list_storage_path, char*, topts->pkg_list_storage_path, g_strdup); ei_mutator_impl_copy (package_list, char*, iopts->pkg_list, g_strdup); ei_mutator_impl_copy (transaction_dir, char*, transaction_dir, g_strdup); ei_mutator_impl (server_port, guint, topts->port_number); ei_mutator_impl_copy (cgi_path, char*, topts->cgi_path, g_strdup); ei_mutator_impl (install_flags, int, install_flags); ei_mutator_impl (interface_flags, int, interface_flags); ei_mutator_impl (problem_filters, int, problem_filters); ei_mutator_impl (package_system, int, package_system); ei_access_impl (verbose, gboolean, iopts->mode_verbose, FALSE); ei_access_impl (silent, gboolean, iopts->mode_silent, FALSE); ei_access_impl (debug, gboolean, iopts->mode_debug, FALSE); ei_access_impl (test, gboolean, iopts->mode_test, FALSE); ei_access_impl (force, gboolean, iopts->mode_force, FALSE); ei_access_impl (depend, gboolean, iopts->mode_depend, FALSE); ei_access_impl (update, gboolean, iopts->mode_update, FALSE); ei_access_impl (uninstall, gboolean, iopts->mode_uninstall, FALSE); ei_access_impl (downgrade, gboolean, iopts->mode_downgrade, FALSE); ei_access_impl (protocol, URLType , iopts->protocol, PROTOCOL_LOCAL); ei_access_impl (tmp_dir, char*, topts->tmp_dir, NULL); ei_access_impl (rpmrc_file, char*, topts->rpmrc_file, NULL); ei_access_impl (server, char*, topts->hostname, NULL); ei_access_impl (package_list_storage_path, char*, topts->pkg_list_storage_path, NULL); ei_access_impl (package_list, char*, iopts->pkg_list, NULL); ei_access_impl (transaction_dir, char*, transaction_dir, NULL); ei_access_impl (root_dirs, GList*, root_dirs, NULL); ei_access_impl (server_port, guint, topts->port_number, 0); ei_access_impl (cgi_path, char*, topts->cgi_path, NULL); ei_access_impl (install_flags, int, install_flags, 0); ei_access_impl (interface_flags, int, interface_flags, 0); ei_access_impl (problem_filters, int, problem_filters, 0); ei_access_impl (package_system, int, package_system, 0); void eazel_install_set_root_dirs (EazelInstall *service, const GList *new_roots) { string_list_copy (&service->private->root_dirs, new_roots); }