ipkg_install.c

来自「this is the pkg installer for linux」· C语言 代码 · 共 1,943 行 · 第 1/5 页

C
1,943
字号
	  response = get_user_response("    Configuration file '%s'\n"				       "    ==> File on system created by you or by a script.\n"				       "    ==> File also in package provided by package maintainer.\n"				       "       What would you like to do about it ?  Your options are:\n"				       "        Y or I  : install the package maintainer's version\n"				       "        N or O  : keep your currently-installed version\n"				       "          D     : show the differences between the versions (if diff is installed)\n"				       "     The default action is to keep your current version.\n"				       "    *** %s (Y/I/N/O/D) [default=N] ? ", file_name, short_file_name);	  if (strcmp(response, "y") == 0	      || strcmp(response, "i") == 0	      || strcmp(response, "yes") == 0) {	       free(response);	       return 0;	  }	  if (strcmp(response, "d") == 0) {	       char *cmd;	       free(response);	       /* XXX: BUG rewrite to use exec or busybox's internal diff */	       sprintf_alloc(&cmd, "diff -u %s %s", backup, file_name);	       xsystem(cmd);	       free(cmd);	       printf("    [Press ENTER to continue]\n");	       response = file_read_line_alloc(stdin);	       free(response);	       continue;	  }	  free(response);	  return 1;     }}/* XXX: CLEANUP: I'd like to move all of the code for   creating/cleaning pkg->tmp_unpack_dir directly into pkg.c. (Then,   it would make sense to cleanup pkg->tmp_unpack_dir directly from   pkg_deinit for example). */static int cleanup_temporary_files(ipkg_conf_t *conf, pkg_t *pkg){     DIR *tmp_dir;     struct dirent *dirent;     char *tmp_file;#ifdef IPKG_DEBUG_NO_TMP_CLEANUP#error     ipkg_message(conf, IPKG_DEBUG,		  "%s: Not cleaning up %s since ipkg compiled with IPKG_DEBUG_NO_TMP_CLEANUP\n",		  __FUNCTION__, pkg->tmp_unpack_dir);     return 0;#endif     if (pkg->tmp_unpack_dir && file_is_dir(pkg->tmp_unpack_dir)) {	  tmp_dir = opendir(pkg->tmp_unpack_dir);	  if (tmp_dir) {	       while (1) {		    dirent = readdir(tmp_dir);		    if (dirent == NULL) {			 break;		    }		    sprintf_alloc(&tmp_file, "%s/%s",				  pkg->tmp_unpack_dir, dirent->d_name);		    if (! file_is_dir(tmp_file)) {			 unlink(tmp_file);		    }		    free(tmp_file);	       }	       closedir(tmp_dir);	       rmdir(pkg->tmp_unpack_dir);	       free(pkg->tmp_unpack_dir);	       pkg->tmp_unpack_dir = NULL;	  }     }     ipkg_message(conf, IPKG_INFO, "cleanup_temporary_files: pkg=%s local_filename=%s tmp_dir=%s\n",		  pkg->name, pkg->local_filename, conf->tmp_dir);     if (pkg->local_filename && strncmp(pkg->local_filename, conf->tmp_dir, strlen(conf->tmp_dir)) == 0) {	  unlink(pkg->local_filename);	  free(pkg->local_filename);	  pkg->local_filename = NULL;     }     return 0;}static char *backup_filename_alloc(const char *file_name){     char *backup;     sprintf_alloc(&backup, "%s%s", file_name, IPKG_BACKUP_SUFFIX);     return backup;}int backup_make_backup(ipkg_conf_t *conf, const char *file_name){     int err;     char *backup;         backup = backup_filename_alloc(file_name);     err = file_copy(file_name, backup);     if (err) {	  ipkg_message(conf, IPKG_ERROR,		       "%s: Failed to copy %s to %s\n",		       __FUNCTION__, file_name, backup);     }     free(backup);     return err;}static int backup_exists_for(const char *file_name){     int ret;     char *backup;     backup = backup_filename_alloc(file_name);     ret = file_exists(backup);     free(backup);     return ret;}static int backup_remove(const char *file_name){     char *backup;     backup = backup_filename_alloc(file_name);     unlink(backup);     free(backup);     return 0;}#ifdef CONFIG_IPKG_PROCESS_ACTIONSint ipkg_remove_packages(ipkg_conf_t *conf, pkg_vec_t *pkgs_to_remove) {     /* first, remove the packages that need removing */     for (i = 0 ; i < pkgs_to_remove->len; i++ ) {	  pkg_t *pkg = pkgs_to_remove->pkgs[i];	  err = ipkg_remove_pkg(conf, pkg,0);	  if (err) return err;     }     return 0;}int ipkg_process_actions_sanity_check(ipkg_conf_t *conf, pkg_vec_t *pkgs_to_remove, pkg_vec_t *pkgs_superseded, pkg_vec_t *pkgs_to_install){     int i;     /* now one more pass checking on the ones that need to be installed */     for (i = 0 ; i < pkgs_to_install->len; i++ ) {	  pkg_t *pkg = pkgs_to_install->pkgs[i];	  if (pkg->dest == NULL)	       pkg->dest = conf->default_dest;	  pkg->state_want = SW_INSTALL;	  /* Abhaya: conflicts check */	  err = check_conflicts_for(conf, pkg);	  if (err) { return err; }     }     return 0;}int ipkg_process_actions_unpack_packages(ipkg_conf_t *conf, pkg_vec_t *pkgs_to_remove, pkg_vec_t *pkgs_to_install){     int i;     /* now one more pass checking on the ones that need to be installed */     for (i = 0 ; i < pkgs_to_install->len; i++ ) {	  pkg_t *pkg = pkgs_to_install->pkgs[i];	  /* XXX: FEATURE: Need to really support Provides/Replaces: here at some point */	  pkg_vec_t *replacees = pkg_vec_alloc();	  pkg_get_installed_replacees(conf, pkg, replacees);	  /* XXX: BUG: we really should treat replacement more like an upgrade	   *      Instead, we're going to remove the replacees 	   */	  err = pkg_remove_installed_replacees(conf, replacees);	  if (err) return err;	  pkg->state_flag |= SF_REMOVED_REPLACEES;     }     return 0;}int ipkg_process_actions_unpack_packages(ipkg_conf_t *conf, pkg_vec_t *pkgs_to_remove, pkg_vec_t *pkgs_to_install){     int i;     /* now one more pass checking on the ones that need to be installed */     for (i = 0 ; i < pkgs_to_install->len; i++ ) {	  pkg_t *pkg = pkgs_to_install->pkgs[i];	  if (pkg->local_filename == NULL) {	       err = ipkg_download_pkg(conf, pkg, conf->tmp_dir);	       if (err) {		    ipkg_message(conf, IPKG_ERROR,				 "Failed to download %s. Perhaps you need to run 'ipkg update'?\n",				 pkg->name);		    return err;	       }	  }	  if (pkg->tmp_unpack_dir == NULL) {	       err = unpack_pkg_control_files(conf, pkg);	       if (err) return err;	  }     }     return 0;}int ipkg_process_actions_prerm(ipkg_conf_t *conf, pkg_vec_t *pkgs_to_install){     int i;     /* now one more pass checking on the ones that need to be installed */     for (i = 0 ; i < pkgs_to_install->len; i++ ) {	  pkg_t *pkg = pkgs_to_install->pkgs[i];	  pkg_t *old_pkg = pkg->old_pkg;	  err = prerm_upgrade_old_pkg(conf, pkg, old_pkg);	  if (err) return err;	  err = prerm_deconfigure_conflictors(conf, pkg, replacees);	  if (err) return err;	  err = preinst_configure(conf, pkg, old_pkg);	  if (err) return err;	  err = backup_modified_conffiles(conf, pkg, old_pkg);	  if (err) return err;	  err = postrm_upgrade_old_pkg(conf, pkg, old_pkg);	  if (err) return err;     }     return 0;}int ipkg_process_actions_install(ipkg_conf_t *conf, pkg_vec_t *pkgs_to_install){     int i;     /* now one more pass checking on the ones that need to be installed */     for (i = 0 ; i < pkgs_to_install->len; i++ ) {	  pkg_t *pkg = pkgs_to_install->pkgs[i];	  pkg_t *old_pkg = pkg->old_pkg;	  if (old_pkg) {	       old_pkg->state_want = SW_DEINSTALL;	       if (old_pkg->state_flag & SF_NOPRUNE) {		    ipkg_message(conf, IPKG_INFO,				 "  not removing obsolesced files because package marked noprune\n");	       } else {		    ipkg_message(conf, IPKG_INFO,				 "  removing obsolesced files\n");		    remove_obsolesced_files(conf, pkg, old_pkg);	       }	  }	  ipkg_message(conf, IPKG_INFO,		       "  installing maintainer scripts\n");	  install_maintainer_scripts(conf, pkg, old_pkg);	  /* the following just returns 0 */	  remove_disappeared(conf, pkg);	  ipkg_message(conf, IPKG_INFO,		       "  installing data files\n");	  install_data_files(conf, pkg);	  ipkg_message(conf, IPKG_INFO,		       "  resolving conf files\n");	  resolve_conffiles(conf, pkg);	  pkg->state_status = SS_UNPACKED;	  if (old_pkg) {	       old_pkg->state_status = SS_NOT_INSTALLED;	  }	  time(&pkg->installed_time);	  ipkg_message(conf, IPKG_INFO,		       "  cleanup temp files\n");	  cleanup_temporary_files(conf, pkg);	  if (pkg->parent)	       pkg->parent->state_status = pkg->state_status;     }     return 0;}int ipkg_process_actions_unwind_prerm(ipkg_conf_t *conf, pkg_vec_t *pkgs_to_install){     int i;     /* now one more pass checking on the ones that need to be installed */     for (i = 0 ; i < pkgs_to_install->len; i++ ) {	  pkg_t *pkg = pkgs_to_install->pkgs[i];	  pkg_t *old_pkg = pkg->old_pkg;	  if (old_pkg) {	       if (old_pkg->state_flags & SF_POSTRM_UPGRADE)		    postrm_upgrade_old_pkg_unwind(conf, pkg, old_pkg);	       if (old_pkg->state_flags & SF_CHECK_DATA_FILE_CLASHES)		    check_data_file_clashes_unwind(conf, pkg, old_pkg);	       if (old_pkg->state_flags & SF_BACKUP_MODIFIED_CONFFILES)		    backup_modified_conffiles_unwind(conf, pkg, old_pkg);	       if (old_pkg->state_flags & SF_PREINST_CONFIGURE)		    preinst_configure_unwind(conf, pkg, old_pkg);	       if (old_pkg->state_flags & SF_DECONFIGURE_CONFLICTORS)		    prerm_deconfigure_conflictors_unwind(conf, pkg, replacees);	       if (old_pkg->state_flags & SF_PRERM_UPGRADE)		    prerm_upgrade_old_pkg_unwind(conf, pkg, old_pkg);	       if (old_pkg->state_flags & SF_REMOVED_REPLACEES)		    remove_installed_replacees_unwind(conf, pkg, old_pkg);	  }     }     return 0;}/*  * Perform all the actions. * * pkgs_to_remove are packages marked for removal. * pkgs_superseded are the old packages being replaced by upgrades. * * Assumes pkgs_to_install includes all dependences, recursively, sorted in installable order. */int ipkg_process_actions(ipkg_conf_t *conf, pkg_vec_t *pkgs_to_remove, pkg_vec_t *pkgs_superseded, pkg_vec_t *pkgs_to_install){     int err;     int i;     err = ipkg_remove_packages(conf, pkgs_to_remove);     if (err) return err;     err = ipkg_process_actions_sanity_check(conf, pkgs_superseded, pkgs_to_install);     if (err) return err;     err = ipkg_process_actions_remove_replacees(conf, pkgs_to_install);     if (err) goto UNWIND;     /* @@@@ look at ipkg_install_pkg for handling replacements */     err = ipkg_process_actions_unpack_packages(conf, pkgs_to_install);     if (err) goto UNWIND;     /*       * Now that we have the packages unpacked, we can look for data      * file clashes.  First, we mark the files from the superseded      * packages as obsolete.  Then we scan the files in      * pkgs_to_install, and only complain about clashes with      * non-obsolete files.      */     err = ipkg_process_actions_check_data_file_clashes(conf, pkgs_superseded, pkgs_to_install);     if (err) goto UNWIND;     /* this was before checking data file clashes */     err = ipkg_process_actions_prerm(conf, pkgs_superseded, pkgs_to_install);     if (err) goto UNWIND;     /* point of no return: no unwinding after this */     err = ipkg_process_actions_install(conf, pkgs_to_install);     if (err) return err;     ipkg_message(conf, IPKG_INFO, "Done.\n");     return 0; UNWIND:     ipkg_process_actions_unwind(conf, pkgs_to_install);     ipkg_message(conf, IPKG_INFO,		  "  cleanup temp files\n");     cleanup_temporary_files(conf, pkg);     ipkg_message(conf, IPKG_INFO,		  "Failed.\n");     return err;}#endif

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?