jigdo API
Last update by Admin on 2010-05-23
recursedir.hh
Go to the documentation of this file.00001 /* $Id: recursedir.hh,v 1.14 2003/03/03 20:47:17 richard Exp $ -*- C++ -*- 00002 __ _ 00003 |_) /| Copyright (C) 2001-2002 | richard@ 00004 | \/¯| Richard Atterer | atterer.net 00005 ¯ '` ¯ 00006 This program is free software; you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License, version 2. See 00008 the file COPYING for details. 00009 00010 */ 00016 #ifndef RECURSEDIR_HH 00017 #define RECURSEDIR_HH 00018 00019 #include <config.h> 00020 00021 #include <dirent.hh> 00022 00023 #include <fstream> 00024 #include <iostream> 00025 #include <queue> 00026 #include <set> 00027 #include <stack> 00028 00029 #include <sys/types.h> 00030 #include <sys/stat.h> 00031 #include <unistd-jigdo.h> 00032 00033 #include <debug.hh> 00034 #include <recursedir.fh> 00035 //______________________________________________________________________ 00036 00038 struct RecurseError : Error { 00039 explicit RecurseError(const string& m) : Error(m) { } 00040 explicit RecurseError(const char* m) : Error(m) { } 00041 }; 00042 00050 class RecurseDir { 00051 public: 00052 RecurseDir() : curDir(), recurseStack(), objects(), objectsFrom(), 00053 fileList(), listStream(0) { } 00054 inline ~RecurseDir(); 00055 00057 void addFile(const char* name) { objects.push(string(name)); } 00059 void addFile(const string& name) { objects.push(name); } 00061 void addFilesFrom(const char* name) { objectsFrom.push(string(name)); } 00062 void addFilesFrom(const string& name) { objectsFrom.push(name); } 00063 00065 bool empty() const { return objects.empty() && objectsFrom.empty(); } 00066 00077 bool getName(string& result, struct stat* fileInfo = 0, 00078 bool checkFiles = true) 00079 throw(RecurseError, bad_alloc); 00080 00084 private: 00085 // Insert fileInfo in beenThere, return true if it was already there 00086 inline bool alreadyVisited(const struct stat* fileInfo); 00087 // For recording device/inode of objects already visited 00088 struct DevIno { 00089 DevIno(const struct stat* s) : dev(s->st_dev), ino(s->st_ino) { } 00090 bool operator<(const DevIno& d) const { 00091 return (ino < d.ino) || (ino == d.ino && dev < d.dev); } 00092 dev_t dev; ino_t ino; 00093 }; 00094 // One stack entry (recursion level) when recursing into directories 00095 struct Level { 00096 Level(DIR* d, size_t l) : dir(d), dirNameLen(l) { } 00097 void close() { if (dir == 0) return; closedir(dir); dir = 0; } 00098 DIR* dir; // Handle for readdir() 00099 size_t dirNameLen; // Length to shorten curDir to to get this dir's name 00100 }; 00101 string curDir; 00102 stack<Level> recurseStack; 00103 00104 inline bool getNextObjectName(string& result) 00105 throw(RecurseError); 00106 queue<string> objects; // Queue of filenames to output/dirs to recurse into 00107 queue<string> objectsFrom; // Files containing filenames 00108 ifstream fileList; // Was head of objectsFrom once, now has been opened 00109 istream* listStream; // null if not open, else &fileList, or &cin 00110 # if HAVE_LSTAT 00111 set<DevIno> beenThere; // Already visited inodes, for loop prevention 00112 # endif 00113 }; 00114 //______________________________________________________________________ 00115 00116 #if HAVE_LSTAT 00117 inline bool isSymlink(struct stat* buf) { return S_ISLNK(buf->st_mode); } 00118 bool RecurseDir::alreadyVisited(const struct stat* fileInfo) { 00119 pair<set<DevIno>::iterator, bool> 00120 ins = beenThere.insert(DevIno(fileInfo)); 00121 return !ins.second; 00122 } 00123 #else 00124 inline int lstat(const char* filename, struct stat* buf) { 00125 return stat(filename, buf); 00126 } 00127 inline bool isSymlink(struct stat*) { return false; } 00128 bool RecurseDir::alreadyVisited(const struct stat*) { return false; } 00129 #endif 00130 //____________________ 00131 00132 RecurseDir::~RecurseDir() { 00133 if (listStream != 0 && listStream != &cin) fileList.close(); 00134 while (!recurseStack.empty()) { 00135 recurseStack.top().close(); 00136 recurseStack.pop(); 00137 } 00138 } 00139 00140 #endif
Generated on Tue Sep 23 14:27:41 2008 for jigdo by
