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-11-17 13:03:53 -05:00
DirectoryStorage : : DirectoryStorage ( const RsPeerId & pid , const std : : string & fname )
: mPeerId ( pid ) , mDirStorageMtx ( " Directory storage " + pid . toStdString ( ) ) , mLastSavedTime ( 0 ) , mChanged ( false ) , mFileName ( fname )
2016-07-27 15:22:59 -04:00
{
2016-11-17 13:03:53 -05:00
{
RS_STACK_MUTEX ( mDirStorageMtx ) ;
mFileHierarchy = new InternalFileHierarchyStorage ( ) ;
}
load ( fname ) ;
2016-07-27 15:22:59 -04:00
}
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-11-21 10:14:11 -05:00
bool DirectoryStorage : : updateSubDirectoryList ( const EntryIndex & indx , const std : : set < std : : string > & subdirs , const RsFileHash & hash_salt )
2016-07-27 15:22:59 -04:00
{
RS_STACK_MUTEX ( mDirStorageMtx ) ;
2016-10-12 17:20:38 -04:00
bool res = mFileHierarchy - > updateSubDirectoryList ( indx , subdirs , hash_salt ) ;
2016-11-17 13:03:53 -05:00
mChanged = true ;
2016-08-26 10:29:02 -04:00
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 ) ;
2016-11-17 13:03:53 -05:00
mChanged = true ;
2016-08-26 10:29:02 -04:00
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 ) ;
2016-11-17 15:27:37 -05:00
mChanged = true ;
2016-08-26 10:29:02 -04:00
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 ) ;
2016-11-17 13:03:53 -05:00
mChanged = true ;
2016-07-27 15:22:59 -04:00
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-11-17 13:03:53 -05:00
mChanged = true ;
2016-07-27 15:22:59 -04:00
return mFileHierarchy - > updateHash ( index , hash ) ;
2016-07-24 23:48:22 -04:00
}
2016-11-11 14:25:11 -05:00
void DirectoryStorage : : getStatistics ( SharedDirStats & stats )
{
RS_STACK_MUTEX ( mDirStorageMtx ) ;
mFileHierarchy - > getStatistics ( stats ) ;
}
2016-07-24 23:48:22 -04:00
2016-10-12 17:31:32 -04:00
bool DirectoryStorage : : load ( const std : : string & local_file_name )
2016-07-21 00:16:12 -04:00
{
2016-09-03 07:29:23 -04:00
RS_STACK_MUTEX ( mDirStorageMtx ) ;
2016-11-17 13:03:53 -05:00
mChanged = false ;
2016-10-12 17:31:32 -04:00
return 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 ( ) ;
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-11-14 15:58:58 -05:00
d . max_mtime = dir_entry - > dir_most_recent_time ;
d . mtime = dir_entry - > dir_modtime ;
2016-08-16 17:44:48 -04:00
d . name = dir_entry - > dir_name ;
2016-10-23 14:42:59 -04:00
d . path = RsDirUtil : : makePath ( dir_entry - > dir_parent_path , dir_entry - > dir_name ) ;
2016-08-16 17:44:48 -04:00
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 ;
2016-11-14 15:58:58 -05:00
d . max_mtime = file_entry - > file_modtime ;
2016-08-16 17:44:48 -04:00
d . name = file_entry - > file_name ;
d . hash = file_entry - > file_hash ;
2016-11-14 15:58:58 -05:00
d . mtime = file_entry - > file_modtime ;
2016-08-16 17:44:48 -04:00
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 )
2016-10-23 14:42:59 -04:00
d . path = RsDirUtil : : makePath ( parent_dir_entry - > dir_parent_path , parent_dir_entry - > dir_name ) ;
2016-08-16 17:44:48 -04:00
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-11-17 13:03:53 -05:00
void DirectoryStorage : : checkSave ( )
{
time_t now = time ( NULL ) ;
if ( mChanged & & mLastSavedTime + MIN_INTERVAL_BETWEEN_REMOTE_DIRECTORY_SAVE < now )
2016-11-19 14:15:53 -05:00
{
{
RS_STACK_MUTEX ( mDirStorageMtx ) ;
locked_check ( ) ;
}
save ( mFileName ) ;
{
RS_STACK_MUTEX ( mDirStorageMtx ) ;
mLastSavedTime = now ;
mChanged = false ;
}
}
2016-11-17 13:03:53 -05:00
}
2016-07-27 15:22:59 -04:00
/******************************************************************************************************************/
/* Local Directory Storage */
/******************************************************************************************************************/
2016-10-29 12:35:48 -04:00
RsFileHash LocalDirectoryStorage : : makeEncryptedHash ( const RsFileHash & hash )
{
return RsDirUtil : : sha1sum ( hash . toByteArray ( ) , hash . SIZE_IN_BYTES ) ;
}
2016-10-29 11:59:03 -04:00
bool LocalDirectoryStorage : : locked_findRealHash ( const RsFileHash & hash , RsFileHash & real_hash ) const
{
std : : map < RsFileHash , RsFileHash > : : const_iterator it = mEncryptedHashes . find ( hash ) ;
if ( it = = mEncryptedHashes . end ( ) )
return false ;
real_hash = it - > second ;
return true ;
}
int LocalDirectoryStorage : : searchHash ( const RsFileHash & hash , RsFileHash & real_hash , EntryIndex & result ) const
{
RS_STACK_MUTEX ( mDirStorageMtx ) ;
if ( locked_findRealHash ( hash , real_hash ) & & mFileHierarchy - > searchHash ( real_hash , result ) )
return true ;
if ( mFileHierarchy - > searchHash ( hash , result ) )
{
real_hash . clear ( ) ;
return true ;
}
return false ;
}
2016-07-27 15:22:59 -04:00
void LocalDirectoryStorage : : setSharedDirectoryList ( const std : : list < SharedDirInfo > & lst )
{
2016-11-21 10:14:11 -05:00
std : : set < std : : string > dirs_with_new_virtualname ;
2016-07-31 09:59:58 -04:00
2016-11-21 10:14:11 -05:00
{
RS_STACK_MUTEX ( mDirStorageMtx ) ;
2016-08-06 13:04:54 -04:00
2016-11-21 10:14:11 -05:00
// Chose virtual name if not supplied, and remove duplicates.
2016-08-06 13:04:54 -04:00
2016-11-21 10:14:11 -05:00
std : : set < std : : string > virtual_names ; // maps virtual to real name
std : : list < SharedDirInfo > processed_list ;
2016-08-06 13:04:54 -04:00
2016-11-21 10:14:11 -05:00
for ( std : : list < SharedDirInfo > : : const_iterator it ( lst . begin ( ) ) ; it ! = lst . end ( ) ; + + it )
{
int i = 0 ;
std : : string candidate_virtual_name = it - > virtualname ;
2016-08-06 13:04:54 -04:00
2016-11-21 10:14:11 -05:00
if ( candidate_virtual_name . empty ( ) )
candidate_virtual_name = RsDirUtil : : getTopDir ( it - > filename ) ;
2016-08-06 13:04:54 -04:00
2016-11-21 10:14:11 -05:00
while ( virtual_names . find ( candidate_virtual_name ) ! = virtual_names . end ( ) )
rs_sprintf_append ( candidate_virtual_name , " -%d " , + + i ) ;
2016-08-06 13:04:54 -04:00
2016-11-21 10:14:11 -05:00
SharedDirInfo d ( * it ) ;
d . virtualname = candidate_virtual_name ;
processed_list . push_back ( d ) ;
virtual_names . insert ( candidate_virtual_name ) ;
}
// now for each member of the processed list, check if it is an existing shared directory that has been changed. If so, we need to update the dir TS of that directory
std : : map < std : : string , SharedDirInfo > new_dirs ;
for ( std : : list < SharedDirInfo > : : const_iterator it ( processed_list . begin ( ) ) ; it ! = processed_list . end ( ) ; + + it )
{
std : : map < std : : string , SharedDirInfo > : : iterator it2 = mLocalDirs . find ( it - > filename ) ;
if ( it2 ! = mLocalDirs . end ( ) & & it2 - > second . virtualname ! = it - > virtualname )
dirs_with_new_virtualname . insert ( it - > filename ) ;
2016-08-06 13:04:54 -04:00
2016-11-21 10:14:11 -05:00
new_dirs [ it - > filename ] = * it ;
}
2016-08-06 13:04:54 -04:00
2016-11-21 10:14:11 -05:00
mLocalDirs = new_dirs ;
}
mTSChanged = true ;
// now update the TS off-mutex.
2016-09-18 12:34:39 -04:00
2016-11-21 10:14:11 -05:00
for ( DirIterator dirit ( this , root ( ) ) ; dirit ; + + dirit )
if ( dirs_with_new_virtualname . find ( dirit . name ( ) ) ! = dirs_with_new_virtualname . end ( ) )
{
std : : cerr < < " Updating TS of local dir \" " < < dirit . name ( ) < < " \" with changed virtual name " < < std : : endl ;
setDirectoryLocalModTime ( * dirit , time ( NULL ) ) ;
}
2016-07-27 15:22:59 -04:00
}
2016-11-21 10:14:11 -05:00
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 ) ;
}
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.
2016-11-21 10:14:11 -05:00
if ( ! SharedDirInfo : : sameLists ( it - > second . parent_groups , info . parent_groups ) | | it - > second . filename ! = info . filename | | it - > second . shareflags ! = info . shareflags | | it - > second . virtualname ! = info . virtualname )
2016-09-15 15:45:00 -04:00
{
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
2016-11-05 12:32:40 -04:00
bool unfinished_files_below ;
time_t last_modf_time = mFileHierarchy - > recursUpdateLastModfTime ( EntryIndex ( 0 ) , unfinished_files_below ) ;
2016-09-18 12:34:39 -04:00
mTSChanged = false ;
2016-08-22 01:49:45 -04:00
2016-09-18 16:05:27 -04:00
# ifdef DEBUG_LOCAL_DIRECTORY_STORAGE
2016-11-05 12:32:40 -04:00
std : : cerr < < " LocalDirectoryStorage: global last modf time is " < < last_modf_time < < " (which is " < < time ( NULL ) - last_modf_time < < " secs ago), unfinished files below= " < < unfinished_files_below < < std : : endl ;
2016-09-27 03:50:59 -04:00
# else
// remove unused variable warning
// variable is only used for debugging
( void ) last_modf_time ;
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-10-29 12:35:48 -04:00
bool LocalDirectoryStorage : : updateHash ( const EntryIndex & index , const RsFileHash & hash )
{
{
RS_STACK_MUTEX ( mDirStorageMtx ) ;
2016-08-22 01:49:45 -04:00
2016-10-29 12:35:48 -04:00
mEncryptedHashes [ makeEncryptedHash ( hash ) ] = hash ;
}
return mFileHierarchy - > updateHash ( index , hash ) ;
}
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 ) ;
2016-09-25 05:05:01 -04:00
# ifdef DEBUG_LOCAL_DIRECTORY_STORAGE
std : : cerr < < " Serialising Dir entry " < < std : : hex < < indx < < " for client id " < < client_id < < std : : endl ;
# endif
2016-08-26 10:29:02 -04:00
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-09-25 05:05:01 -04:00
# ifdef DEBUG_LOCAL_DIRECTORY_STORAGE
std : : cerr < < " pushing subdir " < < hash < < " , array position= " < < i < < " indx= " < < dir - > subdirs [ i ] < < std : : endl ;
# endif
2016-09-08 15:34:53 -04:00
}
2016-09-25 05:05:01 -04:00
# ifdef DEBUG_LOCAL_DIRECTORY_STORAGE
else
std : : cerr < < " not pushing subdir " < < hash < < " , array position= " < < i < < " indx= " < < dir - > subdirs [ i ] < < " : permission denied for this peer. " < < std : : endl ;
# endif
2016-08-31 16:47:05 -04:00
2016-10-01 09:46:32 -04:00
// now count the files that do not have a null hash (meaning the hash has indeed been computed)
uint32_t allowed_subfiles = 0 ;
for ( uint32_t i = 0 ; i < dir - > subfiles . size ( ) ; + + i )
{
const InternalFileHierarchyStorage : : FileEntry * file = mFileHierarchy - > getFileEntry ( dir - > subfiles [ i ] ) ;
if ( file ! = NULL & & ! file - > file_hash . isNull ( ) )
allowed_subfiles + + ;
}
2016-11-25 14:05:23 -05:00
unsigned char * section_data = ( unsigned char * ) rs_malloc ( FL_BASE_TMP_SECTION_SIZE ) ;
if ( ! section_data )
return false ;
uint32_t section_size = FL_BASE_TMP_SECTION_SIZE ;
2016-08-26 10:29:02 -04:00
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 ;
2016-10-01 09:46:32 -04:00
if ( ! FileListIO : : writeField ( section_data , section_size , section_offset , FILE_LIST_IO_TAG_RAW_NUMBER , ( uint32_t ) allowed_subfiles ) ) 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
2016-10-22 17:48:19 -04:00
unsigned char * file_section_data = ( unsigned char * ) rs_malloc ( FL_BASE_TMP_SECTION_SIZE ) ;
2016-11-25 14:05:23 -05:00
if ( ! file_section_data )
return false ;
2016-10-22 17:48:19 -04:00
uint32_t file_section_size = FL_BASE_TMP_SECTION_SIZE ;
2016-11-25 14:05:23 -05:00
2016-08-26 10:29:02 -04:00
for ( uint32_t i = 0 ; i < dir - > subfiles . size ( ) ; + + i )
{
uint32_t file_section_offset = 0 ;
const InternalFileHierarchyStorage : : FileEntry * file = mFileHierarchy - > getFileEntry ( dir - > subfiles [ i ] ) ;
2016-10-01 09:46:32 -04:00
if ( file = = NULL | | file - > file_hash . isNull ( ) )
2016-08-26 10:29:02 -04:00
{
2016-10-01 09:46:32 -04:00
std : : cerr < < " (II) skipping unhashed or Null file entry " < < dir - > subfiles [ i ] < < " to get/send file info. " < < std : : endl ;
2016-08-26 10:29:02 -04:00
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 ;
2016-09-25 05:05:01 -04:00
# ifdef DEBUG_LOCAL_DIRECTORY_STORAGE
std : : cerr < < " pushing subfile " < < file - > hash < < " , array position= " < < i < < " indx= " < < dir - > subfiles [ i ] < < std : : endl ;
# endif
2016-08-26 10:29:02 -04:00
}
2016-11-25 14:05:23 -05:00
free ( file_section_data ) ;
2016-08-26 10:29:02 -04:00
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 ;
}
2016-11-17 13:03:53 -05:00
2016-08-26 10:29:02 -04:00
/******************************************************************************************************************/
/* Remote Directory Storage */
/******************************************************************************************************************/
2016-09-03 07:29:23 -04:00
RemoteDirectoryStorage : : RemoteDirectoryStorage ( const RsPeerId & pid , const std : : string & fname )
2016-11-17 13:03:53 -05:00
: DirectoryStorage ( pid , fname )
2016-09-03 07:29:23 -04:00
{
2016-11-05 10:30:07 -04:00
mLastSweepTime = time ( NULL ) - ( RSRandom : : random_u32 ( ) % DELAY_BETWEEN_REMOTE_DIRECTORIES_SWEEP ) ;
std : : cerr < < " Loaded remote directory for peer " < < pid < < " , inited last sweep time to " < < time ( NULL ) - mLastSweepTime < < " secs ago. " < < std : : endl ;
2016-09-18 16:05:27 -04:00
# 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
}
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-09-27 14:13:02 -04:00
# ifdef DEBUG_REMOTE_DIRECTORY_STORAGE
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-09-27 14:13:02 -04:00
# endif
2016-08-28 12:42:52 -04:00
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-09-27 14:13:02 -04:00
# ifdef DEBUG_REMOTE_DIRECTORY_STORAGE
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-09-27 14:13:02 -04:00
# endif
2016-08-28 12:42:52 -04:00
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-10-22 17:48:19 -04:00
unsigned char * file_section_data = ( unsigned char * ) rs_malloc ( FL_BASE_TMP_SECTION_SIZE ) ;
2016-11-25 14:05:23 -05:00
if ( ! file_section_data )
return false ;
2016-10-22 17:48:19 -04:00
uint32_t file_section_size = FL_BASE_TMP_SECTION_SIZE ;
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
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
2016-09-10 14:47:51 -04:00
subfiles_array . push_back ( f ) ;
2016-08-27 08:09:26 -04:00
}
2016-11-25 14:05:23 -05:00
free ( file_section_data ) ;
2016-08-27 08:09:26 -04:00
RS_STACK_MUTEX ( mDirStorageMtx ) ;
2016-09-27 14:13:02 -04:00
# ifdef DEBUG_REMOTE_DIRECTORY_STORAGE
2016-08-28 12:42:52 -04:00
std : : cerr < < " updating dir entry... " < < std : : endl ;
2016-09-27 14:13:02 -04:00
# endif
2016-08-28 12:42:52 -04:00
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 ;
}