bes Updated for version 3.21.1
The Backend Server (BES) is the lower two tiers of the Hyrax data server
BESFSDir.cc
1// BESFSDir.cc
2
3// This file is part of bes, A C++ back-end server implementation framework
4// for the OPeNDAP Data Access Protocol.
5
6// Copyright (c) 2004-2009 University Corporation for Atmospheric Research
7// Author: Patrick West <pwest@ucar.edu> and Jose Garcia <jgarcia@ucar.edu>
8//
9// This library is free software; you can redistribute it and/or
10// modify it under the terms of the GNU Lesser General Public
11// License as published by the Free Software Foundation; either
12// version 2.1 of the License, or (at your option) any later version.
13//
14// This library is distributed in the hope that it will be useful,
15// but WITHOUT ANY WARRANTY; without even the implied warranty of
16// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17// Lesser General Public License for more details.
18//
19// You should have received a copy of the GNU Lesser General Public
20// License along with this library; if not, write to the Free Software
21// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22//
23// You can contact University Corporation for Atmospheric Research at
24// 3080 Center Green Drive, Boulder, CO 80301
25
26// (c) COPYRIGHT University Corporation for Atmospheric Research 2004-2005
27// Please read the full copyright statement in the file COPYRIGHT_UCAR.
28//
29// Authors:
30// pwest Patrick West <pwest@ucar.edu>
31// jgarcia Jose Garcia <jgarcia@ucar.edu>
32
33#include <sys/types.h>
34#include <sys/stat.h>
35#include <dirent.h>
36#ifdef WIN32
37#include <config.h> // for S_ISDIR macro
38#endif
39#include <stdio.h>
40
41#include "BESFSDir.h"
42#include "BESRegex.h"
43#include "BESInternalError.h"
44
45using std::string;
46
47BESFSDir::BESFSDir(const string &dirName) :
48 _dirName(dirName), _fileExpr(""), _dirLoaded(false)
49{
50}
51
52BESFSDir::BESFSDir(const string &dirName, const string &fileExpr) :
53 _dirName(dirName), _fileExpr(fileExpr), _dirLoaded(false)
54{
55}
56
57BESFSDir::BESFSDir(const BESFSDir &copyFrom) :
58 _dirName(copyFrom._dirName), _fileExpr(copyFrom._fileExpr), _dirLoaded(false)
59{
60}
61
62BESFSDir::~BESFSDir()
63{
64}
65
66BESFSDir::dirIterator BESFSDir::beginOfDirList()
67{
68 if (_dirLoaded == false) {
69 loadDir();
70 _dirLoaded = true;
71 }
72 return _dirList.begin();
73}
74
75BESFSDir::dirIterator BESFSDir::endOfDirList()
76{
77 if (_dirLoaded == false) {
78 loadDir();
79 _dirLoaded = true;
80 }
81 return _dirList.end();
82}
83
84BESFSDir::fileIterator BESFSDir::beginOfFileList()
85{
86 if (_dirLoaded == false) {
87 loadDir();
88 _dirLoaded = true;
89 }
90 return _fileList.begin();
91}
92
93BESFSDir::fileIterator BESFSDir::endOfFileList()
94{
95 if (_dirLoaded == false) {
96 loadDir();
97 _dirLoaded = true;
98 }
99 return _fileList.end();
100}
101
102void BESFSDir::loadDir()
103{
104 DIR * dip;
105 struct dirent *dit;
106
107 try {
108 // open a directory stream
109 // make sure the directory is valid and readable
110 if ((dip = opendir(_dirName.c_str())) == NULL) {
111 string err_str = "ERROR: failed to open directory '" + _dirName + "'";
112 throw BESError(err_str, BES_NOT_FOUND_ERROR, __FILE__, __LINE__);
113 }
114 else {
115 // read in the files in this directory
116 // add each filename to the list of filenames
117 while ((dit = readdir(dip)) != NULL) {
118 struct stat buf;
119 string dirEntry = dit->d_name;
120 if (dirEntry != "." && dirEntry != "..") {
121 string fullPath = _dirName + "/" + dirEntry;
122
123 // This test used to throw a BES_NOT_FOUND_ERROR which I don't think is
124 // correct. If opendir() is used to open _dirName and iterate over the
125 // entries returned by repeated calls to readdir() then how can the
126 // paths be bad? One way, it turns out, is if there is a second process
127 // adding and removing files in _dirName. But I think it's better to
128 // ignore that case then return an error - is it really a BES error if
129 // another process is rude? This showed up when running parallel tests
130 // because the tests keysT and pvolT were stepping on each other. However,
131 // I don't think this is limited to 'make check -j9' since it could be
132 // exploited to crash the bes. jhrg 3/30/17
133 if (-1 == stat(fullPath.c_str(), &buf))
134 continue;
135#if 0
136 // Replaced by 'continue'. jhrg 3/30/17
137 throw BESError(string("Did not find the path: '") + fullPath + "'", BES_NOT_FOUND_ERROR,
138 __FILE__, __LINE__);
139#endif
140 // look at the mode and determine if this is a filename
141 // or a directory name
142 if (S_ISDIR(buf.st_mode)) {
143 _dirList.push_back(BESFSDir(fullPath));
144 }
145 else {
146 if (_fileExpr != "") {
147 BESRegex reg_expr(_fileExpr.c_str());
148 int match_ret = reg_expr.match(dirEntry.c_str(), dirEntry.size());
149 if (match_ret == static_cast<int>(dirEntry.size())) {
150 _fileList.push_back(BESFSFile(_dirName, dirEntry));
151 }
152 }
153 else {
154 _fileList.push_back(BESFSFile(_dirName, dirEntry));
155 }
156 }
157 }
158 }
159 }
160
161 // close the directory
162 closedir(dip);
163 }
164 catch (...) {
165 // close the directory
166 closedir(dip);
167 throw;
168 }
169}
170