|
Packit |
8f70b4 |
/*
|
|
Packit |
8f70b4 |
* lftp - file transfer program
|
|
Packit |
8f70b4 |
*
|
|
Packit |
8f70b4 |
* Copyright (c) 1996-2012 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 <assert.h>
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
#include "FindJobDu.h"
|
|
Packit |
8f70b4 |
#include "CmdExec.h"
|
|
Packit |
8f70b4 |
#include "misc.h"
|
|
Packit |
8f70b4 |
#include "buffer_std.h"
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
CDECL_BEGIN
|
|
Packit |
8f70b4 |
#include "human.h"
|
|
Packit |
8f70b4 |
CDECL_END
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
#define stack_ptr (size_stack.count()-1)
|
|
Packit |
8f70b4 |
#define stack_top (*size_stack.last())
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
FinderJob_Du::FinderJob_Du(FileAccess *s,ArgV *a,FDStream *o)
|
|
Packit |
8f70b4 |
: FinderJob(s), args(a)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
op=args->a0();
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
if(o)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
buf=new IOBufferFDStream(o,IOBuffer::PUT);
|
|
Packit |
8f70b4 |
show_sl=!o->usesfd(1);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
else
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
buf=new IOBuffer_STDOUT(this);
|
|
Packit |
8f70b4 |
show_sl=true;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
Need(FileInfo::SIZE);
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
/* defaults */
|
|
Packit |
8f70b4 |
max_print_depth = -1;
|
|
Packit |
8f70b4 |
print_totals = false;
|
|
Packit |
8f70b4 |
output_block_size = 1024;
|
|
Packit |
8f70b4 |
human_opts = 0;
|
|
Packit |
8f70b4 |
all_files = false;
|
|
Packit |
8f70b4 |
separate_dirs = false;
|
|
Packit |
8f70b4 |
file_count = false;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
tot_size=0;
|
|
Packit |
8f70b4 |
success=false;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
Init(a->getcurr());
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
FinderJob_Du::~FinderJob_Du()
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
/* process a new directory */
|
|
Packit |
8f70b4 |
void FinderJob_Du::Init(const char *d)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
NextDir(d);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
int FinderJob_Du::Done()
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
return FinderJob::Done() && args->getcurr()==0 && buf->Done();
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void FinderJob_Du::Finish()
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
/* if there's anything left, we had an error; clear the stack */
|
|
Packit |
8f70b4 |
if(stack_ptr != -1) {
|
|
Packit |
8f70b4 |
while(stack_ptr >= 0)
|
|
Packit |
8f70b4 |
Pop();
|
|
Packit |
8f70b4 |
} else success = true; /* at least one succeeded */
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
/* next? */
|
|
Packit |
8f70b4 |
const char *d=args->getnext();
|
|
Packit |
8f70b4 |
if(d) {
|
|
Packit |
8f70b4 |
/* we have another argument */
|
|
Packit |
8f70b4 |
Init(d);
|
|
Packit |
8f70b4 |
return;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
/* we're done */
|
|
Packit |
8f70b4 |
if (print_totals) /* don't print totals on error */
|
|
Packit |
8f70b4 |
print_size(tot_size, _("total"));
|
|
Packit |
8f70b4 |
buf->PutEOF();
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
const char *FinderJob_Du::MakeFileName(const char *n)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
return size_stack.count()>0 ? dir_file(size_stack.last()->dir,n) : n;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
off_t FinderJob_Du::BlockCeil(off_t size) const
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
size+=output_block_size-1;
|
|
Packit |
8f70b4 |
size-=size%output_block_size;
|
|
Packit |
8f70b4 |
return size;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
FinderJob::prf_res FinderJob_Du::ProcessFile(const char *d,const FileInfo *fi)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
if(buf->Broken())
|
|
Packit |
8f70b4 |
return PRF_FATAL;
|
|
Packit |
8f70b4 |
if(buf->Error())
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
eprintf("%s: %s\n",op,buf->ErrorText());
|
|
Packit |
8f70b4 |
return PRF_FATAL;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
if(fg_data==0)
|
|
Packit |
8f70b4 |
fg_data=buf->GetFgData(fg);
|
|
Packit |
8f70b4 |
if(buf->Size()>0x10000)
|
|
Packit |
8f70b4 |
return PRF_LATER;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
if(fi->filetype==fi->DIRECTORY)
|
|
Packit |
8f70b4 |
return PRF_OK; /* don't care */
|
|
Packit |
8f70b4 |
if(!file_count && !(fi->defined&fi->SIZE))
|
|
Packit |
8f70b4 |
return PRF_OK; /* can't count this one */
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
/* add this file to the current dir */
|
|
Packit |
8f70b4 |
long long add = BlockCeil(fi->size);
|
|
Packit |
8f70b4 |
if (file_count)
|
|
Packit |
8f70b4 |
add = 1;
|
|
Packit |
8f70b4 |
if(size_stack.count()>0)
|
|
Packit |
8f70b4 |
size_stack.last()->size += add;
|
|
Packit |
8f70b4 |
tot_size += add;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
if(all_files || stack_ptr == -1) {
|
|
Packit |
8f70b4 |
/* this is <, where Pop() is <=, since the file counts in depth */
|
|
Packit |
8f70b4 |
if(max_print_depth == -1 || stack_ptr < max_print_depth)
|
|
Packit |
8f70b4 |
print_size(BlockCeil(fi->size), MakeFileName(fi->name));
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
return PRF_OK;
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void FinderJob_Du::ProcessList(FileSet *f)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
f->Sort(FileSet::BYNAME, true);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
/* push a directory onto the stack */
|
|
Packit |
8f70b4 |
void FinderJob_Du::Push (const char *d)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
size_stack.append(new stack_entry(MakeFileName(d)));
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
/* pop a directory off the stack, combining as necessary */
|
|
Packit |
8f70b4 |
void FinderJob_Du::Pop()
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
assert(stack_ptr!=-1); /* no underflows */
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
/* merge directory's size with its parent */
|
|
Packit |
8f70b4 |
if(!separate_dirs && stack_ptr > 0)
|
|
Packit |
8f70b4 |
size_stack[stack_ptr-1]->size += stack_top.size;
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
size_stack.chop();
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void FinderJob_Du::print_size (long long n_blocks, const char *string)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
char buffer[LONGEST_HUMAN_READABLE + 1];
|
|
Packit |
8f70b4 |
/* We get blocks in bytes, since we don't know the remote system's
|
|
Packit |
8f70b4 |
* block size. */
|
|
Packit |
8f70b4 |
buf->Format("%s\t%s\n",
|
|
Packit |
8f70b4 |
human_readable (n_blocks, buffer, human_opts, 1, human_opts?1:output_block_size),
|
|
Packit |
8f70b4 |
string);
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
/* finished a directory; print it if necessary and pop it off the stack */
|
|
Packit |
8f70b4 |
void FinderJob_Du::Exit()
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
/* print the dir */
|
|
Packit |
8f70b4 |
if(max_print_depth == -1 || stack_ptr <= max_print_depth)
|
|
Packit |
8f70b4 |
print_size(stack_top.size, stack_top.dir);
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
Pop();
|
|
Packit |
8f70b4 |
}
|
|
Packit |
8f70b4 |
|
|
Packit |
8f70b4 |
void FinderJob_Du::Enter(const char *d)
|
|
Packit |
8f70b4 |
{
|
|
Packit |
8f70b4 |
Push(d);
|
|
Packit |
8f70b4 |
}
|