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