2016-09-12 18:01:26 -04:00
/*
* RetroShare File list storage system .
*
* file_sharing / directory_storage . cc
*
* Copyright 2016 Mr . Alice
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Library General Public
* License Version 2 as published by the Free Software Foundation .
*
* This library is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the GNU
* Library General Public License for more details .
*
* You should have received a copy of the GNU Library General Public
* License along with this library ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston , MA 02111 - 1307
* USA .
*
* Please report all bugs and problems to " retroshare.project@gmail.com " .
*
*/
2016-07-24 23:48:22 -04:00
# include <set>
2016-09-23 12:43:48 -04:00
# include <time.h>
2016-08-27 08:09:26 -04:00
# include "serialiser/rstlvbinary.h"
2016-08-31 16:47:05 -04:00
# include "retroshare/rspeers.h"
2016-07-31 09:59:58 -04:00
# include "util/rsdir.h"
2016-08-06 13:04:54 -04:00
# include "util/rsstring.h"
2016-09-03 07:29:23 -04:00
# include "file_sharing_defaults.h"
2016-07-21 00:16:12 -04:00
# include "directory_storage.h"
2016-09-03 07:29:23 -04:00
# include "dir_hierarchy.h"
2016-08-26 10:29:02 -04:00
# include "filelist_io.h"
2016-07-21 00:16:12 -04:00
2016-09-18 16:05:27 -04:00
//#define DEBUG_REMOTE_DIRECTORY_STORAGE 1
2016-07-24 23:48:22 -04:00
/******************************************************************************************************************/
/* Iterators */
/******************************************************************************************************************/
DirectoryStorage : : DirIterator : : DirIterator ( DirectoryStorage * s , DirectoryStorage : : EntryIndex i )
{
mStorage = s - > mFileHierarchy ;
mParentIndex = i ;
mDirTabIndex = 0 ;
}
DirectoryStorage : : FileIterator : : FileIterator ( DirectoryStorage * s , DirectoryStorage : : EntryIndex i )
{
mStorage = s - > mFileHierarchy ;
mParentIndex = i ;
mFileTabIndex = 0 ;
}
DirectoryStorage : : DirIterator & DirectoryStorage : : DirIterator : : operator + + ( )
{
+ + mDirTabIndex ;
return * this ;
}
DirectoryStorage : : FileIterator & DirectoryStorage : : FileIterator : : operator + + ( )
{
+ + mFileTabIndex ;
return * this ;
}
2016-07-27 15:22:59 -04:00
DirectoryStorage : : EntryIndex DirectoryStorage : : FileIterator : : operator * ( ) const { return mStorage - > getSubFileIndex ( mParentIndex , mFileTabIndex ) ; }
DirectoryStorage : : EntryIndex DirectoryStorage : : DirIterator : : operator * ( ) const { return mStorage - > getSubDirIndex ( mParentIndex , mDirTabIndex ) ; }
DirectoryStorage : : FileIterator : : operator bool ( ) const { return * * this ! = DirectoryStorage : : NO_INDEX ; }
DirectoryStorage : : DirIterator : : operator bool ( ) const { return * * this ! = DirectoryStorage : : NO_INDEX ; }
RsFileHash DirectoryStorage : : FileIterator : : hash ( ) const { const InternalFileHierarchyStorage : : FileEntry * f = mStorage - > getFileEntry ( * * this ) ; return f ? ( f - > file_hash ) : RsFileHash ( ) ; }
uint64_t DirectoryStorage : : FileIterator : : size ( ) const { const InternalFileHierarchyStorage : : FileEntry * f = mStorage - > getFileEntry ( * * this ) ; return f ? ( f - > file_size ) : 0 ; }
std : : string DirectoryStorage : : FileIterator : : name ( ) const { const InternalFileHierarchyStorage : : FileEntry * f = mStorage - > getFileEntry ( * * this ) ; return f ? ( f - > file_name ) : std : : string ( ) ; }
time_t DirectoryStorage : : FileIterator : : modtime ( ) const { const InternalFileHierarchyStorage : : FileEntry * f = mStorage - > getFileEntry ( * * this ) ; return f ? ( f - > file_modtime ) : 0 ; }
2016-07-24 23:48:22 -04:00
2016-08-11 08:07:45 -04:00
std : : string DirectoryStorage : : DirIterator : : name ( ) const { const InternalFileHierarchyStorage : : DirEntry * d = mStorage - > getDirEntry ( * * this ) ; return d ? ( d - > dir_name ) : std : : string ( ) ; }
2016-07-24 23:48:22 -04:00
/******************************************************************************************************************/
/* Directory Storage */
/******************************************************************************************************************/
2016-09-03 07:29:23 -04:00
DirectoryStorage : : DirectoryStorage ( const RsPeerId & pid )
: mPeerId ( pid ) , mDirStorageMtx ( " Directory storage " + pid . toStdString ( ) )
2016-07-27 15:22:59 -04:00
{
2016-08-06 13:04:54 -04:00
RS_STACK_MUTEX ( mDirStorageMtx ) ;
2016-07-27 15:22:59 -04:00
mFileHierarchy = new InternalFileHierarchyStorage ( ) ;
}
DirectoryStorage : : EntryIndex DirectoryStorage : : root ( ) const
2016-07-24 23:48:22 -04:00
{
2016-07-27 15:22:59 -04:00
return EntryIndex ( 0 ) ;
2016-07-24 23:48:22 -04:00
}
2016-08-11 08:07:45 -04:00
int DirectoryStorage : : parentRow ( EntryIndex e ) const
{
RS_STACK_MUTEX ( mDirStorageMtx ) ;
return mFileHierarchy - > parentRow ( e ) ;
}
2016-09-15 04:41:40 -04:00
bool DirectoryStorage : : getChildIndex ( EntryIndex e , int row , EntryIndex & c ) const
{
RS_STACK_MUTEX ( mDirStorageMtx ) ;
return mFileHierarchy - > getChildIndex ( e , row , c ) ;
}
2016-08-11 08:07:45 -04:00
uint32_t DirectoryStorage : : getEntryType ( const EntryIndex & indx )
{
RS_STACK_MUTEX ( mDirStorageMtx ) ;
switch ( mFileHierarchy - > getType ( indx ) )
{
case InternalFileHierarchyStorage : : FileStorageNode : : TYPE_DIR : return DIR_TYPE_DIR ;
case InternalFileHierarchyStorage : : FileStorageNode : : TYPE_FILE : return DIR_TYPE_FILE ;
default :
return DIR_TYPE_UNKNOWN ;
}
}
2016-09-15 15:45:00 -04:00
bool DirectoryStorage : : getDirectoryUpdateTime ( EntryIndex index , time_t & update_TS ) const { RS_STACK_MUTEX ( mDirStorageMtx ) ; return mFileHierarchy - > getTS ( index , update_TS , & InternalFileHierarchyStorage : : DirEntry : : dir_update_time ) ; }
bool DirectoryStorage : : getDirectoryRecursModTime ( EntryIndex index , time_t & rec_md_TS ) const { RS_STACK_MUTEX ( mDirStorageMtx ) ; return mFileHierarchy - > getTS ( index , rec_md_TS , & InternalFileHierarchyStorage : : DirEntry : : dir_most_recent_time ) ; }
bool DirectoryStorage : : getDirectoryLocalModTime ( EntryIndex index , time_t & loc_md_TS ) const { RS_STACK_MUTEX ( mDirStorageMtx ) ; return mFileHierarchy - > getTS ( index , loc_md_TS , & InternalFileHierarchyStorage : : DirEntry : : dir_modtime ) ; }
bool DirectoryStorage : : setDirectoryUpdateTime ( EntryIndex index , time_t update_TS ) { RS_STACK_MUTEX ( mDirStorageMtx ) ; return mFileHierarchy - > setTS ( index , update_TS , & InternalFileHierarchyStorage : : DirEntry : : dir_update_time ) ; }
bool DirectoryStorage : : setDirectoryRecursModTime ( EntryIndex index , time_t rec_md_TS ) { RS_STACK_MUTEX ( mDirStorageMtx ) ; return mFileHierarchy - > setTS ( index , rec_md_TS , & InternalFileHierarchyStorage : : DirEntry : : dir_most_recent_time ) ; }
bool DirectoryStorage : : setDirectoryLocalModTime ( EntryIndex index , time_t loc_md_TS ) { RS_STACK_MUTEX ( mDirStorageMtx ) ; return mFileHierarchy - > setTS ( index , loc_md_TS , & InternalFileHierarchyStorage : : DirEntry : : dir_modtime ) ; }
2016-07-24 23:48:22 -04:00
2016-08-28 12:42:52 -04:00
bool DirectoryStorage : : updateSubDirectoryList ( const EntryIndex & indx , const std : : map < std : : string , time_t > & subdirs )
2016-07-27 15:22:59 -04:00
{
RS_STACK_MUTEX ( mDirStorageMtx ) ;
2016-08-26 10:29:02 -04:00
bool res = mFileHierarchy - > updateSubDirectoryList ( indx , subdirs ) ;
locked_check ( ) ;
return res ;
2016-07-27 15:22:59 -04:00
}
2016-07-28 03:29:15 -04:00
bool DirectoryStorage : : updateSubFilesList ( const EntryIndex & indx , const std : : map < std : : string , FileTS > & subfiles , std : : map < std : : string , FileTS > & new_files )
2016-07-24 23:48:22 -04:00
{
RS_STACK_MUTEX ( mDirStorageMtx ) ;
2016-08-26 10:29:02 -04:00
bool res = mFileHierarchy - > updateSubFilesList ( indx , subfiles , new_files ) ;
locked_check ( ) ;
return res ;
2016-07-24 23:48:22 -04:00
}
2016-07-27 15:22:59 -04:00
bool DirectoryStorage : : removeDirectory ( const EntryIndex & indx )
2016-07-24 23:48:22 -04:00
{
RS_STACK_MUTEX ( mDirStorageMtx ) ;
2016-08-26 10:29:02 -04:00
bool res = mFileHierarchy - > removeDirectory ( indx ) ;
locked_check ( ) ;
return res ;
}
void DirectoryStorage : : locked_check ( )
{
std : : string error ;
if ( ! mFileHierarchy - > check ( error ) )
std : : cerr < < " Check error: " < < error < < std : : endl ;
2016-07-24 23:48:22 -04:00
}
2016-07-27 15:22:59 -04:00
bool DirectoryStorage : : updateFile ( const EntryIndex & index , const RsFileHash & hash , const std : : string & fname , uint64_t size , time_t modf_time )
{
RS_STACK_MUTEX ( mDirStorageMtx ) ;
return mFileHierarchy - > updateFile ( index , hash , fname , size , modf_time ) ;
}
bool DirectoryStorage : : updateHash ( const EntryIndex & index , const RsFileHash & hash )
2016-07-24 23:48:22 -04:00
{
RS_STACK_MUTEX ( mDirStorageMtx ) ;
2016-07-27 15:22:59 -04:00
return mFileHierarchy - > updateHash ( index , hash ) ;
2016-07-24 23:48:22 -04:00
}
2016-08-20 10:23:11 -04:00
int DirectoryStorage : : searchHash ( const RsFileHash & hash , std : : list < EntryIndex > & results ) const
{
RS_STACK_MUTEX ( mDirStorageMtx ) ;
return mFileHierarchy - > searchHash ( hash , results ) ;
}
2016-07-21 00:16:12 -04:00
void DirectoryStorage : : load ( const std : : string & local_file_name )
{
2016-09-03 07:29:23 -04:00
RS_STACK_MUTEX ( mDirStorageMtx ) ;
mFileHierarchy - > load ( local_file_name ) ;
2016-07-21 00:16:12 -04:00
}
void DirectoryStorage : : save ( const std : : string & local_file_name )
{
2016-09-03 07:29:23 -04:00
RS_STACK_MUTEX ( mDirStorageMtx ) ;
mFileHierarchy - > save ( local_file_name ) ;
2016-07-21 00:16:12 -04:00
}
2016-07-27 18:48:28 -04:00
void DirectoryStorage : : print ( )
{
RS_STACK_MUTEX ( mDirStorageMtx ) ;
mFileHierarchy - > print ( ) ;
}
2016-08-11 08:07:45 -04:00
2016-09-12 17:37:19 -04:00
int DirectoryStorage : : searchTerms ( const std : : list < std : : string > & terms , std : : list < EntryIndex > & results ) const
2016-08-11 08:07:45 -04:00
{
2016-09-12 17:37:19 -04:00
RS_STACK_MUTEX ( mDirStorageMtx ) ;
return mFileHierarchy - > searchTerms ( terms , results ) ;
}
2016-09-13 06:05:22 -04:00
int DirectoryStorage : : searchBoolExp ( RsRegularExpression : : Expression * exp , std : : list < EntryIndex > & results ) const
2016-09-12 17:37:19 -04:00
{
RS_STACK_MUTEX ( mDirStorageMtx ) ;
return mFileHierarchy - > searchBoolExp ( exp , results ) ;
2016-08-11 08:07:45 -04:00
}
2016-08-16 17:44:48 -04:00
bool DirectoryStorage : : extractData ( const EntryIndex & indx , DirDetails & d )
{
2016-09-08 17:43:14 -04:00
RS_STACK_MUTEX ( mDirStorageMtx ) ;
2016-08-16 17:44:48 -04:00
d . children . clear ( ) ;
time_t now = time ( NULL ) ;
2016-08-27 10:38:15 -04:00
uint32_t type = mFileHierarchy - > getType ( indx ) ;
2016-08-16 17:44:48 -04:00
2016-08-19 12:49:42 -04:00
d . ref = ( void * ) ( intptr_t ) indx ;
2016-08-27 10:38:15 -04:00
if ( type = = InternalFileHierarchyStorage : : FileStorageNode : : TYPE_DIR ) /* has children --- fill */
2016-08-16 17:44:48 -04:00
{
2016-08-27 10:38:15 -04:00
const InternalFileHierarchyStorage : : DirEntry * dir_entry = mFileHierarchy - > getDirEntry ( indx ) ;
2016-08-16 17:44:48 -04:00
/* extract all the entries */
for ( DirectoryStorage : : DirIterator it ( this , indx ) ; it ; + + it )
{
DirStub stub ;
stub . type = DIR_TYPE_DIR ;
stub . name = it . name ( ) ;
stub . ref = ( void * ) ( intptr_t ) * it ; // this is updated by the caller, who knows which friend we're dealing with
d . children . push_back ( stub ) ;
}
for ( DirectoryStorage : : FileIterator it ( this , indx ) ; it ; + + it )
{
DirStub stub ;
stub . type = DIR_TYPE_FILE ;
stub . name = it . name ( ) ;
stub . ref = ( void * ) ( intptr_t ) * it ;
d . children . push_back ( stub ) ;
}
d . type = DIR_TYPE_DIR ;
d . hash . clear ( ) ;
d . count = dir_entry - > subdirs . size ( ) + dir_entry - > subfiles . size ( ) ;
2016-09-05 15:22:11 -04:00
d . min_age = now - dir_entry - > dir_most_recent_time ;
2016-08-16 17:44:48 -04:00
d . name = dir_entry - > dir_name ;
d . path = dir_entry - > dir_parent_path + " / " + dir_entry - > dir_name ;
d . parent = ( void * ) ( intptr_t ) dir_entry - > parent_index ;
if ( indx = = 0 )
{
d . type = DIR_TYPE_PERSON ;
d . name = mPeerId . toStdString ( ) ;
}
}
2016-08-27 10:38:15 -04:00
else if ( type = = InternalFileHierarchyStorage : : FileStorageNode : : TYPE_FILE )
2016-08-16 17:44:48 -04:00
{
const InternalFileHierarchyStorage : : FileEntry * file_entry = mFileHierarchy - > getFileEntry ( indx ) ;
2016-08-27 10:38:15 -04:00
2016-08-16 17:44:48 -04:00
d . type = DIR_TYPE_FILE ;
d . count = file_entry - > file_size ;
d . min_age = now - file_entry - > file_modtime ;
d . name = file_entry - > file_name ;
d . hash = file_entry - > file_hash ;
d . age = now - file_entry - > file_modtime ;
d . parent = ( void * ) ( intptr_t ) file_entry - > parent_index ;
const InternalFileHierarchyStorage : : DirEntry * parent_dir_entry = mFileHierarchy - > getDirEntry ( file_entry - > parent_index ) ;
if ( parent_dir_entry ! = NULL )
d . path = parent_dir_entry - > dir_parent_path + " / " + parent_dir_entry - > dir_name + " / " ;
else
d . path = " " ;
}
2016-08-27 10:38:15 -04:00
else
return false ;
2016-08-16 17:44:48 -04:00
d . flags . clear ( ) ;
return true ;
}
2016-09-08 17:43:14 -04:00
bool DirectoryStorage : : getDirHashFromIndex ( const EntryIndex & index , RsFileHash & hash ) const
{
RS_STACK_MUTEX ( mDirStorageMtx ) ;
return mFileHierarchy - > getDirHashFromIndex ( index , hash ) ;
}
bool DirectoryStorage : : getIndexFromDirHash ( const RsFileHash & hash , EntryIndex & index ) const
{
RS_STACK_MUTEX ( mDirStorageMtx ) ;
return mFileHierarchy - > getIndexFromDirHash ( hash , index ) ;
}
2016-07-27 15:22:59 -04:00
/******************************************************************************************************************/
/* Local Directory Storage */
/******************************************************************************************************************/
void LocalDirectoryStorage : : setSharedDirectoryList ( const std : : list < SharedDirInfo > & lst )
{
RS_STACK_MUTEX ( mDirStorageMtx ) ;
2016-07-31 09:59:58 -04:00
2016-08-06 13:04:54 -04:00
// Chose virtual name if not supplied, and remove duplicates.
std : : set < std : : string > virtual_names ; // maps virtual to real name
std : : list < SharedDirInfo > processed_list ;
2016-07-31 09:59:58 -04:00
for ( std : : list < SharedDirInfo > : : const_iterator it ( lst . begin ( ) ) ; it ! = lst . end ( ) ; + + it )
2016-08-06 13:04:54 -04:00
{
int i = 0 ;
std : : string candidate_virtual_name = it - > virtualname ;
if ( candidate_virtual_name . empty ( ) )
candidate_virtual_name = RsDirUtil : : getTopDir ( it - > filename ) ;
while ( virtual_names . find ( candidate_virtual_name ) ! = virtual_names . end ( ) )
rs_sprintf_append ( candidate_virtual_name , " -%d " , + + i ) ;
SharedDirInfo d ( * it ) ;
d . virtualname = candidate_virtual_name ;
processed_list . push_back ( d ) ;
virtual_names . insert ( candidate_virtual_name ) ;
}
mLocalDirs . clear ( ) ;
for ( std : : list < SharedDirInfo > : : const_iterator it ( processed_list . begin ( ) ) ; it ! = processed_list . end ( ) ; + + it )
mLocalDirs [ it - > filename ] = * it ;
2016-09-18 12:34:39 -04:00
mTSChanged = true ;
2016-07-27 15:22:59 -04:00
}
void LocalDirectoryStorage : : getSharedDirectoryList ( std : : list < SharedDirInfo > & lst )
{
RS_STACK_MUTEX ( mDirStorageMtx ) ;
2016-07-31 09:59:58 -04:00
lst . clear ( ) ;
for ( std : : map < std : : string , SharedDirInfo > : : iterator it ( mLocalDirs . begin ( ) ) ; it ! = mLocalDirs . end ( ) ; + + it )
lst . push_back ( it - > second ) ;
}
2016-09-01 14:02:47 -04:00
static bool sameLists ( const std : : list < RsNodeGroupId > & l1 , const std : : list < RsNodeGroupId > & l2 )
2016-08-31 16:47:05 -04:00
{
2016-09-01 14:02:47 -04:00
std : : list < RsNodeGroupId > : : const_iterator it1 ( l1 . begin ( ) ) ;
std : : list < RsNodeGroupId > : : const_iterator it2 ( l2 . begin ( ) ) ;
2016-08-31 16:47:05 -04:00
for ( ; ( it1 ! = l1 . end ( ) & & it2 ! = l2 . end ( ) ) ; + + it1 , + + it2 )
if ( * it1 ! = * it2 )
return false ;
return it1 = = l1 . end ( ) & & it2 = = l2 . end ( ) ;
}
2016-07-31 09:59:58 -04:00
void LocalDirectoryStorage : : updateShareFlags ( const SharedDirInfo & info )
{
2016-09-15 15:45:00 -04:00
bool changed = false ;
2016-07-31 09:59:58 -04:00
{
2016-09-15 15:45:00 -04:00
RS_STACK_MUTEX ( mDirStorageMtx ) ;
2016-08-31 16:47:05 -04:00
2016-09-15 15:45:00 -04:00
std : : map < std : : string , SharedDirInfo > : : iterator it = mLocalDirs . find ( info . filename ) ;
2016-08-31 16:47:05 -04:00
2016-09-15 15:45:00 -04:00
if ( it = = mLocalDirs . end ( ) )
{
std : : cerr < < " (EE) LocalDirectoryStorage::updateShareFlags: directory \" " < < info . filename < < " \" not found " < < std : : endl ;
return ;
}
2016-08-31 16:47:05 -04:00
2016-09-15 15:45:00 -04:00
// we compare the new info with the old one. If the two group lists have a different order, they will be seen as different. Not a big deal. We just
// want to make sure that if they are different, flags get updated.
if ( ! sameLists ( it - > second . parent_groups , info . parent_groups ) | | it - > second . filename ! = info . filename | | it - > second . shareflags ! = info . shareflags | | it - > second . virtualname ! = info . virtualname )
{
it - > second = info ;
2016-09-18 16:05:27 -04:00
# ifdef DEBUG_LOCAL_DIRECTORY_STORAGE
2016-09-15 15:45:00 -04:00
std : : cerr < < " Updating dir mod time because flags at level 0 have changed. " < < std : : endl ;
2016-09-18 16:05:27 -04:00
# endif
2016-09-15 15:45:00 -04:00
changed = true ;
}
2016-08-31 16:47:05 -04:00
}
2016-09-15 15:45:00 -04:00
if ( changed )
2016-09-18 12:34:39 -04:00
{
2016-09-15 15:45:00 -04:00
setDirectoryLocalModTime ( 0 , time ( NULL ) ) ;
2016-09-18 12:34:39 -04:00
mTSChanged = true ;
}
2016-07-27 15:22:59 -04:00
}
2016-07-31 09:59:58 -04:00
bool LocalDirectoryStorage : : convertSharedFilePath ( const std : : string & path , std : : string & fullpath )
{
std : : string shpath = RsDirUtil : : removeRootDir ( path ) ;
std : : string basedir = RsDirUtil : : getRootDir ( path ) ;
std : : string realroot ;
{
RS_STACK_MUTEX ( mDirStorageMtx ) ;
realroot = locked_findRealRootFromVirtualFilename ( basedir ) ;
}
if ( realroot . empty ( ) )
return false ;
/* construct full name */
fullpath = realroot + " / " ;
fullpath + = shpath ;
return true ;
}
2016-09-18 12:34:39 -04:00
void LocalDirectoryStorage : : notifyTSChanged ( )
{
RS_STACK_MUTEX ( mDirStorageMtx ) ;
mTSChanged = true ;
}
2016-08-22 01:49:45 -04:00
void LocalDirectoryStorage : : updateTimeStamps ( )
{
RS_STACK_MUTEX ( mDirStorageMtx ) ;
2016-09-18 12:34:39 -04:00
if ( mTSChanged )
{
2016-09-18 16:05:27 -04:00
# ifdef DEBUG_LOCAL_DIRECTORY_STORAGE
2016-09-18 12:34:39 -04:00
std : : cerr < < " Updating recursive TS for local shared dirs... " < < std : : endl ;
2016-09-18 16:05:27 -04:00
# endif
2016-09-18 12:34:39 -04:00
time_t last_modf_time = mFileHierarchy - > recursUpdateLastModfTime ( EntryIndex ( 0 ) ) ;
mTSChanged = false ;
2016-08-22 01:49:45 -04:00
2016-09-18 16:05:27 -04:00
# ifdef DEBUG_LOCAL_DIRECTORY_STORAGE
2016-09-18 12:34:39 -04:00
std : : cerr < < " LocalDirectoryStorage: global last modf time is " < < last_modf_time < < " (which is " < < time ( NULL ) - last_modf_time < < " secs ago) " < < std : : endl ;
2016-09-18 16:05:27 -04:00
# endif
2016-09-18 12:34:39 -04:00
}
2016-08-22 01:49:45 -04:00
}
2016-07-31 09:59:58 -04:00
std : : string LocalDirectoryStorage : : locked_findRealRootFromVirtualFilename ( const std : : string & virtual_rootdir ) const
{
/**** MUST ALREADY BE LOCKED ****/
std : : map < std : : string , SharedDirInfo > : : const_iterator cit = mLocalDirs . find ( virtual_rootdir ) ;
if ( cit = = mLocalDirs . end ( ) )
{
2016-09-18 16:05:27 -04:00
std : : cerr < < " (EE) locked_findRealRootFromVirtualFilename() Invalid RootDir: " < < virtual_rootdir < < std : : endl ;
2016-07-31 09:59:58 -04:00
return std : : string ( ) ;
}
return cit - > second . filename ;
}
2016-08-11 08:07:45 -04:00
bool LocalDirectoryStorage : : extractData ( const EntryIndex & indx , DirDetails & d )
2016-07-31 09:59:58 -04:00
{
2016-08-16 17:44:48 -04:00
bool res = DirectoryStorage : : extractData ( indx , d ) ;
2016-08-11 08:07:45 -04:00
2016-08-16 17:44:48 -04:00
if ( ! res )
return false ;
2016-08-11 08:07:45 -04:00
2016-08-16 17:44:48 -04:00
// here we should update the file sharing flags
2016-08-11 08:07:45 -04:00
2016-08-30 15:28:32 -04:00
return getFileSharingPermissions ( indx , d . flags , d . parent_groups ) ;
}
2016-09-12 17:37:19 -04:00
bool LocalDirectoryStorage : : getFileInfo ( DirectoryStorage : : EntryIndex i , FileInfo & info )
{
DirDetails d ;
extractData ( i , d ) ;
if ( d . type ! = DIR_TYPE_FILE )
{
std : : cerr < < " (EE) LocalDirectoryStorage: asked for file info for index " < < i < < " which is not a file. " < < std : : endl ;
return false ;
}
info . storage_permission_flags = d . flags ; // Combination of the four RS_DIR_FLAGS_*. Updated when the file is a local stored file.
info . parent_groups = d . parent_groups ;
info . transfer_info_flags = TransferRequestFlags ( ) ; // various flags from RS_FILE_HINTS_*
info . path = d . path + " / " + d . name ;
info . fname = d . name ;
info . hash = d . hash ;
info . size = d . count ;
// all this stuff below is not useful in this case.
info . mId = 0 ; /* (GUI) Model Id -> unique number */
info . ext . clear ( ) ;
info . avail = 0 ; /* how much we have */
info . rank = 0 ;
info . age = 0 ;
info . queue_position = 0 ;
info . searchId = 0 ; /* 0 if none */
/* Transfer Stuff */
info . transfered = 0 ;
info . tfRate = 0 ; /* in kbytes */
info . downloadStatus = FT_STATE_COMPLETE ;
std : : list < TransferInfo > peers ;
info . priority = SPEED_NORMAL ;
info . lastTS = 0 ;
return true ;
}
2016-09-01 14:02:47 -04:00
bool LocalDirectoryStorage : : getFileSharingPermissions ( const EntryIndex & indx , FileStorageFlags & flags , std : : list < RsNodeGroupId > & parent_groups )
2016-08-30 15:28:32 -04:00
{
RS_STACK_MUTEX ( mDirStorageMtx ) ;
2016-08-31 16:47:05 -04:00
return locked_getFileSharingPermissions ( indx , flags , parent_groups ) ;
}
2016-08-30 15:28:32 -04:00
2016-09-01 14:02:47 -04:00
bool LocalDirectoryStorage : : locked_getFileSharingPermissions ( const EntryIndex & indx , FileStorageFlags & flags , std : : list < RsNodeGroupId > & parent_groups )
2016-08-31 16:47:05 -04:00
{
2016-08-30 15:28:32 -04:00
flags . clear ( ) ;
parent_groups . clear ( ) ;
2016-08-29 15:30:56 -04:00
std : : string base_dir ;
2016-08-30 15:28:32 -04:00
const InternalFileHierarchyStorage : : FileStorageNode * n = mFileHierarchy - > getNode ( indx ) ;
if ( n = = NULL )
return false ;
for ( DirectoryStorage : : EntryIndex i = ( ( n - > type ( ) = = InternalFileHierarchyStorage : : FileStorageNode : : TYPE_FILE ) ? ( ( intptr_t ) n - > parent_index ) : indx ) ; ; )
2016-08-29 15:30:56 -04:00
{
const InternalFileHierarchyStorage : : DirEntry * e = mFileHierarchy - > getDirEntry ( i ) ;
if ( e = = NULL )
break ;
if ( e - > parent_index = = 0 )
{
base_dir = e - > dir_name ;
break ;
}
i = e - > parent_index ;
}
if ( ! base_dir . empty ( ) )
{
std : : map < std : : string , SharedDirInfo > : : const_iterator it = mLocalDirs . find ( base_dir ) ;
2016-08-11 08:07:45 -04:00
2016-08-29 15:30:56 -04:00
if ( it = = mLocalDirs . end ( ) )
{
std : : cerr < < " (EE) very weird bug: base directory \" " < < base_dir < < " \" not found in shared dir list. " < < std : : endl ;
return false ;
}
2016-09-01 14:02:47 -04:00
2016-08-30 15:28:32 -04:00
flags = it - > second . shareflags ;
parent_groups = it - > second . parent_groups ;
2016-08-29 15:30:56 -04:00
}
2016-08-11 08:07:45 -04:00
return true ;
}
2016-08-26 10:29:02 -04:00
2016-09-10 07:57:05 -04:00
std : : string LocalDirectoryStorage : : locked_getVirtualDirName ( EntryIndex indx ) const
{
if ( indx = = 0 )
return std : : string ( ) ;
const InternalFileHierarchyStorage : : DirEntry * dir = mFileHierarchy - > getDirEntry ( indx ) ;
if ( dir - > parent_index ! = 0 )
return dir - > dir_name ;
std : : map < std : : string , SharedDirInfo > : : const_iterator it = mLocalDirs . find ( dir - > dir_name ) ;
if ( it = = mLocalDirs . end ( ) )
{
std : : cerr < < " (EE) Cannot find real name " < < dir - > dir_name < < " at level 1 among shared dirs. Bug? " < < std : : endl ;
return std : : string ( ) ;
}
return it - > second . virtualname ;
}
std : : string LocalDirectoryStorage : : locked_getVirtualPath ( EntryIndex indx ) const
{
if ( indx = = 0 )
return std : : string ( ) ;
std : : string res ;
const InternalFileHierarchyStorage : : DirEntry * dir = mFileHierarchy - > getDirEntry ( indx ) ;
while ( dir - > parent_index ! = 0 )
{
dir = mFileHierarchy - > getDirEntry ( dir - > parent_index ) ;
res + = dir - > dir_name + " / " + res ;
}
std : : map < std : : string , SharedDirInfo > : : const_iterator it = mLocalDirs . find ( dir - > dir_name ) ;
if ( it = = mLocalDirs . end ( ) )
{
std : : cerr < < " (EE) Cannot find real name " < < dir - > dir_name < < " at level 1 among shared dirs. Bug? " < < std : : endl ;
return std : : string ( ) ;
}
return it - > second . virtualname + " / " + res ;
}
2016-08-31 16:47:05 -04:00
bool LocalDirectoryStorage : : serialiseDirEntry ( const EntryIndex & indx , RsTlvBinaryData & bindata , const RsPeerId & client_id )
2016-08-26 10:29:02 -04:00
{
RS_STACK_MUTEX ( mDirStorageMtx ) ;
const InternalFileHierarchyStorage : : DirEntry * dir = mFileHierarchy - > getDirEntry ( indx ) ;
if ( dir = = NULL )
{
std : : cerr < < " (EE) serialiseDirEntry: ERROR. Cannot find entry " < < ( void * ) ( intptr_t ) indx < < std : : endl ;
return false ;
}
2016-08-31 16:47:05 -04:00
// compute list of allowed subdirs
2016-09-08 15:34:53 -04:00
std : : vector < RsFileHash > allowed_subdirs ;
2016-08-31 16:47:05 -04:00
FileStorageFlags node_flags ;
2016-09-01 14:02:47 -04:00
std : : list < RsNodeGroupId > node_groups ;
2016-08-31 16:47:05 -04:00
// for each subdir, compute the node flags and groups, then ask rsPeers to compute the mask that result from these flags for the particular peer supplied in parameter
for ( uint32_t i = 0 ; i < dir - > subdirs . size ( ) ; + + i )
if ( indx ! = 0 | | ( locked_getFileSharingPermissions ( dir - > subdirs [ i ] , node_flags , node_groups ) & & ( rsPeers - > computePeerPermissionFlags ( client_id , node_flags , node_groups ) & RS_FILE_HINTS_BROWSABLE ) ) )
2016-09-08 15:34:53 -04:00
{
2016-09-10 11:25:29 -04:00
RsFileHash hash ;
if ( ! mFileHierarchy - > getDirHashFromIndex ( dir - > subdirs [ i ] , hash ) )
{
std : : cerr < < " (EE) Cannot get hash from subdir index " < < dir - > subdirs [ i ] < < " . Weird bug. " < < std : : endl ;
return false ;
}
2016-09-08 15:34:53 -04:00
allowed_subdirs . push_back ( hash ) ;
}
2016-08-31 16:47:05 -04:00
2016-08-26 10:29:02 -04:00
unsigned char * section_data = NULL ;
uint32_t section_size = 0 ;
uint32_t section_offset = 0 ;
// we need to send:
// - the name of the directory, its TS
// - the index entry for each subdir (the updte TS are exchanged at a higher level)
// - the file info for each subfile
//
2016-09-10 07:57:05 -04:00
std : : string virtual_dir_name = locked_getVirtualDirName ( indx ) ;
2016-08-26 10:29:02 -04:00
2016-09-10 07:57:05 -04:00
if ( ! FileListIO : : writeField ( section_data , section_size , section_offset , FILE_LIST_IO_TAG_DIR_NAME , virtual_dir_name ) ) return false ;
2016-09-05 15:22:11 -04:00
if ( ! FileListIO : : writeField ( section_data , section_size , section_offset , FILE_LIST_IO_TAG_RECURS_MODIF_TS , ( uint32_t ) dir - > dir_most_recent_time ) ) return false ;
2016-09-10 07:57:05 -04:00
if ( ! FileListIO : : writeField ( section_data , section_size , section_offset , FILE_LIST_IO_TAG_MODIF_TS , ( uint32_t ) dir - > dir_modtime ) ) return false ;
2016-08-26 10:29:02 -04:00
// serialise number of subdirs and number of subfiles
2016-08-31 16:47:05 -04:00
if ( ! FileListIO : : writeField ( section_data , section_size , section_offset , FILE_LIST_IO_TAG_RAW_NUMBER , ( uint32_t ) allowed_subdirs . size ( ) ) ) return false ;
if ( ! FileListIO : : writeField ( section_data , section_size , section_offset , FILE_LIST_IO_TAG_RAW_NUMBER , ( uint32_t ) dir - > subfiles . size ( ) ) ) return false ;
2016-08-26 10:29:02 -04:00
// serialise subdirs entry indexes
2016-08-31 16:47:05 -04:00
for ( uint32_t i = 0 ; i < allowed_subdirs . size ( ) ; + + i )
2016-09-08 15:34:53 -04:00
if ( ! FileListIO : : writeField ( section_data , section_size , section_offset , FILE_LIST_IO_TAG_ENTRY_INDEX , allowed_subdirs [ i ] ) ) return false ;
2016-08-26 10:29:02 -04:00
// serialise directory subfiles, with info for each of them
for ( uint32_t i = 0 ; i < dir - > subfiles . size ( ) ; + + i )
{
unsigned char * file_section_data = NULL ;
uint32_t file_section_offset = 0 ;
uint32_t file_section_size = 0 ;
const InternalFileHierarchyStorage : : FileEntry * file = mFileHierarchy - > getFileEntry ( dir - > subfiles [ i ] ) ;
if ( file = = NULL )
{
std : : cerr < < " (EE) cannot reach file entry " < < dir - > subfiles [ i ] < < " to get/send file info. " < < std : : endl ;
continue ;
}
if ( ! FileListIO : : writeField ( file_section_data , file_section_size , file_section_offset , FILE_LIST_IO_TAG_FILE_NAME , file - > file_name ) ) return false ;
if ( ! FileListIO : : writeField ( file_section_data , file_section_size , file_section_offset , FILE_LIST_IO_TAG_FILE_SIZE , file - > file_size ) ) return false ;
if ( ! FileListIO : : writeField ( file_section_data , file_section_size , file_section_offset , FILE_LIST_IO_TAG_FILE_SHA1_HASH , file - > file_hash ) ) return false ;
2016-08-27 17:56:23 -04:00
if ( ! FileListIO : : writeField ( file_section_data , file_section_size , file_section_offset , FILE_LIST_IO_TAG_MODIF_TS , ( uint32_t ) file - > file_modtime ) ) return false ;
2016-08-26 10:29:02 -04:00
// now write the whole string into a single section in the file
if ( ! FileListIO : : writeField ( section_data , section_size , section_offset , FILE_LIST_IO_TAG_REMOTE_FILE_ENTRY , file_section_data , file_section_offset ) ) return false ;
free ( file_section_data ) ;
}
2016-09-18 16:05:27 -04:00
# ifdef DEBUG_LOCAL_DIRECTORY_STORAGE
2016-08-26 10:29:02 -04:00
std : : cerr < < " Serialised dir entry to send for entry index " < < ( void * ) ( intptr_t ) indx < < " . Data size is " < < section_size < < " bytes " < < std : : endl ;
2016-09-18 16:05:27 -04:00
# endif
2016-08-26 10:29:02 -04:00
2016-08-27 17:56:23 -04:00
bindata . bin_data = section_data ;
bindata . bin_len = section_offset ;
2016-08-26 10:29:02 -04:00
return true ;
}
/******************************************************************************************************************/
/* Remote Directory Storage */
/******************************************************************************************************************/
2016-09-03 07:29:23 -04:00
RemoteDirectoryStorage : : RemoteDirectoryStorage ( const RsPeerId & pid , const std : : string & fname )
: DirectoryStorage ( pid ) , mLastSavedTime ( 0 ) , mChanged ( false ) , mFileName ( fname )
{
load ( fname ) ;
2016-09-06 17:05:46 -04:00
2016-09-18 16:05:27 -04:00
std : : cerr < < " Loaded remote directory for peer " < < pid < < std : : endl ;
# ifdef DEBUG_REMOTE_DIRECTORY_STORAGE
2016-09-06 17:05:46 -04:00
mFileHierarchy - > print ( ) ;
2016-09-18 16:05:27 -04:00
# endif
2016-09-03 07:29:23 -04:00
}
void RemoteDirectoryStorage : : checkSave ( )
{
time_t now = time ( NULL ) ;
if ( mChanged & & mLastSavedTime + MIN_INTERVAL_BETWEEN_REMOTE_DIRECTORY_SAVE < now )
{
save ( mFileName ) ;
mLastSavedTime = now ;
}
}
bool RemoteDirectoryStorage : : deserialiseUpdateDirEntry ( const EntryIndex & indx , const RsTlvBinaryData & bindata )
2016-08-26 10:29:02 -04:00
{
2016-08-27 08:09:26 -04:00
const unsigned char * section_data = ( unsigned char * ) bindata . bin_data ;
uint32_t section_size = bindata . bin_len ;
2016-08-27 17:56:23 -04:00
uint32_t section_offset = 0 ;
2016-08-26 10:29:02 -04:00
2016-09-18 16:05:27 -04:00
# ifdef DEBUG_REMOTE_DIRECTORY_STORAGE
2016-08-26 10:29:02 -04:00
std : : cerr < < " RemoteDirectoryStorage::deserialiseDirEntry(): deserialising directory content for friend " < < peerId ( ) < < " , and directory " < < indx < < std : : endl ;
2016-09-18 16:05:27 -04:00
# endif
2016-08-26 10:29:02 -04:00
2016-08-27 08:09:26 -04:00
std : : string dir_name ;
2016-08-27 17:56:23 -04:00
uint32_t most_recent_time , dir_modtime ;
2016-08-27 08:09:26 -04:00
if ( ! FileListIO : : readField ( section_data , section_size , section_offset , FILE_LIST_IO_TAG_DIR_NAME , dir_name ) ) return false ;
if ( ! FileListIO : : readField ( section_data , section_size , section_offset , FILE_LIST_IO_TAG_RECURS_MODIF_TS , most_recent_time ) ) return false ;
if ( ! FileListIO : : readField ( section_data , section_size , section_offset , FILE_LIST_IO_TAG_MODIF_TS , dir_modtime ) ) return false ;
2016-08-28 12:42:52 -04:00
std : : cerr < < " dir name : \" " < < dir_name < < " \" " < < std : : endl ;
std : : cerr < < " most recent time : " < < most_recent_time < < std : : endl ;
std : : cerr < < " modification time : " < < dir_modtime < < std : : endl ;
2016-08-27 08:09:26 -04:00
// serialise number of subdirs and number of subfiles
uint32_t n_subdirs , n_subfiles ;
if ( ! FileListIO : : readField ( section_data , section_size , section_offset , FILE_LIST_IO_TAG_RAW_NUMBER , n_subdirs ) ) return false ;
if ( ! FileListIO : : readField ( section_data , section_size , section_offset , FILE_LIST_IO_TAG_RAW_NUMBER , n_subfiles ) ) return false ;
2016-08-28 12:42:52 -04:00
std : : cerr < < " number of subdirs : " < < n_subdirs < < std : : endl ;
std : : cerr < < " number of files : " < < n_subfiles < < std : : endl ;
2016-08-27 08:09:26 -04:00
// serialise subdirs entry indexes
2016-09-08 15:34:53 -04:00
std : : vector < RsFileHash > subdirs_hashes ;
RsFileHash subdir_hash ;
2016-08-27 08:09:26 -04:00
for ( uint32_t i = 0 ; i < n_subdirs ; + + i )
{
2016-09-08 15:34:53 -04:00
if ( ! FileListIO : : readField ( section_data , section_size , section_offset , FILE_LIST_IO_TAG_ENTRY_INDEX , subdir_hash ) ) return false ;
2016-08-27 08:09:26 -04:00
2016-09-08 15:34:53 -04:00
subdirs_hashes . push_back ( subdir_hash ) ;
2016-08-27 08:09:26 -04:00
}
// deserialise directory subfiles, with info for each of them
2016-09-10 14:47:51 -04:00
std : : vector < InternalFileHierarchyStorage : : FileEntry > subfiles_array ;
2016-08-27 08:09:26 -04:00
for ( uint32_t i = 0 ; i < n_subfiles ; + + i )
{
// Read the full data section for the file
unsigned char * file_section_data = NULL ;
uint32_t file_section_size = 0 ;
if ( ! FileListIO : : readField ( section_data , section_size , section_offset , FILE_LIST_IO_TAG_REMOTE_FILE_ENTRY , file_section_data , file_section_size ) ) return false ;
uint32_t file_section_offset = 0 ;
2016-09-10 14:47:51 -04:00
InternalFileHierarchyStorage : : FileEntry f ;
uint32_t modtime = 0 ;
if ( ! FileListIO : : readField ( file_section_data , file_section_size , file_section_offset , FILE_LIST_IO_TAG_FILE_NAME , f . file_name ) ) return false ;
if ( ! FileListIO : : readField ( file_section_data , file_section_size , file_section_offset , FILE_LIST_IO_TAG_FILE_SIZE , f . file_size ) ) return false ;
if ( ! FileListIO : : readField ( file_section_data , file_section_size , file_section_offset , FILE_LIST_IO_TAG_FILE_SHA1_HASH , f . file_hash ) ) return false ;
if ( ! FileListIO : : readField ( file_section_data , file_section_size , file_section_offset , FILE_LIST_IO_TAG_MODIF_TS , modtime ) ) return false ;
2016-08-27 08:09:26 -04:00
2016-09-10 14:47:51 -04:00
f . file_modtime = modtime ;
2016-08-27 08:09:26 -04:00
free ( file_section_data ) ;
2016-09-10 14:47:51 -04:00
subfiles_array . push_back ( f ) ;
2016-08-27 08:09:26 -04:00
}
RS_STACK_MUTEX ( mDirStorageMtx ) ;
2016-08-28 12:42:52 -04:00
std : : cerr < < " updating dir entry... " < < std : : endl ;
2016-09-08 15:34:53 -04:00
// First create the entries for each subdir and each subfile, if needed.
2016-09-10 14:47:51 -04:00
if ( ! mFileHierarchy - > updateDirEntry ( indx , dir_name , most_recent_time , dir_modtime , subdirs_hashes , subfiles_array ) )
2016-08-27 08:09:26 -04:00
{
std : : cerr < < " (EE) Cannot update dir entry with index " < < indx < < " : entry does not exist. " < < std : : endl ;
return false ;
}
2016-09-03 07:29:23 -04:00
mChanged = true ;
2016-08-26 10:29:02 -04:00
return true ;
}