|
Packit |
8f70b4 |
/*
|
|
Packit |
8f70b4 |
* lftp - file transfer program
|
|
Packit |
8f70b4 |
*
|
|
Packit |
8f70b4 |
* Copyright (c) 1996-2016 by Alexander V. Lukyanov (lav@yars.free.net)
|
|
Packit |
8f70b4 |
*
|
|
Packit |
8f70b4 |
* This program is free software; you can redistribute it and/or modify
|
|
Packit |
8f70b4 |
* it under the terms of the GNU General Public License as published by
|
|
Packit |
8f70b4 |
* the Free Software Foundation; either version 3 of the License, or
|
|
Packit |
8f70b4 |
* (at your option) any later version.
|
|
Packit |
8f70b4 |
*
|
|
Packit |
8f70b4 |
* This program is distributed in the hope that it will be useful,
|
|
Packit |
8f70b4 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
8f70b4 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit |
8f70b4 |
* GNU General Public License for more details.
|
|
Packit |
8f70b4 |
*
|
|
Packit |
8f70b4 |
* You should have received a copy of the GNU General Public License
|
|
Packit |
8f70b4 |
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
Packit |
8f70b4 |
*/
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
#include <config.h>
|
|
Packit |
8f70b4 |
#include "FileSet.h"
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
#include <stddef.h>
|
|
Packit |
8f70b4 |
#include <sys/types.h>
|
|
Packit |
8f70b4 |
#include <sys/stat.h>
|
|
Packit |
8f70b4 |
#include <utime.h>
|
|
Packit |
8f70b4 |
#include <stdlib.h>
|
|
Packit |
8f70b4 |
#include <unistd.h>
|
|
Packit |
8f70b4 |
#include <sys/stat.h>
|
|
Packit |
8f70b4 |
#include <fnmatch.h>
|
|
Packit |
8f70b4 |
#include <assert.h>
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
#include <grp.h>
|
|
Packit |
8f70b4 |
#include <pwd.h>
|
|
Packit |
8f70b4 |
#include <ctype.h>
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
#include "misc.h"
|
|
Packit |
8f70b4 |
#include "ResMgr.h"
|
|
Packit |
8f70b4 |
#include "StringPool.h"
|
|
Packit |
8f70b4 |
#include "IdNameCache.h"
|
|
Packit |
8f70b4 |
#include "PatternSet.h"
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
#ifdef HAVE_SYS_STATFS_H
|
|
Packit |
8f70b4 |
# include <sys/statfs.h>
|
|
Packit |
8f70b4 |
#endif
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
#define fnum files.count()
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void FileInfo::Merge(const FileInfo& f)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(strcmp(basename_ptr(name),basename_ptr(f.name)))
|
|
Packit |
8f70b4 |
return;
|
|
Packit |
8f70b4 |
MergeInfo(f,~defined);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
void FileInfo::MergeInfo(const FileInfo& f,unsigned dif)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
dif&=f.defined;
|
|
Packit |
8f70b4 |
if(dif&MODE) {
|
|
Packit |
8f70b4 |
SetMode(f.mode);
|
|
Packit |
8f70b4 |
if(mode!=SYMLINK && mode!=REDIRECT)
|
|
Packit |
8f70b4 |
symlink.unset();
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
if(dif&DATE || (defined&DATE && f.defined&DATE && f.date.ts_prec
|
|
Packit |
8f70b4 |
SetDate(f.date,f.date.ts_prec);
|
|
Packit |
8f70b4 |
if(dif&SIZE)
|
|
Packit |
8f70b4 |
SetSize(f.size);
|
|
Packit |
8f70b4 |
if(dif&TYPE)
|
|
Packit |
8f70b4 |
SetType(f.filetype);
|
|
Packit |
8f70b4 |
if(dif&SYMLINK)
|
|
Packit |
8f70b4 |
SetSymlink(f.symlink);
|
|
Packit |
8f70b4 |
if(dif&USER)
|
|
Packit |
8f70b4 |
SetUser(f.user);
|
|
Packit |
8f70b4 |
if(dif&GROUP)
|
|
Packit |
8f70b4 |
SetGroup(f.group);
|
|
Packit |
8f70b4 |
if(dif&NLINKS)
|
|
Packit |
8f70b4 |
SetNlink(f.nlinks);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void FileInfo::SetUser(const char *u)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(u==user)
|
|
Packit |
8f70b4 |
return;
|
|
Packit |
8f70b4 |
user=StringPool::Get(u);
|
|
Packit |
8f70b4 |
def(USER);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void FileInfo::SetGroup(const char *g)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(g==group)
|
|
Packit |
8f70b4 |
return;
|
|
Packit |
8f70b4 |
group=StringPool::Get(g);
|
|
Packit |
8f70b4 |
def(GROUP);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void FileSet::add_before(int pos,FileInfo *fi)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
files.insert(fi,pos);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
void FileSet::Add(FileInfo *fi)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
assert(!sorted);
|
|
Packit |
8f70b4 |
if(!fi->name)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
delete fi;
|
|
Packit |
8f70b4 |
return;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
/* add sorted */
|
|
Packit |
8f70b4 |
int pos = FindGEIndByName(fi->name);
|
|
Packit |
8f70b4 |
if(pos < fnum && !strcmp(files[pos]->name,fi->name)) {
|
|
Packit |
8f70b4 |
files[pos]->Merge(*fi);
|
|
Packit |
8f70b4 |
delete fi;
|
|
Packit |
8f70b4 |
return;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
add_before(pos,fi);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void FileSet::Sub(int i)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
assert(!sorted);
|
|
Packit |
8f70b4 |
files.remove(i);
|
|
Packit |
8f70b4 |
if(ind>i)
|
|
Packit |
8f70b4 |
ind--;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
FileInfo *FileSet::Borrow(int i)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
FileInfo *fi=files[i].borrow();
|
|
Packit |
8f70b4 |
Sub(i);
|
|
Packit |
8f70b4 |
return fi;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void FileSet::assert_sorted() const
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
for(int i=0; i
|
|
Packit |
8f70b4 |
assert(strcmp(files[i]->name,files[i+1]->name)<0);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void FileSet::Merge_insert(const FileSet *set)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(!set)
|
|
Packit |
8f70b4 |
return;
|
|
Packit |
8f70b4 |
for(int i=0; i<set->fnum; i++)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
const Ref<FileInfo>& fi=set->files[i];
|
|
Packit |
8f70b4 |
int pos = FindGEIndByName(fi->name);
|
|
Packit |
8f70b4 |
if(pos < fnum && !strcmp(files[pos]->name,fi->name))
|
|
Packit |
8f70b4 |
files[pos]->Merge(*fi);
|
|
Packit |
8f70b4 |
else
|
|
Packit |
8f70b4 |
add_before(pos,new FileInfo(*fi));
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
void FileSet::Merge(const FileSet *set)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
assert(!sorted);
|
|
Packit |
8f70b4 |
if(!set || !set->fnum)
|
|
Packit |
8f70b4 |
return;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
// estimate work to be done by Merge_insert
|
|
Packit |
8f70b4 |
int pos = FindGEIndByName(set->files[0]->name);
|
|
Packit |
8f70b4 |
if(fnum-pos < fnum*2/set->fnum) {
|
|
Packit |
8f70b4 |
Merge_insert(set);
|
|
Packit |
8f70b4 |
return;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
RefArray<FileInfo> new_set;
|
|
Packit |
8f70b4 |
int i=0;
|
|
Packit |
8f70b4 |
int j=0;
|
|
Packit |
8f70b4 |
while(i<set->fnum && j
|
|
Packit |
8f70b4 |
Ref<FileInfo>& fi1=files[j];
|
|
Packit |
8f70b4 |
const Ref<FileInfo>& fi2=set->files[i];
|
|
Packit |
8f70b4 |
int cmp = strcmp(fi1->name,fi2->name);
|
|
Packit |
8f70b4 |
if(cmp==0) {
|
|
Packit |
8f70b4 |
fi1->Merge(*fi2);
|
|
Packit |
8f70b4 |
new_set.append(fi1.borrow());
|
|
Packit |
8f70b4 |
i++; j++;
|
|
Packit |
8f70b4 |
} else if(cmp>0) {
|
|
Packit |
8f70b4 |
new_set.append(new FileInfo(*fi2));
|
|
Packit |
8f70b4 |
i++;
|
|
Packit |
8f70b4 |
} else {
|
|
Packit |
8f70b4 |
new_set.append(fi1.borrow());
|
|
Packit |
8f70b4 |
j++;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
while(i<set->fnum) {
|
|
Packit |
8f70b4 |
const Ref<FileInfo>& fi2=set->files[i];
|
|
Packit |
8f70b4 |
new_set.append(new FileInfo(*fi2));
|
|
Packit |
8f70b4 |
i++;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
if(new_set.count()==0)
|
|
Packit |
8f70b4 |
return;
|
|
Packit |
8f70b4 |
while(j
|
|
Packit |
8f70b4 |
Ref<FileInfo>& fi1=files[j];
|
|
Packit |
8f70b4 |
new_set.append(fi1.borrow());
|
|
Packit |
8f70b4 |
j++;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
files.move_here(new_set);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void FileSet::PrependPath(const char *path)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
for(int i=0; i
|
|
Packit |
8f70b4 |
files[i]->SetName(dir_file(path, files[i]->name));
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
FileSet::FileSet()
|
|
Packit |
8f70b4 |
: sort_mode(BYNAME), ind(0)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
FileSet::~FileSet()
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
/* we don't copy the sort state--nothing needs it, and it'd
|
|
Packit |
8f70b4 |
* be a bit of a pain to implement. */
|
|
Packit |
8f70b4 |
FileSet::FileSet(FileSet const *set)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(!set) {
|
|
Packit |
8f70b4 |
ind=0;
|
|
Packit |
8f70b4 |
return;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
ind=set->ind;
|
|
Packit |
8f70b4 |
for(int i=0; i<set->fnum; i++)
|
|
Packit |
8f70b4 |
files.append(new FileInfo(*(set->files[i])));
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
static int files_sort_name(const Ref<FileInfo> *s1, const Ref<FileInfo> *s2)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
return strcmp((*s1)->name, (*s2)->name);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
static int (*compare)(const char *s1, const char *s2);
|
|
Packit |
8f70b4 |
static int rev_cmp;
|
|
Packit |
8f70b4 |
static RefArray<FileInfo> *files_cmp;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
static int sort_name(const int *s1, const int *s2)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
const FileInfo *p1=(*files_cmp)[*s1];
|
|
Packit |
8f70b4 |
const FileInfo *p2=(*files_cmp)[*s2];
|
|
Packit |
8f70b4 |
return compare(p1->name, p2->name) * rev_cmp;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
static int sort_size(const int *s1, const int *s2)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
const FileInfo *p1=(*files_cmp)[*s1];
|
|
Packit |
8f70b4 |
const FileInfo *p2=(*files_cmp)[*s2];
|
|
Packit |
8f70b4 |
if(p1->size > p2->size) return -rev_cmp;
|
|
Packit |
8f70b4 |
if(p1->size < p2->size) return rev_cmp;
|
|
Packit |
8f70b4 |
return 0;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
static int sort_dirs(const int *s1, const int *s2)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
const FileInfo *p1=(*files_cmp)[*s1];
|
|
Packit |
8f70b4 |
const FileInfo *p2=(*files_cmp)[*s2];
|
|
Packit |
8f70b4 |
if((p1->filetype == FileInfo::DIRECTORY) && !(p2->filetype == FileInfo::DIRECTORY)) return -rev_cmp;
|
|
Packit |
8f70b4 |
if(!(p1->filetype == FileInfo::DIRECTORY) && (p2->filetype == FileInfo::DIRECTORY)) return rev_cmp;
|
|
Packit |
8f70b4 |
return 0;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
static int sort_rank(const int *s1, const int *s2)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
const FileInfo *p1=(*files_cmp)[*s1];
|
|
Packit |
8f70b4 |
const FileInfo *p2=(*files_cmp)[*s2];
|
|
Packit |
8f70b4 |
if(p1->GetRank()==p2->GetRank())
|
|
Packit |
8f70b4 |
return sort_name(s1,s2);
|
|
Packit |
8f70b4 |
return p1->GetRank()<p2->GetRank() ? -rev_cmp : rev_cmp;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
static int sort_date(const int *s1, const int *s2)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
const FileInfo *p1=(*files_cmp)[*s1];
|
|
Packit |
8f70b4 |
const FileInfo *p2=(*files_cmp)[*s2];
|
|
Packit |
8f70b4 |
if(p1->date==p2->date)
|
|
Packit |
8f70b4 |
return sort_name(s1,s2);
|
|
Packit |
8f70b4 |
return p1->date>p2->date ? -rev_cmp : rev_cmp;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void FileSet::Sort(sort_e newsort, bool casefold, bool reverse)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(newsort == BYNAME && !casefold && !reverse) {
|
|
Packit |
8f70b4 |
Unsort();
|
|
Packit |
8f70b4 |
return;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
if(casefold) compare = strcasecmp;
|
|
Packit |
8f70b4 |
else compare = strcmp;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
rev_cmp=(reverse?-1:1);
|
|
Packit |
8f70b4 |
files_cmp=&file;;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
if(newsort==BYNAME_FLAT && sort_mode!=BYNAME_FLAT)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
// save original paths to longname, store basename to name,
|
|
Packit |
8f70b4 |
// sort files array according to short names
|
|
Packit |
8f70b4 |
for(int i=0; i
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
Ref<FileInfo> const& fi=files[i];
|
|
Packit |
8f70b4 |
fi->longname.move_here(fi->name);
|
|
Packit |
8f70b4 |
fi->name.set(basename_ptr(fi->longname));
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
files.qsort(files_sort_name);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
xmap<bool> dup;
|
|
Packit |
8f70b4 |
sorted.truncate();
|
|
Packit |
8f70b4 |
for(int i=0; i
|
|
Packit |
8f70b4 |
if(newsort==BYNAME_FLAT && sort_mode!=BYNAME_FLAT) {
|
|
Packit |
8f70b4 |
Ref<FileInfo> const& fi=files[i];
|
|
Packit |
8f70b4 |
if(dup.exists(fi->name))
|
|
Packit |
8f70b4 |
continue;
|
|
Packit |
8f70b4 |
dup.add(fi->name,true);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
sorted.append(i);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
switch(newsort) {
|
|
Packit |
8f70b4 |
case BYNAME_FLAT: /*fallthrough*/
|
|
Packit |
8f70b4 |
case BYNAME: sorted.qsort(sort_name); break;
|
|
Packit |
8f70b4 |
case BYSIZE: sorted.qsort(sort_size); break;
|
|
Packit |
8f70b4 |
case DIRSFIRST: sorted.qsort(sort_dirs); break;
|
|
Packit |
8f70b4 |
case BYRANK: sorted.qsort(sort_rank); break;
|
|
Packit |
8f70b4 |
case BYDATE: sorted.qsort(sort_date); break;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
sort_mode=newsort;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
// reverse current sort order
|
|
Packit |
8f70b4 |
void FileSet::ReverseSort()
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(!sorted) {
|
|
Packit |
8f70b4 |
Sort(BYNAME,false,true);
|
|
Packit |
8f70b4 |
return;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
int i=0;
|
|
Packit |
8f70b4 |
int j=sorted.length()-1;
|
|
Packit |
8f70b4 |
while(i
|
|
Packit |
8f70b4 |
sorted[i]=replace_value(sorted[j],sorted[i]);
|
|
Packit |
8f70b4 |
++i,--j;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
/* Remove the current sort, allowing new entries to be added. */
|
|
Packit |
8f70b4 |
void FileSet::Unsort()
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
sorted.unset();
|
|
Packit |
8f70b4 |
if(sort_mode==BYNAME_FLAT)
|
|
Packit |
8f70b4 |
UnsortFlat();
|
|
Packit |
8f70b4 |
sort_mode=BYNAME;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void FileSet::UnsortFlat()
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
for(int i=0; i
|
|
Packit |
8f70b4 |
assert(files[i]->longname!=0);
|
|
Packit |
8f70b4 |
files[i]->name.move_here(files[i]->longname);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
files.qsort(files_sort_name);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void FileSet::Empty()
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
Unsort();
|
|
Packit |
8f70b4 |
files.unset();
|
|
Packit |
8f70b4 |
ind=0;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void FileSet::SubtractSame(const FileSet *set,int ignore)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(!set)
|
|
Packit |
8f70b4 |
return;
|
|
Packit |
8f70b4 |
for(int i=0; i
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
FileInfo *f=set->FindByName(files[i]->name);
|
|
Packit |
8f70b4 |
if(f && files[i]->SameAs(f,ignore))
|
|
Packit |
8f70b4 |
Sub(i--);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void FileSet::SubtractAny(const FileSet *set)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(!set)
|
|
Packit |
8f70b4 |
return;
|
|
Packit |
8f70b4 |
for(int i=0; i
|
|
Packit |
8f70b4 |
if(set->FindByName(files[i]->name))
|
|
Packit |
8f70b4 |
Sub(i--);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void FileSet::SubtractNotIn(const FileSet *set)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(!set) {
|
|
Packit |
8f70b4 |
Empty();
|
|
Packit |
8f70b4 |
return;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
for(int i=0; i
|
|
Packit |
8f70b4 |
if(!set->FindByName(files[i]->name))
|
|
Packit |
8f70b4 |
Sub(i--);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
void FileSet::SubtractSameType(const FileSet *set)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(!set)
|
|
Packit |
8f70b4 |
return;
|
|
Packit |
8f70b4 |
for(int i=0; i
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
FileInfo *f=set->FindByName(files[i]->name);
|
|
Packit |
8f70b4 |
if(f && files[i]->defined&FileInfo::TYPE && f->defined&FileInfo::TYPE
|
|
Packit |
8f70b4 |
&& files[i]->filetype==f->filetype)
|
|
Packit |
8f70b4 |
Sub(i--);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
void FileSet::SubtractDirs(const FileSet *set)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(!set)
|
|
Packit |
8f70b4 |
return;
|
|
Packit |
8f70b4 |
for(int i=0; i
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(!files[i]->TypeIs(FileInfo::DIRECTORY))
|
|
Packit |
8f70b4 |
continue;
|
|
Packit |
8f70b4 |
FileInfo *f=set->FindByName(files[i]->name);
|
|
Packit |
8f70b4 |
if(f && f->TypeIs(f->DIRECTORY))
|
|
Packit |
8f70b4 |
Sub(i--);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
void FileSet::SubtractNotOlderDirs(const FileSet *set)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(!set)
|
|
Packit |
8f70b4 |
return;
|
|
Packit |
8f70b4 |
for(int i=0; i
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(!files[i]->TypeIs(FileInfo::DIRECTORY)
|
|
Packit |
8f70b4 |
|| !files[i]->Has(FileInfo::DATE))
|
|
Packit |
8f70b4 |
continue;
|
|
Packit |
8f70b4 |
FileInfo *f=set->FindByName(files[i]->name);
|
|
Packit |
8f70b4 |
if(f && f->TypeIs(f->DIRECTORY) && f->NotOlderThan(files[i]->date))
|
|
Packit |
8f70b4 |
Sub(i--);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void FileSet::SubtractTimeCmp(bool (FileInfo::*cmp)(time_t) const,time_t t)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
for(int i=0; i
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(files[i]->defined&FileInfo::TYPE
|
|
Packit |
8f70b4 |
&& files[i]->filetype!=FileInfo::NORMAL)
|
|
Packit |
8f70b4 |
continue;
|
|
Packit |
8f70b4 |
if((files[i].get()->*cmp)(t))
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
Sub(i);
|
|
Packit |
8f70b4 |
i--;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void FileSet::SubtractSizeOutside(const Range *r)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
for(int i=0; i
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(files[i]->defined&FileInfo::TYPE
|
|
Packit |
8f70b4 |
&& files[i]->filetype!=FileInfo::NORMAL)
|
|
Packit |
8f70b4 |
continue;
|
|
Packit |
8f70b4 |
if(files[i]->SizeOutside(r))
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
Sub(i);
|
|
Packit |
8f70b4 |
i--;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
void FileSet::SubtractDirs()
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
for(int i=0; i
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(files[i]->defined&FileInfo::TYPE
|
|
Packit |
8f70b4 |
&& files[i]->filetype==FileInfo::DIRECTORY)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
Sub(i);
|
|
Packit |
8f70b4 |
i--;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
void FileSet::SubtractNotDirs()
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
for(int i=0; i
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(!(files[i]->defined&FileInfo::TYPE)
|
|
Packit |
8f70b4 |
|| files[i]->filetype!=FileInfo::DIRECTORY)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
Sub(i);
|
|
Packit |
8f70b4 |
i--;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void FileSet::ExcludeDots()
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
for(int i=0; i
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(!strcmp(files[i]->name,".") || !strcmp(files[i]->name,".."))
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
Sub(i);
|
|
Packit |
8f70b4 |
i--;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
void FileSet::ExcludeCompound()
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
for(int i=0; i
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
const char *name=files[i]->name;
|
|
Packit |
8f70b4 |
if(!strncmp(name,"./~",3))
|
|
Packit |
8f70b4 |
name+=3;
|
|
Packit |
8f70b4 |
if(strchr(name,'/'))
|
|
Packit |
8f70b4 |
Sub(i--);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void FileSet::ExcludeUnaccessible(const char *user)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
for(int i=0; i
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(!files[i]->Has(FileInfo::MODE) || !files[i]->Has(FileInfo::TYPE))
|
|
Packit |
8f70b4 |
continue;
|
|
Packit |
8f70b4 |
unsigned mask=0444;
|
|
Packit |
8f70b4 |
if(user && files[i]->Has(FileInfo::USER))
|
|
Packit |
8f70b4 |
mask=(!strcmp(files[i]->user,user)?0400:0044);
|
|
Packit |
8f70b4 |
if((files[i]->TypeIs(FileInfo::NORMAL) && !(files[i]->mode&mask))
|
|
Packit |
8f70b4 |
|| (files[i]->TypeIs(FileInfo::DIRECTORY) && !(files[i]->mode&mask&(files[i]->mode<<2))))
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
Sub(i);
|
|
Packit |
8f70b4 |
i--;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
bool FileInfo::SameAs(const FileInfo *fi,int ignore) const
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(defined&NAME && fi->defined&NAME)
|
|
Packit |
8f70b4 |
if(strcmp(name,fi->name))
|
|
Packit |
8f70b4 |
return false;
|
|
Packit |
8f70b4 |
if(defined&TYPE && fi->defined&TYPE)
|
|
Packit |
8f70b4 |
if(filetype!=fi->filetype)
|
|
Packit |
8f70b4 |
return false;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
if((defined&TYPE && filetype==DIRECTORY)
|
|
Packit |
8f70b4 |
|| (fi->defined&TYPE && fi->filetype==DIRECTORY))
|
|
Packit |
8f70b4 |
return false; // can't guarantee directory is the same (recursively)
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
if(defined&SYMLINK_DEF && fi->defined&SYMLINK_DEF)
|
|
Packit |
8f70b4 |
return (strcmp(symlink,fi->symlink)==0);
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
if(defined&DATE && fi->defined&DATE && !(ignore&DATE))
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
time_t p=date.ts_prec;
|
|
Packit |
8f70b4 |
if(p<fi->date.ts_prec)
|
|
Packit |
8f70b4 |
p=fi->date.ts_prec;
|
|
Packit |
8f70b4 |
if(!(ignore&IGNORE_DATE_IF_OLDER && date<fi->date)
|
|
Packit |
8f70b4 |
&& labs(date-fi->date)>p)
|
|
Packit |
8f70b4 |
return false;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
if(defined&SIZE && fi->defined&SIZE && !(ignore&SIZE))
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(!(ignore&IGNORE_SIZE_IF_OLDER && defined&DATE && fi->defined&DATE
|
|
Packit |
8f70b4 |
&& date<fi->date)
|
|
Packit |
8f70b4 |
&& (size!=fi->size))
|
|
Packit |
8f70b4 |
return false;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
return true;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
bool FileInfo::NotOlderThan(time_t t) const
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
return((defined&DATE) && date>=t);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
bool FileInfo::NotNewerThan(time_t t) const
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
return((defined&DATE) && date<=t);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
bool FileInfo::OlderThan(time_t t) const
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
return((defined&DATE) && date
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
bool FileInfo::NewerThan(time_t t) const
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
return((defined&DATE) && date>t);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
bool FileInfo::SizeOutside(const Range *r) const
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
return((defined&SIZE) && !r->Match(size));
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void FileSet::Count(int *d,int *f,int *s,int *o) const
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
for(int i=0; i
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
switch(files[i]->filetype)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
case(FileInfo::DIRECTORY):
|
|
Packit |
8f70b4 |
if(d) (*d)++;
|
|
Packit |
8f70b4 |
break;
|
|
Packit |
8f70b4 |
case(FileInfo::NORMAL):
|
|
Packit |
8f70b4 |
if(f) (*f)++;
|
|
Packit |
8f70b4 |
break;
|
|
Packit |
8f70b4 |
case(FileInfo::SYMLINK):
|
|
Packit |
8f70b4 |
if(s) (*s)++;
|
|
Packit |
8f70b4 |
break;
|
|
Packit |
8f70b4 |
default:
|
|
Packit |
8f70b4 |
if(o) (*o)++;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void FileSet::CountBytes(long long *b) const
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
for(int i=0; i
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(files[i]->filetype==FileInfo::NORMAL && files[i]->Has(FileInfo::SIZE))
|
|
Packit |
8f70b4 |
(*b)+=files[i]->size;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
/* assumes sorted by name. binary search for name, returning the first name
|
|
Packit |
8f70b4 |
* >= name; returns fnum if name is greater than all names. */
|
|
Packit |
8f70b4 |
int FileSet::FindGEIndByName(const char *name) const
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
int l = 0, u = fnum - 1;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
/* no files or name is greater than the max file: */
|
|
Packit |
8f70b4 |
if(!fnum || strcmp(files[u]->name, name) < 0)
|
|
Packit |
8f70b4 |
return fnum;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
/* we have files, and u >= name (meaning l <= name <= u); loop while
|
|
Packit |
8f70b4 |
* this is true: */
|
|
Packit |
8f70b4 |
while(l < u) {
|
|
Packit |
8f70b4 |
/* find the midpoint: */
|
|
Packit |
8f70b4 |
int m = (l + u) / 2;
|
|
Packit |
8f70b4 |
int cmp = strcmp(files[m]->name, name);
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
/* if files[m]->name > name, update the upper bound: */
|
|
Packit |
8f70b4 |
if (cmp > 0)
|
|
Packit |
8f70b4 |
u = m;
|
|
Packit |
8f70b4 |
/* if files[m]->name < name, update the lower bound: */
|
|
Packit |
8f70b4 |
else if (cmp < 0)
|
|
Packit |
8f70b4 |
l = m+1;
|
|
Packit |
8f70b4 |
else /* otherwise found exact match */
|
|
Packit |
8f70b4 |
return m;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
return u;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
FileInfo *FileSet::FindByName(const char *name) const
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
int n = FindGEIndByName(name);
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
if(n < fnum && !strcmp(files[n]->name,name))
|
|
Packit |
8f70b4 |
return files[n].get_non_const();
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
return 0;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
static bool do_exclude_match(const char *prefix,const FileInfo *fi,const PatternSet *x)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
const char *name=dir_file(prefix,fi->name);
|
|
Packit |
8f70b4 |
if(fi->defined&fi->TYPE && fi->filetype==fi->DIRECTORY)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
char *name1=alloca_strdup2(name,1);
|
|
Packit |
8f70b4 |
strcat(name1,"/");
|
|
Packit |
8f70b4 |
name=name1;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
return x->MatchExclude(name);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void FileSet::Exclude(const char *prefix,const PatternSet *x,FileSet *fsx)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(!x)
|
|
Packit |
8f70b4 |
return;
|
|
Packit |
8f70b4 |
for(int i=0; i
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(do_exclude_match(prefix,files[i],x))
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(fsx)
|
|
Packit |
8f70b4 |
fsx->Add(Borrow(i));
|
|
Packit |
8f70b4 |
else
|
|
Packit |
8f70b4 |
Sub(i);
|
|
Packit |
8f70b4 |
i--;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
#if 0
|
|
Packit |
8f70b4 |
void FileSet::Dump(const char *tag) const
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
printf("%s:",tag);
|
|
Packit |
8f70b4 |
for(int i=0; i
|
|
Packit |
8f70b4 |
printf(" %s",files[i]->name.get());
|
|
Packit |
8f70b4 |
printf("\n");
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
#endif
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
// *** Manipulations with set of local files
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void FileSet::LocalUtime(const char *dir,bool only_dirs,bool flat)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
for(int i=0; i
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
const Ref<FileInfo>& file=files[i];
|
|
Packit |
8f70b4 |
if(file->defined & file->DATE)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(!(file->defined & file->TYPE))
|
|
Packit |
8f70b4 |
continue;
|
|
Packit |
8f70b4 |
if(file->filetype==file->SYMLINK)
|
|
Packit |
8f70b4 |
continue;
|
|
Packit |
8f70b4 |
if(only_dirs && file->filetype!=file->DIRECTORY)
|
|
Packit |
8f70b4 |
continue;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
const char *name=file->name;
|
|
Packit |
8f70b4 |
if(flat)
|
|
Packit |
8f70b4 |
name=basename_ptr(name);
|
|
Packit |
8f70b4 |
const char *local_name=dir_file(dir,name);
|
|
Packit |
8f70b4 |
struct utimbuf ut;
|
|
Packit |
8f70b4 |
struct stat st;
|
|
Packit |
8f70b4 |
ut.actime=ut.modtime=file->date;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
if(stat(local_name,&st)!=-1 && labs(st.st_mtime-file->date)>file->date.ts_prec)
|
|
Packit |
8f70b4 |
utime(local_name,&ut);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
void FileSet::LocalChmod(const char *dir,mode_t mask,bool flat)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
for(int i=0; i
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
const Ref<FileInfo>& file=files[i];
|
|
Packit |
8f70b4 |
if(file->defined & file->MODE)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(file->defined & file->TYPE
|
|
Packit |
8f70b4 |
&& file->filetype==file->SYMLINK)
|
|
Packit |
8f70b4 |
continue;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
const char *name=file->name;
|
|
Packit |
8f70b4 |
if(flat)
|
|
Packit |
8f70b4 |
name=basename_ptr(name);
|
|
Packit |
8f70b4 |
const char *local_name=dir_file(dir,name);
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
struct stat st;
|
|
Packit |
8f70b4 |
mode_t new_mode=file->mode&~mask;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
if(stat(local_name,&st)!=-1 && (st.st_mode&07777)!=new_mode)
|
|
Packit |
8f70b4 |
chmod(local_name,new_mode);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
void FileSet::LocalChown(const char *dir,bool flat)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
for(int i=0; i
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
const Ref<FileInfo>& file=files[i];
|
|
Packit |
8f70b4 |
if(file->defined & (file->USER|file->GROUP))
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
#ifndef HAVE_LCHOWN
|
|
Packit |
8f70b4 |
if(file->defined & file->TYPE
|
|
Packit |
8f70b4 |
&& file->filetype==file->SYMLINK)
|
|
Packit |
8f70b4 |
continue;
|
|
Packit |
8f70b4 |
#define lchown chown
|
|
Packit |
8f70b4 |
#endif
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
const char *name=file->name;
|
|
Packit |
8f70b4 |
if(flat)
|
|
Packit |
8f70b4 |
name=basename_ptr(name);
|
|
Packit |
8f70b4 |
const char *local_name=dir_file(dir,name);
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
struct stat st;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
if(lstat(local_name,&st)==-1)
|
|
Packit |
8f70b4 |
continue;
|
|
Packit |
8f70b4 |
uid_t new_uid=st.st_uid;
|
|
Packit |
8f70b4 |
gid_t new_gid=st.st_gid;
|
|
Packit |
8f70b4 |
if(file->defined&file->USER)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
int u=PasswdCache::LookupS(file->user);
|
|
Packit |
8f70b4 |
if(u!=-1)
|
|
Packit |
8f70b4 |
new_uid=u;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
if(file->defined&file->GROUP)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
int g=GroupCache::LookupS(file->group);
|
|
Packit |
8f70b4 |
if(g!=-1)
|
|
Packit |
8f70b4 |
new_gid=g;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
if(new_uid!=st.st_uid || new_gid!=st.st_gid)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(lchown(local_name,new_uid,new_gid)==-1)
|
|
Packit |
8f70b4 |
/* don't care */;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
FileInfo * FileSet::operator[](int i) const
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(i>=fnum || i<0)
|
|
Packit |
8f70b4 |
return 0;
|
|
Packit |
8f70b4 |
if(sorted)
|
|
Packit |
8f70b4 |
i=sorted[i];
|
|
Packit |
8f70b4 |
return files[i].get_non_const();
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
FileInfo *FileSet::curr()
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
return (*this)[ind];
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
FileInfo *FileSet::next()
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(ind
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
ind++;
|
|
Packit |
8f70b4 |
return curr();
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
return 0;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
void FileSet::SubtractCurr()
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
Sub(ind--);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void FileInfo::Init()
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
filetype=UNKNOWN;
|
|
Packit |
8f70b4 |
mode=(mode_t)-1;
|
|
Packit |
8f70b4 |
date=NO_DATE;
|
|
Packit |
8f70b4 |
size=NO_SIZE;
|
|
Packit |
8f70b4 |
nlinks=0;
|
|
Packit |
8f70b4 |
defined=0;
|
|
Packit |
8f70b4 |
need=0;
|
|
Packit |
8f70b4 |
user=0; group=0;
|
|
Packit |
8f70b4 |
rank=0;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
FileInfo::FileInfo(const FileInfo &fi)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
Init();
|
|
Packit |
8f70b4 |
name.set(fi.name);
|
|
Packit |
8f70b4 |
symlink.set(fi.symlink);
|
|
Packit |
8f70b4 |
user=fi.user;
|
|
Packit |
8f70b4 |
group=fi.group;
|
|
Packit |
8f70b4 |
defined=fi.defined;
|
|
Packit |
8f70b4 |
filetype=fi.filetype;
|
|
Packit |
8f70b4 |
mode=fi.mode;
|
|
Packit |
8f70b4 |
date=fi.date;
|
|
Packit |
8f70b4 |
size=fi.size;
|
|
Packit |
8f70b4 |
nlinks=fi.nlinks;
|
|
Packit |
8f70b4 |
longname.set(fi.longname);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
FileInfo::~FileInfo()
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
#ifndef S_ISLNK
|
|
Packit |
8f70b4 |
# define S_ISLNK(mode) (S_IFLNK==(mode&S_IFMT))
|
|
Packit |
8f70b4 |
#endif
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void FileInfo::LocalFile(const char *name, bool follow_symlinks)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(!this->name)
|
|
Packit |
8f70b4 |
SetName(name);
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
struct stat st;
|
|
Packit |
8f70b4 |
if(lstat(name,&st)==-1)
|
|
Packit |
8f70b4 |
return;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
check_again:
|
|
Packit |
8f70b4 |
FileInfo::type t;
|
|
Packit |
8f70b4 |
if(S_ISDIR(st.st_mode))
|
|
Packit |
8f70b4 |
t=FileInfo::DIRECTORY;
|
|
Packit |
8f70b4 |
else if(S_ISREG(st.st_mode))
|
|
Packit |
8f70b4 |
t=FileInfo::NORMAL;
|
|
Packit |
8f70b4 |
else if(S_ISLNK(st.st_mode))
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(follow_symlinks)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(stat(name,&st)!=-1)
|
|
Packit |
8f70b4 |
goto check_again;
|
|
Packit |
8f70b4 |
// dangling symlink, don't follow it.
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
t=FileInfo::SYMLINK;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
else
|
|
Packit |
8f70b4 |
return; // ignore other type files
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
SetSize(st.st_size);
|
|
Packit |
8f70b4 |
int prec=0;
|
|
Packit |
8f70b4 |
#if defined(HAVE_STATFS) && defined(MSDOS_SUPER_MAGIC)
|
|
Packit |
8f70b4 |
struct statfs stfs;
|
|
Packit |
8f70b4 |
if(statfs(name,&stfs)!=-1 && stfs.f_type==MSDOS_SUPER_MAGIC)
|
|
Packit |
8f70b4 |
prec=1; // MS-DOS fs has 2-second resolution
|
|
Packit |
8f70b4 |
#endif
|
|
Packit |
8f70b4 |
SetDate(st.st_mtime,prec);
|
|
Packit |
8f70b4 |
SetMode(st.st_mode&07777);
|
|
Packit |
8f70b4 |
SetType(t);
|
|
Packit |
8f70b4 |
SetNlink(st.st_nlink);
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
SetUser(PasswdCache::LookupS(st.st_uid));
|
|
Packit |
8f70b4 |
SetGroup(GroupCache::LookupS(st.st_gid));
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
if(t==SYMLINK)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
char *buf=string_alloca(st.st_size+1);
|
|
Packit |
8f70b4 |
int res=readlink(name,buf,st.st_size);
|
|
Packit |
8f70b4 |
if(res!=-1)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
buf[res]=0;
|
|
Packit |
8f70b4 |
SetSymlink(buf);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
/* parse_ls_line: too common procedure to make it protocol specific */
|
|
Packit |
8f70b4 |
/*
|
|
Packit |
8f70b4 |
-rwxr-xr-x 1 lav root 4771 Sep 12 1996 install-sh
|
|
Packit |
8f70b4 |
-rw-r--r-- 1 lav root 1349 Feb 2 14:10 lftp.lsm
|
|
Packit |
8f70b4 |
drwxr-xr-x 4 lav root 1024 Feb 22 15:32 lib
|
|
Packit |
8f70b4 |
lrwxrwxrwx 1 lav root 33 Feb 14 17:45 ltconfig -> /usr/share/libtool/ltconfig
|
|
Packit |
8f70b4 |
NOTE: group may be missing.
|
|
Packit |
8f70b4 |
*/
|
|
Packit |
8f70b4 |
FileInfo *FileInfo::parse_ls_line(const char *line_c,int line_len,const char *tz)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
char *line=string_alloca(line_len+1);
|
|
Packit |
8f70b4 |
memcpy(line,line_c,line_len);
|
|
Packit |
8f70b4 |
line[line_len]=0;
|
|
Packit |
8f70b4 |
char *next=0;
|
|
Packit |
8f70b4 |
FileInfo *fi=0; /* don't instantiate until we at least have something */
|
|
Packit |
8f70b4 |
#define FIRST_TOKEN strtok_r(line," \t",&next)
|
|
Packit |
8f70b4 |
#define NEXT_TOKEN strtok_r(NULL," \t",&next)
|
|
Packit |
8f70b4 |
#define ERR do{delete fi;return(0);}while(0)
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
/* parse perms */
|
|
Packit |
8f70b4 |
char *t = FIRST_TOKEN;
|
|
Packit |
8f70b4 |
if(t==0)
|
|
Packit |
8f70b4 |
ERR;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
fi = new FileInfo;
|
|
Packit |
8f70b4 |
switch(t[0])
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
case('l'): // symlink
|
|
Packit |
8f70b4 |
fi->SetType(fi->SYMLINK);
|
|
Packit |
8f70b4 |
break;
|
|
Packit |
8f70b4 |
case('d'): // directory
|
|
Packit |
8f70b4 |
fi->SetType(fi->DIRECTORY);
|
|
Packit |
8f70b4 |
break;
|
|
Packit |
8f70b4 |
case('-'): // plain file
|
|
Packit |
8f70b4 |
fi->SetType(fi->NORMAL);
|
|
Packit |
8f70b4 |
break;
|
|
Packit |
8f70b4 |
case('b'): // block
|
|
Packit |
8f70b4 |
case('c'): // char
|
|
Packit |
8f70b4 |
case('p'): // pipe
|
|
Packit |
8f70b4 |
case('s'): // sock
|
|
Packit |
8f70b4 |
case('D'): // Door
|
|
Packit |
8f70b4 |
// ignore them
|
|
Packit |
8f70b4 |
default:
|
|
Packit |
8f70b4 |
ERR;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
mode_t mode=parse_perms(t+1);
|
|
Packit |
8f70b4 |
if(mode!=(mode_t)-1)
|
|
Packit |
8f70b4 |
fi->SetMode(mode);
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
// link count
|
|
Packit |
8f70b4 |
t = NEXT_TOKEN;
|
|
Packit |
8f70b4 |
if(!t)
|
|
Packit |
8f70b4 |
ERR;
|
|
Packit |
8f70b4 |
fi->SetNlink(atoi(t));
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
// user
|
|
Packit |
8f70b4 |
t = NEXT_TOKEN;
|
|
Packit |
8f70b4 |
if(!t)
|
|
Packit |
8f70b4 |
ERR;
|
|
Packit |
8f70b4 |
fi->SetUser(t);
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
// group or size
|
|
Packit |
8f70b4 |
char *group_or_size = NEXT_TOKEN;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
// size or month
|
|
Packit |
8f70b4 |
t = NEXT_TOKEN;
|
|
Packit |
8f70b4 |
if(!t)
|
|
Packit |
8f70b4 |
ERR;
|
|
Packit |
8f70b4 |
if(isdigit((unsigned char)*t))
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
// it's size, so the previous was group:
|
|
Packit |
8f70b4 |
fi->SetGroup(group_or_size);
|
|
Packit |
8f70b4 |
long long size;
|
|
Packit |
8f70b4 |
int n;
|
|
Packit |
8f70b4 |
if(sscanf(t,"%lld%n",&size,&n)==1 && t[n]==0)
|
|
Packit |
8f70b4 |
fi->SetSize(size);
|
|
Packit |
8f70b4 |
t = NEXT_TOKEN;
|
|
Packit |
8f70b4 |
if(!t)
|
|
Packit |
8f70b4 |
ERR;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
else
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
// it was month, so the previous was size:
|
|
Packit |
8f70b4 |
long long size;
|
|
Packit |
8f70b4 |
int n;
|
|
Packit |
8f70b4 |
if(sscanf(group_or_size,"%lld%n",&size,&n)==1 && group_or_size[n]==0)
|
|
Packit |
8f70b4 |
fi->SetSize(size);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
struct tm date;
|
|
Packit |
8f70b4 |
memset(&date,0,sizeof(date));
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
date.tm_mon=parse_month(t);
|
|
Packit |
8f70b4 |
if(date.tm_mon==-1)
|
|
Packit |
8f70b4 |
date.tm_mon=0;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
const char *day_of_month = NEXT_TOKEN;
|
|
Packit |
8f70b4 |
if(!day_of_month)
|
|
Packit |
8f70b4 |
ERR;
|
|
Packit |
8f70b4 |
date.tm_mday=atoi(day_of_month);
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
bool year_anomaly=false;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
// time or year
|
|
Packit |
8f70b4 |
t = NEXT_TOKEN;
|
|
Packit |
8f70b4 |
if(!t)
|
|
Packit |
8f70b4 |
ERR;
|
|
Packit |
8f70b4 |
date.tm_isdst=-1;
|
|
Packit |
8f70b4 |
date.tm_hour=date.tm_min=0;
|
|
Packit |
8f70b4 |
date.tm_sec=30;
|
|
Packit |
8f70b4 |
int prec=30;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
if(sscanf(t,"%2d:%2d",&date.tm_hour,&date.tm_min)==2)
|
|
Packit |
8f70b4 |
date.tm_year=guess_year(date.tm_mon,date.tm_mday,date.tm_hour,date.tm_min) - 1900;
|
|
Packit |
8f70b4 |
else
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(day_of_month+strlen(day_of_month)+1 == t)
|
|
Packit |
8f70b4 |
year_anomaly=true;
|
|
Packit |
8f70b4 |
date.tm_year=atoi(t)-1900;
|
|
Packit |
8f70b4 |
/* We don't know the hour. Set it to something other than 0, or
|
|
Packit |
8f70b4 |
* DST -1 will end up changing the date. */
|
|
Packit |
8f70b4 |
date.tm_hour = 12;
|
|
Packit |
8f70b4 |
date.tm_min=0;
|
|
Packit |
8f70b4 |
date.tm_sec=0;
|
|
Packit |
8f70b4 |
prec=12*HOUR;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
fi->SetDate(mktime_from_tz(&date,tz),prec);
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
char *name=strtok_r(NULL,"",&next;;
|
|
Packit |
8f70b4 |
if(!name)
|
|
Packit |
8f70b4 |
ERR;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
// there are ls which output extra space after year.
|
|
Packit |
8f70b4 |
if(year_anomaly && *name==' ')
|
|
Packit |
8f70b4 |
name++;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
if(fi->filetype==fi->SYMLINK)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
char *arrow=name;
|
|
Packit |
8f70b4 |
while((arrow=strstr(arrow," -> "))!=0)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(arrow!=name && arrow[4]!=0)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
*arrow=0;
|
|
Packit |
8f70b4 |
fi->SetSymlink(arrow+4);
|
|
Packit |
8f70b4 |
break;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
arrow++;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
fi->SetName(name);
|
|
Packit |
8f70b4 |
fi->SetLongName(line_c);
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
return fi;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
int FileSet::Have() const
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
int bits=0;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
for(int i=0; i
|
|
Packit |
8f70b4 |
bits |= files[i]->defined;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
return bits;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
static int fnmatch_dir(const char *pattern,const FileInfo *file)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
bool inverted = (pattern[0]=='!');
|
|
Packit |
8f70b4 |
if(inverted || (pattern[0]=='\\' && pattern[1]=='!'))
|
|
Packit |
8f70b4 |
pattern++;
|
|
Packit |
8f70b4 |
const char *name=file->name;
|
|
Packit |
8f70b4 |
if(file->defined&file->TYPE && file->filetype==file->DIRECTORY)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
char *n=alloca_strdup2(name,1);
|
|
Packit |
8f70b4 |
strcat(n,"/");
|
|
Packit |
8f70b4 |
name=n;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
int result=fnmatch(pattern,name,FNM_PATHNAME|FNM_CASEFOLD);
|
|
Packit |
8f70b4 |
if(inverted)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(result==0)
|
|
Packit |
8f70b4 |
result=FNM_NOMATCH;
|
|
Packit |
8f70b4 |
else if(result==FNM_NOMATCH)
|
|
Packit |
8f70b4 |
result=0;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
return result;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void FileSet::SortByPatternList(const char *list_c)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
const int max_rank=1000000;
|
|
Packit |
8f70b4 |
for(int i=0; i
|
|
Packit |
8f70b4 |
files[i]->SetRank(max_rank);
|
|
Packit |
8f70b4 |
char *list=alloca_strdup(list_c);
|
|
Packit |
8f70b4 |
int rank=0;
|
|
Packit |
8f70b4 |
for(char *p=strtok(list," "); p; p=strtok(0," "), rank++)
|
|
Packit |
8f70b4 |
for(int i=0; i
|
|
Packit |
8f70b4 |
if(files[i]->GetRank()==max_rank && !fnmatch_dir(p,files[i]))
|
|
Packit |
8f70b4 |
files[i]->SetRank(rank);
|
|
Packit |
8f70b4 |
Sort(BYRANK);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void FileInfo::MakeLongName()
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
char filetype_s[2]="-";
|
|
Packit |
8f70b4 |
char &filetype_c=filetype_s[0];
|
|
Packit |
8f70b4 |
switch(filetype)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
case NORMAL: break;
|
|
Packit |
8f70b4 |
case UNKNOWN: break;
|
|
Packit |
8f70b4 |
case DIRECTORY: filetype_c='d'; break;
|
|
Packit |
8f70b4 |
case SYMLINK: filetype_c='l'; break;
|
|
Packit |
8f70b4 |
case REDIRECT: filetype_c='L'; break;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
int mode1=(defined&MODE?mode:
|
|
Packit |
8f70b4 |
(filetype_c=='d'?0755:(filetype_c=='l'?0777:0644)));
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
const char *usergroup="";
|
|
Packit |
8f70b4 |
if(defined&(USER|GROUP)) {
|
|
Packit |
8f70b4 |
usergroup=xstring::format("%.16s%s%.16s",defined&USER?user:"?",
|
|
Packit |
8f70b4 |
defined&GROUP?"/":"",defined&GROUP?group:"");
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
int w=20-strlen(usergroup);
|
|
Packit |
8f70b4 |
if(w<1)
|
|
Packit |
8f70b4 |
w=1;
|
|
Packit |
8f70b4 |
char size_str[21];
|
|
Packit |
8f70b4 |
if(defined&SIZE)
|
|
Packit |
8f70b4 |
snprintf(size_str,sizeof(size_str),"%*lld",w,(long long)size);
|
|
Packit |
8f70b4 |
else
|
|
Packit |
8f70b4 |
snprintf(size_str,sizeof(size_str),"%*s",w,"-");
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
const char *date_str="-";
|
|
Packit |
8f70b4 |
if(defined&DATE)
|
|
Packit |
8f70b4 |
date_str=TimeDate(date).IsoDateTime();
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
longname.vset(filetype_s,format_perms(mode1)," ",usergroup," ",size_str,
|
|
Packit |
8f70b4 |
" ",date_str," ",name.get(),NULL);
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
if(defined&SYMLINK_DEF)
|
|
Packit |
8f70b4 |
longname.vappend(" -> ",symlink.get(),NULL);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
size_t FileSet::EstimateMemory() const
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
size_t size=sizeof(FileSet)
|
|
Packit |
8f70b4 |
+files.count()*files.get_element_size()
|
|
Packit |
8f70b4 |
+sorted.count()*sorted.get_element_size();
|
|
Packit |
8f70b4 |
for(int i=0; i
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
size+=sizeof(FileInfo);
|
|
Packit |
8f70b4 |
size+=xstrlen(files[i]->name);
|
|
Packit |
8f70b4 |
size+=xstrlen(files[i]->symlink);
|
|
Packit |
8f70b4 |
size+=xstrlen(files[i]->longname);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
return size;
|
|
Packit |
8f70b4 |
}
|