255 lines
7.1 KiB
C++
255 lines
7.1 KiB
C++
// Copyright (C) 2003 Davis E. King (davis@dlib.net)
|
|
// License: Boost Software License See LICENSE.txt for the full license.
|
|
#ifndef DLIB_DIR_NAV_KERNEL_2_CPp_
|
|
#define DLIB_DIR_NAV_KERNEL_2_CPp_
|
|
|
|
#include "../platform.h"
|
|
|
|
#ifdef POSIX
|
|
|
|
|
|
#include "dir_nav_kernel_2.h"
|
|
|
|
|
|
|
|
|
|
|
|
namespace dlib
|
|
{
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
// ----------------------------------------------------------------------------------------
|
|
// file object implementation
|
|
// ----------------------------------------------------------------------------------------
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
void file::
|
|
init (
|
|
const std::string& name
|
|
)
|
|
{
|
|
using namespace std;
|
|
|
|
|
|
|
|
char buf[PATH_MAX];
|
|
if (realpath(name.c_str(),buf) == 0)
|
|
{
|
|
// the file was not found
|
|
throw file_not_found("Unable to find file " + name);
|
|
}
|
|
state.full_name = buf;
|
|
|
|
|
|
string::size_type pos = state.full_name.find_last_of(directory::get_separator());
|
|
if (pos == string::npos)
|
|
{
|
|
// no valid full path has no separtor characters.
|
|
throw file_not_found("Unable to find file " + name);
|
|
}
|
|
state.name = state.full_name.substr(pos+1);
|
|
|
|
|
|
// now find the size of this file
|
|
struct stat64 buffer;
|
|
if (::stat64(state.full_name.c_str(), &buffer) ||
|
|
S_ISDIR(buffer.st_mode))
|
|
{
|
|
// there was an error during the call to stat64 or
|
|
// name is actually a directory
|
|
throw file_not_found("Unable to find file " + name);
|
|
}
|
|
else
|
|
{
|
|
state.file_size = static_cast<uint64>(buffer.st_size);
|
|
|
|
|
|
state.last_modified = std::chrono::system_clock::from_time_t(buffer.st_mtime);
|
|
#ifdef _BSD_SOURCE
|
|
state.last_modified += std::chrono::duration_cast<std::chrono::system_clock::duration>(std::chrono::nanoseconds(buffer.st_atim.tv_nsec));
|
|
#endif
|
|
}
|
|
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
bool file::
|
|
operator == (
|
|
const file& rhs
|
|
) const
|
|
{
|
|
using namespace std;
|
|
if (state.full_name.size() == 0 && rhs.state.full_name.size() == 0)
|
|
return true;
|
|
|
|
// These files might have different names but actually represent the same
|
|
// file due to the presence of symbolic links.
|
|
char buf[PATH_MAX];
|
|
string left, right;
|
|
if (realpath(state.full_name.c_str(),buf) == 0)
|
|
return false;
|
|
left = buf;
|
|
|
|
if (realpath(rhs.state.full_name.c_str(),buf) == 0)
|
|
return false;
|
|
right = buf;
|
|
|
|
return (left == right);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
// ----------------------------------------------------------------------------------------
|
|
// directory object implementation
|
|
// ----------------------------------------------------------------------------------------
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
void directory::
|
|
init (
|
|
const std::string& name
|
|
)
|
|
{
|
|
using namespace std;
|
|
|
|
|
|
char buf[PATH_MAX];
|
|
if (realpath(name.c_str(),buf) == 0)
|
|
{
|
|
// the directory was not found
|
|
throw dir_not_found("Unable to find directory " + name);
|
|
}
|
|
state.full_name = buf;
|
|
|
|
|
|
const char sep = get_separator();
|
|
if (is_root_path(state.full_name) == false)
|
|
{
|
|
// ensure that thre is not a trialing separator
|
|
if (state.full_name[state.full_name.size()-1] == sep)
|
|
state.full_name.erase(state.full_name.size()-1);
|
|
|
|
// pick out the directory name
|
|
string::size_type pos = state.full_name.find_last_of(sep);
|
|
state.name = state.full_name.substr(pos+1);
|
|
}
|
|
else
|
|
{
|
|
// ensure that there is a trailing separator
|
|
if (state.full_name[state.full_name.size()-1] != sep)
|
|
state.full_name += sep;
|
|
}
|
|
|
|
|
|
struct stat64 buffer;
|
|
// now check that this is actually a valid directory
|
|
if (::stat64(state.full_name.c_str(),&buffer))
|
|
{
|
|
// the directory was not found
|
|
throw dir_not_found("Unable to find directory " + name);
|
|
}
|
|
else if (S_ISDIR(buffer.st_mode) == 0)
|
|
{
|
|
// It is not a directory
|
|
throw dir_not_found("Unable to find directory " + name);
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
char directory::
|
|
get_separator (
|
|
)
|
|
{
|
|
return '/';
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
bool directory::
|
|
operator == (
|
|
const directory& rhs
|
|
) const
|
|
{
|
|
using namespace std;
|
|
if (state.full_name.size() == 0 && rhs.state.full_name.size() == 0)
|
|
return true;
|
|
|
|
// These directories might have different names but actually represent the same
|
|
// directory due to the presence of symbolic links.
|
|
char buf[PATH_MAX];
|
|
string left, right;
|
|
if (realpath(state.full_name.c_str(),buf) == 0)
|
|
return false;
|
|
left = buf;
|
|
|
|
if (realpath(rhs.state.full_name.c_str(),buf) == 0)
|
|
return false;
|
|
right = buf;
|
|
|
|
return (left == right);
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
const directory directory::
|
|
get_parent (
|
|
) const
|
|
{
|
|
using namespace std;
|
|
// if *this is the root then just return *this
|
|
if (is_root())
|
|
{
|
|
return *this;
|
|
}
|
|
else
|
|
{
|
|
directory temp;
|
|
|
|
const char sep = get_separator();
|
|
|
|
string::size_type pos = state.full_name.find_last_of(sep);
|
|
temp.state.full_name = state.full_name.substr(0,pos);
|
|
|
|
if ( is_root_path(temp.state.full_name))
|
|
{
|
|
temp.state.full_name += sep;
|
|
}
|
|
else
|
|
{
|
|
pos = temp.state.full_name.find_last_of(sep);
|
|
if (pos != string::npos)
|
|
{
|
|
temp.state.name = temp.state.full_name.substr(pos+1);
|
|
}
|
|
else
|
|
{
|
|
temp.state.full_name += sep;
|
|
}
|
|
}
|
|
return temp;
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
bool directory::
|
|
is_root_path (
|
|
const std::string& path
|
|
) const
|
|
{
|
|
const char sep = get_separator();
|
|
if (path.size() == 1 && path[0] == sep)
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
}
|
|
|
|
#endif // POSIX
|
|
|
|
#endif // DLIB_DIR_NAV_KERNEL_2_CPp_
|
|
|