Skip to content

Commit

Permalink
Fixed zero-file-issue on Linux
Browse files Browse the repository at this point in the history
  • Loading branch information
FlorianReimold committed Mar 1, 2024
1 parent dabb316 commit 978020c
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 56 deletions.
108 changes: 56 additions & 52 deletions fineftp-server/src/unix/file_man.cpp
Expand Up @@ -15,69 +15,73 @@
namespace fineftp
{

namespace {

std::mutex guard;
std::map<std::string, std::weak_ptr<ReadableFile>> files;

} // namespace

ReadableFile::~ReadableFile()
{
if (nullptr != data_)
namespace
{
::munmap(data_, size_);
}
std::mutex guard;
std::map<std::string, std::weak_ptr<ReadableFile>> files;
} // namespace

const std::lock_guard<std::mutex> lock{guard};
if (!pth_.empty())
ReadableFile::~ReadableFile()
{
(void)files.erase(pth_);
}
}
if (nullptr != data_)
{
::munmap(data_, size_);
}

std::shared_ptr<ReadableFile> ReadableFile::get(const std::string& pth)
{
// See if we already have this file mapped
const std::lock_guard<std::mutex> lock{guard};
auto fit = files.find(pth);
if (files.end() != fit)
{
auto p = fit->second.lock();
if (p)
const std::lock_guard<std::mutex> lock{guard};
if (!path_.empty())
{
return p;
(void)files.erase(path_);
}
}

auto handle = ::open(pth.c_str(), O_RDONLY);
if (-1 == handle)
{
return {};
}

struct stat st {};
if (-1 == ::fstat(handle, &st))
std::shared_ptr<ReadableFile> ReadableFile::get(const std::string& file_path)
{
::close(handle);
return {};
}
// See if we already have this file mapped
const std::lock_guard<std::mutex> lock{guard};
auto existing_files_it = files.find(file_path);
if (files.end() != existing_files_it)
{
auto readable_file_ptr = existing_files_it->second.lock();
if (readable_file_ptr)
{
return readable_file_ptr;
}
}

auto* map_start = ::mmap(nullptr, st.st_size, PROT_READ, MAP_SHARED, handle, 0);
if (MAP_FAILED == map_start)
{
::close(handle);
return {};
}
auto handle = ::open(file_path.c_str(), O_RDONLY);
if (-1 == handle)
{
return {};
}

::close(handle);
struct stat file_status {};
if (-1 == ::fstat(handle, &file_status))
{
::close(handle);
return {};
}

std::shared_ptr<ReadableFile> p{new ReadableFile{}};
p->pth_ = pth;
p->size_ = st.st_size;
p->data_ = static_cast<uint8_t*>(map_start);
files[p->pth_] = p;
return p;
}
void* map_start = nullptr;

if (file_status.st_size > 0)
{
// Only mmap file with a size > 0
map_start = ::mmap(nullptr, file_status.st_size, PROT_READ, MAP_SHARED, handle, 0);
if (MAP_FAILED == map_start)
{
::close(handle);
return {};
}
}

::close(handle);

std::shared_ptr<ReadableFile> readable_file_ptr{new ReadableFile{}};
readable_file_ptr->path_ = file_path;
readable_file_ptr->size_ = file_status.st_size;
readable_file_ptr->data_ = static_cast<uint8_t*>(map_start);
files[readable_file_ptr->path_] = readable_file_ptr;
return readable_file_ptr;
}
}
8 changes: 4 additions & 4 deletions fineftp-server/src/unix/file_man.h
Expand Up @@ -28,10 +28,10 @@ class ReadableFile

/// Retrieves the file at the specified path.
///
/// @param pth The path of the file.
/// @param file_path The path of the file.
///
/// @param The requested file or nullptr if the file could not be retrieved.
static std::shared_ptr<ReadableFile> get(const std::string& pth);
static std::shared_ptr<ReadableFile> get(const std::string& file_path);

/// Returns the size of the file.
///
Expand All @@ -51,7 +51,7 @@ class ReadableFile
private:
ReadableFile() = default;

std::string pth_ = {};
std::string path_ = {};
std::size_t size_ = {};
std::uint8_t* data_ = {};
};
Expand Down Expand Up @@ -118,7 +118,7 @@ inline const std::uint8_t* ReadableFile::data() const

inline const std::string& ReadableFile::path() const
{
return pth_;
return path_;
}

}
Expand Down

0 comments on commit 978020c

Please sign in to comment.