blob: 28123a234ef554ebe46adef2bee29c8c154d4d06 [file] [log] [blame]
/*
* Copyright (c) 2014 The Native Client Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#define __STDC_FORMAT_MACROS
#include <errno.h>
#include <fcntl.h>
#include <inttypes.h>
#include <stdio.h>
#include <unistd.h>
#include "nacl_main.h"
#include "ppapi_simple/ps.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/cpp/completion_callback.h"
#include "ppapi/cpp/instance_handle.h"
#include "ppapi/cpp/module.h"
#include "ppapi/cpp/url_loader.h"
#include "ppapi/cpp/url_request_info.h"
#include "ppapi/cpp/url_response_info.h"
static int Download(const char* url, const char* dst) {
int32_t result;
pp::InstanceHandle instance(PSGetInstanceId());
pp::URLRequestInfo url_request(instance);
url_request.SetURL(url);
url_request.SetMethod("GET");
url_request.SetAllowCrossOriginRequests(true);
url_request.SetRecordDownloadProgress(true);
pp::URLLoader url_loader(instance);
result = url_loader.Open(url_request, pp::BlockUntilComplete());
if (result != PP_OK) {
fprintf(stderr, "ERROR: Can't open url (%d): %s\n", result, url);
return 1;
}
int fh = open(dst, O_WRONLY | O_CREAT);
if (fh < 0) {
fprintf(stderr, "ERROR: Can't open file (%d): %s\n", errno, dst);
return 1;
}
pp::URLResponseInfo info = url_loader.GetResponseInfo();
if (info.GetStatusCode() != 200) {
fprintf(stderr, "ERROR: got http error code %d for: %s\n",
info.GetStatusCode(), url);
return 1;
}
char buffer[0x10000];
ssize_t len;
int64_t received = 0;
int64_t total = 0;
for (;;) {
result = url_loader.ReadResponseBody(
buffer, sizeof buffer, pp::BlockUntilComplete());
if (result <= 0)
break;
len = write(fh, buffer, result);
if (len != result) {
fprintf(stderr, "ERROR: Failed writing to file (%d): %s\n", errno, dst);
close(fh);
return 1;
}
url_loader.GetDownloadProgress(&received, &total);
printf("[%"PRId64"/%"PRId64" KiB %"PRId64"%%]\r",
received / 1024, total / 1024, received * 100 / total);
fflush(stdout);
} while (result > 0);
printf(" \r");
printf("[%"PRId64"/%"PRId64" KiB 100%%] Done.\n",
received / 1024, total / 1024);
if (result != PP_OK) {
fprintf(stderr, "ERROR: Failed downloading url (%d): %s\n", result, url);
close(fh);
return 1;
}
if (close(fh) < 0) {
fprintf(stderr, "ERROR: Failed closing file (%d): %s\n", errno, dst);
return 1;
}
return 0;
}
int nacl_main(int argc, char *argv[]) {
if (argc != 3) {
fprintf(stderr, "USAGE: %s <url> <dst>\n", argv[0]);
fprintf(stderr, "\n");
fprintf(stderr, "NOTE: This utility can only be used to download URLs\n");
fprintf(stderr, "from the same origin or that have been whitelisted\n");
fprintf(stderr, "in an extension manifest\n");
return 1;
}
return Download(argv[1], argv[2]);
}