Index: uspace/app/download/main.c
===================================================================
--- uspace/app/download/main.c	(revision fab2746a5541d35bc79cbed917f66153231e4a4b)
+++ uspace/app/download/main.c	(revision 9621c7dd134d4f9ad92d35ccd95913ca38bff027)
@@ -57,6 +57,6 @@
 static void syntax_print(void)
 {
-	fprintf(stderr, "Usage: download <url>\n");
-	fprintf(stderr, "  This will write the data to stdout, so you may want\n");
+	fprintf(stderr, "Usage: download [-o <outfile>] <url>\n");
+	fprintf(stderr, "  Without -o, data will be written to stdout, so you may want\n");
 	fprintf(stderr, "  to redirect the output, e.g.\n");
 	fprintf(stderr, "\n");
@@ -66,18 +66,54 @@
 int main(int argc, char *argv[])
 {
-	if (argc != 2) {
+	int i;
+	char *ofname = NULL;
+	FILE *ofile = NULL;
+	size_t buf_size = 4096;
+	void *buf = NULL;
+	uri_t *uri = NULL;
+	int rc;
+
+	if (argc < 2) {
 		syntax_print();
-		return 2;
-	}
-	
-	uri_t *uri = uri_parse(argv[1]);
+		rc = EINVAL;
+		goto error;
+	}
+	
+	i = 1;
+	
+	if (str_cmp(argv[i], "-o") == 0) {
+		++i;
+		if (argc < i + 1) {
+			syntax_print();
+			rc = EINVAL;
+			goto error;
+		}
+		
+		ofname = argv[i++];
+		ofile = fopen(ofname, "wb");
+		if (ofile == NULL) {
+			fprintf(stderr, "Error creating '%s'.\n", ofname);
+			rc = EINVAL;
+			goto error;
+		}
+	}
+	
+	if (argc != i + 1) {
+		syntax_print();
+		rc = EINVAL;
+		goto error;
+	}
+	
+	uri = uri_parse(argv[i]);
 	if (uri == NULL) {
 		fprintf(stderr, "Failed parsing URI\n");
-		return 2;
+		rc = EINVAL;
+		goto error;
 	}
 	
 	if (!uri_validate(uri)) {
 		fprintf(stderr, "The URI is invalid\n");
-		return 2;
+		rc = EINVAL;
+		goto error;
 	}
 	
@@ -86,18 +122,21 @@
 	if (str_cmp(uri->scheme, "http") != 0) {
 		fprintf(stderr, "Only http scheme is supported at the moment\n");
-		return 2;
+		rc = EINVAL;
+		goto error;
 	}
 	
 	if (uri->host == NULL) {
 		fprintf(stderr, "host not set\n");
-		return 2;
+		rc = EINVAL;
+		goto error;
 	}
 	
 	uint16_t port = 80;
 	if (uri->port != NULL) {
-		int rc = str_uint16_t(uri->port, NULL, 10, true, &port);
+		rc = str_uint16_t(uri->port, NULL, 10, true, &port);
 		if (rc != EOK) {
 			fprintf(stderr, "Invalid port number: %s\n", uri->port);
-			return 2;
+			rc = EINVAL;
+			goto error;
 		}
 	}
@@ -111,14 +150,13 @@
 		if (server_path == NULL) {
 			fprintf(stderr, "Failed allocating path\n");
-			uri_destroy(uri);
-			return 3;
-		}
-	}
-	else {
-		int rc = asprintf(&server_path, "%s?%s", path, uri->query);
+			rc = ENOMEM;
+			goto error;
+		}
+	} else {
+		rc = asprintf(&server_path, "%s?%s", path, uri->query);
 		if (rc < 0) {
 			fprintf(stderr, "Failed allocating path\n");
-			uri_destroy(uri);
-			return 3;
+			rc = ENOMEM;
+			goto error;
 		}
 	}
@@ -128,13 +166,12 @@
 	if (req == NULL) {
 		fprintf(stderr, "Failed creating request\n");
-		uri_destroy(uri);
-		return 3;
-	}
-	
-	int rc = http_headers_append(&req->headers, "Host", uri->host);
+		rc = ENOMEM;
+		goto error;
+	}
+	
+	rc = http_headers_append(&req->headers, "Host", uri->host);
 	if (rc != EOK) {
 		fprintf(stderr, "Failed setting Host header: %s\n", str_error(rc));
-		uri_destroy(uri);
-		return rc;
+		goto error;
 	}
 	
@@ -142,13 +179,12 @@
 	if (rc != EOK) {
 		fprintf(stderr, "Failed creating User-Agent header: %s\n", str_error(rc));
-		uri_destroy(uri);
-		return rc;
+		goto error;
 	}
 	
 	http_t *http = http_create(uri->host, port);
 	if (http == NULL) {
-		uri_destroy(uri);
 		fprintf(stderr, "Failed creating HTTP object\n");
-		return 3;
+		rc = ENOMEM;
+		goto error;
 	}
 	
@@ -156,6 +192,6 @@
 	if (rc != EOK) {
 		fprintf(stderr, "Failed connecting: %s\n", str_error(rc));
-		uri_destroy(uri);
-		return rc;
+		rc = EIO;
+		goto error;
 	}
 	
@@ -163,6 +199,6 @@
 	if (rc != EOK) {
 		fprintf(stderr, "Failed sending request: %s\n", str_error(rc));
-		uri_destroy(uri);
-		return rc;
+		rc = EIO;
+		goto error;
 	}
 	
@@ -172,6 +208,6 @@
 	if (rc != EOK) {
 		fprintf(stderr, "Failed receiving response: %s\n", str_error(rc));
-		uri_destroy(uri);
-		return rc;
+		rc = EIO;
+		goto error;
 	}
 	
@@ -179,17 +215,15 @@
 		fprintf(stderr, "Server returned status %d %s\n", response->status,
 		    response->message);
-	}
-	else {
-		size_t buf_size = 4096;
-		void *buf = malloc(buf_size);
+	} else {
+		buf = malloc(buf_size);
 		if (buf == NULL) {
 			fprintf(stderr, "Failed allocating buffer\n)");
-			uri_destroy(uri);
-			return ENOMEM;
+			rc = ENOMEM;
+			goto error;
 		}
 		
 		int body_size;
 		while ((body_size = recv_buffer(&http->recv_buffer, buf, buf_size)) > 0) {
-			fwrite(buf, 1, body_size, stdout);
+			fwrite(buf, 1, body_size, ofile != NULL ? ofile : stdout);
 		}
 		
@@ -199,6 +233,19 @@
 	}
 	
+	free(buf);
 	uri_destroy(uri);
+	if (fclose(ofile) != 0) {
+		printf("Error writing '%s'.\n", ofname);
+		return EIO;
+	}
+
 	return EOK;
+error:
+	free(buf);
+	if (uri != NULL)
+		uri_destroy(uri);
+	if (ofile != NULL)
+		fclose(ofile);
+	return rc;
 }
 
