Skip to content

Commit

Permalink
Distinguish between missing file and read error
Browse files Browse the repository at this point in the history
  • Loading branch information
wch committed Nov 30, 2018
1 parent 3cbe074 commit f3e487d
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 15 deletions.
17 changes: 11 additions & 6 deletions src/filedatasource-unix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,31 @@
#include <unistd.h>
#include <errno.h>

int FileDataSource::initialize(const std::string& path, bool owned) {
FileDataSourceResult FileDataSource::initialize(const std::string& path, bool owned) {
// This can be called from either the main thread or background thread.

_fd = open(path.c_str(), O_RDONLY);
if (_fd == -1) {
_lastErrorMessage = "Error opening file " + path + ": " + toString(errno) + "\n";
return 1;
if (errno == ENOENT) {
_lastErrorMessage = "File does not exist: " + path + "\n";
return FDS_NOT_EXIST;
} else {
_lastErrorMessage = "Error opening file " + path + ": " + toString(errno) + "\n";
return FDS_ERROR;
}
}
else {
struct stat info = {0};
if (fstat(_fd, &info)) {
_lastErrorMessage = "Error opening path " + path + ": " + toString(errno) + "\n";
::close(_fd);
return 1;
return FDS_ERROR;
}

if (S_ISDIR(info.st_mode)) {
_lastErrorMessage = "File data source is a directory: " + path + "\n";
::close(_fd);
return 1;
return FDS_ISDIR;
}

_length = info.st_size;
Expand All @@ -37,7 +42,7 @@ int FileDataSource::initialize(const std::string& path, bool owned) {
// It's OK to continue
}

return 0;
return FDS_OK;
}
}

Expand Down
12 changes: 11 additions & 1 deletion src/filedatasource.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,16 @@

#include "uvutil.h"


// Status codes for FileDataSource::initialize().
enum FileDataSourceResult {
FDS_OK = 0, // Initialization worked
FDS_NOT_EXIST, // File did not exist
FDS_ISDIR, // File is a directory
FDS_ERROR // Other error
};


class FileDataSource : public DataSource {
#ifdef _WIN32
HANDLE _hFile;
Expand All @@ -16,7 +26,7 @@ class FileDataSource : public DataSource {
public:
FileDataSource() {}

int initialize(const std::string& path, bool owned);
FileDataSourceResult initialize(const std::string& path, bool owned);
uint64_t size() const;
uv_buf_t getData(size_t bytesDesired);
void freeData(uv_buf_t buffer);
Expand Down
22 changes: 14 additions & 8 deletions src/webapplication.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -189,9 +189,11 @@ boost::shared_ptr<HttpResponse> listToResponse(
// - body: Character vector (which is charToRaw-ed) or raw vector, or NULL
if (std::find(names.begin(), names.end(), "bodyFile") != names.end()) {
FileDataSource* pFDS = new FileDataSource();
int ret = pFDS->initialize(Rcpp::as<std::string>(response["bodyFile"]),
Rcpp::as<bool>(response["bodyFileOwned"]));
if (ret != 0) {
FileDataSourceResult ret = pFDS->initialize(
Rcpp::as<std::string>(response["bodyFile"]),
Rcpp::as<bool>(response["bodyFileOwned"])
);
if (ret != FDS_OK) {
REprintf(pFDS->lastErrorMessage().c_str());
}
pDataSource = pFDS;
Expand Down Expand Up @@ -508,16 +510,20 @@ boost::shared_ptr<HttpResponse> RWebApplication::staticFileResponse(

// Self-frees when response is written
FileDataSource* pDataSource = new FileDataSource();
int ret = pDataSource->initialize(local_path, false);
FileDataSourceResult ret = pDataSource->initialize(local_path, false);

if (ret != 0) {
if (ret != FDS_OK) {
// Couldn't read the file
delete pDataSource;

if (sp.options.fallthrough.get()) {
return nullptr;
if (ret == FDS_NOT_EXIST || ret == FDS_ISDIR) {
if (sp.options.fallthrough.get()) {
return nullptr;
} else {
return error_response(pRequest, 404);
}
} else {
return error_response(pRequest, 404);
return error_response(pRequest, 500);
}
}

Expand Down

0 comments on commit f3e487d

Please sign in to comment.