|
degate 0.1.1
|
00001 /* 00002 00003 This file is part of the IC reverse engineering tool degate. 00004 00005 Copyright 2008, 2009, 2010 by Martin Schobert 00006 00007 Degate is free software: you can redistribute it and/or modify 00008 it under the terms of the GNU General Public License as published by 00009 the Free Software Foundation, either version 3 of the License, or 00010 any later version. 00011 00012 Degate is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 GNU General Public License for more details. 00016 00017 You should have received a copy of the GNU General Public License 00018 along with degate. If not, see <http://www.gnu.org/licenses/>. 00019 00020 */ 00021 00022 #include <FileSystem.h> 00023 #include <Configuration.h> 00024 #include <degate_exceptions.h> 00025 00026 #include <sys/types.h> 00027 #include <sys/stat.h> 00028 #include <unistd.h> 00029 #include <errno.h> 00030 #include <stdlib.h> 00031 #include <dirent.h> 00032 #include <string.h> 00033 #include <limits.h> 00034 00035 #include <boost/filesystem/operations.hpp> 00036 #include <boost/filesystem/path.hpp> 00037 #include <boost/format.hpp> 00038 #include <boost/foreach.hpp> 00039 #include <iostream> 00040 #include <string> 00041 00042 using namespace degate; 00043 using namespace boost::filesystem; 00044 00045 /** @todo Instead of writing own wrapper functions, it would be better to 00046 use the boost filesystem abstraction. 00047 */ 00048 00049 bool degate::is_directory(std::string const & path) { 00050 struct stat stat_buf; 00051 if(stat(path.c_str(), &stat_buf) == 0) { 00052 return S_ISDIR(stat_buf.st_mode) ? true : false; 00053 } 00054 return false; 00055 } 00056 00057 bool degate::is_file(std::string const & path) { 00058 struct stat stat_buf; 00059 if(stat(path.c_str(), &stat_buf) == 0) { 00060 return S_ISREG(stat_buf.st_mode) ? true : false; 00061 } 00062 return false; 00063 } 00064 00065 bool degate::is_symlink(std::string const & path) { 00066 struct stat stat_buf; 00067 if(stat(path.c_str(), &stat_buf) == 0) { 00068 return S_ISLNK(stat_buf.st_mode) ? true : false; 00069 } 00070 return false; 00071 } 00072 00073 bool degate::file_exists(std::string const & path) { 00074 struct stat stat_buf; 00075 return stat(path.c_str(), &stat_buf) == 0 ? true : false; 00076 } 00077 00078 std::string degate::get_basedir(std::string const & path) { 00079 00080 std::string resolved_path; 00081 00082 if(file_exists(path)) { 00083 resolved_path = get_realpath(path); 00084 00085 if(is_directory(resolved_path)) return resolved_path; 00086 else { 00087 return resolved_path.substr(0, resolved_path.find_last_of('/')); 00088 } 00089 } 00090 else { 00091 // treat it as a file name 00092 size_t last_pos = path.find_last_of('/'); 00093 if(last_pos != 0) 00094 return path.substr(0, last_pos); 00095 else return "/"; 00096 } 00097 00098 } 00099 00100 00101 std::string degate::get_realpath(std::string const& path) { 00102 char resolved_path[PATH_MAX]; 00103 if(realpath(path.c_str(), resolved_path) == NULL) { 00104 boost::format fmter("Error in get_realpath(). Can't get real path for %1%."); 00105 fmter % path; 00106 throw degate::InvalidPathException(fmter.str()); 00107 } 00108 else return std::string(resolved_path); 00109 } 00110 00111 00112 std::string degate::get_file_suffix(std::string const& path) { 00113 size_t last_occurance = path.rfind(".", path.size()); 00114 if(last_occurance < path.size()) { 00115 return path.substr(last_occurance + 1, path.size() - last_occurance); 00116 } 00117 else return std::string(); 00118 } 00119 00120 00121 void degate::remove_file(std::string const& path) { 00122 if(unlink(path.c_str()) != 0) { 00123 throw degate::FileSystemException(strerror(errno)); 00124 } 00125 } 00126 00127 void degate::remove_directory(std::string const& path) { 00128 boost::filesystem::path p(path); 00129 boost::filesystem::remove_all(path); 00130 } 00131 00132 void degate::create_directory(std::string const& directory, mode_t mode) { 00133 00134 if(mkdir(directory.c_str(), mode) != 0) { 00135 throw degate::FileSystemException(strerror(errno)); 00136 } 00137 00138 } 00139 00140 std::string degate::create_temp_directory() { 00141 return create_temp_directory(generate_temp_file_pattern(get_temp_directory())); 00142 } 00143 00144 std::string degate::create_temp_directory(std::string const & directory_pattern) { 00145 char template_str[PATH_MAX]; 00146 strncpy(template_str, directory_pattern.c_str(), sizeof(template_str)); 00147 char * dirname = mkdtemp(template_str); 00148 return std::string(dirname); 00149 } 00150 00151 00152 std::string degate::generate_temp_file_pattern(std::string const & basedir) { 00153 return basedir + std::string("/temp.XXXXXXXXXXX"); 00154 } 00155 00156 00157 std::list<std::string> degate::read_directory(std::string const& path, bool prefix_path) { 00158 00159 DIR * dir = NULL; 00160 struct dirent * dir_ent = NULL; 00161 00162 std::string rpth = get_realpath(path); 00163 00164 if((dir = opendir(rpth.c_str())) == NULL) 00165 throw degate::FileSystemException(strerror(errno)); 00166 00167 std::list<std::string> retlist; 00168 00169 while((dir_ent = readdir(dir)) != NULL) 00170 if(!(!strcmp(dir_ent->d_name, ".") || 00171 !strcmp(dir_ent->d_name, ".."))) 00172 00173 retlist.push_back(prefix_path ? join_pathes(path, dir_ent->d_name) : dir_ent->d_name); 00174 00175 closedir(dir); 00176 00177 return retlist; 00178 } 00179 00180 00181 00182 std::string degate::join_pathes(std::string const& base_path, std::string const& extension_path) { 00183 return base_path + std::string("/") + extension_path; 00184 } 00185 00186 00187 std::string degate::get_filename_from_path(std::string const& path) { 00188 size_t last_occurance = path.rfind("/", path.size()); 00189 if(last_occurance < path.size()) { 00190 return path.substr(last_occurance + 1, path.size() - last_occurance); 00191 } 00192 else return path; 00193 } 00194 00195 std::string degate::get_basename(std::string const& path) { 00196 std::string filename(get_filename_from_path(path)); 00197 00198 size_t last_occurance = filename.rfind(".", filename.size()); 00199 if(last_occurance < filename.size()) 00200 return filename.substr(0, last_occurance); 00201 else return filename; 00202 } 00203 00204 00205 // a copy from qemu 00206 00207 char *realpath_alloc(const char *path) 00208 { 00209 int buff_len; 00210 char *result; 00211 00212 #ifdef PATH_MAX 00213 buff_len = PATH_MAX; 00214 #else 00215 buff_len = pathconf(path, _PC_PATH_MAX); 00216 if (buff_len <= 0) 00217 buff_len = 4096; 00218 #endif 00219 00220 ++buff_len; 00221 result = (char*)malloc(buff_len * sizeof(char)); 00222 if (!result) 00223 return NULL; 00224 00225 if(realpath(path, result) == NULL) { 00226 free(result); 00227 return NULL; 00228 } 00229 else return result; 00230 } 00231 00232 00233 char * _get_relative_path(const char * const path, const char * const relative_to) { 00234 char *path_real; 00235 char *path_prefix; 00236 char *path_real_suffix; 00237 char *path_real_to; 00238 char *path_real_to_suffix; 00239 char *result; 00240 int prefix_len, i, slash_count; 00241 char *string_end; 00242 char path_separator; 00243 #ifdef _WIN32 00244 path_separator = '\\'; 00245 #else 00246 path_separator = '/'; 00247 #endif 00248 00249 if (NULL == path || NULL == relative_to) 00250 return NULL; 00251 00252 path_real = realpath_alloc(path); 00253 if (!path_real) 00254 return NULL; 00255 path_real_to = realpath_alloc(relative_to); 00256 if (!path_real_to) 00257 { 00258 free(path_real); 00259 return NULL; 00260 } 00261 00262 if (0 == strcmp(path_real, path_real_to)) 00263 { 00264 free(path_real); 00265 free(path_real_to); 00266 00267 //the two directories are equal, the relative path is an empty string 00268 result = (char*)malloc(sizeof(char)); 00269 *result = '\0'; 00270 return result; 00271 } 00272 00273 result = NULL; 00274 00275 //eliminate the common prefix 00276 for (prefix_len = 0; 00277 path_real[prefix_len] != '\0' && 00278 path_real_to[prefix_len] != '\0' && 00279 path_real[prefix_len] == path_real_to[prefix_len]; 00280 ++prefix_len); 00281 00282 path_prefix = path_real; 00283 path_real_suffix = path_real + prefix_len; 00284 while ('\0' != *path_real_suffix && 00285 #ifdef _WIN32 00286 ('/' == *path_real_suffix || '\\' == *path_real_suffix) 00287 #else 00288 ('/' == *path_real_suffix) 00289 #endif 00290 ) { *path_real_suffix++ = '\0'; } 00291 00292 path_real_to_suffix = path_real_to + prefix_len; 00293 while ('\0' != *path_real_to_suffix && 00294 #ifdef _WIN32 00295 ('/' == *path_real_to_suffix || '\\' == *path_real_to_suffix) 00296 #else 00297 ('/' == *path_real_to_suffix) 00298 #endif 00299 ) { *path_real_to_suffix++ = '\0'; } 00300 00301 slash_count = 0; 00302 for (i = 0; '\0' != path_real_to_suffix[i]; ++i) 00303 #ifdef _WIN32 00304 if ('/' == path_real_to_suffix[i] || '\\' == path_real_to_suffix[i]) 00305 #else 00306 if ('/' == path_real_to_suffix[i]) 00307 #endif 00308 ++slash_count; 00309 if ('\0' != *path_real_to_suffix) ++slash_count; 00310 result = (char*)malloc(sizeof(char) * (4 + 3 * slash_count + strlen(path_real_suffix))); 00311 00312 string_end = result; 00313 for (i = 0; i < slash_count; ++i) 00314 { 00315 if (i > 0) 00316 *string_end++ = path_separator; 00317 *string_end++ = '.'; 00318 *string_end++ = '.'; 00319 } 00320 if (0 == slash_count) 00321 *string_end++ = '.'; 00322 if ('\0' != *path_real_suffix) 00323 { 00324 *string_end++ = path_separator; 00325 for (i = 0; '\0' != path_real_suffix[i]; ++i) 00326 *string_end++ = path_real_suffix[i]; 00327 } 00328 *string_end++ = '\0'; 00329 00330 free(path_real); 00331 free(path_real_to); 00332 return result; 00333 } 00334 00335 std::string degate::get_relative_path(std::string const& path, 00336 std::string const& relative_to) { 00337 00338 //boost::format fmter("\npath=%1%\nrelative_to=%2%"); 00339 //fmter % path % relative_to; 00340 //std::cout << fmter.str() << std::endl; 00341 00342 char * rel_path = _get_relative_path(path.c_str(), relative_to.c_str()); 00343 00344 std::string ret(rel_path); 00345 00346 //std::cout << "rel_path=" << ret << std::endl; 00347 00348 free(rel_path); 00349 return ret; 00350 } 00351 00352 00353 00354 boost::filesystem::path degate::strip_path(boost::filesystem::path const& strip_from, 00355 boost::filesystem::path const& strip_what) { 00356 00357 path::iterator src_path_iter = strip_what.begin(); 00358 path::iterator src_path_end = strip_what.end(); 00359 path stripped; 00360 00361 BOOST_FOREACH(path s, strip_from) { 00362 if(src_path_iter != src_path_end && *src_path_iter == s) 00363 ++src_path_iter; 00364 else 00365 stripped /= s; 00366 } 00367 00368 return stripped; 00369 }
1.7.4