"Fossies" - the Fresh Open Source Software Archive

Member "qdiff-0.9.1/tfiletools.cc" (21 Oct 2008, 7344 Bytes) of package /linux/privat/old/qdiff-0.9.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "tfiletools.cc" see the Fossies "Dox" file reference documentation.

    1 /*GPL*START*
    2  *
    3  * tfilesync.h - file and directory handling tolls header file
    4  * 
    5  * Copyright (C) 2000 by Johannes Overmann <Johannes.Overmann@gmx.de>
    6  * 
    7  * This program is free software; you can redistribute it and/or modify
    8  * it under the terms of the GNU General Public License as published by
    9  * the Free Software Foundation; either version 2 of the License, or
   10  * (at your option) any later version.
   11  * 
   12  * This program is distributed in the hope that it will be useful,
   13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   15  * GNU General Public License for more details.
   16  * 
   17  * You should have received a copy of the GNU General Public License
   18  * along with this program; if not, write to the Free Software
   19  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
   20  * *GPL*END*/  
   21 
   22 #include <sys/types.h>
   23 #include <dirent.h>
   24 #include "tfiletools.h"
   25 
   26 #define COUNT_VERBOSE_STEP 1000
   27 
   28 // TFile implementation
   29 
   30 TFile::FileType TFile::filetype() const {
   31    if(isregular()) return FT_REGULAR;
   32    else if(isdir()) return FT_DIR;
   33    else if(issymlink()) return FT_SYMLINK;
   34    else if(ischardev()) return FT_CHARDEV;
   35    else if(isblockdev()) return FT_BLOCKDEV;
   36    else if(isfifo()) return FT_FIFO;
   37    else if(issocket()) return FT_SOCKET;
   38    else return FT_UNKNOWN;
   39 }
   40 
   41 tstring TFile::filetypeLongStr() const {
   42    switch(filetype()) {
   43     case FT_SOCKET:   return "socket";      
   44     case FT_SYMLINK:  return "symbolic link";   
   45     case FT_REGULAR:  return "regular file";    
   46     case FT_BLOCKDEV: return "block device";    
   47     case FT_DIR:      return "directory";      
   48     case FT_CHARDEV:  return "character device";    
   49     case FT_FIFO:     return "fifo";
   50     default: { tstring t; t.sprintf("%#o", int(filetypebits())); return t; }
   51    }
   52 }
   53 
   54 char TFile::filetypeChar() const {
   55    switch(filetype()) {
   56     case FT_SOCKET:   return 's';      
   57     case FT_SYMLINK:  return 'l';   
   58     case FT_REGULAR:  return '-';   
   59     case FT_BLOCKDEV: return 'b';   
   60     case FT_DIR:      return 'd';      
   61     case FT_CHARDEV:  return 'c';   
   62     case FT_FIFO:     return 'p';
   63     default:          return '?';
   64    }
   65 }
   66 
   67 tstring TFile::filetypeStr7() const {
   68    switch(filetype()) {
   69     case FT_SOCKET:   return "socket ";
   70     case FT_SYMLINK:  return "symlink"; 
   71     case FT_REGULAR:  return "regular"; 
   72     case FT_BLOCKDEV: return "blockdv"; 
   73     case FT_DIR:      return "dir    ";      
   74     case FT_CHARDEV:  return "chardev"; 
   75     case FT_FIFO:     return "fifo   ";
   76     default:          return "unknown";
   77    }
   78 }
   79 
   80 void TFile::getstat() const {
   81    if(stated) return;
   82    if(name_.empty()) throw TNotInitializedException("TFile");
   83    TFile *t = const_cast<TFile*>(this);
   84 #ifndef __STRICT_ANSI__
   85    if(follow_links) {     
   86 #endif
   87      if(stat(name_.c_str(), &(t->statbuf))) throw TFileOperationErrnoException(name_.c_str(), "stat");
   88 #ifndef __STRICT_ANSI__
   89    } else {
   90      if(lstat(name_.c_str(), &(t->statbuf))) throw TFileOperationErrnoException(name_.c_str(), "lstat");
   91    }
   92 #endif
   93    t->stated = true;
   94    num_stated++;
   95 }
   96 
   97 
   98 
   99 // TDir implementation
  100 
  101 size_t TDir::numRecursive(bool low_mem, const char *verbose, bool count_files, bool count_dirs) const {
  102    size_t r = 0;
  103    if(count_files) r = numFiles();
  104    if(count_dirs) r += numDirs();
  105    if(verbose) { 
  106       verbose_num += r; 
  107       if(verbose_num > (old_verbose_num + COUNT_VERBOSE_STEP)) {
  108      printf("counting %s in %s: %11u\r", count_files ? (count_dirs ? "files and dirs" : "files") : (count_dirs ? "dirs" : "nothing"), verbose, unsigned(verbose_num));
  109      fflush(stdout); 
  110      old_verbose_num = verbose_num;
  111       }
  112    } 
  113    for(size_t i = 0; i < numDirs(); i++) 
  114      r += dir(i).numRecursive(low_mem, verbose, count_files, count_dirs);
  115    if(low_mem) freeMem();
  116    return r;
  117 }
  118 
  119 void TDir::scan() const {
  120    if(scanned) return;
  121    assert(subTreeContext);
  122    if(name().empty()) throw TNotInitializedException("TDir");
  123    TDir *t = const_cast<TDir*>(this);
  124    // maximum depth already reached? if so treat directory as empty
  125    if(depth >= subTreeContext->max_depth)
  126    {
  127        t->scanned = true;
  128        return;
  129    }
  130    // prevent crossing filesystems?
  131    if(!subTreeContext->cross_filesystems) {
  132       if(subTreeContext->root->device() != device()) {
  133      // consider directory empty because it is on a different filesystem than the subtree root
  134      t->scanned = true;
  135      return;
  136       }
  137    }
  138    // scan directory
  139    struct dirent *dire = 0;
  140    DIR *tdir = opendir(name().c_str());
  141    if(tdir == 0) throw TFileOperationErrnoException(name().c_str(), "opendir");
  142    size_t dirs_left = hardlinks() - 2;
  143    while((dire = readdir(tdir)) != 0) {
  144       if((dire->d_name[0] != '.') || (strcmp(".", dire->d_name) && strcmp("..", dire->d_name))) {
  145      TFile f((name() + "/") + dire->d_name);
  146      if((dirs_left || no_leaf_optimize) && f.isdir()) {
  147         t->name2dirid[dire->d_name] = dirs.size();
  148         t->dirs[dirs.size()] = TDir(f, *subTreeContext, depth + 1);
  149         dirs_left--;
  150      } else {
  151         t->name2fileid[dire->d_name] = files.size();
  152         t->files[files.size()] = f;
  153      }
  154       }
  155    }   
  156    closedir(tdir);
  157    t->scanned = true;
  158    // update access time
  159    invalidateStat();
  160 }
  161 
  162 size_t TDir::verbose_num = 0;
  163 size_t TDir::old_verbose_num = 0;
  164 bool TFile::follow_links = false;
  165 size_t TFile::num_stated = 0;
  166 #ifdef WIN32
  167 bool TDir::no_leaf_optimize = true;
  168 #else
  169 bool TDir::no_leaf_optimize = false;
  170 #endif
  171 
  172 
  173 // global functions
  174 tvector<tstring> findFilesRecursive(const TDir& dir) {
  175    // return value
  176    tvector<tstring> r;
  177    
  178    // add files
  179    for(size_t i = 0; i < dir.numFiles(); i++) 
  180      r.push_back(dir.file(i).name());
  181 
  182    // add dirs recursively
  183    for(size_t j = 0; j < dir.numDirs(); j++)
  184      r += findFilesRecursive(dir.dir(j));
  185    
  186    // return list
  187    return r;
  188 }
  189 
  190 
  191 tvector<tstring> filterExtensions(const tvector<tstring>& list, const tvector<tstring>& extensions, bool remove) {
  192    // create lookup map
  193    tmap<tstring,int> ext;
  194    for(size_t i = 0; i < extensions.size(); i++)
  195      ext[extensions[i]] = 1;
  196 
  197    // filter list
  198    tvector<tstring> r;
  199    for(size_t j = 0; j < list.size(); j++) {
  200       tstring e = list[j];
  201       e.extractFilenameExtension();
  202       if(ext.contains(e) != remove)
  203     r.push_back(list[j]);
  204    }
  205         
  206    // return list
  207    return r;
  208 }
  209 
  210 
  211 void makeDirectoriesIncludingParentsIfNecessary(const tstring& dirname, bool verbose, bool dummy) {
  212    // check whether dirname already exists
  213    try {
  214       TFile f(dirname);
  215       // if it exists and is a directory we are done
  216       if(f.isdir()) return;
  217    }
  218    // else we need to create the parent directory and then dirname
  219    catch(const TFileOperationErrnoException& e) {
  220       if(e.err == ENOENT) {
  221      // create parent dir
  222      tstring parent = dirname;
  223      parent.removeDirSlash();
  224      parent.extractPath();
  225      if(!parent.empty())
  226        makeDirectoriesIncludingParentsIfNecessary(parent, verbose, dummy);  // recurse
  227      
  228      // create dirname
  229      if(verbose)
  230        printf("creating directory '%s'\n", dirname.c_str());
  231      if(!dummy)
  232        if(mkdir(dirname.c_str(), S_IRWXU) == -1)
  233          throw TFileOperationErrnoException(dirname.c_str(), "mkdir");
  234      return;
  235       } else throw;
  236    }
  237    
  238    // if we get here dirname exists and is not a directory: error
  239    throw TFileOperationErrnoException(dirname.c_str(), "makeDirectoriesIncludingParentsIfNecessary", ENOTDIR);
  240 }
  241