file_manip.cpp revision cc2ee177dbb3befca43e36cfc56778b006c3d050
1/** 2 * @file file_manip.cpp 3 * Useful file management helpers 4 * 5 * @remark Copyright 2002 OProfile authors 6 * @remark Read the file COPYING 7 * 8 * @author Philippe Elie 9 * @author John Levon 10 */ 11 12#include <unistd.h> 13#include <sys/stat.h> 14#include <dirent.h> 15#include <fnmatch.h> 16 17#include <cstdio> 18#include <cerrno> 19#include <iostream> 20#include <vector> 21 22#include "op_file.h" 23 24#include "file_manip.h" 25#include "string_manip.h" 26 27using namespace std; 28 29 30bool copy_file(string const & source, string const & destination) 31{ 32 struct stat buf; 33 int status = stat(source.c_str(), &buf); 34 35 if (status == 0) { 36 /* FIXME: This code should avoid using system() if possible. */ 37 string copy_command("cp -a -f " + source + " " + destination); 38 status = system(copy_command.c_str()); 39 } 40 return !status; 41} 42 43 44bool is_directory(string const & dirname) 45{ 46 struct stat st; 47 return !stat(dirname.c_str(), &st) && S_ISDIR(st.st_mode); 48} 49 50 51bool is_files_identical(string const & file1, string const & file2) 52{ 53 struct stat st1; 54 struct stat st2; 55 56 if (stat(file1.c_str(), &st1) == 0 && stat(file2.c_str(), &st2) == 0) { 57 if (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino) 58 return true; 59 } 60 61 return false; 62} 63 64 65string const op_realpath(string const & name) 66{ 67 static char tmp[PATH_MAX]; 68 if (!realpath(name.c_str(), tmp)) 69 return name; 70 return string(tmp); 71} 72 73 74bool op_file_readable(string const & file) 75{ 76 return op_file_readable(file.c_str()); 77} 78 79inline static bool is_directory_name(char const * name) 80{ 81 return name[0] == '.' && 82 (name[1] == '\0' || 83 (name[1] == '.' && name[2] == '\0')); 84} 85 86 87bool create_file_list(list<string> & file_list, string const & base_dir, 88 string const & filter, bool recursive) 89{ 90 DIR * dir; 91 struct dirent * ent; 92 93 if (!(dir = opendir(base_dir.c_str()))) 94 return false; 95 96 while ((ent = readdir(dir)) != 0) { 97 if (!is_directory_name(ent->d_name) && 98 fnmatch(filter.c_str(), ent->d_name, 0) != FNM_NOMATCH) { 99 if (recursive) { 100 struct stat stat_buffer; 101 string name = base_dir + '/' + ent->d_name; 102 if (stat(name.c_str(), &stat_buffer) == 0) { 103 if (S_ISDIR(stat_buffer.st_mode) && 104 !S_ISLNK(stat_buffer.st_mode)) { 105 // recursive retrieve 106 create_file_list(file_list, 107 name, filter, 108 recursive); 109 } else { 110 file_list.push_back(name); 111 } 112 } 113 } else { 114 file_list.push_back(ent->d_name); 115 } 116 } 117 } 118 119 closedir(dir); 120 121 return true; 122} 123 124 125/** 126 * @param path_name the path where we remove trailing '/' 127 * 128 * erase all trailing '/' in path_name except if the last '/' is at pos 0 129 */ 130static string erase_trailing_path_separator(string const & path_name) 131{ 132 string result(path_name); 133 134 while (result.length() > 1) { 135 if (result[result.length() - 1] != '/') 136 break; 137 result.erase(result.length() - 1, 1); 138 } 139 140 return result; 141} 142 143 144string op_dirname(string const & file_name) 145{ 146 string result = erase_trailing_path_separator(file_name); 147 if (result.find_first_of('/') == string::npos) 148 return "."; 149 150 // catch result == "/" 151 if (result.length() == 1) 152 return result; 153 154 size_t pos = result.find_last_of('/'); 155 156 // "/usr" must return "/" 157 if (pos == 0) 158 pos = 1; 159 160 result.erase(pos, result.length() - pos); 161 162 // "////usr" must return "/" 163 return erase_trailing_path_separator(result); 164} 165 166 167string op_basename(string const & path_name) 168{ 169 string result = erase_trailing_path_separator(path_name); 170 171 // catch result == "/" 172 if (result.length() == 1) 173 return result; 174 175 return erase_to_last_of(result, '/'); 176} 177