diff options
-rw-r--r-- | mdk-stage1/network.c | 150 |
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; +} |