Canola  0.8.D001
lib/search_path.cc
Go to the documentation of this file.
00001 //
00002 // canola - canon canola 1614p emulator
00003 // Copyright (C) 2011, 2012 Peter Miller
00004 //
00005 // This program is free software; you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License, version 3, as
00007 // published by the Free Software Foundation.
00008 //
00009 // This program is distributed in the hope that it will be useful,
00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012 // General Public License for more details.
00013 //
00014 // You should have received a copy of the GNU General Public License along
00015 // with this program. If not, see <http://www.gnu.org/licenses/>.
00016 //
00017 
00018 #include <lib/ac/errno.h>
00019 #include <sys/stat.h>
00020 #include <libexplain/stat.h>
00021 #include <libexplain/output.h>
00022 
00023 #include <lib/libdir.h>
00024 #include <lib/path_join.h>
00025 #include <lib/search_path.h>
00026 
00027 
00028 search_path::~search_path()
00029 {
00030 }
00031 
00032 
00033 search_path::search_path() :
00034     have_system(false)
00035 {
00036 }
00037 
00038 
00039 search_path::search_path(const std::string &a_subdir, bool dot) :
00040     subdir(a_subdir),
00041     have_system(false)
00042 {
00043     if (dot)
00044         path.push_back(".");
00045 }
00046 
00047 
00048 static bool
00049 dir_exists(const std::string &path)
00050 {
00051     struct stat st;
00052     return (stat(path.c_str(), &st) >= 0 && S_ISDIR(st.st_mode));
00053 }
00054 
00055 
00056 void
00057 search_path::append(const std::string &dir)
00058 {
00059     path.push_back(dir);
00060 
00061     if (!subdir.empty())
00062     {
00063         std::string s = path_join(dir, subdir);
00064         if (dir_exists(s))
00065             path.push_back(s);
00066     }
00067 }
00068 
00069 
00070 std::string
00071 search_path::find(const std::string &filename)
00072 {
00073     if (!have_system)
00074     {
00075         have_system = true;
00076         std::string dir = configured_datadir();
00077         dir = path_join(dir, "canola");
00078         append(dir);
00079     }
00080 
00081     for (path_t::const_iterator it = path.begin(); it != path.end(); ++it)
00082     {
00083         std::string fn = path_join(*it, filename);
00084         struct stat st;
00085         if (stat(fn.c_str(), &st) >= 0)
00086             return fn;
00087         int err = errno;
00088         if (err != ENOENT)
00089         {
00090             explain_output_error_and_die
00091             (
00092                 "%s",
00093                 explain_stat(fn.c_str(), &st)
00094             );
00095         }
00096     }
00097 
00098     if (path.front() == ".")
00099         return filename;
00100     std::string fn = path_join(path.back(), filename);
00101     struct stat st;
00102     explain_output_error_and_die
00103     (
00104         "%s",
00105         explain_errno_stat(ENOENT, fn.c_str(), &st)
00106     );
00107     return fn;
00108 }