1 /* 2 * lftp - file transfer program 3 * 4 * Copyright (c) 1996-2017 by Alexander V. Lukyanov (lav@yars.free.net) 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 3 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #ifndef MIRRORJOB_H 21 #define MIRRORJOB_H 22 23 #include "FileAccess.h" 24 #include "FileSet.h" 25 #include "Job.h" 26 #include "PatternSet.h" 27 #include "misc.h" 28 29 class MirrorJob : public Job 30 { 31 public: 32 enum recursion_mode_t { 33 RECURSION_ALWAYS, 34 RECURSION_NEVER, 35 RECURSION_MISSING, 36 RECURSION_NEWER, 37 }; 38 39 private: 40 enum state_t 41 { 42 INITIAL_STATE, 43 MAKE_TARGET_DIR, 44 CHANGING_DIR_SOURCE, 45 CHANGING_DIR_TARGET, 46 GETTING_LIST_INFO, 47 WAITING_FOR_TRANSFER, 48 TARGET_REMOVE_OLD, 49 TARGET_REMOVE_OLD_FIRST, 50 TARGET_CHMOD, 51 TARGET_MKDIR, 52 SOURCE_REMOVING_SAME, 53 FINISHING, 54 LAST_EXEC, 55 DONE 56 }; 57 state_t state; 58 59 FileAccessRef source_session; 60 FileAccessRef target_session; 61 bool target_is_local; 62 bool source_is_local; 63 64 long long bytes_transferred; 65 long long bytes_to_transfer; 66 67 Ref<FileSet> target_set; 68 Ref<FileSet> target_set_excluded; 69 Ref<FileSet> source_set; 70 Ref<FileSet> target_set_recursive; 71 Ref<FileSet> source_set_recursive; 72 73 Ref<FileSet> to_transfer; 74 Ref<FileSet> to_mkdir; 75 Ref<FileSet> same; 76 Ref<FileSet> to_rm; 77 Ref<FileSet> to_rm_mismatched; 78 Ref<FileSet> old_files_set; 79 Ref<FileSet> new_files_set; 80 Ref<FileSet> to_rm_src; 81 void InitSets(); // deduce above sets from source_set and target_set 82 void ExcludeEmptyDir(const char *target_rel_dir); 83 bool only_dirs; // to_transfer (or to_mkdir) contains directories only 84 RemoveSourceLater(const FileInfo * fi)85 void RemoveSourceLater(const FileInfo *fi) { 86 if(!remove_source_files) 87 return; 88 if(!to_rm_src) 89 to_rm_src=new FileSet(); 90 to_rm_src->Add(new FileInfo(*fi)); 91 } 92 AddBytesTransferred(long long b)93 void AddBytesTransferred(long long b) { 94 bytes_transferred+=b; 95 if(parent_mirror) 96 parent_mirror->AddBytesTransferred(b); 97 } AddBytesToTransfer(long long b)98 void AddBytesToTransfer(long long b) { 99 bytes_to_transfer+=b; 100 if(parent_mirror) 101 parent_mirror->AddBytesToTransfer(b); 102 } 103 104 void HandleFile(FileInfo *); 105 106 bool create_target_dir; 107 bool no_target_dir; // target directory does not exist (for script_only) 108 bool remove_this_source_dir; 109 110 SMTaskRef<ListInfo> source_list_info; 111 SMTaskRef<ListInfo> target_list_info; 112 113 xstring_c source_dir; 114 xstring_c source_relative_dir; 115 xstring_c target_dir; 116 xstring_c target_relative_dir; 117 118 struct Statistics 119 { 120 int tot_files,new_files,mod_files,del_files; 121 int dirs,del_dirs; 122 int tot_symlinks,new_symlinks,mod_symlinks,del_symlinks; 123 int error_count; 124 long long bytes; 125 double time; 126 Statistics(); 127 void Reset(); 128 void Add(const Statistics &); 129 bool HaveSomethingDone(unsigned mirror_flags); 130 }; 131 Statistics stats; 132 133 double transfer_time_elapsed; 134 TimeDate transfer_start_ts; 135 136 /* root_transfer_count is the global counter in the root mirror, 137 * and weight of a non-root mirror in global transfer_count otherwise. */ 138 int root_transfer_count; 139 140 unsigned flags; 141 recursion_mode_t recursion_mode; 142 int max_error_count; 143 144 Ref<PatternSet> top_exclude; 145 Ref<PatternSet> my_exclude; 146 const PatternSet *exclude; 147 148 bool create_remote_dir; 149 150 void Report(const char *fmt,...) PRINTF_LIKE(2,3); 151 void va_Report(const char *fmt,va_list v); 152 int verbose_report; 153 MirrorJob *parent_mirror; 154 MirrorJob *root_mirror; 155 156 time_t newer_than; 157 time_t older_than; 158 Ref<Range> my_size_range; 159 const Range *size_range; 160 161 xstring_c script_name; 162 FILE *script; 163 bool script_only; 164 bool script_needs_closing; 165 bool use_cache; 166 bool remove_source_files; 167 bool remove_source_dirs; 168 bool skip_noaccess; 169 170 int parallel; 171 int pget_n; 172 int pget_minchunk; 173 174 xstring_c on_change; 175 176 mode_t get_mode_mask(); 177 178 int source_redirections; 179 int target_redirections; 180 181 void HandleChdir(FileAccessRef& session, int &redirections); 182 void HandleListInfoCreation(const FileAccessRef& session,SMTaskRef<ListInfo>& list_info, 183 const char *relative_dir); 184 void HandleListInfo(SMTaskRef<ListInfo>& list_info,Ref<FileSet>& set,Ref<FileSet> *fsx=0); 185 186 void MirrorStarted(); 187 void MirrorFinished(); 188 void TransferStarted(class CopyJob *cp); 189 void JobStarted(Job *j); 190 void TransferFinished(Job *j); 191 void JobFinished(Job *j); 192 193 off_t GetBytesCount(); 194 double GetTimeSpent(); 195 196 public: 197 enum 198 { 199 ALLOW_SUID=1<<0, 200 DELETE=1<<1, 201 NO_RECURSION=1<<2, 202 ONLY_NEWER=1<<3, 203 NO_PERMS=1<<4, 204 CONTINUE=1<<5, 205 REPORT_NOT_DELETED=1<<6, 206 RETR_SYMLINKS=1<<7, 207 NO_UMASK=1<<8, 208 ALLOW_CHOWN=1<<9, 209 IGNORE_TIME=1<<10, 210 REMOVE_FIRST=1<<11, 211 IGNORE_SIZE=1<<12, 212 NO_SYMLINKS=1<<13, 213 LOOP=1<<14, 214 ONLY_EXISTING=1<<15, 215 NO_EMPTY_DIRS=1<<16, 216 DEPTH_FIRST=1<<17, 217 ASCII=1<<18, 218 SCAN_ALL_FIRST=1<<19, 219 OVERWRITE=1<<20, 220 UPLOAD_OLDER=1<<21, 221 TRANSFER_ALL=1<<22, 222 TARGET_FLAT=1<<23, 223 DELETE_EXCLUDED=1<<24, 224 REVERSE=1<<25, 225 }; SetFlags(unsigned f,bool v)226 void SetFlags(unsigned f,bool v) 227 { 228 if(v) 229 flags|=f; 230 else 231 flags&=~f; 232 } FlagsSet(unsigned f)233 bool FlagsSet(unsigned f) const { return (flags&f)==f; } FlagSet(unsigned f)234 bool FlagSet(unsigned f) const { return (flags&f); } AnyFlagSet(unsigned f)235 bool AnyFlagSet(unsigned f) const { return (flags&f); } 236 237 MirrorJob(MirrorJob *parent,FileAccess *f,FileAccess *target, 238 const char *new_source_dir,const char *new_target_dir); 239 ~MirrorJob(); 240 241 int Do(); Done()242 int Done() { return state==DONE; } 243 void ShowRunStatus(const SMTaskRef<StatusLine>&); 244 xstring& FormatStatus(xstring&,int v,const char *); 245 xstring& FormatShortStatus(xstring&); SayFinal()246 void SayFinal() { PrintStatus(0,""); } ExitCode()247 int ExitCode() { return stats.error_count!=0; } 248 SetExclude(PatternSet * x)249 void SetExclude(PatternSet *x) { my_exclude=x; exclude=my_exclude; } SetExclude(const PatternSet * x)250 void SetExclude(const PatternSet *x) { exclude=x; } SetSizeRange(Range * r)251 void SetSizeRange(Range *r) { my_size_range=r; size_range=my_size_range; } SetSizeRange(const Range * r)252 void SetSizeRange(const Range *r) { size_range=r; } SetTopExclude(PatternSet * x)253 void SetTopExclude(PatternSet *x) { top_exclude=x; } 254 SetVerbose(int v)255 void SetVerbose(int v) { verbose_report=v; } 256 CreateRemoteDir()257 void CreateRemoteDir() { create_remote_dir=true; } 258 259 void SetNewerThan(const char *file); 260 void SetOlderThan(const char *file); 261 UseCache(bool u)262 void UseCache(bool u) { use_cache=u; } RemoveSourceFiles()263 void RemoveSourceFiles() { remove_source_files=true; } RemoveSourceDirs()264 void RemoveSourceDirs() { remove_source_files=remove_source_dirs=true; } SkipNoAccess()265 void SkipNoAccess() { skip_noaccess=true; } 266 SetParallel(int p)267 void SetParallel(int p) { parallel=p; } SetPGet(int n)268 void SetPGet(int n) { pget_n=n; } 269 270 void Fg(); 271 void Bg(); 272 273 const char *SetRecursionMode(const char *r); 274 const char *SetScriptFile(const char *n); 275 void ScriptOnly(bool yes=true) 276 { 277 script_only=yes; 278 } SetMaxErrorCount(int ec)279 void SetMaxErrorCount(int ec) { max_error_count=ec; } 280 void SetOnChange(const char *oc); 281 static const char *AddPattern(Ref<PatternSet>& exclude,char opt,const char *optarg); 282 static const char *AddPatternsFrom(Ref<PatternSet>& exclude,char opt,const char *file); 283 GetExecSession()284 FileAccess const& GetExecSession() 285 { 286 return FlagSet(REVERSE)?*target_session:*source_session; 287 } 288 }; 289 290 #endif//MIRRORJOB_H 291