Blame src/FindJobDu.cc

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
}