diff -ur curl-7.19.2.orig/configure.ac curl-7.19.2/configure.ac
--- curl-7.19.2.orig/configure.ac	2008-11-11 00:22:59.000000000 +0900
+++ curl-7.19.2/configure.ac	2008-12-12 23:52:17.000000000 +0900
@@ -1467,6 +1467,98 @@
 AM_CONDITIONAL(HAVE_LIBZ, test x"$AMFIXLIB" = x1)
 
 dnl **********************************************************************
+dnl Check for the presence of LIBMETALINK libraries and headers
+dnl **********************************************************************
+
+dnl Check for & handle argument to --with-metalink.
+
+_cppflags=$CPPFLAGS
+_ldflags=$LDFLAGS
+AC_ARG_WITH(metalink,
+AC_HELP_STRING([--with-metalink=PATH],[search for libmetalink in PATH])
+AC_HELP_STRING([--without-metalink],[disable use of libmetalink.]),
+               [OPT_METALINK="$withval"])
+
+if test "$OPT_METALINK" = "no" ; then
+    AC_MSG_WARN([metalink disabled])
+else
+  if test "$OPT_METALINK" = "yes" ; then
+     OPT_METALINK=""
+  fi
+
+  if test -z "$OPT_METALINK"; then
+     dnl check for the lib first without setting any new path, since many
+     dnl people have it in the default path
+
+     AC_CHECK_LIB(metalink, metalink_parse_file,
+                  dnl libmetalink found, set the variable
+                  [HAVE_LIBMETALINK="1"],
+                  dnl if no lib found, try /usr/local
+                  [OPT_METALINK="/usr/local"])
+  fi
+
+  dnl Add a nonempty path to the compiler flags
+  if test -n "$OPT_METALINK"; then
+     CPPFLAGS="$CPPFLAGS -I$OPT_METALINK/include"
+     LDFLAGS="$LDFLAGS -L$OPT_METALINK/lib$libsuff"
+  fi
+
+  AC_CHECK_HEADER([metalink/metalink_parser.h],
+    [
+    dnl metalink/metalink_parser.h was found
+    HAVE_METALINK_H="1"
+    dnl if the lib wan't found already, try again with the new paths
+    if test "$HAVE_LIBMETALINK" != "1"; then
+      AC_CHECK_LIB(metalink, metalink_parse_file,
+                   [
+                   dnl the lib was found!
+                   HAVE_LIBMETALINK="1"
+                   ],
+                   [ CPPFLAGS=$_cppflags
+                   LDFLAGS=$_ldflags])
+    fi
+    ],
+    [
+      dnl metalink/metalink_parser.h was not found, restore the flags
+      CPPFLAGS=$_cppflags
+      LDFLAGS=$_ldflags]
+    )
+
+  if test "$HAVE_LIBMETALINK" = "1" && test "$HAVE_METALINK_H" != "1"
+  then
+    AC_MSG_WARN([configure found only the libmetalink lib, not the header file!])
+    HAVE_LIBMETALINK=""
+  elif test "$HAVE_LIBMETALINK" != "1" && test "$HAVE_METALINK_H" = "1"
+  then
+    AC_MSG_WARN([configure found only the libmetalink header file, not the lib!])
+  elif test "$HAVE_LIBMETALINK" = "1" && test "$HAVE_METALINK_H" = "1"
+  then
+    dnl both header and lib were found!
+    AC_SUBST(HAVE_LIBMETALINK)
+    AC_DEFINE(HAVE_METALINK_H, 1, [if you have the metalink/metalink_parser.h header file])
+    AC_DEFINE(HAVE_LIBMETALINK, 1, [if libmetalink is available])
+
+    CURL_LIBS="$CURL_LIBS -lmetalink"
+    LIBS="$LIBS -lmetalink"
+
+    dnl replace 'HAVE_LIBMETALINK' in the automake makefile.ams
+    AMFIXLIB="1"
+    AC_MSG_NOTICE([found both libmetalink and metalink/metalink_parser.h header])
+    curl_metalink_msg="enabled"
+
+    dnl when shared libs were found in a path that the run-time
+    dnl linker doesn't search through, we need to add it to
+    dnl LD_LIBRARY_PATH to prevent further configure tests to fail
+    dnl due to this
+
+    LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$OPT_METALINK/lib$libsuff"
+    export LD_LIBRARY_PATH
+    AC_MSG_NOTICE([Added $OPT_METALINK/lib$libsuff to LD_LIBRARY_PATH])
+
+  fi
+fi
+
+dnl **********************************************************************
 dnl Check for the presence of LIBSSH2 libraries and headers
 dnl **********************************************************************
 
@@ -2606,6 +2698,7 @@
   ca cert path:    ${capath}
   LDAP support:    ${curl_ldap_msg}
   LDAPS support:   ${curl_ldaps_msg} 
+  metalink support:${curl_metalink_msg}
 ])
 
 if test "x$soname_bump" = "xyes"; then
diff -ur curl-7.19.2.orig/src/main.c curl-7.19.2/src/main.c
--- curl-7.19.2.orig/src/main.c	2008-10-29 07:12:02.000000000 +0900
+++ curl-7.19.2/src/main.c	2008-12-12 23:52:17.000000000 +0900
@@ -114,6 +114,10 @@
 #include <netinet/tcp.h> /* for TCP_KEEPIDLE, TCP_KEEPINTVL */
 #endif
 
+#ifdef HAVE_LIBMETALINK
+#include <metalink/metalink_parser.h>
+#endif /* HAVE_LIBMETALINK */
+
 /* The last #include file should be: */
 #ifdef CURLDEBUG
 #ifndef CURLTOOLDEBUG
@@ -675,6 +679,11 @@
 struct getout {
   struct getout *next; /* next one */
   char *url;     /* the URL we deal with */
+#ifdef HAVE_LIBMETALINK
+  char **alternate_url; /* the URL for fail over, but it contains URL pointed
+                           by the above url pointer.
+                           This is used for metalink download. */
+#endif /* HAVE_LIBMETALINK */
   char *outfile; /* where to store the output */
   char *infile;  /* file to upload, if GETOUT_UPLOAD is set */
   int flags;     /* options */
@@ -1672,6 +1681,9 @@
     {"$2", "socks5-hostname", TRUE},
     {"$3", "keepalive-time",  TRUE},
     {"$4", "post302",    FALSE},
+#ifdef HAVE_LIBMETALINK
+    {"$5", "metalink",   TRUE},
+#endif /* HAVE_LIBMETALINK */
 
     {"0", "http1.0",     FALSE},
     {"1", "tlsv1",       FALSE},
@@ -2181,8 +2193,66 @@
       case '4': /* --post302 */
         config->post302 = toggle;
         break;
+#ifdef HAVE_LIBMETALINK
+      case '5': /* --metalink */
+        {
+          metalink_error_t r;
+          metalink_t* metalink;
+          metalink_file_t **files;
+          metalink_checksum_t** checksums;
+	  
+          r = metalink_parse_file(nextarg, &metalink);
+
+          if(r != 0) {
+            fprintf(stderr, "ERROR: code=%d\n", r);
+            exit(EXIT_FAILURE);
+          }
+          for(files = metalink->files; *files; files++) {
+            /* Skip an entry which has no resource. */
+            if(!(*files)->resources[0]) continue;
+            struct getout *url;
+            if(config->url_get || (config->url_get=config->url_list)) {
+              /* there's a node here, if it already is filled-in continue to
+                 find an "empty" node */
+              while(config->url_get && (config->url_get->flags&GETOUT_URL))
+                config->url_get = config->url_get->next;
+            }
+	    
+            /* now there might or might not be an available node to fill in! */
+	    
+            if(config->url_get)
+              /* existing node */
+              url = config->url_get;
+            else
+              /* there was no free node, create one! */
+              url=new_getout(config);
+	    
+            if(url) {
+              metalink_resource_t **resources;
+              size_t count;
+              char **alternate_url;
+              /* fill in the URL */
+              GetStr(&url->url, (*files)->resources[0]->url);
+              url->flags |= GETOUT_URL;
+              count = 0;
+              for(resources = (*files)->resources; *resources; ++resources)
+                count++;
+              url->alternate_url = calloc(sizeof(char*), count+1);
+              alternate_url = url->alternate_url;
+              for(resources = (*files)->resources; *resources;
+                  resources++, alternate_url++) {
+                /* fill in the URL */
+                GetStr(alternate_url, (*resources)->url);
+              }
+              *alternate_url = 0;
+            }
+          }
+          metalink_delete(metalink);
+          break;
+        }
       }
       break;
+#endif /* HAVE_LIBMETALINK */
     case '#': /* --progress-bar */
       config->progressmode = toggle?CURL_PROGRESS_BAR:0;
       break;
@@ -4237,7 +4307,17 @@
 
       /* Here's looping around each globbed URL */
       for(i = 0;
+#ifdef HAVE_LIBMETALINK
+          /* Turn off URL globing if metalink is used for now */
+          (!urlnode->alternate_url
+           && (url = urls?glob_next_url(urls):(i?NULL:strdup(url))))
+            ||
+            (urlnode->alternate_url
+             && (url = urlnode->alternate_url[i]?
+                 strdup(urlnode->alternate_url[i]):NULL));
+#else /* !HAVE_LIBMETALINK */
           (url = urls?glob_next_url(urls):(i?NULL:strdup(url)));
+#endif /* !HAVE_LIBMETALINK */
           i++) {
         /* NOTE: In the condition expression in the for() statement above, the
            'url' variable is only ever strdup()ed if (i == 0) and thus never
@@ -5007,6 +5087,15 @@
         if(infdopen)
           close(infd);
 
+#ifdef HAVE_LIBMETALINK
+        /* Exit loop here if metalink is used and curl_easy_perform returns OK.
+         * TODO need more strict check whether the transfer is completed or
+         * another URI should be tried.
+         */
+        if(urlnode->alternate_url && res == CURLE_OK) {
+          break;
+        }
+#endif /* HAVE_LIBMETALINK */
       } /* loop to the next URL */
 
       if(urls) {
@@ -5031,6 +5120,15 @@
     /* empty this urlnode struct */
     if(urlnode->url)
       free(urlnode->url);
+#ifdef HAVE_LIBMETALINK
+    if(urlnode->alternate_url) {
+      char **urls;
+      for(urls = urlnode->alternate_url; (*urls); urls++) {
+	free(*urls);
+      }
+      free(urlnode->alternate_url);
+    }
+#endif /* HAVE_LIBMETALINK */
     if(urlnode->outfile)
       free(urlnode->outfile);
     if(urlnode->infile)

