"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.

    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