Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members

StatDir.C

Go to the documentation of this file.
00001 // Copyright (C) 2001, Compaq Computer Corporation
00002 // 
00003 // This file is part of Vesta.
00004 // 
00005 // Vesta is free software; you can redistribute it and/or
00006 // modify it under the terms of the GNU Lesser General Public
00007 // License as published by the Free Software Foundation; either
00008 // version 2.1 of the License, or (at your option) any later version.
00009 // 
00010 // Vesta is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013 // Lesser General Public License for more details.
00014 // 
00015 // You should have received a copy of the GNU Lesser General Public
00016 // License along with Vesta; if not, write to the Free Software
00017 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018 
00019 // Last modified on Fri Apr 29 00:14:59 EDT 2005 by ken@xorian.net         
00020 //      modified on Mon Jul 15 17:01:12 EDT 2002 by kcschalk@shr.intel.com 
00021 //      modified on Sat Feb 12 13:10:03 PST 2000 by mann  
00022 //      modified on Tue May  4 11:16:45 PDT 1999 by heydon
00023 
00024 #include <sys/types.h>
00025 #include <sys/stat.h>
00026 #if defined(__digital__)
00027 #include <sys/mode.h>
00028 #endif
00029 #include <dirent.h>
00030 #include <Basics.H>
00031 #include <FS.H>
00032 #include <AtomicFile.H>
00033 #include "StatError.H"
00034 #include "StatDir.H"
00035 
00036 using std::cout;
00037 using std::endl;
00038 
00039 int DirObj::Search(int verbose, /*INOUT*/ Stat::Collection &stats)
00040   throw (StatError::UnevenLevels,
00041          StatError::BadMPKFile, StatError::EndOfFile,
00042          FS::Failure, FS::DoesNotExist)
00043 {
00044     if (verbose >= 1) {
00045         cout << "  " << this->path << endl;
00046     }
00047 
00048     // iterate over children
00049     int chLevel = -1;
00050     int cnt;
00051     {
00052       DirEntry *entry = (DirEntry *) NULL;
00053       DirIter it(this);
00054       for (cnt = 0; it.Next(/*OUT*/ entry); cnt++) {
00055         int l = entry->Search(verbose, /*INOUT*/ stats);
00056         if (chLevel < 0) chLevel = l;
00057         else if (chLevel != l) throw (StatError::UnevenLevels(this->path));
00058       }
00059       entry = (DirEntry *) NULL; // drop on floor for GC
00060     }
00061 
00062     // update fan-out for this level
00063     int thisLevel = chLevel + 1;
00064     StatCount *sc;
00065     if (stats.fanout.size() <= thisLevel) {
00066         assert(stats.fanout.size() == thisLevel);
00067         sc = NEW(StatCount);
00068         stats.fanout.addhi(sc);
00069     } else {
00070         sc = stats.fanout.get(thisLevel);
00071     }
00072     sc->AddVal(cnt, NEW_CONSTR(Stat::Location, (this->path)));
00073     return thisLevel;
00074 }
00075 
00076 DirIter::DirIter(const DirObj *dirObj) throw (FS::Failure, FS::DoesNotExist)
00077   : path(dirObj->path), done(false)
00078 {
00079     if ((this->dir = opendir(this->path.cchars())) == NULL) {
00080         if (errno == ENOENT) throw FS::DoesNotExist();
00081         else throw FS::Failure(Text("opendir"), dirObj->path);
00082     }
00083     this->path += '/'; // add terminating slash
00084 }
00085 
00086 static bool IsDotDir(char *arc) throw ()
00087 {
00088     return (!strcmp(arc, ".") || !strcmp(arc, ".."));
00089 }
00090 
00091 static bool IsTempFile(const Text &path) throw ()
00092 /* Return true iff "path" ends in an arc of the form "<hex-digit>+;*". */
00093 {
00094     int slashIx = path.FindCharR('/');
00095     int semiIx = path.FindChar(AtomicFile::reserved_char, slashIx);
00096     if (semiIx <= 0) return false;
00097     for (int i = slashIx + 1; i < semiIx; i++) {
00098         if (!isxdigit(path[i])) return false;
00099     }
00100     return true;
00101 }
00102 
00103 bool DirIter::Next(/*OUT*/ DirEntry* &entry)
00104   throw (StatError::EndOfFile, FS::Failure, FS::DoesNotExist)
00105 {
00106     if (done) return false;
00107     while (true) {
00108         // read directory entry; if no more, close and return
00109         struct dirent *sysDirEnt;
00110         if ((sysDirEnt = readdir(this->dir)) == (struct dirent *)NULL) {
00111             done = true;
00112             if (closedir(this->dir) < 0) {
00113                 throw FS::Failure(Text("closedir"), this->path);
00114             }
00115             return false;
00116         }
00117 
00118         // skip "." and ".."
00119         if (IsDotDir(sysDirEnt->d_name)) continue;
00120 
00121         // skip if this is a temporary file created by VestaAtomicLog
00122         Text fullname(this->path + sysDirEnt->d_name);
00123         struct stat statBuff;
00124         DirEntry::FSStat(fullname, /*OUT*/ &statBuff);
00125         if (S_ISREG(statBuff.st_mode) && IsTempFile(fullname)) {
00126             continue;
00127         }
00128 
00129         // otherwise, open the entry and return
00130         entry = DirEntry::Open(fullname, &statBuff);
00131         break; // exit loop
00132     }
00133     return true;
00134 }

Generated on Mon May 8 00:48:36 2006 for Vesta by  doxygen 1.4.2