00001 #ifndef __XRDOUCNSWALK_HH 00002 #define __XRDOUCNSWALK_HH 00003 /******************************************************************************/ 00004 /* */ 00005 /* X r d O u c N S W a l k . h h */ 00006 /* */ 00007 /* (c) 2009 by the Board of Trustees of the Leland Stanford, Jr., University */ 00008 /* All Rights Reserved */ 00009 /* Produced by Andrew Hanushevsky for Stanford University under contract */ 00010 /* DE-AC02-76-SFO0515 with the Department of Energy */ 00011 /* */ 00012 /* This file is part of the XRootD software suite. */ 00013 /* */ 00014 /* XRootD is free software: you can redistribute it and/or modify it under */ 00015 /* the terms of the GNU Lesser General Public License as published by the */ 00016 /* Free Software Foundation, either version 3 of the License, or (at your */ 00017 /* option) any later version. */ 00018 /* */ 00019 /* XRootD is distributed in the hope that it will be useful, but WITHOUT */ 00020 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */ 00021 /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */ 00022 /* License for more details. */ 00023 /* */ 00024 /* You should have received a copy of the GNU Lesser General Public License */ 00025 /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */ 00026 /* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */ 00027 /* */ 00028 /* The copyright holder's institutional names and contributor's names may not */ 00029 /* be used to endorse or promote products derived from this software without */ 00030 /* specific prior written permission of the institution or contributor. */ 00031 /******************************************************************************/ 00032 00033 #include <stdlib.h> 00034 #include <fcntl.h> 00035 #include <sys/types.h> 00036 #include <sys/stat.h> 00037 00038 00039 class XrdOucTList; 00040 class XrdSysError; 00041 00042 class XrdOucNSWalk 00043 { 00044 public: 00045 00046 struct NSEnt 00047 { 00048 struct NSEnt *Next; // -> Next entry in the indexed directory 00049 char *Path; // Path name to file if opts & noPath (Path == File) 00050 char *File; // File name component 00051 int Plen; // strlen(Path) 00052 struct stat Stat; // stat() of Path if opts & retStat 00053 char *Link; // -> Link data if opts & retLink 00054 int Lksz; // Length of link data 00055 00056 enum Etype {isBad = 0, isDir, isFile, isLink, isMisc}; 00057 00058 Etype Type; // One of the above. If isLink then Link is invalid! 00059 00060 NSEnt() : Next(0), Path(0), Plen(0), Link(0), Lksz(0) {} 00061 ~NSEnt() {if (Path) free(Path); 00062 if (Link) free(Link); 00063 } 00064 }; 00065 00066 // Calling Index() provides the requested directory entries with a return code: 00067 // NSEnts != 0 && rc == 0: Normal ending. 00068 // NSEnts != 0 && rc != 0: Potentially short list as indexing aborted w/ err. 00069 // NSEnts == 0 && rc == 0: End of indexing no more entries can be returned. 00070 // NSEnts == 0 && rc != 0: Abort occured before any entries could be returned. 00071 // 00072 // When opts & skpErrs is true, then rc may be zero even when an error occured. 00073 // 00074 // If opts & Recurse, indexing will traverse the directory tree, one directory 00075 // at a time. For a complete traversal you sould keep calling Index() until 00076 // it returns 0 with rc == 0. When dPath is supplied, a pointer to the base 00077 // directory is returned as well (see noPath). 00078 // 00079 NSEnt *Index(int &rc, const char **dPath=0); 00080 00081 // The CallBack class is used to intercept empty directories. When set by a 00082 // call to setCallBack(); should an empty directory (i.e., one with no entries 00083 // or only with a lock file) in encountered a call is made to to the isEmpty() 00084 // method. If lkFn is zero, the directory is empty; otherwise, lkFn is the name 00085 // of the singleton lock file. To unset the callback use setCallBack(0); 00086 // 00087 class CallBack 00088 {public: 00089 virtual 00090 void isEmpty(struct stat *dStat, const char *dPath, const char *lkFn)=0; 00091 00092 CallBack() {} 00093 virtual ~CallBack() {} 00094 }; 00095 00096 void setCallBack(CallBack *cbP=0) {edCB = cbP;} 00097 00098 // When erp in the constructor is null, no error messages are printed. Such 00099 // messages can be routed to "cerr" if setMsgOn is called to establish a 00100 // messages prefix (e.g. "<cmd>:") for use by command line commands. 00101 // 00102 void setMsgOn(const char *pfx) {mPfx = pfx;} 00103 00104 // The following are processing options passed to the constructor 00105 // 00106 static const int retDir = 0x0001; // Return directories (implies retStat) 00107 static const int retFile= 0x0002; // Return files (implies retStat) 00108 static const int retLink= 0x0004; // Return link data (implies retStat) 00109 static const int retMisc= 0x0008; // Return other types (implies retStat) 00110 static const int retAll = 0x000f; // Return everything 00111 00112 static const int retStat= 0x0010; // return stat() information 00113 static const int retIDLO= 0x0020; // Names returned in decreasing length order 00114 static const int retIILO= 0x0040; // Names returned in increasing length order 00115 static const int Recurse= 0x0080; // Recursive traversal, 1 Level per Index() 00116 static const int noPath = 0x0100; // Do not include the full directory path 00117 static const int skpErrs= 0x8000; // Skip any entry causing an error 00118 00119 XrdOucNSWalk(XrdSysError *erp, // Error msg object. If 0->silent 00120 const char *dname, // Initial directory path 00121 const char *LKfn=0, // Lock file name (see note below) 00122 int opts=retAll, // Options (see above) 00123 XrdOucTList *xP=0); // 1st Level dir exclude list 00124 ~XrdOucNSWalk(); 00125 00126 // Note: When Lkfn is supplied and it exists in a directory about to be indexed 00127 // then the file is opened in r/w mode and an exclusive lock is obtained. 00128 // If either fails, the the directory is not indexed and Index() will 00129 // return null pointer with rc != 0. Note that the lkfn is not returned 00130 // as a directory entry if an empty directory call back has been set. 00131 00132 private: 00133 void addEnt(XrdOucNSWalk::NSEnt *eP); 00134 int Build(); 00135 int Emsg(const char *pfx, int rc, const char *tx1, const char *tx2=0); 00136 int getLink(XrdOucNSWalk::NSEnt *eP); 00137 int getStat(XrdOucNSWalk::NSEnt *eP, int doLstat=0); 00138 int getStat(); 00139 int inXList(const char *dName); 00140 int isSymlink(); 00141 int LockFile(); 00142 void setPath(char *newpath); 00143 00144 XrdSysError *eDest; 00145 XrdOucTList *DList; 00146 XrdOucTList *XList; 00147 struct NSEnt *DEnts; 00148 struct stat dStat; 00149 CallBack *edCB; 00150 const char *mPfx; 00151 char DPath[1032]; 00152 char *File; 00153 char *LKFn; 00154 int LKfd; 00155 int DPfd; 00156 int Opts; 00157 int errOK; 00158 int isEmpty; 00159 }; 00160 #endif