1 /*
2  * lftp - file transfer program
3  *
4  * Copyright (c) 1996-2016 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 FILESET_H
21 #define FILESET_H
22 
23 #include <sys/types.h>
24 #include "xarray.h"
25 
26 #undef TYPE
27 
28 class TimeInterval;
29 class Range;
30 
31 #define NO_SIZE	     ((off_t)-1L)
32 #define NO_SIZE_YET  ((off_t)-2L)
33 #define NO_DATE	     ((time_t)-1L)
34 #define NO_DATE_YET  ((time_t)-2L)
35 
36 struct FileTimestamp
37 {
38    time_t ts;
39    int ts_prec;
FileTimestampFileTimestamp40    FileTimestamp() : ts(NO_DATE_YET), ts_prec(0) {}
setFileTimestamp41    void set(time_t ts1,int ts1_prec) { ts=ts1; ts_prec=ts1_prec; }
is_setFileTimestamp42    bool is_set() { return ts!=NO_DATE && ts!=NO_DATE_YET; }
time_tFileTimestamp43    operator time_t() const { return ts; }
44    time_t operator=(time_t t) { set(t,0); return t; }
45 };
46 
47 class FileInfo
48 {
def(unsigned m)49    void def(unsigned m) { defined|=m; need&=~m; }
50 public:
51    xstring  name;
52    xstring  longname;
53    xstring_c symlink;
54    xstring_c uri;
55    mode_t   mode;
56    FileTimestamp date;
57    off_t    size;
58    xstring  data;
59    const char *user, *group;
60    int      nlinks;
61 
62    enum	 type
63    {
64       UNKNOWN=0,
65       DIRECTORY,
66       SYMLINK,
67       NORMAL,
68       REDIRECT,
69    };
70    type	 filetype;
71 
72    enum defined_bits
73    {
74       NAME=001,MODE=002,DATE=004,TYPE=010,SYMLINK_DEF=020,
75       SIZE=0100,USER=0200,GROUP=0400,NLINKS=01000,
76 
77       IGNORE_SIZE_IF_OLDER=02000, // for ignore mask
78       IGNORE_DATE_IF_OLDER=04000, // for ignore mask
79 
80       ALL_INFO=NAME|MODE|DATE|TYPE|SYMLINK_DEF|SIZE|USER|GROUP|NLINKS
81    };
82    unsigned defined;
83    unsigned need;
84 
85    int rank;
86 
87    void Init();
FileInfo()88    FileInfo() { Init(); }
89    FileInfo(const FileInfo &fi);
FileInfo(const char * n)90    FileInfo(const char *n) { Init(); SetName(n); }
FileInfo(const xstring & n)91    FileInfo(const xstring& n) { Init(); SetName(n); }
92    ~FileInfo();
93 
SetName(const char * n)94    void SetName(const char *n) { name.set(n); def(NAME); }
SetName(const xstring & n)95    void SetName(const xstring& n) { name.set(n); def(NAME); }
96    void SetUser(const char *n);
97    void SetGroup(const char *n);
98    void LocalFile(const char *name, bool follow_symlinks);
99    static FileInfo *parse_ls_line(const char *line,int line_len,const char *tz);
parse_ls_line(const char * line,const char * tz)100    static FileInfo *parse_ls_line(const char *line,const char *tz) { return parse_ls_line(line,strlen(line),tz); }
101 
SetMode(mode_t m)102    void SetMode(mode_t m) { mode=m; def(MODE); }
SetDate(time_t t,int prec)103    void SetDate(time_t t,int prec) { date.set(t,prec); def(DATE); }
SetType(type t)104    void SetType(type t) { filetype=t; def(TYPE); }
SetSymlink(const char * s)105    void SetSymlink(const char *s) { symlink.set(s); filetype=SYMLINK; def(TYPE|SYMLINK_DEF); }
SetRedirect(const char * s)106    void SetRedirect(const char *s) { symlink.set(s); filetype=REDIRECT; def(TYPE|SYMLINK_DEF); }
GetRedirect()107    const char *GetRedirect() const { return symlink; }
SetSize(off_t s)108    void	SetSize(off_t s) { size=s; def(SIZE); }
SetNlink(int n)109    void	SetNlink(int n) { nlinks=n; def(NLINKS); }
110 
111    void	 Merge(const FileInfo&);
112    void  MergeInfo(const FileInfo& f,unsigned mask);
113 
114    bool	 SameAs(const FileInfo *,int ignore) const;
115    bool	 OlderThan(time_t t) const;
116    bool	 NewerThan(time_t t) const;
117    bool	 NotOlderThan(time_t t) const;
118    bool	 NotNewerThan(time_t t) const;
119    bool  SizeOutside(const Range *r) const;
TypeIs(type t)120    bool	 TypeIs(type t) const { return (defined&TYPE) && filetype==t; }
121 
SetAssociatedData(const void * d,int len)122    void	 SetAssociatedData(const void *d,int len) { data.nset((const char*)d,len); }
GetAssociatedData()123    const void *GetAssociatedData() const { return data; }
124 
SetRank(int r)125    void SetRank(int r) { rank=r; }
GetRank()126    int GetRank() const { return rank; }
127    void MakeLongName();
SetLongName(const char * s)128    void SetLongName(const char *s) { longname.set(s); }
GetLongName()129    const char *GetLongName() { if(!longname) MakeLongName(); return longname; }
130 
131    operator const char *() const { return name; }
132 
Has(unsigned m)133    bool Has(unsigned m) const { return defined&m; }
HasAny(unsigned m)134    bool HasAny(unsigned m) const { return defined&m; }
HasAll(unsigned m)135    bool HasAll(unsigned m) const { return (defined&m)==m; }
136 
Need(unsigned m)137    void Need(unsigned m) { need|=m; }
NoNeed(unsigned m)138    void NoNeed(unsigned m) { need&=~m; }
139 };
140 
141 class PatternSet;
142 
143 class FileSet
144 {
145 public:
146    enum sort_e { BYNAME, BYSIZE, DIRSFIRST, BYRANK, BYDATE, BYNAME_FLAT };
147 
148 private:
149    RefArray<FileInfo> files;
150 
151    /* indexes when sort != NAME: */
152    xarray<int> sorted;
153    sort_e sort_mode;
154 
155    int	 ind;
156 
157    void	 Sub(int);
158    FileInfo *Borrow(int);
159 
160    void add_before(int pos,FileInfo *fi);
161    void assert_sorted() const;
162 
163 public:
164    FileSet();
165    FileSet(const FileSet *s);
166    ~FileSet();
167 
168    void Empty();
169 
get_fnum()170    int	 get_fnum() const { return files.count(); }
count()171    int	 count() const { return files.count(); }
curr_index()172    int	 curr_index() const { return ind; }
curr_pct()173    int	 curr_pct() const { return count()==0 ? 100 : ind*100/count(); }
174 
175    void	 Add(FileInfo *);
176    void	 Merge(const FileSet *);
177    void	 Merge_insert(const FileSet *set);
178    void	 SubtractSame(const FileSet *,int ignore);
179    void	 SubtractAny(const FileSet *);
180    void  SubtractTimeCmp(bool (FileInfo::*cmp)(time_t) const,time_t);
SubtractOlderThan(time_t t)181    void  SubtractOlderThan(time_t t) { SubtractTimeCmp(&FileInfo::OlderThan,t); }
SubtractNewerThan(time_t t)182    void  SubtractNewerThan(time_t t) { SubtractTimeCmp(&FileInfo::NewerThan,t); }
SubtractNotOlderThan(time_t t)183    void  SubtractNotOlderThan(time_t t) { SubtractTimeCmp(&FileInfo::NotOlderThan,t); }
SubtractNotNewerThan(time_t t)184    void  SubtractNotNewerThan(time_t t) { SubtractTimeCmp(&FileInfo::NotNewerThan,t); }
185    void  SubtractSizeOutside(const Range *r);
186    void  SubtractDirs();
187    void  SubtractNotDirs();
188    void  SubtractNotIn(const FileSet *);
189    void  SubtractSameType(const FileSet *);
190    void  SubtractDirs(const FileSet *);
191    void  SubtractNotOlderDirs(const FileSet *);
192    void  SubtractCurr();
193    bool  SubtractByName(const char *name);
194    void  Sort(sort_e newsort, bool casefold=false, bool reverse=false);
195    void  Unsort();
196    void	 SortByPatternList(const char *list_c);
197    void	 ReverseSort();
198    void	 UnsortFlat();
199 
200    void	 Exclude(const char *prefix,const PatternSet *x,FileSet *fsx=0);
201    void	 ExcludeDots();
202    void	 ExcludeCompound();
203    void	 ExcludeUnaccessible(const char *user=0);
204 
rewind()205    void	 rewind() { ind=0; }
206    FileInfo *curr();
207    FileInfo *next();
borrow_curr()208    FileInfo *borrow_curr() { return Borrow(ind--); }
209 
210    void	 LocalRemove(const char *dir);
211    void	 LocalUtime(const char *dir,bool only_dirs=false,bool flat=false);
212    void	 LocalChmod(const char *dir,mode_t mask=0,bool flat=false);
213    void	 LocalChown(const char *dir,bool flat=false);
214 
215    void Count(int *d,int *f,int *s,int *o) const;
216    void CountBytes(long long *b) const;
217 
218    int FindGEIndByName(const char *name) const;
219    FileInfo *FindByName(const char *name) const;
220 
SetSize(const char * name,off_t size)221    void  SetSize(const char *name,off_t size)
222    {
223       FileInfo *f=FindByName(name);
224       if(f)
225 	 f->SetSize(size);
226    }
SetDate(const char * name,time_t date,int prec)227    void  SetDate(const char *name,time_t date,int prec)
228    {
229       FileInfo *f=FindByName(name);
230       if(f)
231 	 f->SetDate(date,prec);
232    }
233 
234    /* add a path to all files */
235    void PrependPath(const char *path);
236 
237    /* get all defined_bits used by this fileset */
238    int Have() const;
239 
240    FileInfo * operator[](int i) const;
241 
242    size_t EstimateMemory() const;
243    void Dump(const char *tag) const;
244 };
245 
246 #endif // FILESET_H
247