00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <string.h>
00021 #include <ctype.h>
00022
00023 #include "FileConfigTree.h"
00024 #include "FileConfigNode.h"
00025 #include "SyncEvolutionUtil.h"
00026
00027 #include <boost/foreach.hpp>
00028
00029 #include <unistd.h>
00030 #include <sys/stat.h>
00031 #include <errno.h>
00032 #include <fcntl.h>
00033 #include <dirent.h>
00034
00035 FileConfigTree::FileConfigTree(const string &root,
00036 bool oldLayout) :
00037 m_root(root),
00038 m_oldLayout(oldLayout)
00039 {
00040 }
00041
00042 string FileConfigTree::getRootPath() const
00043 {
00044 return normalizePath(m_root);
00045 }
00046
00047 void FileConfigTree::flush()
00048 {
00049 BOOST_FOREACH(const NodeCache_t::value_type &node, m_nodes) {
00050 node.second->flush();
00051 }
00052 }
00053
00054 void FileConfigTree::reset()
00055 {
00056 m_nodes.clear();
00057 }
00058
00059 boost::shared_ptr<ConfigNode> FileConfigTree::open(const string &path,
00060 ConfigTree::PropertyType type,
00061 const string &otherId)
00062 {
00063 string fullpath;
00064 string filename;
00065
00066 fullpath = normalizePath(m_root + "/" + path + "/");
00067 if (type == other) {
00068 if (m_oldLayout) {
00069 fullpath += "/changes";
00070 if (!otherId.empty()) {
00071 fullpath += "_";
00072 fullpath += otherId;
00073 }
00074 filename = "config.txt";
00075 } else {
00076 filename += ".other";
00077 if (!otherId.empty()) {
00078 filename += "_";
00079 filename += otherId;
00080 }
00081 filename += ".ini";
00082 }
00083 } else {
00084 filename = m_oldLayout ? "config.txt" :
00085 type == hidden ? ".internal.ini" :
00086 "config.ini";
00087 }
00088
00089 string fullname = normalizePath(fullpath + "/" + filename);
00090 NodeCache_t::iterator found = m_nodes.find(fullname);
00091 if (found != m_nodes.end()) {
00092 return found->second;
00093 } else {
00094 boost::shared_ptr<ConfigNode> node(new FileConfigNode(fullpath, filename));
00095 return m_nodes[fullname] = node;
00096 }
00097 }
00098
00099 static inline bool isNode(const string &dir, const string &name) {
00100 struct stat buf;
00101 string fullpath = dir + "/" + name;
00102 return !stat(fullpath.c_str(), &buf) && S_ISDIR(buf.st_mode);
00103 }
00104
00105 list<string> FileConfigTree::getChildren(const string &path)
00106 {
00107 list<string> res;
00108
00109 string fullpath;
00110 fullpath = normalizePath(m_root + "/" + path);
00111
00112
00113 if (!access(fullpath.c_str(), F_OK)) {
00114 ReadDir dir(fullpath);
00115 BOOST_FOREACH(const string entry, dir) {
00116 if (isNode(fullpath, entry)) {
00117 res.push_back(entry);
00118 }
00119 }
00120 }
00121
00122
00123
00124
00125 fullpath += "/";
00126 BOOST_FOREACH(const NodeCache_t::value_type &node, m_nodes) {
00127 string currpath = node.first;
00128 if (currpath.size() > fullpath.size() &&
00129 currpath.substr(0, fullpath.size()) == fullpath) {
00130
00131
00132
00133 size_t start = fullpath.size();
00134 size_t end = currpath.find('/', start);
00135 if (currpath.npos != end) {
00136
00137
00138
00139 if (currpath.npos == currpath.find('/', end + 1)) {
00140
00141 string name = currpath.substr(start, end - start);
00142 if (res.end() == find(res.begin(), res.end(), name)) {
00143 res.push_back(name);
00144 }
00145 }
00146 }
00147 }
00148 }
00149
00150 return res;
00151 }