/* * lftp - file transfer program * * Copyright (c) 1996-2017 by Alexander V. Lukyanov (lav@yars.free.net) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef MIRRORJOB_H #define MIRRORJOB_H #include "FileAccess.h" #include "FileSet.h" #include "Job.h" #include "PatternSet.h" #include "misc.h" class MirrorJob : public Job { public: enum recursion_mode_t { RECURSION_ALWAYS, RECURSION_NEVER, RECURSION_MISSING, RECURSION_NEWER, }; private: enum state_t { INITIAL_STATE, MAKE_TARGET_DIR, CHANGING_DIR_SOURCE, CHANGING_DIR_TARGET, GETTING_LIST_INFO, WAITING_FOR_TRANSFER, TARGET_REMOVE_OLD, TARGET_REMOVE_OLD_FIRST, TARGET_CHMOD, TARGET_MKDIR, SOURCE_REMOVING_SAME, FINISHING, LAST_EXEC, DONE }; state_t state; FileAccessRef source_session; FileAccessRef target_session; bool target_is_local; bool source_is_local; long long bytes_transferred; long long bytes_to_transfer; Ref target_set; Ref target_set_excluded; Ref source_set; Ref target_set_recursive; Ref source_set_recursive; Ref to_transfer; Ref to_mkdir; Ref same; Ref to_rm; Ref to_rm_mismatched; Ref old_files_set; Ref new_files_set; Ref to_rm_src; void InitSets(); // deduce above sets from source_set and target_set bool only_dirs; // to_transfer (or to_mkdir) contains directories only void RemoveSourceLater(const FileInfo *fi) { if(!remove_source_files) return; if(!to_rm_src) to_rm_src=new FileSet(); to_rm_src->Add(new FileInfo(*fi)); } void AddBytesTransferred(long long b) { bytes_transferred+=b; if(parent_mirror) parent_mirror->AddBytesTransferred(b); } void AddBytesToTransfer(long long b) { bytes_to_transfer+=b; if(parent_mirror) parent_mirror->AddBytesToTransfer(b); } void HandleFile(FileInfo *); bool create_target_dir; bool no_target_dir; // target directory does not exist (for script_only) bool remove_this_source_dir; SMTaskRef source_list_info; SMTaskRef target_list_info; xstring_c source_dir; xstring_c source_relative_dir; xstring_c target_dir; xstring_c target_relative_dir; struct Statistics { int tot_files,new_files,mod_files,del_files; int dirs,del_dirs; int tot_symlinks,new_symlinks,mod_symlinks,del_symlinks; int error_count; long long bytes; double time; Statistics(); void Reset(); void Add(const Statistics &); bool HaveSomethingDone(unsigned mirror_flags); }; Statistics stats; double transfer_time_elapsed; TimeDate transfer_start_ts; /* root_transfer_count is the global counter in the root mirror, * and weight of a non-root mirror in global transfer_count otherwise. */ int root_transfer_count; unsigned flags; recursion_mode_t recursion_mode; int max_error_count; Ref top_exclude; Ref my_exclude; const PatternSet *exclude; bool create_remote_dir; void Report(const char *fmt,...) PRINTF_LIKE(2,3); void va_Report(const char *fmt,va_list v); int verbose_report; MirrorJob *parent_mirror; MirrorJob *root_mirror; time_t newer_than; time_t older_than; Ref my_size_range; const Range *size_range; xstring_c script_name; FILE *script; bool script_only; bool script_needs_closing; bool use_cache; bool remove_source_files; bool remove_source_dirs; bool skip_noaccess; int parallel; int pget_n; int pget_minchunk; xstring_c on_change; mode_t get_mode_mask(); int source_redirections; int target_redirections; void HandleChdir(FileAccessRef& session, int &redirections); void HandleListInfoCreation(const FileAccessRef& session,SMTaskRef& list_info, const char *relative_dir); void HandleListInfo(SMTaskRef& list_info,Ref& set,Ref *fsx=0); void MirrorStarted(); void MirrorFinished(); void TransferStarted(class CopyJob *cp); void JobStarted(Job *j); void TransferFinished(Job *j); void JobFinished(Job *j); off_t GetBytesCount(); double GetTimeSpent(); public: enum { ALLOW_SUID=1<<0, DELETE=1<<1, NO_RECURSION=1<<2, ONLY_NEWER=1<<3, NO_PERMS=1<<4, CONTINUE=1<<5, REPORT_NOT_DELETED=1<<6, RETR_SYMLINKS=1<<7, NO_UMASK=1<<8, ALLOW_CHOWN=1<<9, IGNORE_TIME=1<<10, REMOVE_FIRST=1<<11, IGNORE_SIZE=1<<12, NO_SYMLINKS=1<<13, LOOP=1<<14, ONLY_EXISTING=1<<15, NO_EMPTY_DIRS=1<<16, DEPTH_FIRST=1<<17, ASCII=1<<18, SCAN_ALL_FIRST=1<<19, OVERWRITE=1<<20, UPLOAD_OLDER=1<<21, TRANSFER_ALL=1<<22, TARGET_FLAT=1<<23, DELETE_EXCLUDED=1<<24, }; void SetFlags(unsigned f,bool v) { if(v) flags|=f; else flags&=~f; } bool FlagsSet(unsigned f) const { return (flags&f)==f; } bool FlagSet(unsigned f) const { return (flags&f); } bool AnyFlagSet(unsigned f) const { return (flags&f); } MirrorJob(MirrorJob *parent,FileAccess *f,FileAccess *target, const char *new_source_dir,const char *new_target_dir); ~MirrorJob(); int Do(); int Done() { return state==DONE; } void ShowRunStatus(const SMTaskRef&); xstring& FormatStatus(xstring&,int v,const char *); xstring& FormatShortStatus(xstring&); void SayFinal() { PrintStatus(0,""); } int ExitCode() { return stats.error_count!=0; } void SetExclude(PatternSet *x) { my_exclude=x; exclude=my_exclude; } void SetExclude(const PatternSet *x) { exclude=x; } void SetSizeRange(Range *r) { my_size_range=r; size_range=my_size_range; } void SetSizeRange(const Range *r) { size_range=r; } void SetTopExclude(PatternSet *x) { top_exclude=x; } void SetVerbose(int v) { verbose_report=v; } void CreateRemoteDir() { create_remote_dir=true; } void SetNewerThan(const char *file); void SetOlderThan(const char *file); void UseCache(bool u) { use_cache=u; } void RemoveSourceFiles() { remove_source_files=true; } void RemoveSourceDirs() { remove_source_files=remove_source_dirs=true; } void SkipNoAccess() { skip_noaccess=true; } void SetParallel(int p) { parallel=p; } void SetPGet(int n) { pget_n=n; } void Fg(); void Bg(); const char *SetRecursionMode(const char *r); const char *SetScriptFile(const char *n); void ScriptOnly(bool yes=true) { script_only=yes; } void SetMaxErrorCount(int ec) { max_error_count=ec; } void SetOnChange(const char *oc); static const char *AddPattern(Ref& exclude,char opt,const char *optarg); static const char *AddPatternsFrom(Ref& exclude,char opt,const char *file); }; #endif//MIRRORJOB_H