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 } // anon namespace
00126 
00127 string const extra_images::locate_image(string const & image_name,
00128                image_error & error, bool fixup) const
00129 {
00130     // Skip search since root_path can be non empty and we want
00131     // to lookup only in root_path in this case.
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     // We catch a case where root_path.empty() since we skipped a
00146     // search in "/" above when archive_path is empty. The case where
00147     // root_path.empty() && archive_path.empty() is the normal one, none
00148     // of --root or archive: as been given on command line.
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     // not found, try a module search
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     // We can't get multiple result except if only one result is prefixed
00189     // by archive_path or by root_path.
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 }

Generated on 8 Nov 2012 for Oprofile by  doxygen 1.6.1