summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mdk-stage1/network.c150
1 files changed, 149 insertions, 1 deletions
diff --git a/mdk-stage1/network.c b/mdk-stage1/network.c
index f9e3951c3..7cae99e47 100644
--- a/mdk-stage1/network.c
+++ b/mdk-stage1/network.c
@@ -21,7 +21,6 @@
#include <stdlib.h>
#include <unistd.h>
-#include <string.h>
#include <sys/socket.h>
#include <net/if.h>
#include <arpa/inet.h>
@@ -47,6 +46,10 @@
#include "network.h"
+/* include it after config-stage1.h so that _GNU_SOURCE is defined and strndup is available */
+#include <string.h>
+
+static int choose_mirror_from_list(const char *desired_protocol, char **host, char **filepath);
static void error_message_net(void) /* reduce code size */
{
@@ -728,6 +731,10 @@ enum return_type ftp_prepare(void)
int use_http_proxy;
char ftp_hostname[500];
+ if (answers == NULL)
+ answers = (char **) malloc(sizeof(questions));
+ results = choose_mirror_from_list("ftp", &answers[0], &answers[1]);
+
results = ask_from_entries_auto("Please enter the name or IP address of the FTP server, "
"the directory containing the " DISTRIB_NAME " Distribution, "
"and the login/pass if necessary (leave login blank for anonymous). "
@@ -904,3 +911,144 @@ enum return_type http_prepare(void)
return RETURN_OK;
}
+
+static int mirrorlist_entry_split(const char *entry, char *mirror[4]) /* mirror = { medium, protocol, host, path } */
+{
+ char *medium_sep, *protocol_sep, *host_sep, *path_sep;
+
+ medium_sep = strchr(entry, ':');
+ if (!medium_sep || medium_sep == entry) {
+ log_message("NETWORK: no medium in \"%s\"", entry);
+ return -1;
+ }
+
+ mirror[0] = strndup(entry, medium_sep - entry);
+ entry = medium_sep + 1;
+
+ protocol_sep = strstr(entry, "://");
+ if (!protocol_sep || protocol_sep == entry) {
+ log_message("NETWORK: no protocol in \"%s\"", entry);
+ return -1;
+ }
+
+ mirror[1] = strndup(entry, protocol_sep - entry);
+ entry = protocol_sep + 3;
+
+ host_sep = strchr(entry, '/');
+ if (!host_sep || host_sep == entry) {
+ log_message("NETWORK: no hostname in \"%s\"", entry);
+ return -1;
+ }
+
+ mirror[2] = strndup(entry, host_sep - entry);
+ entry = host_sep;
+
+ path_sep = strstr(entry, "/Mandrake/RPMS");
+ if (!path_sep || path_sep == entry) {
+ log_message("NETWORK: this path isn't valid : \"%s\"", entry);
+ return -1;
+ }
+
+ mirror[3] = strndup(entry, path_sep - entry);
+
+ return 0;
+}
+
+static int choose_mirror_from_list(const char *protocol, char **selected_host, char **filepath) {
+ enum return_type results;
+ char *mirrorlist[MIRRORLIST_MAX_ITEMS][4];
+ char *medialist[MIRRORLIST_MAX_MEDIA+1];
+ int mirrorlist_number = 0, media_number = 0;
+ int fd, size, line_pos = 0;
+ char line[500];
+
+ if (IS_AUTOMATIC)
+ return RETURN_OK;
+
+
+ fd = http_download_file(MIRRORLIST_HOST, MIRRORLIST_PATH, &size, NULL, NULL, NULL);
+ if (fd < 0) {
+ log_message("HTTP: unable to get mirrors list");
+ return RETURN_ERROR;
+ }
+
+ while (read(fd, line + line_pos, 1) > 0) {
+ if (line[line_pos] == '\n') {
+ line[line_pos] = '\0';
+ line_pos = 0;
+
+ /* skip medium if it looks like an updates one */
+ if (strstr(line, "updates"))
+ continue;
+
+ if (mirrorlist_entry_split(line, mirrorlist[mirrorlist_number]) < 0)
+ continue;
+
+ /* add medium in media list if different from previous one */
+ if (media_number < 1 ||
+ strcmp(mirrorlist[mirrorlist_number][0], medialist[media_number-1])) {
+ medialist[media_number] = mirrorlist[mirrorlist_number][0];
+ media_number++;
+ }
+
+ mirrorlist_number++;
+ } else {
+ line_pos++;
+ }
+
+ if (mirrorlist_number >= MIRRORLIST_MAX_ITEMS || media_number >= MIRRORLIST_MAX_MEDIA)
+ break;
+ }
+ close(fd);
+
+ medialist[media_number] = NULL;
+
+ do {
+ char *hosts[MIRRORLIST_MAX_ITEMS+1];
+ char *selected_medium;
+ int host_index = 0, mirrorlist_index;
+
+ results = ask_from_list("Please select a medium in the list, "
+ "or cancel to specify the mirror.",
+ medialist, &selected_medium);
+
+ if (results != RETURN_OK)
+ break;
+
+ /* select hosts matching medium and protocol */
+ for (mirrorlist_index = 0; mirrorlist_index < mirrorlist_number; mirrorlist_index++) {
+ if (!strcmp(mirrorlist[mirrorlist_index][0], selected_medium) &&
+ !strcmp(mirrorlist[mirrorlist_index][1], protocol)) {
+ hosts[host_index] = mirrorlist[mirrorlist_index][2];
+ host_index++;
+ if (host_index == MIRRORLIST_MAX_ITEMS)
+ break;
+ }
+
+ }
+ hosts[host_index+1] = NULL;
+
+ results = ask_from_list("Please select a mirror in the list, "
+ "or cancel to specify it.",
+ hosts, selected_host);
+ if (results != RETURN_OK) {
+ break;
+ }
+
+ /* select the path according to medium, protocol and host */
+ for (mirrorlist_index = 0; mirrorlist_index < mirrorlist_number; mirrorlist_index++) {
+ if (!strcmp(mirrorlist[mirrorlist_index][0], selected_medium) &&
+ !strcmp(mirrorlist[mirrorlist_index][1], protocol) &&
+ !strcmp(mirrorlist[mirrorlist_index][2], *selected_host)) {
+ *filepath = mirrorlist[mirrorlist_index][3];
+ return RETURN_OK;
+ }
+ }
+
+ stg1_info_message("Unable to find the path for this mirror, please select another one");
+ results = RETURN_BACK;
+
+ } while (results == RETURN_BACK);
+
+ return RETURN_ERROR;
+}