From eb6ba2a703db3a84bb3d9cb5538d2f3ab688b730 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Sun, 21 Dec 2014 14:06:44 +0900 Subject: [PATCH 1/3] copy the request entity to temporary file if the source is stdin and if it is not a regular file --- src/nghttp.cc | 61 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 49 insertions(+), 12 deletions(-) diff --git a/src/nghttp.cc b/src/nghttp.cc index 480d1a3b..b4e39a12 100644 --- a/src/nghttp.cc +++ b/src/nghttp.cc @@ -2082,17 +2082,54 @@ int run(char **uris, int n) { struct stat data_stat; if (!config.datafile.empty()) { - data_fd = open(config.datafile.c_str(), O_RDONLY | O_BINARY); - if (data_fd == -1) { - std::cerr << "[ERROR] Could not open file " << config.datafile - << std::endl; - return 1; - } - if (fstat(data_fd, &data_stat) == -1) { - close(data_fd); - std::cerr << "[ERROR] Could not stat file " << config.datafile - << std::endl; - return 1; + if (config.datafile == "-") { + if (fstat(0, &data_stat) == 0 && + (data_stat.st_mode & S_IFMT) == S_IFREG) { + // use STDIN if it is a regular file + data_fd = 0; + } else { + // copy the contents of STDIN to a temporary file + char tempfn[] = "/tmp/nghttp.temp.XXXXXX"; + data_fd = mkstemp(tempfn); + if (data_fd == -1) { + std::cerr << "[ERROR] Could not create a temporary file in /tmp" + << std::endl; + return 1; + } + while (1) { + char buf[1024]; + ssize_t rret, wret; + while ((rret = read(0, buf, sizeof(buf))) == -1 && errno == EINTR) + ; + if (rret == 0) + break; + if (rret == -1) { + std::cerr << "[ERROR] I/O error while reading from STDIN" + << std::endl; + return 1; + } + while ((wret = write(data_fd, buf, rret)) == -1 && errno == EINTR) + ; + if (wret != rret) { + std::cerr << "[ERROR] I/O error while writing to temporary file" + << std::endl; + return 1; + } + } + } + } else { + data_fd = open(config.datafile.c_str(), O_RDONLY | O_BINARY); + if (data_fd == -1) { + std::cerr << "[ERROR] Could not open file " << config.datafile + << std::endl; + return 1; + } + if (fstat(data_fd, &data_stat) == -1) { + close(data_fd); + std::cerr << "[ERROR] Could not stat file " << config.datafile + << std::endl; + return 1; + } } data_prd.source.fd = data_fd; data_prd.read_callback = file_read_callback; @@ -2369,7 +2406,7 @@ int main(int argc, char **argv) { config.stat = true; break; case 'd': - config.datafile = strcmp("-", optarg) == 0 ? "/dev/stdin" : optarg; + config.datafile = optarg; break; case 'm': config.multiply = strtoul(optarg, nullptr, 10); From 125f62b71e464ccc6669c40a2e4e9a07d9ea0537 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Mon, 22 Dec 2014 07:24:36 +0900 Subject: [PATCH 2/3] unlink the temporary file immediately after calling mkstemp --- src/nghttp.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/nghttp.cc b/src/nghttp.cc index b4e39a12..1aac801a 100644 --- a/src/nghttp.cc +++ b/src/nghttp.cc @@ -2096,6 +2096,10 @@ int run(char **uris, int n) { << std::endl; return 1; } + if (unlink(tempfn) != 0) { + std::cerr << "[WARNING] failed to unlink temporary file:" << tempfn + << std::endl; + } while (1) { char buf[1024]; ssize_t rret, wret; From 45d0d731ebf900af6cbaaa3e7f66f5aa38f54307 Mon Sep 17 00:00:00 2001 From: Kazuho Oku Date: Mon, 22 Dec 2014 07:26:02 +0900 Subject: [PATCH 3/3] fill-in `data_stat` after copying the request entity into the temporary file --- src/nghttp.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/nghttp.cc b/src/nghttp.cc index 1aac801a..3670bfff 100644 --- a/src/nghttp.cc +++ b/src/nghttp.cc @@ -2120,6 +2120,11 @@ int run(char **uris, int n) { return 1; } } + if (fstat(data_fd, &data_stat) == -1) { + close(data_fd); + std::cerr << "[ERROR] Could not stat temporary file" << std::endl; + return 1; + } } } else { data_fd = open(config.datafile.c_str(), O_RDONLY | O_BINARY);