wget: -O FILE is allowed to overwrite existing file (compat)
[oweals/busybox.git] / networking / wget.c
index 5feb539d5174fc053abb222307c9c2dd16dc1e3f..3f9954cf5dcfc440d0e052122f98a155a070860c 100644 (file)
 struct host_info {
        // May be used if we ever will want to free() all xstrdup()s...
        /* char *allocated; */
-       char    *path;
-       char    *user;
-       char    *host;
-       int      port;
-       smallint is_ftp;
+       const char *path;
+       const char *user;
+       char       *host;
+       int         port;
+       smallint    is_ftp;
 };
 
 
@@ -142,7 +142,7 @@ static void progressmeter(int flag)
                /* last call to progressmeter */
                alarm(0);
                transferred = 0;
-               putc('\n', stderr);
+               fputc('\n', stderr);
        } else {
                if (flag == -1) {
                        /* first call to progressmeter */
@@ -318,9 +318,7 @@ static void parse_url(char *src_url, struct host_info *h)
        p = strchr(h->host, '?'); if (!sp || (p && sp > p)) sp = p;
        p = strchr(h->host, '#'); if (!sp || (p && sp > p)) sp = p;
        if (!sp) {
-               /* must be writable because of bb_get_last_path_component() */
-               static char nullstr[] ALIGN1 = "";
-               h->path = nullstr;
+               h->path = "";
        } else if (*sp == '/') {
                *sp = '\0';
                h->path = sp + 1;
@@ -328,7 +326,7 @@ static void parse_url(char *src_url, struct host_info *h)
                // http://busybox.net?login=john@doe is a valid URL
                // memmove converts to:
                // http:/busybox.nett?login=john@doe...
-               memmove(h->host-1, h->host, sp - h->host);
+               memmove(h->host - 1, h->host, sp - h->host);
                h->host--;
                sp[-1] = '\0';
                h->path = sp;
@@ -411,8 +409,8 @@ int wget_main(int argc, char **argv)
        llist_t *headers_llist = NULL;
 #endif
        FILE *sfp = NULL;               /* socket to web/ftp server         */
-       FILE *dfp = NULL;               /* socket to ftp server (data)      */
-       char *fname_out = NULL;         /* where to direct output (-O)      */
+       FILE *dfp;                      /* socket to ftp server (data)      */
+       char *fname_out;                /* where to direct output (-O)      */
        bool got_clen = 0;              /* got content-length: from server  */
        int output_fd = -1;
        bool use_proxy = 1;             /* Use proxies if env vars are set  */
@@ -497,40 +495,31 @@ int wget_main(int argc, char **argv)
                }
        }
 
-       /* Guess an output filename */
-       if (!fname_out) {
-               // Dirty hack. Needed because bb_get_last_path_component
-               // will destroy trailing / by storing '\0' in last byte!
-               if (!last_char_is(target.path, '/')) {
-                       fname_out = bb_get_last_path_component(target.path);
-#if ENABLE_FEATURE_WGET_STATUSBAR
-                       curfile = fname_out;
-#endif
-               }
-               if (!fname_out || !fname_out[0]) {
-                       /* bb_get_last_path_component writes
-                        * to last '/' only. We don't have one here... */
+       /* Guess an output filename, if there was no -O FILE */
+       if (!(opt & WGET_OPT_OUTNAME)) {
+               fname_out = bb_get_last_path_component_nostrip(target.path);
+               /* handle "wget http://kernel.org//" */
+               if (fname_out[0] == '/' || !fname_out[0])
                        fname_out = (char*)"index.html";
-#if ENABLE_FEATURE_WGET_STATUSBAR
-                       curfile = fname_out;
-#endif
-               }
-               if (dir_prefix != NULL)
+               /* -P DIR is considered only if there was no -O FILE */
+               if (dir_prefix)
                        fname_out = concat_path_file(dir_prefix, fname_out);
-#if ENABLE_FEATURE_WGET_STATUSBAR
        } else {
-               curfile = bb_get_last_path_component(fname_out);
-#endif
+               if (LONE_DASH(fname_out)) {
+                       /* -O - */
+                       output_fd = 1;
+                       opt &= ~WGET_OPT_CONTINUE;
+               }
        }
+#if ENABLE_FEATURE_WGET_STATUSBAR
+       curfile = bb_get_last_path_component_nostrip(fname_out);
+#endif
+
        /* Impossible?
        if ((opt & WGET_OPT_CONTINUE) && !fname_out)
                bb_error_msg_and_die("cannot specify continue (-c) without a filename (-O)"); */
 
        /* Determine where to start transfer */
-       if (LONE_DASH(fname_out)) {
-               output_fd = 1;
-               opt &= ~WGET_OPT_CONTINUE;
-       }
        if (opt & WGET_OPT_CONTINUE) {
                output_fd = open(fname_out, O_WRONLY);
                if (output_fd >= 0) {
@@ -757,9 +746,13 @@ int wget_main(int argc, char **argv)
         */
 
        /* Do it before progressmeter (want to have nice error message) */
-       if (output_fd < 0)
-               output_fd = xopen(fname_out,
-                       O_WRONLY|O_CREAT|O_EXCL|O_TRUNC);
+       if (output_fd < 0) {
+               int o_flags = O_WRONLY | O_CREAT | O_TRUNC | O_EXCL;
+               /* compat with wget: -O FILE can overwrite */
+               if (opt & WGET_OPT_OUTNAME)
+                       o_flags = O_WRONLY | O_CREAT | O_TRUNC;
+               output_fd = xopen(fname_out, o_flags);
+       }
 
        if (!(opt & WGET_OPT_QUIET))
                progressmeter(-1);