Logo Search packages:      
Sourcecode: gaffitter version File versions  Download package

DiskUsage.cc

// ---------------------------------------------------------------------
// $Id: DiskUsage.cc,v 1.17 2006/08/11 14:44:00 daaugusto Exp $
//
//   DiskUsage.cc (created on Tue Aug 23 01:08:35 BRT 2005)
// 
//   Genetic Algorithm File Fitter (gaffitter)
//
//   Copyright (C) 2005-2006 Douglas A. Augusto
// 
// This file is part of gaffitter.
// 
// gaffitter 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 2 of the License, or (at
// your option) any later version.
// 
// gaffitter 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 gaffitter; if not, write to the Free Software Foundation,
// Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
// ---------------------------------------------------------------------

/** 
 * This macro determines which file system interface shall be used, one
 * replacing the other. `_FILE_OFFSET_BITS' allows the 64 bit interface
 * to replace the old interface.
 *
 * If `_FILE_OFFSET_BITS' is undefined, or if it is defined to the value
 * `32', nothing changes. The 32 bit interface is used and types like
 * `off_t' have a size of 32 bits on 32 bit systems.
 *
 * On 32bit systems 'stat -> stat64' and 'lstat -> lstat64'
 * transparently.
*/
#define _FILE_OFFSET_BITS 64

#include "DiskUsage.hh"
#include "util/Exception.hh"

#include <sys/stat.h>
#include <dirent.h>
#include <unistd.h>

#include <string>
#include <iostream>

using namespace std;

//----------------------------------------------------------------------
unsigned DiskUsage::m_block_size;

//----------------------------------------------------------------------
Params::UBigInt 
00059 DiskUsage::GetSize(const char* filename) 
{
   struct stat st;
   if (lstat(filename, &st) != 0)
   {
      cerr << "> Could not read: " << filename << endl;
      return 0;
   }
      
   if (S_ISDIR(st.st_mode))
   {
      char saved_path[m_max_path_name], tmp_path[m_max_path_name];

      // saves current path before chdir to 'filename' directory
      if (getcwd(saved_path, m_max_path_name-1) == NULL)
      {
         cerr << "> Path name too long; maximum " << m_max_path_name-1 
              << " chars." << endl;
         return 0;
      }

      if (chdir(filename) != 0) 
      {
         cerr << "> Could not chdir to: " << filename << endl;
         return 0;
      }

      if (getcwd(tmp_path, m_max_path_name-1) == NULL)
      {
         cerr << "> Path name too long; maximum " << m_max_path_name-1 
              << " chars." << endl;
         return 0;
      }

      if (lstat(tmp_path, &st) != 0)
      {
         cerr << "> Could not read dir: " << tmp_path << endl;
         return 0;
      }

      Params::UBigInt total = 
                AllocationSize(static_cast<Params::UBigInt>(st.st_size)) 
                                         + DepthFirstTraversal(tmp_path);

      // return to original path (important!)
      chdir(saved_path);

      return total;
   }
   else // ISREG, ISLNK, ISFIFO, ISBLK, ...
      return AllocationSize(static_cast<Params::UBigInt>(st.st_size));
}

//----------------------------------------------------------------------
Params::UBigInt
00114 DiskUsage::AllocationSize(Params::UBigInt size) 
{
   Params::UBigInt remainder = size % m_block_size;

   // Test if the filesize is smaller than allocation block. 
   // 0-size files also occupy space: = allocation block 
   if (remainder || size==0) 
      return size += m_block_size - remainder;
   
   // the filesize match perfectly the allocation block
   return size;
}

//----------------------------------------------------------------------
Params::UBigInt
00129 DiskUsage::DepthFirstTraversal(const char* currdir) 
{
   if (chdir(currdir) != 0)
   {
      cerr << "> Could not chdir to: " << currdir << endl;
      return 0;
   }

   Params::UBigInt sum = 0;

   // open the directory
   DIR *dir = opendir(".");
   if (dir == NULL)
   {
      cerr << "> Could not open dir: " << currdir << endl;
      chdir("..");

      return 0;
   }

   struct dirent *de;
   while (de = readdir(dir))
   {
      struct stat st;
      if (lstat(de->d_name, &st) != 0)
      {
         cerr << "> Could not read: " << de->d_name << endl;
         continue;
      }

      if (S_ISDIR(st.st_mode)) // is a directory (= recursive)
      {
         string tmp_str = de->d_name;

         if ((tmp_str != ".") && (tmp_str != ".."))
         {
            string filename = string(currdir) + "/" + tmp_str;

            sum += AllocationSize(static_cast<Params::UBigInt>(st.st_size)) 
                                    + DepthFirstTraversal(filename.c_str());
         }
      }
      else // ISREG, ISLNK, ISFIFO, ISBLK, ...
         sum += AllocationSize(static_cast<Params::UBigInt>(st.st_size));
   }
   closedir(dir);
   chdir("..");

   return sum;
}

//----------------------------------------------------------------------

Generated by  Doxygen 1.6.0   Back to index