00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <sys/types.h>
00024 #include <sys/stat.h>
00025 #if defined(__digital__)
00026 #include <sys/mode.h>
00027 #endif
00028 #include <dirent.h>
00029 #include <Basics.H>
00030 #include <FS.H>
00031 #include <AtomicFile.H>
00032 #include <FP.H>
00033 #include <CacheArgs.H>
00034 #include <CacheConfig.H>
00035 #include <VestaVal.H>
00036 #include <CacheEntry.H>
00037 #include <SPKFile.H>
00038 #include <SMultiPKFileRep.H>
00039
00040 using std::ostream;
00041 using std::ifstream;
00042 using std::cout;
00043 using std::cerr;
00044 using std::endl;
00045
00046 void Error(char *msg, char *arg = (char *)NULL) throw ()
00047 {
00048 cout << "Error: " << msg;
00049 if (arg != (char *)NULL) cout << ": `" << arg << "'";
00050 cout << endl;
00051 cout << "SYNTAX: PrintCacheVal [ -n | -N ] [ -ci num ] [ path ]" << endl;
00052 exit(1);
00053 }
00054
00055 bool OpenFile(const Text fname, ifstream &ifs) throw (FS::Failure)
00056
00057
00058
00059
00060
00061 {
00062 try {
00063 FS::OpenReadOnly(fname, ifs);
00064 }
00065 catch (FS::DoesNotExist) {
00066 cerr << "Error: unable to open '" << fname << "' for reading." << endl;
00067 return false;
00068 }
00069 return true;
00070 }
00071
00072 static void SearchMPK(ostream &os, const Text &fname, int nSwitch, int ciOnly)
00073 throw (SMultiPKFileRep::BadMPKFile, FS::EndOfFile, FS::Failure)
00074 {
00075
00076 if (nSwitch > 0) {
00077 os << "MultiPKFile " << fname << ':';
00078 if (nSwitch > 1) os << endl;
00079 }
00080
00081
00082 ifstream ifs;
00083 if (!OpenFile(fname, ifs)) return;
00084
00085 try {
00086
00087 SMultiPKFileRep::Header hdr(ifs);
00088 hdr.ReadEntries(ifs);
00089 hdr.ReadPKFiles(ifs);
00090 FS::Close(ifs);
00091
00092
00093 int entryCnt = 0;
00094 for (int i = 0; i < hdr.num; i++) {
00095 SMultiPKFileRep::HeaderEntry *he;
00096 bool inTbl = hdr.pkTbl.Get(*(hdr.pkSeq[i]), he);
00097 assert(inTbl);
00098
00099
00100 SPKFile *pkFile = he->pkfile;
00101 SPKFile::CFPEntryIter it(pkFile->OldEntries());
00102 FP::Tag fp; CE::List *entries;
00103 while (it.Next( fp, entries)) {
00104
00105 while (entries != (CE::List *)NULL) {
00106 CE::T *ent = entries->Head();
00107 if (ciOnly < 0 || ciOnly == ent->CI()) {
00108
00109 entryCnt++;
00110 const VestaVal::T *val = ent->Value();
00111 switch (nSwitch) {
00112 case 0:
00113
00114 FS::Write(os, (char *)(&(val->len)),
00115 sizeof(val->len));
00116 FS::Write(os, val->bytes, val->len);
00117 break;
00118 case 1:
00119
00120 break;
00121 case 2:
00122
00123 os << " ci = " << ent->CI()
00124 << "; value length = " << val->len << endl;
00125 break;
00126 }
00127 }
00128 entries = entries->Tail();
00129 }
00130 }
00131 }
00132 if (nSwitch == 1) os << " entries = " << entryCnt << endl;
00133 } catch (...) {
00134 if (nSwitch == 1) os << endl;
00135 FS::Close(ifs);
00136 throw;
00137 }
00138 }
00139
00140 static void FSStat(const Text &path, struct stat *buffer)
00141 throw (FS::Failure, FS::DoesNotExist)
00142 {
00143 if (stat(path.cchars(), buffer) != 0) {
00144 if (errno == ENOENT) throw FS::DoesNotExist();
00145 else throw FS::Failure(Text("stat"), path);
00146 }
00147 }
00148
00149 static bool IsDotDir(char *arc) throw ()
00150 {
00151 return (!strcmp(arc, ".") || !strcmp(arc, ".."));
00152 }
00153
00154 static bool IsTempFile(const Text &path) throw ()
00155
00156 {
00157 int slashIx = path.FindCharR('/');
00158 int semiIx = path.FindChar(AtomicFile::reserved_char, slashIx);
00159 if (semiIx <= 0) return false;
00160 for (int i = slashIx + 1; i < semiIx; i++) {
00161 if (!isxdigit(path[i])) return false;
00162 }
00163 return true;
00164 }
00165
00166 static void SearchPath2(ostream &os, const Text &path, int nSwitch,
00167 int ciOnly, struct stat *statBuff) throw (FS::EndOfFile, FS::Failure)
00168 {
00169
00170 if (S_ISDIR(statBuff->st_mode)) {
00171
00172 DIR *dir;
00173 if ((dir = opendir(path.cchars())) == NULL) {
00174 assert(errno != ENOENT);
00175 throw FS::Failure(Text("opendir"), path);
00176 }
00177 Text pathSlash(path + '/');
00178 struct dirent *sysDirEnt;
00179 while ((sysDirEnt = readdir(dir)) != (struct dirent *)NULL) {
00180
00181 if (IsDotDir(sysDirEnt->d_name)) continue;
00182
00183
00184 Text fullname(pathSlash + sysDirEnt->d_name);
00185 struct stat buffer;
00186 FSStat(fullname, &buffer);
00187 if (S_ISREG(buffer.st_mode) && IsTempFile(fullname)) {
00188 continue;
00189 }
00190
00191
00192 SearchPath2(os, fullname, nSwitch, ciOnly, &buffer);
00193 }
00194 if (closedir(dir) < 0) {
00195 throw FS::Failure(Text("closedir"), path);
00196 }
00197 } else {
00198
00199 assert(S_ISREG(statBuff->st_mode));
00200 try {
00201 SearchMPK(os, path, nSwitch, ciOnly);
00202 } catch (SMultiPKFileRep::BadMPKFile) {
00203 cerr << "Warning: ignoring bad MultiPKFile:" <<endl << path <<endl;
00204 }
00205 }
00206 }
00207
00208 static void SearchPath(ostream &os, const char *path, int nSwitch, int ciOnly)
00209 throw (FS::EndOfFile, FS::Failure)
00210 {
00211
00212 Text fullpath(path);
00213 if (path[0] != '/') {
00214
00215 if (fullpath.Length() > 0) {
00216 fullpath = Config_SCachePath + ('/' + fullpath);
00217 } else {
00218 fullpath = Config_SCachePath;
00219 }
00220 }
00221
00222
00223 struct stat buffer;
00224 FSStat(fullpath, &buffer);
00225 SearchPath2(os, fullpath, nSwitch, ciOnly, &buffer);
00226 }
00227
00228 int main(int argc, char *argv[])
00229 {
00230
00231 int nSwitch = 0;
00232 int ci = -1;
00233
00234
00235 int arg = 1;
00236 while (arg < argc && *argv[arg] == '-') {
00237 if (strcmp(argv[arg], "-n") == 0) {
00238 nSwitch = 1; arg++;
00239 } else if (strcmp(argv[arg], "-N") == 0) {
00240 nSwitch = 2; arg++;
00241 } else if (CacheArgs::StartsWith(argv[arg], "-ci")) {
00242 arg++;
00243 if (arg < argc-1) {
00244 int res = sscanf(argv[arg], "%d", &ci);
00245 if (res != 1 || ci < 0) {
00246 Error("argument to `-ci' is not a non-negative integer",
00247 argv[arg]);
00248 }
00249 arg++;
00250 } else {
00251 Error("no argument for `-ci'");
00252 }
00253 } else {
00254 Error("unrecognized switch", argv[arg]);
00255 }
00256 }
00257 if (arg < argc - 1) {
00258 Error("at most one `path' argument allowed", argv[arg]);
00259 }
00260 const char *path = (arg < argc) ? argv[arg] : "";
00261
00262
00263 try {
00264 SearchPath(cout, path, nSwitch, ci);
00265 }
00266 catch (FS::EndOfFile) {
00267 cerr << "Fatal error: unexpected end-of-file" << endl;
00268 exit(3);
00269 }
00270 catch (FS::Failure &f) {
00271 cerr << f;
00272 exit(4);
00273 }
00274 return 0;
00275 }