/* Check if the mirror carries the architecture that's being installed. */
int check_arch (void) {
	char *command;
	FILE *f = NULL;
	char *hostname, *directory, *suite = NULL;
	int valid = 0;

	hostname = add_protocol("hostname");
	debconf_get(debconf, hostname);
	free(hostname);
	hostname = strdup(debconf->value);
	directory = add_protocol("directory");
	debconf_get(debconf, directory);
	free(directory);
	directory = strdup(debconf->value);

	/* As suite has been determined previously, this should not fail */
	debconf_get(debconf, DEBCONF_BASE "suite");
	if (strlen(debconf->value) > 0) {
		suite = strdup(debconf->value);

		asprintf(&command, "wget -q %s://%s%s/dists/%s/main/binary-%s/Release -O - | grep Architecture",
			 protocol, hostname, directory, suite, ARCH_TEXT);
		di_log(DI_LOG_LEVEL_DEBUG, "command: %s", command);
		f = popen(command, "r");
		free(command);

		if (f != NULL) {
			char buf[SUITE_LENGTH];
			if (fgets(buf, SUITE_LENGTH - 1, f))
				if (strlen(buf) > 1)
					valid = 1;
		}
		pclose(f);
	}

	free(hostname);
	free(directory);
	if (suite)
		free(suite);

	if (valid) {
		return 0;
	}
	else {
		di_log(DI_LOG_LEVEL_DEBUG, "Architecture not supported by selected mirror");
		debconf_input(debconf, "critical", DEBCONF_BASE "noarch");
		if (debconf_go(debconf) == 30)
			exit(10); /* back up to menu */
		else
			return 1; /* back to beginning of questions */
	}
}
/* Get the codename for the selected suite. */
int get_codename (void) {
	char *command;
	FILE *f = NULL;
	char *hostname, *directory, *suite = NULL;
	int ret = 1;

	hostname = add_protocol("hostname");
	debconf_get(debconf, hostname);
	free(hostname);
	hostname = strdup(debconf->value);
	directory = add_protocol("directory");
	debconf_get(debconf, directory);
	free(directory);
	directory = strdup(debconf->value);

	/* As suite has been determined previously, this should not fail */
	debconf_get(debconf, DEBCONF_BASE "suite");
	if (strlen(debconf->value) > 0) {
		suite = strdup(debconf->value);

		asprintf(&command, "wget -q %s://%s%s/dists/%s/Release -O - | grep ^Codename: | cut -d' ' -f 2",
			 protocol, hostname, directory, suite);
		di_log(DI_LOG_LEVEL_DEBUG, "command: %s", command);
		f = popen(command, "r");
		free(command);

		if (f != NULL) {
			char buf[SUITE_LENGTH];
			if (fgets(buf, SUITE_LENGTH - 1, f)) {
				if (buf[strlen(buf) - 1] == '\n')
					buf[strlen(buf) - 1] = '\0';
				debconf_set(debconf, DEBCONF_BASE "codename", buf);
				di_log(DI_LOG_LEVEL_INFO, "codename set to: %s", buf);
				ret = 0;
			}
		}
		pclose(f);
	}

	free(hostname);
	free(directory);
	if (suite)
		free(suite);

	if (ret != 0)
		di_log(DI_LOG_LEVEL_ERROR, "Error getting codename");
	return ret;
}
Exemplo n.º 3
0
/* Gets the package list from the retriever and parses it. If a new default
 * retriever has been set, caches the file (except in low memory mode), will
 * use the cached file later when asked to install udebs using the default
 * retriever. */
di_packages *retriever_packages(di_packages_allocator *allocator) {
	di_packages *packages;
	char *command;
	int ret;

	if (! retriever_usecached) {
		command = xasprintf("%s packages " DOWNLOAD_PACKAGES, get_retriever());
		ret = di_exec_shell_log(command);
		free(command);
		if (ret != 0)
			return NULL;
		packages = di_system_packages_read_file(DOWNLOAD_PACKAGES, allocator);
	}
	else {
		packages = di_system_packages_read_file(DOWNLOAD_PACKAGES_DEFAULT, allocator);
	}

	if (retriever_newdefault && packages) {
		rename(DOWNLOAD_PACKAGES, DOWNLOAD_PACKAGES_DEFAULT);
	}
	else {
		unlink(DOWNLOAD_PACKAGES);
	}

	if (!packages) {
		di_log(DI_LOG_LEVEL_ERROR, "can't find packages file");
	}
	return packages;
}
static int validate_mirror(void) {
	char *mir;
	char *host;
	char *dir;
	int valid;

	mir = add_protocol("mirror");
	host = add_protocol("hostname");
	dir = add_protocol("directory");

	if (! manual_entry) {
		char *mirror;

		/*
		 * Copy information about the selected
		 * mirror into mirror/{protocol}/{hostname,directory},
		 * which is the standard location other
		 * tools can look at.
		 */
		debconf_get(debconf, mir);
		mirror = strdup(debconf->value);
		debconf_set(debconf, host, mirror);
		debconf_set(debconf, dir, mirror_root(mirror));
		free(mirror);

		if (base_on_cd) {
			/* We have the base system on the CD, so instead of
			 * trying to contact the mirror (which might take
			 * some time to time out if there's no network
			 * connection), let's just assume that the CD will
			 * be sufficient to get a basic system up, setting
			 * suite to PREFERRED_DISTRIBUTION if unset and
			 * codename = suite. Note that this is an
			 * Ubuntu-specific change since (a) Debian netinst
			 * CDs etc. may not be able to install a complete
			 * system from the network and (b) codename != suite
			 * in Debian.
			 *
			 * We only do this for mirrors in our mirror list,
			 * since we assume that those have a good chance of
			 * not being typoed. For manually-entered mirrors,
			 * we still do full mirror validation.
			 */
			di_log(DI_LOG_LEVEL_INFO, "base system installable from CD; skipping mirror check");
			debconf_get(debconf, DEBCONF_BASE "suite");
			if (!*debconf->value) {
				di_log(DI_LOG_LEVEL_INFO, "falling back to suite %s", PREFERRED_DISTRIBUTION);
				debconf_set(debconf, DEBCONF_BASE "suite", PREFERRED_DISTRIBUTION);
			}
			debconf_get(debconf, DEBCONF_BASE "suite");
			di_log(DI_LOG_LEVEL_INFO, "falling back to codename %s", debconf->value);
			debconf_set(debconf, DEBCONF_BASE "codename", debconf->value);
			exit(0);
		}

		valid = find_suite();
	}
	else {
		/* check to see if the entered data is basically ok */
		int ok = 1;
		debconf_get(debconf, host);
		if (debconf->value == NULL || strcmp(debconf->value, "") == 0 || strchr(debconf->value, '/') != NULL) {
			ok = 0;
		}
		debconf_get(debconf, dir);
		if (debconf->value == NULL || strcmp(debconf->value, "") == 0) {
			ok = 0;
		}

		if (ok) {
			valid = find_suite();
		}
		else {
			valid = 0;
		}
	}

	free(mir);
	free(host);
	free(dir);

	if (valid) {
		return 0;
	}
	else {
		debconf_input(debconf, "critical", DEBCONF_BASE "bad");
		if (debconf_go(debconf) == 30)
			exit(10); /* back up to menu */
		else
			return 1; /* back to beginning of questions */
	}
}
/*
 * Using the current debconf settings for a mirror, figure out which suite
 * to use from the mirror and set mirror/suite.
 *
 * This is accomplished by downloading the Release file from the mirror.
 * Suite selection tries each suite in turn, and stops at the first one that
 * seems usable.
 *
 * If no Release file is found, returns false. That probably means the
 * mirror is broken or unreachable.
 */
int find_suite (void) {
	char *command;
	FILE *f = NULL;
	char *hostname, *directory;
	int nbr_suites = sizeof(suites)/SUITE_LENGTH;
	int i;
	int ret = 0;
	char buf[SUITE_LENGTH];

	if (show_progress) {
		debconf_progress_start(debconf, 0, 1,
				       DEBCONF_BASE "checking_title");
		debconf_progress_info(debconf,
				      DEBCONF_BASE "checking_download");
	}

	hostname = add_protocol("hostname");
	debconf_get(debconf, hostname);
	free(hostname);
	hostname = strdup(debconf->value);
	directory = add_protocol("directory");
	debconf_get(debconf, directory);
	free(directory);
	directory = strdup(debconf->value);

	/* Try each suite in turn until one is found that works. */
	for (i=0; i <= nbr_suites && ! ret; i++) {
		char *suite;

		if (i == 0) {
			/* First check for a preseeded suite. */
			debconf_get(debconf, DEBCONF_BASE "suite");
			if (strlen(debconf->value) > 0) {
				suite = strdup(debconf->value);
			}
			else {
				/* Read this file to find the default suite
				 * to use. */
				f = fopen("/etc/default-release", "r");
				if (f != NULL) {
					if (fgets(buf, SUITE_LENGTH - 1, f)) {
						if (buf[strlen(buf) - 1] == '\n')
							buf[strlen(buf) - 1] = '\0';
						suite = strdup(buf);
						fclose(f);
					}
					else {
						fclose(f);
						continue;
					}
				}
				else {
					continue;
				}
			}
			
		}
		else {
			suite = strdup(suites[i - 1]);
		}

		asprintf(&command, "wget -q %s://%s%s/dists/%s/Release -O - | grep ^Suite: | cut -d' ' -f 2",
			 protocol, hostname, directory, suite);
		di_log(DI_LOG_LEVEL_DEBUG, "command: %s", command);
		f = popen(command, "r");
		free(command);

		if (f != NULL) {
			if (fgets(buf, SUITE_LENGTH - 1, f)) {
				if (buf[strlen(buf) - 1] == '\n')
					buf[strlen(buf) - 1] = '\0';
				debconf_set(debconf, DEBCONF_BASE "suite", buf);
				ret = 1;
			}
		}

		pclose(f);
		free(suite);
	}

	free(hostname);
	free(directory);

	if (show_progress) {
		debconf_progress_step(debconf, 1);
		debconf_progress_stop(debconf);
	}

	return ret;
}
Exemplo n.º 6
0
bool di_packages_resolve_dependencies_recurse (di_packages_resolve_dependencies_check *r, di_package *package, di_package *dependend_package)
{
  di_slist_node *node;

  /* did we already check this package? */
  if (package->resolver & r->resolver)
  {
#ifdef ENABLE_EXTENSIVE_DEBUG
    if (package->resolver & (r->resolver << 1))
      di_log (DI_LOG_LEVEL_DEBUG, "resolver (%s): already done, okay", package->package);
    else
      di_log (DI_LOG_LEVEL_DEBUG, "resolver (%s): already done, not okay", package->package);
#endif
    return package->resolver & (r->resolver << 1);
  }

  package->resolver |= r->resolver;
  package->resolver |= (r->resolver << 1);

#ifdef ENABLE_EXTENSIVE_DEBUG
  di_log (DI_LOG_LEVEL_DEBUG, "resolver (%s): start", package->package);
#endif

  switch (package->type)
  {
    case di_package_type_real_package:
      for (node = package->depends.head; node; node = node->next)
      {
        di_package_dependency *d = node->data;

        if ((d->type == di_package_dependency_type_depends ||
             d->type == di_package_dependency_type_pre_depends) &&
            !r->check_real (r, package, d))
          goto error;
      }

#ifdef ENABLE_EXTENSIVE_DEBUG
      if (dependend_package)
        di_log (DI_LOG_LEVEL_DEBUG, "resolver (%s): mark, dependency from %s", package->package, dependend_package->package);
      else
        di_log (DI_LOG_LEVEL_DEBUG, "resolver (%s): mark", package->package);
#endif
      
      r->do_real (package, r->do_real_data);
      break;

    case di_package_type_virtual_package:

#ifdef ENABLE_EXTENSIVE_DEBUG
      if (dependend_package)
        di_log (DI_LOG_LEVEL_DEBUG, "resolver (%s): search, dependency from %s", package->package, dependend_package->package);
      else
        di_log (DI_LOG_LEVEL_DEBUG, "resolver (%s): search", package->package);
#endif
      
      for (node = package->depends.head; node; node = node->next)
      {
        di_package_dependency *d = node->data;

        if (d->type == di_package_dependency_type_reverse_provides)
          package->resolver &= ~(r->resolver << 2);
      }

      while (1)
      {
        di_package_dependency *best_provide = NULL;

        for (node = package->depends.head; node; node = node->next)
        {
          di_package_dependency *d = node->data;

          if (d->type == di_package_dependency_type_reverse_provides)
          {
            if (!(package->resolver & (r->resolver << 2)))
              best_provide = r->check_virtual (package, best_provide, d, r->check_virtual_data);
          }
        }

        if (best_provide)
        {
          if (r->check_real (r, dependend_package, best_provide))
            break;
          else
            package->resolver |= (r->resolver << 2);
        }
        else if (!r->check_non_existant (r, package, NULL))
          goto error;
        else
          break;
      }

      break;

    case di_package_type_non_existent:
      if (!r->check_non_existant (r, package, NULL))
        goto error;
  }

  return true;

error:
#ifdef ENABLE_EXTENSIVE_DEBUG
  di_log (DI_LOG_LEVEL_DEBUG, "resolver (%s): not okay", package->package);
#endif
  package->resolver &= ~(r->resolver << 1);
  return false;
}
Exemplo n.º 7
0
int 
task_chain (struct task_act *tk, struct di_block *di)
{
	struct oper_act	* on;
	struct DSError	* err = &(tk->tk_resp.di_error.de_err);
	struct di_block	* di_tmp;
	char		refer_ok = TRUE;

#ifdef DEBUG
	DLOG(log_dsap, LLOG_DEBUG, ("task_chain called with:"));
	di_list_log(di);
#endif

	/* NB At some point this routine must assign the di_block list to
	* either the task (if it is intended to geneate a referral) or to
	* an operation hanging off that task if it is intended to chain the
	* task. This is fine when there are no deferred di_blocks, but when
	* there are then the information they will eventually contain is
	* needed to make a full decision on whether to chain or refer.
	* This needs a lot of thought to get right, for now the chain/refer
	* decision is made once and for all on the basis of the information
	* available now. Any information not available is assumed to force a
	* referral (the safe option  -  until network connectivity is considered)!
	* THis may introduce the unwelcome effect that a first request to a
	* DSA may produce a referral where subsequent requests do not - so much
	* for consistency but it won't happen that often if DSA info is cached
	* sensibly.
	*/

	/*
	*  Generate the referral which the DSA will pass back if
	*  chaining is disallowed or oper_chain fails for all
	*  DSAs listed.
	*/

	sort_dsa_list (&di);

	if ((di_tmp = select_refer_dsa (di,tk)) == NULL_DI_BLOCK) {
		/* The remote END is probably unable to follow the referral - chain if allowed */
		refer_ok = FALSE;
		for(di_tmp=di; di_tmp!=NULL_DI_BLOCK; di_tmp=di_tmp->di_next) {
			if(di_tmp->di_state == DI_DEFERRED)
				continue;

#ifdef DEBUG
			DLOG(log_dsap, LLOG_DEBUG, ("About to call di2cref with:"));
			di_log(di_tmp);
#endif
			if(di2cref(di_tmp, err, tk->tk_conn->cn_ctx) == OK)
				break;
		}
	} else if (di2cref(di_tmp, err, tk->tk_conn->cn_ctx) != OK)
		di_tmp = NULL_DI_BLOCK;	/* waiting... */

	if(di_tmp == NULL_DI_BLOCK) {
		/*
		*  Want to generate a referral - but all di_blocks (if any)
		*  are deferred. Would we be lying too much if we said the
		*  DSA was "busy" at this point???
		*/
		ds_error_free (err);
		err->dse_type = DSE_SERVICEERROR;
		err->ERR_SERVICE.DSE_sv_problem = DSE_SV_BUSY;
		di_desist(di);
		return(NOTOK);
	}

	/*
	*  If it would be inappropriate to chain this operation, then
	*  generate a referral from the di_block list.
	*/

	if(chain_ok(tk,refer_ok,di_tmp->di_dn) == FALSE) {
		DLOG(log_dsap, LLOG_DEBUG, ("Referring!"));
		di_desist(di);
		return(NOTOK);
	}

	DLOG(log_dsap, LLOG_DEBUG, ("Chaining!"));
	/* Chain. Generate the new operation to send */
	if((on = task2oper(tk)) == NULLOPER) {
		DLOG(log_dsap, LLOG_DEBUG, ("Why did task2oper fail??"));
		ds_error_free (err);
		err->dse_type = DSE_SERVICEERROR;
		err->ERR_SERVICE.DSE_sv_problem = DSE_SV_UNAVAILABLE;
		di_desist(di);
		return(NOTOK);
	}

	if(ti_is_elem(tk->tk_dx.dx_arg.dca_charg.cha_trace,
				  tk->tk_dx.dx_arg.dca_charg.cha_trace->ti_next)) {
		DLOG (log_dsap,LLOG_TRACE,("Loop found in oper_chain()"));
		ds_error_free (err);
		err->dse_type = DSE_SERVICEERROR;
		err->ERR_SERVICE.DSE_sv_problem = DSE_SV_LOOPDETECT;
		return(NOTOK);
	}

	on->on_next_task = tk->tk_operlist;
	tk->tk_operlist = on;
	on->on_task = tk;

	/* Hand control of di_blocks to the operation */
	on->on_dsas = di;
	for(di_tmp = di; di_tmp != NULL_DI_BLOCK; di_tmp=di_tmp->di_next) {
		di_tmp->di_type = DI_OPERATION;
		di_tmp->di_oper = on;
	}

	if(oper_chain(on) != OK) {
		oper_task_extract(on);
		oper_free(on);
		return(NOTOK);
	}

#ifdef QUIPU_CONSOLE
	/* SPT trying to insert a chain_analyse here. */
	/* The aim is to add this chained command to */
	/* the open_call_avs structure */

	chaining_analyse(tk, di) ;
#endif /* QUIPU_CONSOLE */

	return(OK);
}
static int find_releases(void) {
	int nbr_suites = sizeof(suites)/SUITE_LENGTH;
	int i, r = 0;
	int bad_mirror = 0, have_default = 0;
	struct release_t release;
	char *default_suite;

	default_suite = get_default_suite();
	if (default_suite == NULL)
		di_log(DI_LOG_LEVEL_ERROR, "no default release specified");

	if (show_progress) {
		debconf_progress_start(debconf, 0, nbr_suites,
				       DEBCONF_BASE "checking_title");
		debconf_progress_info(debconf,
				      DEBCONF_BASE "checking_download");
	}

	/* Initialize releases; also ensures NULL termination of the array */
	memset(&releases, 0, sizeof(releases));

	/* Try to get Release files for all suites. */
	if (! base_on_cd) {
		for (i=0; i < nbr_suites && r < MAXRELEASES; i++) {
			memset(&release, 0, sizeof(release));
			if (get_release(&release, suites[i])) {
				if (release.status & IS_VALID) {
					if (strcmp(release.name, default_suite) == 0 ||
					    strcmp(release.suite, default_suite) == 0) {
						release.status |= IS_DEFAULT;
						have_default = 1;
					}
					/* Only list oldstable if it's the default */
					if (strcmp(suites[i], "oldstable") != 0 ||
					    (release.status & IS_DEFAULT))
						releases[r++] = release;
				} else {
					bad_mirror = 1;
					break;
				}
			}

			if (show_progress)
				debconf_progress_step(debconf, 1);
		}
		if (r == MAXRELEASES)
			di_log(DI_LOG_LEVEL_ERROR, "array overflow: more releases than allowed by MAXRELEASES");
		if (! bad_mirror && r == 0)
			di_log(DI_LOG_LEVEL_INFO, "mirror does not have any suite symlinks");
	}

	/* Try to get Release file using the default "suite". */
	if (! bad_mirror && (base_on_cd || ! have_default)) {
		memset(&release, 0, sizeof(release));
		if (get_release(&release, default_suite)) {
			if (release.status & IS_VALID) {
				release.status |= IS_DEFAULT;
				releases[r++] = release;
				have_default = 1;
			} else {
				bad_mirror = 1;
			}
		} else {
			di_log(DI_LOG_LEVEL_WARNING,
				"mirror does not support the specified release (%s)",
				default_suite);
		}
		if (r == MAXRELEASES)
			di_log(DI_LOG_LEVEL_ERROR, "array overflow: more releases than allowed by MAXRELEASES");
	}

	if (show_progress) {
		debconf_progress_set(debconf, nbr_suites);
		debconf_progress_stop(debconf);
	}

	if (r == 0 || bad_mirror) {
		unset_seen_flags();
		free(default_suite);
		free(release.name);
		free(release.suite);

		debconf_input(debconf, "critical", DEBCONF_BASE "bad");
		if (debconf_go(debconf) == 30)
			exit(10); /* back up to menu */
		else
			return 1; /* back to beginning of questions */
	}

	if (! base_on_cd && ! have_default) {
		unset_seen_flags();

		debconf_subst(debconf, DEBCONF_BASE "no-default",
			"RELEASE", default_suite);
		free(default_suite);

		debconf_input(debconf, "critical", DEBCONF_BASE "no-default");
		if (debconf_go(debconf) == 30) {
			exit(10); /* back up to menu */
		} else {
			debconf_get(debconf, DEBCONF_BASE "no-default");
			if (strcmp(debconf->value, "false"))
				return 1; /* back to beginning of questions */
		}
	} else {
		free(default_suite);
	}

	return 0;
}
/*
 * Fetch a Release file, extract its Suite and Codename and check its valitity.
 */
static int get_release(struct release_t *release, const char *name) {
	char *command;
	FILE *f = NULL;
	char *hostname, *directory;
	char line[80];
	char buf[SUITE_LENGTH];

	if (base_on_cd && ! manual_entry) {
		/* We have the base system on the CD, so instead of trying
		 * to contact the mirror (which might take some time to time
		 * out if there's no network connection), let's just assume
		 * that the CD will be sufficient to get a basic system up,
		 * setting codename = suite.  Note that this is an
		 * Ubuntu-specific change since (a) Debian netinst CDs etc.
		 * may not be able to install a complete system from the
		 * network and (b) codename != suite in Debian.
		 *
		 * We only do this for mirrors in our mirror list, since we
		 * assume that those have a good chance of not being typoed.
		 * For manually-entered mirrors, we still do full mirror
		 * validation.
		 */
		di_log(DI_LOG_LEVEL_INFO, "base system installable from CD; skipping mirror check");
		release->name = strdup(name);
		release->suite = strdup(name);
		release->status = IS_VALID | GET_CODENAME;
		return 1;
	}

	hostname = add_protocol("hostname");
	debconf_get(debconf, hostname);
	free(hostname);
	hostname = strdup(debconf->value);
	directory = add_protocol("directory");
	debconf_get(debconf, directory);
	free(directory);
	directory = strdup(debconf->value);

	asprintf(&command, "wget -q %s://%s%s/dists/%s/Release -O - | grep -E '^(Suite|Codename):'",
		 protocol, hostname, directory, name);
	di_log(DI_LOG_LEVEL_DEBUG, "command: %s", command);
	f = popen(command, "r");
	free(command);
	free(hostname);
	free(directory);

	if (f != NULL) {
		while (fgets(line, sizeof(line), f) != NULL) {
			char *value;

			if (line[strlen(line) - 1] == '\n')
				line[strlen(line) - 1] = '\0';
			if ((value = strstr(line, ": ")) != NULL) {
				strncpy(buf, value + 2, SUITE_LENGTH - 1);
				buf[SUITE_LENGTH - 1] = '\0';
				if (strncmp(line, "Codename:", 9) == 0)
					release->name = strdup(buf);
				if (strncmp(line, "Suite:", 6) == 0)
					release->suite = strdup(buf);
			}
		}
		if (release->name != NULL && strcmp(release->name, name) == 0)
			release->status |= IS_VALID | GET_CODENAME;
		if (release->suite != NULL && strcmp(release->suite, name) == 0)
			release->status |= IS_VALID | GET_SUITE;

		if ((release->name != NULL || release->suite != NULL) &&
		    !(release->status & IS_VALID))
			log_invalid_release(name, "Suite or Codename");

		/* Cross-validate the Release file */
		if (release->status & IS_VALID)
			if (! cross_validate_release(release))
				log_invalid_release(name, (release->status & GET_SUITE) ? "Codename" : "Suite");

		/* In case there is no Codename field */
		if ((release->status & IS_VALID) && release->name == NULL)
			release->name = strdup(name);

		// di_log(DI_LOG_LEVEL_DEBUG, "get_release(): %s -> %s:%s (0x%x)",
		//	name, release->suite, release->name, release->status);
	}

	pclose(f);

	if (release->name != NULL) {
		return 1;
	} else {
		free(release->suite);
		return 0;
	}
}
void log_invalid_release(const char *name, const char *field) {
	di_log(DI_LOG_LEVEL_WARNING,
		"broken mirror: invalid %s in Release file for %s", field, name);
}