From d1a4f74ef2c86042a0cbe0e83e611596df27575f Mon Sep 17 00:00:00 2001 From: Taybin Rutkin Date: Thu, 29 Jun 2006 16:29:19 +0000 Subject: Added path.cc and tokenizer.h from win32 branch. Added mountpoint.cc support for non-getmntent() systems. git-svn-id: svn://localhost/ardour2/trunk@653 d708f5d6-7413-0410-9779-e7cbd77b26cf --- libs/pbd3/SConscript | 7 +- libs/pbd3/mountpoint.cc | 55 ++++++++++++++-- libs/pbd3/path.cc | 164 ++++++++++++++++++++++++++++++++++++++++++++++ libs/pbd3/pbd/path.h | 113 ++++++++++++++++++++++++++++++++ libs/pbd3/pbd/tokenizer.h | 49 ++++++++++++++ 5 files changed, 381 insertions(+), 7 deletions(-) create mode 100644 libs/pbd3/path.cc create mode 100644 libs/pbd3/pbd/path.h create mode 100644 libs/pbd3/pbd/tokenizer.h diff --git a/libs/pbd3/SConscript b/libs/pbd3/SConscript index 2766b3c5ed..cebb2472aa 100644 --- a/libs/pbd3/SConscript +++ b/libs/pbd3/SConscript @@ -10,7 +10,7 @@ pbd3 = env.Copy() domain = 'libpbd' -pbd3.Append(DOMAIN=domain,MAJOR=4,MINOR=0,MICRO=0) +pbd3.Append(DOMAIN=domain,MAJOR=4,MINOR=1,MICRO=0) pbd3.Append(CXXFLAGS="-DPACKAGE=\\\"" + domain + "\\\"") pbd3.Append(CXXFLAGS="-D_REENTRANT -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE") pbd3.Append(CXXFLAGS="-DLIBSIGC_DISABLE_DEPRECATED") @@ -24,6 +24,7 @@ convert.cc dmalloc.cc error.cc mountpoint.cc +path.cc pathscanner.cc pool.cc pthread_utils.cc @@ -50,9 +51,11 @@ pbd3.Merge ([ libraries['sigc2'], libraries['xml'], libraries['glibmm2'], librar pbd3.VersionBuild(['version.cc','pbd/version.h'], 'SConscript') libpbd3 = pbd3.SharedLibrary('pbd', pbd3_files) - Default(libpbd3) +mount_env = Environment(CCFLAGS='-DTEST_MOUNTPOINT -Ilibs/pbd3') +mount_env.Program('mountpoint', 'mountpoint.cc') + if env['NLS']: i18n (pbd3, pbd3_files, env) diff --git a/libs/pbd3/mountpoint.cc b/libs/pbd3/mountpoint.cc index 160f5e921c..c1bcb375f3 100644 --- a/libs/pbd3/mountpoint.cc +++ b/libs/pbd3/mountpoint.cc @@ -88,7 +88,7 @@ mountpoint (string path) return best; } -#else // no getmntent() +#else // !HAVE_GETMNTENT #include #include @@ -97,10 +97,55 @@ mountpoint (string path) string mountpoint (string path) { -//XXX IMPLEMENT ME using getmntinfo() or getfsstat(). - return "/"; + struct statfs *mntbufp = 0; + int count; + unsigned int maxmatch = 0; + unsigned int matchlen; + const char *cpath = path.c_str(); + char best[PATH_MAX+1]; + + if ((count = getmntinfo(&mntbufp, MNT_NOWAIT)) == 0) { + free(mntbufp); + return "\0"; + } + + best[0] = '\0'; + + for (int i = 0; i < count; ++i) { + unsigned int n = 0; + matchlen = 0; + + /* note: strcmp's semantics are not + strict enough to use for this. + */ + + while (cpath[n] && mntbufp[i].f_mntonname[n]) { + if (cpath[n] != mntbufp[i].f_mntonname[n]) { + break; + } + matchlen++; + n++; + } + + if (cpath[matchlen] == '\0') { + snprintf(best, sizeof(best), "%s", mntbufp[i].f_mntonname); + free(mntbufp); + return best; + + } else { + + if (matchlen > maxmatch) { + snprintf (best, sizeof(best), "%s", mntbufp[i].f_mntonname); + maxmatch = matchlen; + } + } + } + + free(mntbufp); + + return best; } -#endif +#endif // HAVE_GETMNTENT #ifdef TEST_MOUNTPOINT @@ -110,4 +155,4 @@ main (int argc, char *argv[]) exit (0); } -#endif +#endif // TEST_MOUNTPOINT diff --git a/libs/pbd3/path.cc b/libs/pbd3/path.cc new file mode 100644 index 0000000000..80f916c9ae --- /dev/null +++ b/libs/pbd3/path.cc @@ -0,0 +1,164 @@ +/* + Copyright (C) 2006 Paul Davis + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#include + +#include +#include + +#include +#include + +#include +#include + +namespace PBD { + +Path::Path () +{ + +} + +Path::Path (const string& path) +{ + vector tmp; + + if(!tokenize ( path, string(":;"), std::back_inserter (tmp))) { + g_warning ("%s : %s\n", G_STRLOC, G_STRFUNC); + return; + } + + add_readable_directories (tmp); +} + +Path::Path (const vector& paths) +{ + add_readable_directories (paths); +} + +Path::Path (const Path& other) + : m_dirs(other.m_dirs) +{ + +} + +bool +Path::readable_directory (const string& directory_path) +{ + if (g_access (directory_path.c_str(), R_OK) == 0) { + if (Glib::file_test(directory_path, Glib::FILE_TEST_IS_DIR)) { + return true; + } else { + g_warning (" %s : Path exists but is not a directory\n", G_STRLOC); + } + } else { + g_warning ("%s : %s : %s\n", G_STRLOC, directory_path.c_str(), g_strerror(errno)); + } + return false; +} + +void +Path::add_readable_directory (const string& directory_path) +{ + if(readable_directory(directory_path)) { + m_dirs.push_back(directory_path); + } +} + +void +Path::add_readable_directories (const vector& paths) +{ + for(vector::const_iterator i = paths.begin(); i != paths.end(); ++i) { + add_readable_directory (*i); + } +} + +const string +Path::path_string() const +{ + string path; + + for (vector::const_iterator i = m_dirs.begin(); i != m_dirs.end(); ++i) { + path += (*i); + path += G_SEARCHPATH_SEPARATOR; + } + + g_message ("%s : %s", G_STRLOC, path.c_str()); + + return path.substr (0, path.length() - 1); // drop final colon +} + +const Path& +Path::operator= (const Path& path) +{ + m_dirs = path.m_dirs; + return *this; +} + +const Path& +Path::operator+= (const string& directory_path) +{ + add_readable_directory (directory_path); + return *this; +} + +const Path +operator+ (const Path& lhs_path, const Path& rhs_path) +{ + Path tmp_path(lhs_path); // does this do what I think it does. + // concatenate paths into new Path + tmp_path.m_dirs.insert(tmp_path.m_dirs.end(), rhs_path.m_dirs.begin(), rhs_path.m_dirs.end()); + return tmp_path; +} + +Path& +Path::add_subdirectory_to_path (const string& subdir) +{ + vector tmp; + string directory_path; + + for (vector::iterator i = m_dirs.begin(); i != m_dirs.end(); ++i) { + directory_path = Glib::build_filename (*i, subdir); + if(readable_directory(directory_path)) { + tmp.push_back(directory_path); + } + } + m_dirs = tmp; + return *this; +} + +bool +find_file_in_path (const Path& path, const string& filename, string& resulting_path) +{ + for (vector::const_iterator i = path.dirs().begin(); i != path.dirs().end(); ++i) { + resulting_path = Glib::build_filename ((*i), filename); + if (g_access (resulting_path.c_str(), R_OK) == 0) { + g_message ("File %s found in Path : %s\n", resulting_path.c_str(), + path.path_string().c_str()); + return true; + } + } + + g_warning ("%s : Could not locate file %s in path %s\n", G_STRLOC, filename.c_str(), + path.path_string().c_str()); + + return false; +} + +} // namespace PBD + diff --git a/libs/pbd3/pbd/path.h b/libs/pbd3/pbd/path.h new file mode 100644 index 0000000000..0b77a7c237 --- /dev/null +++ b/libs/pbd3/pbd/path.h @@ -0,0 +1,113 @@ +/* + Copyright (C) 2006 Paul Davis + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +*/ + +#ifndef PBD_PATH +#define PBD_PATH + +#include +#include + +namespace PBD { + +using std::string; +using std::vector; + +/** + The Path class is a helper class for getting a vector of absolute + paths contained in a path string where a path string contains + absolute directory paths separated by a colon(:) or a semi-colon(;) + on windows. + */ +class Path { +public: + + /** + Create an empty Path. + */ + Path (); + + /** + Initialize Path from a string, each absolute path contained + in the "path" will be accessed to ensure it exists and is + readable. + \param path A path string. + */ + Path (const string& path); + + /** + Initialize Path from a vector of path strings, each absolute + path contained in paths will be accessed to ensure it + exists and is readable. + \param path A path string. + */ + Path (const vector& paths); + + Path(const Path& path); + + /** + Indicate whether there are any directories in m_dirs, if Path is + initialized with an empty string as the result of for instance + calling Glib::getenv where the environment variable doesn't + exist or if none of the directories in the path string are + accessible then false is returned. + + \return true if there are any paths in m_paths. + */ + //operator bool () const { return !m_dirs.empty(); } + + /** + \return vector containing the absolute paths to the directories + contained + */ + operator const vector& () const { return m_dirs; } + + /** + \return vector containing the absolute paths to the directories + contained + */ + const vector& dirs () const { return m_dirs; } + + const string path_string() const; + + const Path& operator= (const Path& path); + + const Path& operator+= (const string& directory_path); + + Path& add_subdirectory_to_path (const string& subdirectory); + +protected: + + friend const Path operator+ (const Path&, const Path&); + + bool readable_directory (const string& directory_path); + + void add_readable_directory (const string& directory_path); + + void add_readable_directories (const vector& paths); + + vector m_dirs; + +}; + +bool find_file_in_path (const Path& path, const string& filename, string& resulting_path_to_file); + +} // namespace PBD + +#endif // PBD_PATH + + diff --git a/libs/pbd3/pbd/tokenizer.h b/libs/pbd3/pbd/tokenizer.h new file mode 100644 index 0000000000..a976b79341 --- /dev/null +++ b/libs/pbd3/pbd/tokenizer.h @@ -0,0 +1,49 @@ +#ifndef PBD_TOKENIZER +#define PBD_TOKENIZER + +#include +#include + +namespace PBD { + +/** + Tokenize string, this should work for standard + strings aswell as Glib::ustring. This is a bit of a hack, + there are much better string tokenizing patterns out there. +*/ +template +unsigned int +tokenize(const StringType& str, + const StringType& delims, + Iter it) +{ + typename StringType::size_type start_pos = 0; + typename StringType::size_type end_pos = 0; + unsigned int token_count = 0; + + do { + start_pos = str.find_first_not_of(delims, start_pos); + end_pos = str.find_first_of(delims, start_pos); + if (start_pos != end_pos) { + if (end_pos == str.npos) { + end_pos = str.length(); + } + *it++ = str.substr(start_pos, end_pos - start_pos); + ++token_count; + start_pos = str.find_first_not_of(delims, end_pos + 1); + } + } while (start_pos != str.npos); + + if (start_pos != str.npos) { + *it++ = str.substr(start_pos, str.length() - start_pos); + ++token_count; + } + + return token_count; +} + +} // namespace PBD + +#endif // PBD_TOKENIZER + + -- cgit v1.2.3