Canola
0.8.D001
|
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 }