Added path.cc and tokenizer.h from win32 branch.
authorTaybin Rutkin <taybin@taybin.com>
Thu, 29 Jun 2006 16:29:19 +0000 (16:29 +0000)
committerTaybin Rutkin <taybin@taybin.com>
Thu, 29 Jun 2006 16:29:19 +0000 (16:29 +0000)
Added mountpoint.cc support for non-getmntent() systems.

git-svn-id: svn://localhost/ardour2/trunk@653 d708f5d6-7413-0410-9779-e7cbd77b26cf

libs/pbd3/SConscript
libs/pbd3/mountpoint.cc
libs/pbd3/path.cc [new file with mode: 0644]
libs/pbd3/pbd/path.h [new file with mode: 0644]
libs/pbd3/pbd/tokenizer.h [new file with mode: 0644]

index 2766b3c5eda15f62027acbdf12164f6cf936c314..cebb2472aa0c36c6e06620cb49c988434bc355f9 100644 (file)
@@ -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)
 
index 160f5e921cd77acafd1c11f1b8c68571acd9162f..c1bcb375f3a67f84d1a4d4cc8febb827f6a84de7 100644 (file)
@@ -88,7 +88,7 @@ mountpoint (string path)
        return best;
 }
 
-#else // no getmntent()
+#else // !HAVE_GETMNTENT
 
 #include <sys/param.h>
 #include <sys/ucred.h>
@@ -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 (file)
index 0000000..80f916c
--- /dev/null
@@ -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 <cerrno>
+
+#include <glib.h>
+#include <glib/gstdio.h>
+
+#include <glibmm/miscutils.h>
+#include <glibmm/fileutils.h>
+
+#include <pbd/path.h>
+#include <pbd/tokenizer.h>
+
+namespace PBD {
+
+Path::Path ()
+{
+
+}
+
+Path::Path (const string& path)
+{
+       vector<string> 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<string>& 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<string>& paths)
+{
+       for(vector<string>::const_iterator i = paths.begin(); i != paths.end(); ++i) {
+               add_readable_directory (*i);
+       }
+}
+
+const string
+Path::path_string() const
+{
+       string path;
+
+       for (vector<string>::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<string> tmp;
+       string directory_path;
+
+       for (vector<string>::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<string>::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 (file)
index 0000000..0b77a7c
--- /dev/null
@@ -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 <string>
+#include <vector>
+
+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<string>& 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<string>& () const { return m_dirs; }
+
+       /**
+         \return vector containing the absolute paths to the directories
+         contained
+         */
+       const vector<string>& 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<string>& paths);
+       
+       vector<string> 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 (file)
index 0000000..a976b79
--- /dev/null
@@ -0,0 +1,49 @@
+#ifndef PBD_TOKENIZER
+#define PBD_TOKENIZER
+
+#include <iterator>
+#include <string>
+
+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<typename StringType, typename Iter>
+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
+
+