blob: 0d35acd35a9ffa2fafb72ed921dfdaefc2f2b76b [file] [log] [blame]
/**
* @file file_manip.cpp
* Useful file management helpers
*
* @remark Copyright 2002 OProfile authors
* @remark Read the file COPYING
*
* @author Philippe Elie
* @author John Levon
*/
#include <unistd.h>
#include <sys/stat.h>
#include <dirent.h>
#include <fnmatch.h>
#include <cstdio>
#include <cerrno>
#include <iostream>
#include <vector>
#include "op_file.h"
#include "file_manip.h"
#include "string_manip.h"
using namespace std;
bool copy_file(string const & source, string const & destination)
{
struct stat buf;
int status = stat(source.c_str(), &buf);
if (status == 0) {
/* FIXME: This code should avoid using system() if possible. */
string copy_command("cp -a -f " + source + " " + destination);
status = system(copy_command.c_str());
}
return !status;
}
bool is_directory(string const & dirname)
{
struct stat st;
return !stat(dirname.c_str(), &st) && S_ISDIR(st.st_mode);
}
bool is_files_identical(string const & file1, string const & file2)
{
struct stat st1;
struct stat st2;
if (stat(file1.c_str(), &st1) == 0 && stat(file2.c_str(), &st2) == 0) {
if (st1.st_dev == st2.st_dev && st1.st_ino == st2.st_ino)
return true;
}
return false;
}
string const op_realpath(string const & name)
{
static char tmp[PATH_MAX];
if (!realpath(name.c_str(), tmp))
return name;
return string(tmp);
}
bool op_file_readable(string const & file)
{
return op_file_readable(file.c_str());
}
inline static bool is_directory_name(char const * name)
{
return name[0] == '.' &&
(name[1] == '\0' ||
(name[1] == '.' && name[2] == '\0'));
}
bool create_file_list(list<string> & file_list, string const & base_dir,
string const & filter, bool recursive)
{
DIR * dir;
struct dirent * ent;
if (!(dir = opendir(base_dir.c_str())))
return false;
while ((ent = readdir(dir)) != 0) {
if (!is_directory_name(ent->d_name) &&
fnmatch(filter.c_str(), ent->d_name, 0) != FNM_NOMATCH) {
if (recursive) {
struct stat stat_buffer;
string name = base_dir + '/' + ent->d_name;
if (stat(name.c_str(), &stat_buffer) == 0) {
if (S_ISDIR(stat_buffer.st_mode) &&
!S_ISLNK(stat_buffer.st_mode)) {
// recursive retrieve
create_file_list(file_list,
name, filter,
recursive);
} else {
file_list.push_back(name);
}
}
} else {
file_list.push_back(ent->d_name);
}
}
}
closedir(dir);
return true;
}
/**
* @param path_name the path where we remove trailing '/'
*
* erase all trailing '/' in path_name except if the last '/' is at pos 0
*/
static string erase_trailing_path_separator(string const & path_name)
{
string result(path_name);
while (result.length() > 1) {
if (result[result.length() - 1] != '/')
break;
result.erase(result.length() - 1, 1);
}
return result;
}
string op_dirname(string const & file_name)
{
string result = erase_trailing_path_separator(file_name);
if (result.find_first_of('/') == string::npos)
return ".";
// catch result == "/"
if (result.length() == 1)
return result;
size_t pos = result.find_last_of('/');
// "/usr" must return "/"
if (pos == 0)
pos = 1;
result.erase(pos, result.length() - pos);
// "////usr" must return "/"
return erase_trailing_path_separator(result);
}
string op_basename(string const & path_name)
{
string result = erase_trailing_path_separator(path_name);
// catch result == "/"
if (result.length() == 1)
return result;
return erase_to_last_of(result, '/');
}