Move check_local_location to FileLoaderUtils.

This commit is contained in:
levlam 2022-10-10 12:58:48 +03:00
parent 6786276481
commit f26f05a074
6 changed files with 110 additions and 109 deletions

View File

@ -412,7 +412,7 @@ static Status check_mtime(std::string &conversion, CSlice original_path) {
conversion = parser.read_all().str();
auto r_stat = stat(original_path);
uint64 actual_mtime = r_stat.is_ok() ? r_stat.ok().mtime_nsec_ : 0;
if (FileManager::are_modification_times_equal(expected_mtime, actual_mtime)) {
if (are_modification_times_equal(expected_mtime, actual_mtime)) {
LOG(DEBUG) << "File \"" << original_path << "\" modification time " << actual_mtime << " matches";
return Status::OK();
}

View File

@ -257,4 +257,100 @@ string get_files_dir(FileType file_type) {
return PSTRING() << get_files_base_dir(file_type) << get_file_type_name(file_type) << TD_DIR_SLASH;
}
bool are_modification_times_equal(int64 old_mtime, int64 new_mtime) {
if (old_mtime == new_mtime) {
return true;
}
if (old_mtime < new_mtime) {
return false;
}
if (old_mtime - new_mtime == 1000000000 && old_mtime % 1000000000 == 0 && new_mtime % 2000000000 == 0) {
// FAT32 has 2 seconds mtime resolution, but file system sometimes reports odd modification time
return true;
}
return false;
}
Result<FullLocalLocationInfo> check_full_local_location(FullLocalLocationInfo local_info, bool skip_file_size_checks) {
constexpr int64 MAX_FILE_SIZE = static_cast<int64>(4000) << 20 /* 4000 MB */;
constexpr int64 MAX_THUMBNAIL_SIZE = 200 * (1 << 10) - 1 /* 200 KB - 1 B */;
constexpr int64 MAX_PHOTO_SIZE = 10 * (1 << 20) /* 10 MB */;
constexpr int64 DEFAULT_VIDEO_NOTE_SIZE_MAX = 12 * (1 << 20) /* 12 MB */;
FullLocalFileLocation &location = local_info.location_;
int64 &size = local_info.size_;
if (location.path_.empty()) {
return Status::Error(400, "File must have non-empty path");
}
auto r_path = realpath(location.path_, true);
if (r_path.is_error()) {
return Status::Error(400, "Can't find real file path");
}
location.path_ = r_path.move_as_ok();
auto r_stat = stat(location.path_);
if (r_stat.is_error()) {
return Status::Error(400, "Can't get stat about the file");
}
auto stat = r_stat.move_as_ok();
if (!stat.is_reg_) {
return Status::Error(400, "File must be a regular file");
}
if (stat.size_ < 0) {
// TODO is it possible?
return Status::Error(400, "File is too big");
}
if (stat.size_ == 0) {
return Status::Error(400, "File must be non-empty");
}
if (size == 0) {
size = stat.size_;
}
if (location.mtime_nsec_ == 0) {
VLOG(file_loader) << "Set file \"" << location.path_ << "\" modification time to " << stat.mtime_nsec_;
location.mtime_nsec_ = stat.mtime_nsec_;
} else if (!are_modification_times_equal(location.mtime_nsec_, stat.mtime_nsec_)) {
VLOG(file_loader) << "File \"" << location.path_ << "\" was modified: old mtime = " << location.mtime_nsec_
<< ", new mtime = " << stat.mtime_nsec_;
return Status::Error(400, PSLICE() << "File \"" << utf8_encode(location.path_) << "\" was modified");
}
if (skip_file_size_checks) {
return std::move(local_info);
}
auto get_file_size_error = [&](Slice reason) {
return Status::Error(400, PSLICE() << "File \"" << utf8_encode(location.path_) << "\" of size " << size
<< " bytes is too big" << reason);
};
if ((location.file_type_ == FileType::Thumbnail || location.file_type_ == FileType::EncryptedThumbnail) &&
size > MAX_THUMBNAIL_SIZE && !begins_with(PathView(location.path_).file_name(), "map") &&
!begins_with(PathView(location.path_).file_name(), "Album cover for ")) {
return get_file_size_error(" for a thumbnail");
}
if (size > MAX_FILE_SIZE) {
return get_file_size_error("");
}
if (location.file_type_ == FileType::Photo && size > MAX_PHOTO_SIZE) {
return get_file_size_error(" for a photo");
}
if (location.file_type_ == FileType::VideoNote &&
size > G()->get_option_integer("video_note_size_max", DEFAULT_VIDEO_NOTE_SIZE_MAX)) {
return get_file_size_error(" for a video note");
}
return std::move(local_info);
}
Status check_partial_local_location(const PartialLocalFileLocation &location) {
TRY_RESULT(stat, stat(location.path_));
if (!stat.is_reg_) {
if (stat.is_dir_) {
return Status::Error(PSLICE() << "Can't use directory \"" << location.path_ << "\" as a file path");
}
return Status::Error("File must be a regular file");
}
// can't check mtime. Hope nobody will mess with this files in our temporary dir.
return Status::OK();
}
} // namespace td

View File

@ -38,4 +38,15 @@ string get_files_temp_dir(FileType file_type);
string get_files_dir(FileType file_type);
bool are_modification_times_equal(int64 old_mtime, int64 new_mtime);
struct FullLocalLocationInfo {
FullLocalFileLocation location_;
int64 size_ = 0;
};
Result<FullLocalLocationInfo> check_full_local_location(FullLocalLocationInfo local_info, bool skip_file_size_checks);
Status check_partial_local_location(const PartialLocalFileLocation &location);
} // namespace td

View File

@ -916,106 +916,10 @@ string FileManager::get_file_name(FileType file_type, Slice path) {
return file_name.str();
}
bool FileManager::are_modification_times_equal(int64 old_mtime, int64 new_mtime) {
if (old_mtime == new_mtime) {
return true;
}
if (old_mtime < new_mtime) {
return false;
}
if (old_mtime - new_mtime == 1000000000 && old_mtime % 1000000000 == 0 && new_mtime % 2000000000 == 0) {
// FAT32 has 2 seconds mtime resolution, but file system sometimes reports odd modification time
return true;
}
return false;
}
bool FileManager::is_remotely_generated_file(Slice conversion) {
return begins_with(conversion, "#map#") || begins_with(conversion, "#audio_t#");
}
Result<FileManager::FullLocalLocationInfo> FileManager::check_local_location(FullLocalLocationInfo local_info,
bool skip_file_size_checks) {
constexpr int64 MAX_THUMBNAIL_SIZE = 200 * (1 << 10) - 1 /* 200 KB - 1 B */;
constexpr int64 MAX_PHOTO_SIZE = 10 * (1 << 20) /* 10 MB */;
constexpr int64 DEFAULT_VIDEO_NOTE_SIZE_MAX = 12 * (1 << 20) /* 12 MB */;
FullLocalFileLocation &location = local_info.location_;
int64 &size = local_info.size_;
if (location.path_.empty()) {
return Status::Error(400, "File must have non-empty path");
}
auto r_path = realpath(location.path_, true);
if (r_path.is_error()) {
return Status::Error(400, "Can't find real file path");
}
location.path_ = r_path.move_as_ok();
auto r_stat = stat(location.path_);
if (r_stat.is_error()) {
return Status::Error(400, "Can't get stat about the file");
}
auto stat = r_stat.move_as_ok();
if (!stat.is_reg_) {
return Status::Error(400, "File must be a regular file");
}
if (stat.size_ < 0) {
// TODO is it possible?
return Status::Error(400, "File is too big");
}
if (stat.size_ == 0) {
return Status::Error(400, "File must be non-empty");
}
if (size == 0) {
size = stat.size_;
}
if (location.mtime_nsec_ == 0) {
VLOG(file_loader) << "Set file \"" << location.path_ << "\" modification time to " << stat.mtime_nsec_;
location.mtime_nsec_ = stat.mtime_nsec_;
} else if (!are_modification_times_equal(location.mtime_nsec_, stat.mtime_nsec_)) {
VLOG(file_loader) << "File \"" << location.path_ << "\" was modified: old mtime = " << location.mtime_nsec_
<< ", new mtime = " << stat.mtime_nsec_;
return Status::Error(400, PSLICE() << "File \"" << utf8_encode(location.path_) << "\" was modified");
}
if (skip_file_size_checks) {
return std::move(local_info);
}
auto get_file_size_error = [&](Slice reason) {
return Status::Error(400, PSLICE() << "File \"" << utf8_encode(location.path_) << "\" of size " << size
<< " bytes is too big" << reason);
};
if ((location.file_type_ == FileType::Thumbnail || location.file_type_ == FileType::EncryptedThumbnail) &&
size > MAX_THUMBNAIL_SIZE && !begins_with(PathView(location.path_).file_name(), "map") &&
!begins_with(PathView(location.path_).file_name(), "Album cover for ")) {
return get_file_size_error(" for a thumbnail");
}
if (size > MAX_FILE_SIZE) {
return get_file_size_error("");
}
if (location.file_type_ == FileType::Photo && size > MAX_PHOTO_SIZE) {
return get_file_size_error(" for a photo");
}
if (location.file_type_ == FileType::VideoNote &&
size > G()->get_option_integer("video_note_size_max", DEFAULT_VIDEO_NOTE_SIZE_MAX)) {
return get_file_size_error(" for a video note");
}
return std::move(local_info);
}
static Status check_partial_local_location(const PartialLocalFileLocation &location) {
TRY_RESULT(stat, stat(location.path_));
if (!stat.is_reg_) {
if (stat.is_dir_) {
return Status::Error(PSLICE() << "Can't use directory \"" << location.path_ << "\" as a file path");
}
return Status::Error("File must be a regular file");
}
// can't check mtime. Hope nobody will mess with this file in our temporary dir.
return Status::OK();
}
void FileManager::check_local_location(FileId file_id, bool skip_file_size_checks) {
auto node = get_sync_file_node(file_id);
if (node) {
@ -1026,7 +930,7 @@ void FileManager::check_local_location(FileId file_id, bool skip_file_size_check
Status FileManager::check_local_location(FileNodePtr node, bool skip_file_size_checks) {
Status status;
if (node->local_.type() == LocalFileLocation::Type::Full) {
auto r_info = check_local_location({node->local_.full(), node->size_}, skip_file_size_checks);
auto r_info = check_full_local_location({node->local_.full(), node->size_}, skip_file_size_checks);
if (r_info.is_error()) {
status = r_info.move_as_error();
} else if (bad_paths_.count(r_info.ok().location_.path_) != 0) {
@ -1212,7 +1116,7 @@ Result<FileId> FileManager::register_file(FileData &&data, FileLocationSource fi
if (!is_from_database) {
Status status;
auto r_info = check_local_location({data.local_.full(), data.size_}, skip_file_size_checks);
auto r_info = check_full_local_location({data.local_.full(), data.size_}, skip_file_size_checks);
if (r_info.is_error()) {
status = r_info.move_as_error();
} else if (bad_paths_.count(r_info.ok().location_.path_) != 0) {

View File

@ -416,8 +416,6 @@ class FileManager final : public FileLoadManager::Callback {
FileManager &operator=(FileManager &&other) = delete;
~FileManager() final;
static bool are_modification_times_equal(int64 old_mtime, int64 new_mtime);
static bool is_remotely_generated_file(Slice conversion);
void init_actor();
@ -618,13 +616,6 @@ class FileManager final : public FileLoadManager::Callback {
void load_from_pmc_result(FileId file_id, Result<FileData> &&result);
FileId register_pmc_file_data(FileData &&data);
struct FullLocalLocationInfo {
FullLocalFileLocation location_;
int64 size_ = 0;
};
static Result<FullLocalLocationInfo> check_local_location(FullLocalLocationInfo local_info,
bool skip_file_size_checks);
Status check_local_location(FileNodePtr node, bool skip_file_size_checks);
static bool try_fix_partial_local_location(FileNodePtr node);
void try_flush_node_full(FileNodePtr node, bool new_remote, bool new_local, bool new_generate, FileDbId other_pmc_id);

View File

@ -6,7 +6,6 @@
//
#include "td/telegram/files/FileStats.h"
#include "td/telegram/files/FileLoaderUtils.h"
#include "td/telegram/td_api.h"
#include "td/utils/algorithm.h"