locate_images.cpp
Go to the documentation of this file.00001
00012 #include "file_manip.h"
00013 #include "locate_images.h"
00014 #include "string_manip.h"
00015
00016 #include <cerrno>
00017 #include <iostream>
00018 #include <sstream>
00019 #include <cstdlib>
00020
00021 using namespace std;
00022
00023
00024 int extra_images::suid;
00025
00026 extra_images::extra_images()
00027 :
00028 uid(++suid)
00029 {
00030 }
00031
00032
00033 void extra_images::populate(vector<string> const & paths,
00034 string const & prefix_path)
00035 {
00036 vector<string>::const_iterator cit = paths.begin();
00037 vector<string>::const_iterator end = paths.end();
00038 for (; cit != end; ++cit) {
00039 string const path = op_realpath(prefix_path + *cit);
00040 list<string> file_list;
00041 create_file_list(file_list, path, "*", true);
00042 list<string>::const_iterator lit = file_list.begin();
00043 list<string>::const_iterator lend = file_list.end();
00044 for (; lit != lend; ++lit) {
00045 value_type v(op_basename(*lit), op_dirname(*lit));
00046 images.insert(v);
00047 }
00048 }
00049 }
00050
00051
00052 void extra_images::populate(vector<string> const & paths,
00053 string const & archive_path_,
00054 string const & root_path_)
00055 {
00056 archive_path = archive_path_;
00057 if (!archive_path.empty())
00058 archive_path = op_realpath(archive_path);
00059
00060 root_path = op_realpath(root_path_);
00061 if (!root_path.empty())
00062 root_path = op_realpath(root_path);
00063
00064 if (root_path.empty() && archive_path.empty())
00065 populate(paths, "");
00066 if (!archive_path.empty())
00067 populate(paths, archive_path);
00068 if (!root_path.empty() && root_path != archive_path)
00069 populate(paths, root_path);
00070 }
00071
00072
00073 vector<string> const extra_images::find(string const & name) const
00074 {
00075 extra_images::matcher match(name);
00076 return find(match);
00077 }
00078
00079
00080 vector<string> const
00081 extra_images::find(extra_images::matcher const & match) const
00082 {
00083 vector<string> matches;
00084
00085 const_iterator cit = images.begin();
00086 const_iterator end = images.end();
00087
00088 for (; cit != end; ++cit) {
00089 if (match(cit->first))
00090 matches.push_back(cit->second + '/' + cit->first);
00091 }
00092
00093 return matches;
00094 }
00095
00096
00097 namespace {
00098
00103 struct module_matcher : public extra_images::matcher {
00104 public:
00105 explicit module_matcher(string const & s)
00106 : extra_images::matcher(s) {}
00107
00108 virtual bool operator()(string const & candidate) const {
00109 if (candidate.length() != value.length())
00110 return false;
00111
00112 for (string::size_type i = 0 ; i < value.length() ; ++i) {
00113 if (value[i] == candidate[i])
00114 continue;
00115 if (value[i] == '_' &&
00116 (candidate[i] == ',' || candidate[i] == '-'))
00117 continue;
00118 return false;
00119 }
00120
00121 return true;
00122 }
00123 };
00124
00125 }
00126
00127 string const extra_images::locate_image(string const & image_name,
00128 image_error & error, bool fixup) const
00129 {
00130
00131
00132 if (!archive_path.empty()) {
00133 string image = op_realpath(archive_path + image_name);
00134 if (op_file_readable(image)) {
00135 error = image_ok;
00136 return fixup ? image : image_name;
00137 }
00138
00139 if (errno == EACCES) {
00140 error = image_unreadable;
00141 return image_name;
00142 }
00143 }
00144
00145
00146
00147
00148
00149 if (!root_path.empty() || archive_path.empty()) {
00150 string image = op_realpath(root_path + image_name);
00151 if (op_file_readable(image)) {
00152 error = image_ok;
00153 return fixup ? image : image_name;
00154 }
00155 }
00156
00157 error = image_not_found;
00158 return image_name;
00159 }
00160
00161 string const extra_images::find_image_path(string const & image_name,
00162 image_error & error, bool fixup) const
00163 {
00164 error = image_ok;
00165
00166 string const image = locate_image(image_name, error, fixup);
00167 if (error != image_not_found)
00168 return image;
00169
00170 string const base = op_basename(image);
00171
00172 vector<string> result = find(base);
00173
00174
00175 if (result.empty())
00176 result = find(module_matcher(base + ".ko"));
00177
00178 if (result.empty()) {
00179 error = image_not_found;
00180 return image_name;
00181 }
00182
00183 if (result.size() == 1) {
00184 error = image_ok;
00185 return fixup ? result[0] : image_name;
00186 }
00187
00188
00189
00190 size_t count = 0;
00191 size_t index = 0;
00192 for (size_t i = 0; i < result.size() && count < 2; ++i) {
00193 if (is_prefix(result[i], archive_path)) {
00194 index = i;
00195 ++count;
00196 }
00197 }
00198
00199 if (count == 0) {
00200 for (size_t i = 0; i < result.size() && count < 2; ++i) {
00201 if (is_prefix(result[i], root_path)) {
00202 index = i;
00203 ++count;
00204 }
00205 }
00206 }
00207
00208 if (count == 1) {
00209 error = image_ok;
00210 return fixup ? result[index] : image_name;
00211 }
00212
00213 error = image_multiple_match;
00214 return image_name;
00215 }
00216
00217
00218 string extra_images::strip_path_prefix(string const & image) const
00219 {
00220 if (archive_path.length() && is_prefix(image, archive_path))
00221 return image.substr(archive_path.size());
00222 if (root_path.length() && is_prefix(image, root_path))
00223 return image.substr(root_path.size());
00224 return image;
00225 }