/*
* lftp - file transfer program
*
* Copyright (c) 1996-2016 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 FILESET_H
#define FILESET_H
#include
#include "xarray.h"
#undef TYPE
class TimeInterval;
class Range;
#define NO_SIZE ((off_t)-1L)
#define NO_SIZE_YET ((off_t)-2L)
#define NO_DATE ((time_t)-1L)
#define NO_DATE_YET ((time_t)-2L)
struct FileTimestamp
{
time_t ts;
int ts_prec;
FileTimestamp() : ts(NO_DATE_YET), ts_prec(0) {}
void set(time_t ts1,int ts1_prec) { ts=ts1; ts_prec=ts1_prec; }
bool is_set() { return ts!=NO_DATE && ts!=NO_DATE_YET; }
operator time_t() const { return ts; }
time_t operator=(time_t t) { set(t,0); return t; }
};
class FileInfo
{
void def(unsigned m) { defined|=m; need&=~m; }
public:
xstring name;
xstring longname;
xstring_c symlink;
xstring_c uri;
mode_t mode;
FileTimestamp date;
off_t size;
xstring data;
const char *user, *group;
int nlinks;
enum type
{
UNKNOWN=0,
DIRECTORY,
SYMLINK,
NORMAL,
REDIRECT,
};
type filetype;
enum defined_bits
{
NAME=001,MODE=002,DATE=004,TYPE=010,SYMLINK_DEF=020,
SIZE=0100,USER=0200,GROUP=0400,NLINKS=01000,
IGNORE_SIZE_IF_OLDER=02000, // for ignore mask
IGNORE_DATE_IF_OLDER=04000, // for ignore mask
ALL_INFO=NAME|MODE|DATE|TYPE|SYMLINK_DEF|SIZE|USER|GROUP|NLINKS
};
unsigned defined;
unsigned need;
int rank;
void Init();
FileInfo() { Init(); }
FileInfo(const FileInfo &fi);
FileInfo(const char *n) { Init(); SetName(n); }
FileInfo(const xstring& n) { Init(); SetName(n); }
~FileInfo();
void SetName(const char *n) { name.set(n); def(NAME); }
void SetName(const xstring& n) { name.set(n); def(NAME); }
void SetUser(const char *n);
void SetGroup(const char *n);
void LocalFile(const char *name, bool follow_symlinks);
static FileInfo *parse_ls_line(const char *line,int line_len,const char *tz);
static FileInfo *parse_ls_line(const char *line,const char *tz) { return parse_ls_line(line,strlen(line),tz); }
void SetMode(mode_t m) { mode=m; def(MODE); }
void SetDate(time_t t,int prec) { date.set(t,prec); def(DATE); }
void SetType(type t) { filetype=t; def(TYPE); }
void SetSymlink(const char *s) { symlink.set(s); filetype=SYMLINK; def(TYPE|SYMLINK_DEF); }
void SetRedirect(const char *s) { symlink.set(s); filetype=REDIRECT; def(TYPE|SYMLINK_DEF); }
const char *GetRedirect() const { return symlink; }
void SetSize(off_t s) { size=s; def(SIZE); }
void SetNlink(int n) { nlinks=n; def(NLINKS); }
void Merge(const FileInfo&);
void MergeInfo(const FileInfo& f,unsigned mask);
bool SameAs(const FileInfo *,int ignore) const;
bool OlderThan(time_t t) const;
bool NewerThan(time_t t) const;
bool NotOlderThan(time_t t) const;
bool NotNewerThan(time_t t) const;
bool SizeOutside(const Range *r) const;
bool TypeIs(type t) const { return (defined&TYPE) && filetype==t; }
void SetAssociatedData(const void *d,int len) { data.nset((const char*)d,len); }
const void *GetAssociatedData() const { return data; }
void SetRank(int r) { rank=r; }
int GetRank() const { return rank; }
void MakeLongName();
void SetLongName(const char *s) { longname.set(s); }
const char *GetLongName() { if(!longname) MakeLongName(); return longname; }
operator const char *() const { return name; }
bool Has(unsigned m) const { return defined&m; }
bool HasAny(unsigned m) const { return defined&m; }
bool HasAll(unsigned m) const { return (defined&m)==m; }
void Need(unsigned m) { need|=m; }
void NoNeed(unsigned m) { need&=~m; }
};
class PatternSet;
class FileSet
{
public:
enum sort_e { BYNAME, BYSIZE, DIRSFIRST, BYRANK, BYDATE, BYNAME_FLAT };
private:
RefArray files;
/* indexes when sort != NAME: */
xarray sorted;
sort_e sort_mode;
int ind;
void Sub(int);
FileInfo *Borrow(int);
void add_before(int pos,FileInfo *fi);
void assert_sorted() const;
public:
FileSet();
FileSet(const FileSet *s);
~FileSet();
void Empty();
int get_fnum() const { return files.count(); }
int count() const { return files.count(); }
int curr_index() const { return ind; }
int curr_pct() const { return count()==0 ? 100 : ind*100/count(); }
void Add(FileInfo *);
void Merge(const FileSet *);
void Merge_insert(const FileSet *set);
void SubtractSame(const FileSet *,int ignore);
void SubtractAny(const FileSet *);
void SubtractTimeCmp(bool (FileInfo::*cmp)(time_t) const,time_t);
void SubtractOlderThan(time_t t) { SubtractTimeCmp(&FileInfo::OlderThan,t); }
void SubtractNewerThan(time_t t) { SubtractTimeCmp(&FileInfo::NewerThan,t); }
void SubtractNotOlderThan(time_t t) { SubtractTimeCmp(&FileInfo::NotOlderThan,t); }
void SubtractNotNewerThan(time_t t) { SubtractTimeCmp(&FileInfo::NotNewerThan,t); }
void SubtractSizeOutside(const Range *r);
void SubtractDirs();
void SubtractNotDirs();
void SubtractNotIn(const FileSet *);
void SubtractSameType(const FileSet *);
void SubtractDirs(const FileSet *);
void SubtractNotOlderDirs(const FileSet *);
void SubtractCurr();
void Sort(sort_e newsort, bool casefold=false, bool reverse=false);
void Unsort();
void SortByPatternList(const char *list_c);
void ReverseSort();
void UnsortFlat();
void Exclude(const char *prefix,const PatternSet *x,FileSet *fsx=0);
void ExcludeDots();
void ExcludeCompound();
void ExcludeUnaccessible(const char *user=0);
void rewind() { ind=0; }
FileInfo *curr();
FileInfo *next();
void LocalRemove(const char *dir);
void LocalUtime(const char *dir,bool only_dirs=false,bool flat=false);
void LocalChmod(const char *dir,mode_t mask=0,bool flat=false);
void LocalChown(const char *dir,bool flat=false);
void Count(int *d,int *f,int *s,int *o) const;
void CountBytes(long long *b) const;
int FindGEIndByName(const char *name) const;
FileInfo *FindByName(const char *name) const;
void SetSize(const char *name,off_t size)
{
FileInfo *f=FindByName(name);
if(f)
f->SetSize(size);
}
void SetDate(const char *name,time_t date,int prec)
{
FileInfo *f=FindByName(name);
if(f)
f->SetDate(date,prec);
}
/* add a path to all files */
void PrependPath(const char *path);
/* get all defined_bits used by this fileset */
int Have() const;
FileInfo * operator[](int i) const;
size_t EstimateMemory() const;
void Dump(const char *tag) const;
};
#endif // FILESET_H