2020-05-03 08:06:34 -04:00
//
// Created by WolverinDEV on 29/04/2020.
//
# include <experimental/filesystem>
# define FS_INCLUDED
# include <log/LogUtils.h>
2020-05-07 15:28:15 -04:00
# include "LocalFileProvider.h"
2020-05-03 08:06:34 -04:00
# include "clnpath.h"
using namespace ts : : server : : file ;
using namespace ts : : server : : file : : filesystem ;
namespace fs = std : : experimental : : filesystem ;
using directory_query_response_t = AbstractProvider : : directory_query_response_t ;
LocalFileSystem : : ~ LocalFileSystem ( ) = default ;
bool LocalFileSystem : : initialize ( std : : string & error_message , const std : : string & root_path_string ) {
auto root_path = fs : : u8path ( root_path_string ) ;
std : : error_code error { } ;
if ( ! fs : : exists ( root_path , error ) ) {
if ( error )
2020-05-07 15:28:15 -04:00
logWarning ( LOG_FT , " Failed to check root path existence. Assuming it does not exist. ({}/{}) " , error . value ( ) , error . message ( ) ) ;
2020-05-03 08:06:34 -04:00
if ( ! fs : : create_directories ( root_path , error ) | | error ) {
error_message = " Failed to create root file system at " + root_path_string + " : " + std : : to_string ( error . value ( ) ) + " / " + error . message ( ) ;
return false ;
}
}
auto croot = clnpath ( fs : : absolute ( root_path ) . string ( ) ) ;
2020-05-07 15:28:15 -04:00
logMessage ( LOG_FT , " Started file system root at {} " , croot ) ;
2020-05-03 08:06:34 -04:00
this - > root_path_ = croot ;
return true ;
}
void LocalFileSystem : : finalize ( ) { }
2020-05-13 05:32:08 -04:00
fs : : path LocalFileSystem : : server_path ( const std : : shared_ptr < VirtualFileServer > & server ) {
return fs : : u8path ( this - > root_path_ ) / fs : : u8path ( " server_ " + std : : to_string ( server - > server_id ( ) ) ) ;
2020-05-03 08:06:34 -04:00
}
2020-05-13 05:32:08 -04:00
fs : : path LocalFileSystem : : server_channel_path ( const std : : shared_ptr < VirtualFileServer > & server , ts : : ChannelId cid ) {
return this - > server_path ( server ) / fs : : u8path ( " channel_ " + std : : to_string ( cid ) ) ;
2020-05-03 08:06:34 -04:00
}
bool LocalFileSystem : : exceeds_base_path ( const fs : : path & base , const fs : : path & target ) {
auto rel_target = clnpath ( target . string ( ) ) ;
if ( rel_target . starts_with ( " .. " ) ) return true ;
auto base_string = clnpath ( fs : : absolute ( base ) . string ( ) ) ;
auto target_string = clnpath ( fs : : absolute ( target ) . string ( ) ) ;
return ! target_string . starts_with ( base_string ) ;
}
bool LocalFileSystem : : is_any_file_locked ( const fs : : path & base , const std : : string & path , std : : string & locked_file ) {
auto c_path = clnpath ( fs : : absolute ( base / fs : : u8path ( path ) ) . string ( ) ) ;
2020-05-07 15:28:15 -04:00
std : : lock_guard lock { this - > locked_files_mutex } ;
2020-05-03 08:06:34 -04:00
for ( const auto & lfile : this - > locked_files_ ) {
if ( lfile . starts_with ( c_path ) ) {
locked_file = lfile . substr ( base . string ( ) . length ( ) ) ;
return true ;
}
}
return false ;
}
2020-05-13 05:32:08 -04:00
std : : string LocalFileSystem : : target_file_path ( FileCategory type , const std : : shared_ptr < VirtualFileServer > & server , ts : : ChannelId cid , const std : : string & path ) {
2020-05-07 15:28:15 -04:00
fs : : path target_path { } ;
switch ( type ) {
case FileCategory : : CHANNEL :
2020-05-13 05:32:08 -04:00
target_path = this - > server_channel_path ( server , cid ) / path ;
2020-05-07 15:28:15 -04:00
break ;
case FileCategory : : ICON :
2020-05-13 05:32:08 -04:00
target_path = this - > server_path ( server ) / " icons " / path ;
2020-05-07 15:28:15 -04:00
break ;
case FileCategory : : AVATAR :
2020-05-13 05:32:08 -04:00
target_path = this - > server_path ( server ) / " avatars " / path ;
2020-05-07 15:28:15 -04:00
break ;
}
return clnpath ( fs : : absolute ( target_path ) . string ( ) ) ;
}
2020-05-13 05:32:08 -04:00
std : : string LocalFileSystem : : absolute_avatar_path ( const std : : shared_ptr < VirtualFileServer > & sid , const std : : string & path ) {
2020-05-07 15:28:15 -04:00
return this - > target_file_path ( FileCategory : : AVATAR , sid , 0 , path ) ;
}
2020-05-13 05:32:08 -04:00
std : : string LocalFileSystem : : absolute_icon_path ( const std : : shared_ptr < VirtualFileServer > & sid , const std : : string & path ) {
2020-05-07 15:28:15 -04:00
return this - > target_file_path ( FileCategory : : ICON , sid , 0 , path ) ;
}
2020-05-13 05:32:08 -04:00
std : : string LocalFileSystem : : absolute_channel_path ( const std : : shared_ptr < VirtualFileServer > & sid , ChannelId cid , const std : : string & path ) {
2020-05-07 15:28:15 -04:00
return this - > target_file_path ( FileCategory : : CHANNEL , sid , cid , path ) ;
}
void LocalFileSystem : : lock_file ( const std : : string & c_path ) {
std : : lock_guard lock { this - > locked_files_mutex } ;
this - > locked_files_ . push_back ( c_path ) ;
}
void LocalFileSystem : : unlock_file ( const std : : string & c_path ) {
std : : lock_guard lock { this - > locked_files_mutex } ;
this - > locked_files_ . erase ( std : : remove_if ( this - > locked_files_ . begin ( ) , this - > locked_files_ . end ( ) , [ & ] ( const auto & p ) { return p = = c_path ; } ) , this - > locked_files_ . end ( ) ) ;
}
2020-05-13 05:32:08 -04:00
std : : shared_ptr < ExecuteResponse < ServerCommandError > > LocalFileSystem : : initialize_server ( const std : : shared_ptr < VirtualFileServer > & id ) {
2020-05-03 08:06:34 -04:00
auto path = this - > server_path ( id ) ;
std : : error_code error { } ;
auto response = this - > create_execute_response < ServerCommandError > ( ) ;
if ( ! fs : : exists ( path , error ) ) {
if ( ! fs : : create_directories ( path , error ) | | error ) {
response - > emplace_fail ( ServerCommandErrorType : : FAILED_TO_CREATE_DIRECTORIES , std : : to_string ( error . value ( ) ) + " / " + error . message ( ) ) ;
return response ;
}
}
//TODO: Copy the default icon
response - > emplace_success ( ) ;
return response ;
}
2020-05-13 05:32:08 -04:00
std : : shared_ptr < ExecuteResponse < ServerCommandError > > LocalFileSystem : : delete_server ( const std : : shared_ptr < VirtualFileServer > & id ) {
2020-05-03 08:06:34 -04:00
auto path = this - > server_path ( id ) ;
std : : error_code error { } ;
auto response = this - > create_execute_response < ServerCommandError > ( ) ;
//TODO: Stop all running file transfers!
if ( fs : : exists ( path , error ) ) {
if ( ! fs : : remove_all ( path , error ) | | error ) {
response - > emplace_fail ( ServerCommandErrorType : : FAILED_TO_DELETE_DIRECTORIES , std : : to_string ( error . value ( ) ) + " / " + error . message ( ) ) ;
return response ;
}
}
response - > emplace_success ( ) ;
return response ;
}
std : : shared_ptr < directory_query_response_t > LocalFileSystem : : query_directory ( const fs : : path & base ,
const std : : string & path ,
bool allow_non_existance ) {
std : : error_code error { } ;
auto response = this - > create_execute_response < DirectoryQueryError , std : : deque < DirectoryEntry > > ( ) ;
auto target_path = base / fs : : u8path ( path ) ;
if ( this - > exceeds_base_path ( base , target_path ) ) {
response - > emplace_fail ( DirectoryQueryErrorType : : PATH_EXCEEDS_ROOT_PATH , " " ) ;
return response ;
}
if ( ! fs : : exists ( target_path , error ) ) {
if ( allow_non_existance )
response - > emplace_success ( ) ;
else
response - > emplace_fail ( DirectoryQueryErrorType : : PATH_DOES_NOT_EXISTS , " " ) ;
return response ;
} else if ( error ) {
2020-05-07 15:28:15 -04:00
logWarning ( LOG_FT , " Failed to check for file at {}: {}. Assuming it does not exists. " , target_path . string ( ) , error . value ( ) , error . message ( ) ) ;
2020-05-03 08:06:34 -04:00
response - > emplace_fail ( DirectoryQueryErrorType : : PATH_DOES_NOT_EXISTS , " " ) ;
return response ;
}
if ( ! fs : : is_directory ( target_path , error ) ) {
response - > emplace_fail ( DirectoryQueryErrorType : : PATH_IS_A_FILE , " " ) ;
return response ;
} else if ( error ) {
2020-05-07 15:28:15 -04:00
logWarning ( LOG_FT , " Failed to check for directory at {}: {}. Assuming its not a directory. " , target_path . string ( ) , error . value ( ) , error . message ( ) ) ;
2020-05-03 08:06:34 -04:00
response - > emplace_fail ( DirectoryQueryErrorType : : PATH_IS_A_FILE , " " ) ;
return response ;
}
std : : deque < DirectoryEntry > entries { } ;
for ( auto & entry : fs : : directory_iterator ( target_path , error ) ) {
auto status = entry . status ( error ) ;
if ( error ) {
2020-05-07 15:28:15 -04:00
logWarning ( LOG_FT , " Failed to query file status for {} ({}/{}). Skipping entry for directory query. " , entry . path ( ) . string ( ) , error . value ( ) , error . message ( ) ) ;
2020-05-03 08:06:34 -04:00
continue ;
}
if ( status . type ( ) = = fs : : file_type : : directory ) {
auto & dentry = entries . emplace_back ( ) ;
dentry . type = DirectoryEntry : : DIRECTORY ;
dentry . name = entry . path ( ) . filename ( ) ;
2020-06-10 12:13:14 -04:00
dentry . empty = fs : : is_empty ( entry . path ( ) , error ) ;
if ( error )
logWarning ( LOG_FT , " Failed to query directory empty state for directory {} ({}/{}) " , target_path . string ( ) , error . value ( ) , error . message ( ) ) ;
2020-05-03 08:06:34 -04:00
dentry . modified_at = fs : : last_write_time ( entry . path ( ) , error ) ;
if ( error )
2020-05-07 15:28:15 -04:00
logWarning ( LOG_FT , " Failed to query last write time for directory {} ({}/{}) " , entry . path ( ) . string ( ) , error . value ( ) , error . message ( ) ) ;
2020-05-03 08:06:34 -04:00
dentry . size = 0 ;
} else if ( status . type ( ) = = fs : : file_type : : regular ) {
auto & dentry = entries . emplace_back ( ) ;
dentry . type = DirectoryEntry : : FILE ;
dentry . name = entry . path ( ) . filename ( ) ;
dentry . modified_at = fs : : last_write_time ( entry . path ( ) , error ) ;
if ( error )
2020-05-07 15:28:15 -04:00
logWarning ( LOG_FT , " Failed to query last write time for file {} ({}/{}). " , entry . path ( ) . string ( ) , error . value ( ) , error . message ( ) ) ;
2020-05-03 08:06:34 -04:00
dentry . size = fs : : file_size ( entry . path ( ) , error ) ;
if ( error )
2020-05-07 15:28:15 -04:00
logWarning ( LOG_FT , " Failed to query size for file {} ({}/{}). " , entry . path ( ) . string ( ) , error . value ( ) , error . message ( ) ) ;
2020-05-03 08:06:34 -04:00
} else {
2020-05-07 15:28:15 -04:00
logWarning ( LOG_FT , " Directory query listed an unknown file type for file {} ({}). " , entry . path ( ) . string ( ) , ( int ) status . type ( ) ) ;
2020-05-03 08:06:34 -04:00
}
}
if ( error & & entries . empty ( ) ) {
response - > emplace_fail ( DirectoryQueryErrorType : : FAILED_TO_LIST_FILES , std : : to_string ( error . value ( ) ) + " / " + error . message ( ) ) ;
return response ;
}
response - > emplace_success ( std : : forward < decltype ( entries ) > ( entries ) ) ;
return response ;
}
2020-05-13 05:32:08 -04:00
std : : shared_ptr < directory_query_response_t > LocalFileSystem : : query_icon_directory ( const std : : shared_ptr < VirtualFileServer > & id ) {
2020-05-03 08:06:34 -04:00
return this - > query_directory ( this - > server_path ( id ) / fs : : u8path ( " icons " ) , " / " , true ) ;
}
2020-05-13 05:32:08 -04:00
std : : shared_ptr < directory_query_response_t > LocalFileSystem : : query_avatar_directory ( const std : : shared_ptr < VirtualFileServer > & id ) {
2020-05-03 08:06:34 -04:00
return this - > query_directory ( this - > server_path ( id ) / fs : : u8path ( " avatars " ) , " / " , true ) ;
}
2020-05-13 05:32:08 -04:00
std : : shared_ptr < directory_query_response_t > LocalFileSystem : : query_channel_directory ( const std : : shared_ptr < VirtualFileServer > & id , ChannelId channelId , const std : : string & path ) {
2020-05-03 08:06:34 -04:00
return this - > query_directory ( this - > server_channel_path ( id , channelId ) , path , false ) ;
}
2020-05-13 05:32:08 -04:00
std : : shared_ptr < ExecuteResponse < DirectoryModifyError > > LocalFileSystem : : create_channel_directory ( const std : : shared_ptr < VirtualFileServer > & id , ChannelId channelId , const std : : string & path ) {
2020-05-03 08:06:34 -04:00
auto channel_path_root = this - > server_channel_path ( id , channelId ) ;
std : : error_code error { } ;
auto response = this - > create_execute_response < DirectoryModifyError > ( ) ;
auto target_path = channel_path_root / fs : : u8path ( path ) ;
if ( this - > exceeds_base_path ( channel_path_root , target_path ) ) {
response - > emplace_fail ( DirectoryModifyErrorType : : PATH_EXCEEDS_ROOT_PATH , " " ) ;
return response ;
}
if ( fs : : exists ( target_path , error ) ) {
response - > emplace_fail ( DirectoryModifyErrorType : : PATH_ALREADY_EXISTS , " " ) ;
return response ;
} else if ( error ) {
2020-05-07 15:28:15 -04:00
logWarning ( LOG_FT , " Failed to check for file at {}: {}. Assuming it does not exists. " , target_path . string ( ) , error . value ( ) , error . message ( ) ) ;
2020-05-03 08:06:34 -04:00
}
if ( ! fs : : create_directories ( target_path , error ) | | error ) {
response - > emplace_fail ( DirectoryModifyErrorType : : FAILED_TO_CREATE_DIRECTORIES , std : : to_string ( error . value ( ) ) + " / " + error . message ( ) ) ;
return response ;
}
response - > emplace_success ( ) ;
return response ;
}
2020-05-13 05:32:08 -04:00
std : : shared_ptr < ExecuteResponse < FileModifyError > > LocalFileSystem : : rename_channel_file ( const std : : shared_ptr < VirtualFileServer > & id , ChannelId channelId , const std : : string & current_path_string , ChannelId targetChannelId , const std : : string & new_path_string ) {
2020-05-03 08:06:34 -04:00
auto channel_path_root = this - > server_channel_path ( id , channelId ) ;
2020-05-13 05:32:08 -04:00
auto target_path_root = this - > server_channel_path ( id , targetChannelId ) ;
2020-05-03 08:06:34 -04:00
std : : error_code error { } ;
std : : string locked_file { } ;
auto response = this - > create_execute_response < FileModifyError > ( ) ;
auto current_path = channel_path_root / fs : : u8path ( current_path_string ) ;
2020-05-13 05:32:08 -04:00
auto target_path = target_path_root / fs : : u8path ( new_path_string ) ;
2020-05-03 08:06:34 -04:00
if ( this - > exceeds_base_path ( channel_path_root , current_path ) ) {
response - > emplace_fail ( FileModifyErrorType : : PATH_EXCEEDS_ROOT_PATH , " " ) ;
return response ;
}
2020-05-13 05:32:08 -04:00
if ( this - > exceeds_base_path ( target_path_root , target_path ) ) {
2020-05-03 08:06:34 -04:00
response - > emplace_fail ( FileModifyErrorType : : TARGET_PATH_EXCEEDS_ROOT_PATH , " " ) ;
return response ;
}
if ( ! fs : : exists ( current_path , error ) ) {
response - > emplace_fail ( FileModifyErrorType : : PATH_DOES_NOT_EXISTS , " " ) ;
return response ;
} else if ( error ) {
2020-05-07 15:28:15 -04:00
logWarning ( LOG_FT , " Failed to check for file at {}: {}. Assuming it does not exists. " , current_path . string ( ) , error . value ( ) , error . message ( ) ) ;
2020-05-03 08:06:34 -04:00
response - > emplace_fail ( FileModifyErrorType : : PATH_DOES_NOT_EXISTS , " " ) ;
return response ;
}
2020-05-13 05:32:08 -04:00
if ( ! fs : : exists ( target_path . parent_path ( ) , error ) ) {
if ( ! fs : : create_directories ( target_path . parent_path ( ) , error ) ) {
response - > emplace_fail ( FileModifyErrorType : : FAILED_TO_CREATE_DIRECTORIES , std : : to_string ( error . value ( ) ) + " / " + error . message ( ) ) ;
return response ;
}
} else if ( error ) {
logWarning ( LOG_FT , " Failed to test for target directory existence for {}: {}/{}. Assuming it does exists " , target_path . parent_path ( ) . string ( ) , error . value ( ) , error . message ( ) ) ;
}
2020-05-03 08:06:34 -04:00
if ( fs : : exists ( target_path , error ) ) {
response - > emplace_fail ( FileModifyErrorType : : TARGET_PATH_ALREADY_EXISTS , " " ) ;
return response ;
} else if ( error ) {
2020-05-07 15:28:15 -04:00
logWarning ( LOG_FT , " Failed to check for file at {}: {}. Assuming it does exists. " , current_path . string ( ) , error . value ( ) , error . message ( ) ) ;
2020-05-03 08:06:34 -04:00
response - > emplace_fail ( FileModifyErrorType : : TARGET_PATH_ALREADY_EXISTS , " " ) ;
return response ;
}
if ( this - > is_any_file_locked ( channel_path_root , current_path , locked_file ) ) {
response - > emplace_fail ( FileModifyErrorType : : SOME_FILES_ARE_LOCKED , locked_file ) ;
return response ;
}
fs : : rename ( current_path , target_path , error ) ;
if ( error ) {
response - > emplace_fail ( FileModifyErrorType : : FAILED_TO_RENAME_FILE , std : : to_string ( error . value ( ) ) + " / " + error . message ( ) ) ;
return response ;
}
response - > emplace_success ( ) ;
return response ;
}
2020-05-13 05:32:08 -04:00
std : : shared_ptr < ExecuteResponse < FileDeleteError , FileDeleteResponse > > LocalFileSystem : : delete_files ( const fs : : path & base ,
const std : : vector < std : : string > & paths ) {
2020-05-03 08:06:34 -04:00
std : : error_code error { } ;
std : : string locked_file { } ;
2020-05-13 05:32:08 -04:00
auto response = this - > create_execute_response < FileDeleteError , FileDeleteResponse > ( ) ;
2020-05-03 08:06:34 -04:00
2020-05-13 05:32:08 -04:00
std : : vector < FileDeleteResponse : : DeleteResult > delete_results { } ;
for ( const auto & path : paths ) {
auto target_path = base / fs : : u8path ( path ) ;
2020-05-03 08:06:34 -04:00
2020-05-13 05:32:08 -04:00
if ( ! fs : : exists ( target_path , error ) ) {
delete_results . emplace_back ( FileDeleteResponse : : StatusType : : PATH_DOES_NOT_EXISTS , " " ) ;
continue ;
} else if ( error ) {
logWarning ( LOG_FT , " Failed to check for file at {}: {}. Assuming it does exists. " , target_path . string ( ) , error . value ( ) , error . message ( ) ) ;
delete_results . emplace_back ( FileDeleteResponse : : StatusType : : PATH_DOES_NOT_EXISTS , " " ) ;
continue ;
}
if ( this - > is_any_file_locked ( base , path , locked_file ) ) {
delete_results . emplace_back ( FileDeleteResponse : : StatusType : : SOME_FILES_ARE_LOCKED , locked_file ) ;
continue ;
}
if ( ! fs : : remove_all ( target_path , error ) | | error ) {
delete_results . emplace_back ( FileDeleteResponse : : StatusType : : FAILED_TO_DELETE_FILES , std : : to_string ( error . value ( ) ) + " / " + error . message ( ) ) ;
continue ;
}
delete_results . emplace_back ( FileDeleteResponse : : StatusType : : SUCCESS , " " ) ;
2020-05-03 08:06:34 -04:00
}
2020-05-13 05:32:08 -04:00
response - > emplace_success ( FileDeleteResponse { delete_results } ) ;
return response ;
}
std : : shared_ptr < ExecuteResponse < FileDeleteError , FileDeleteResponse > > LocalFileSystem : : delete_channel_files ( const std : : shared_ptr < VirtualFileServer > & id , ChannelId channelId , const std : : vector < std : : string > & path ) {
return this - > delete_files ( this - > server_channel_path ( id , channelId ) , path ) ;
}
std : : shared_ptr < ExecuteResponse < FileDeleteError , FileDeleteResponse > > LocalFileSystem : : delete_icons ( const std : : shared_ptr < VirtualFileServer > & id , const std : : vector < std : : string > & icon ) {
return this - > delete_files ( this - > server_path ( id ) / fs : : u8path ( " icons " ) , icon ) ;
}
std : : shared_ptr < ExecuteResponse < FileDeleteError , FileDeleteResponse > > LocalFileSystem : : delete_avatars ( const std : : shared_ptr < VirtualFileServer > & id , const std : : vector < std : : string > & avatar ) {
return this - > delete_files ( this - > server_path ( id ) / fs : : u8path ( " avatars " ) , avatar ) ;
}
2020-06-10 12:13:14 -04:00
std : : shared_ptr < ExecuteResponse < FileInfoError , FileInfoResponse > > LocalFileSystem : : query_file_info ( const std : : vector < std : : tuple < fs : : path , std : : string > > & paths ) {
2020-05-13 05:32:08 -04:00
std : : error_code error { } ;
auto response = this - > create_execute_response < FileInfoError , FileInfoResponse > ( ) ;
std : : vector < FileInfoResponse : : FileInfo > file_infos { } ;
file_infos . reserve ( paths . size ( ) ) ;
2020-06-10 12:13:14 -04:00
for ( const auto & [ base , path ] : paths ) {
2020-05-13 05:32:08 -04:00
auto target_path = base / fs : : u8path ( path ) ;
if ( this - > exceeds_base_path ( base , target_path ) ) {
file_infos . emplace_back ( FileInfoResponse : : StatusType : : PATH_EXCEEDS_ROOT_PATH , " " , DirectoryEntry { } ) ;
continue ;
}
if ( ! fs : : exists ( target_path , error ) ) {
file_infos . emplace_back ( FileInfoResponse : : StatusType : : PATH_DOES_NOT_EXISTS , " " , DirectoryEntry { } ) ;
continue ;
} else if ( error ) {
logWarning ( LOG_FT , " Failed to check for file at {}: {}. Assuming it does not exists. " , target_path . string ( ) , error . value ( ) , error . message ( ) ) ;
file_infos . emplace_back ( FileInfoResponse : : StatusType : : PATH_DOES_NOT_EXISTS , " " , DirectoryEntry { } ) ;
continue ;
}
auto status = fs : : status ( target_path , error ) ;
if ( error ) {
logWarning ( LOG_FT , " Failed to query file status for {} ({}/{}). Skipping entry for file info query. " , target_path . string ( ) , error . value ( ) , error . message ( ) ) ;
file_infos . emplace_back ( FileInfoResponse : : StatusType : : FAILED_TO_QUERY_INFO , " " , DirectoryEntry { } ) ;
continue ;
}
if ( status . type ( ) = = fs : : file_type : : directory ) {
DirectoryEntry dentry { } ;
dentry . type = DirectoryEntry : : DIRECTORY ;
dentry . name = target_path . filename ( ) ;
2020-06-10 12:13:14 -04:00
dentry . empty = fs : : is_empty ( target_path , error ) ;
if ( error )
logWarning ( LOG_FT , " Failed to query directory empty state for directory {} ({}/{}) " , target_path . string ( ) , error . value ( ) , error . message ( ) ) ;
2020-05-13 05:32:08 -04:00
dentry . modified_at = fs : : last_write_time ( target_path , error ) ;
if ( error )
2020-06-10 12:13:14 -04:00
logWarning ( LOG_FT , " Failed to query last write time for directory {} ({}/{}) " , target_path . string ( ) , error . value ( ) , error . message ( ) ) ;
2020-05-13 05:32:08 -04:00
dentry . size = 0 ;
file_infos . emplace_back ( FileInfoResponse : : StatusType : : SUCCESS , " " , dentry ) ;
} else if ( status . type ( ) = = fs : : file_type : : regular ) {
DirectoryEntry dentry { } ;
dentry . type = DirectoryEntry : : FILE ;
dentry . name = target_path . filename ( ) ;
dentry . modified_at = fs : : last_write_time ( target_path , error ) ;
if ( error )
logWarning ( LOG_FT , " Failed to query last write time for file {} ({}/{}). " , target_path . string ( ) , error . value ( ) , error . message ( ) ) ;
dentry . size = fs : : file_size ( target_path , error ) ;
if ( error )
logWarning ( LOG_FT , " Failed to query size for file {} ({}/{}). " , target_path . string ( ) , error . value ( ) , error . message ( ) ) ;
file_infos . emplace_back ( FileInfoResponse : : StatusType : : SUCCESS , " " , dentry ) ;
} else {
logWarning ( LOG_FT , " File info query contains an unknown file type for file {} ({}). " , target_path . string ( ) , ( int ) status . type ( ) ) ;
file_infos . emplace_back ( FileInfoResponse : : StatusType : : UNKNOWN_FILE_TYPE , " " , DirectoryEntry { } ) ;
}
2020-05-03 08:06:34 -04:00
}
2020-05-13 05:32:08 -04:00
response - > emplace_success ( FileInfoResponse { file_infos } ) ;
2020-05-03 08:06:34 -04:00
return response ;
}
2020-06-10 12:13:14 -04:00
std : : shared_ptr < ExecuteResponse < FileInfoError , FileInfoResponse > > LocalFileSystem : : query_channel_info ( const std : : shared_ptr < VirtualFileServer > & sid , const std : : vector < std : : tuple < ChannelId , std : : string > > & files ) {
std : : vector < std : : tuple < fs : : path , std : : string > > file_paths { } ;
for ( const auto & [ channelId , path ] : files )
file_paths . emplace_back ( this - > server_channel_path ( sid , channelId ) , path ) ;
return this - > query_file_info ( file_paths ) ;
2020-05-03 08:06:34 -04:00
}
2020-05-13 05:32:08 -04:00
std : : shared_ptr < ExecuteResponse < FileInfoError , FileInfoResponse > > LocalFileSystem : : query_icon_info ( const std : : shared_ptr < VirtualFileServer > & sid , const std : : vector < std : : string > & paths ) {
2020-06-10 12:13:14 -04:00
std : : vector < std : : tuple < fs : : path , std : : string > > file_paths { } ;
for ( const auto & path : paths )
file_paths . emplace_back ( this - > server_path ( sid ) / fs : : u8path ( " icons " ) , path ) ;
return this - > query_file_info ( file_paths ) ;
2020-05-03 08:06:34 -04:00
}
2020-05-13 05:32:08 -04:00
std : : shared_ptr < ExecuteResponse < FileInfoError , FileInfoResponse > > LocalFileSystem : : query_avatar_info ( const std : : shared_ptr < VirtualFileServer > & sid , const std : : vector < std : : string > & paths ) {
2020-06-10 12:13:14 -04:00
std : : vector < std : : tuple < fs : : path , std : : string > > file_paths { } ;
for ( const auto & path : paths )
file_paths . emplace_back ( this - > server_path ( sid ) / fs : : u8path ( " avatars " ) , path ) ;
return this - > query_file_info ( file_paths ) ;
2020-05-03 08:06:34 -04:00
}