You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
287 lines
6.4 KiB
287 lines
6.4 KiB
// Copyright(C) 1999-2021, 2023 National Technology & Engineering Solutions
|
|
// of Sandia, LLC (NTESS). Under the terms of Contract DE-NA0003525 with
|
|
// NTESS, the U.S. Government retains certain rights in this software.
|
|
//
|
|
// See packages/seacas/LICENSE for details
|
|
|
|
#include <FileInfo.h>
|
|
#include <cstddef>
|
|
#include <cstring>
|
|
#include <string>
|
|
|
|
#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || \
|
|
defined(__MINGW32__) || defined(_WIN64) || defined(__MINGW64__)
|
|
#define __SUP_WINDOWS__ 1
|
|
#endif
|
|
|
|
#if defined(__SUP_WINDOWS__)
|
|
#include <direct.h>
|
|
#include <io.h>
|
|
#define access _access
|
|
#define R_OK 4 /* Test for read permission. */
|
|
#define W_OK 2 /* Test for write permission. */
|
|
#define X_OK 1 /* execute permission - unsupported in windows*/
|
|
#define F_OK 0 /* Test for existence. */
|
|
#ifndef S_ISREG
|
|
#define S_ISREG(m) (((m)&_S_IFMT) == _S_IFREG)
|
|
#define S_ISDIR(m) (((m)&_S_IFMT) == _S_IFDIR)
|
|
#endif
|
|
#else
|
|
#include <sys/unistd.h>
|
|
#endif
|
|
|
|
#include <cstdio>
|
|
#include <sys/stat.h>
|
|
#include <unistd.h>
|
|
|
|
namespace {
|
|
bool internal_access(const std::string &name, int mode);
|
|
bool do_stat(const std::string &filename, struct stat *s);
|
|
} // namespace
|
|
|
|
FileInfo::FileInfo() = default;
|
|
|
|
FileInfo::FileInfo(std::string my_filename) : filename_(std::move(my_filename))
|
|
{
|
|
readable_ = internal_access(filename_, R_OK);
|
|
exists_ = readable_ || internal_access(filename_, F_OK);
|
|
}
|
|
|
|
FileInfo::FileInfo(const char *my_filename) : filename_(std::string(my_filename))
|
|
{
|
|
readable_ = internal_access(filename_, R_OK);
|
|
exists_ = readable_ || internal_access(filename_, F_OK);
|
|
}
|
|
|
|
FileInfo::FileInfo(const FileInfo ©_from) = default;
|
|
|
|
FileInfo::FileInfo(const std::string &dirpath, const std::string &my_filename)
|
|
{
|
|
if (!dirpath.empty()) {
|
|
filename_ = dirpath;
|
|
if (filename_.at(filename_.size() - 1) != '/') {
|
|
static std::string SLASH("/");
|
|
filename_ += SLASH;
|
|
}
|
|
}
|
|
filename_ += my_filename;
|
|
readable_ = internal_access(filename_, R_OK);
|
|
exists_ = readable_ || internal_access(filename_, F_OK);
|
|
}
|
|
|
|
FileInfo::~FileInfo() = default;
|
|
|
|
//: Returns TRUE if the file exists (is readable)
|
|
bool FileInfo::exists() const { return exists_; }
|
|
|
|
//: Returns TRUE if the file is readable
|
|
bool FileInfo::is_readable() const { return readable_; }
|
|
|
|
//: Returns TRUE if the file is writable
|
|
bool FileInfo::is_writable() const { return internal_access(filename_, W_OK); }
|
|
|
|
//: Returns TRUE if the file is executable
|
|
bool FileInfo::is_executable() const { return internal_access(filename_, X_OK); }
|
|
|
|
//: Returns TRUE if we are pointing to a file or a symbolic link to
|
|
//: a file.
|
|
bool FileInfo::is_file() const
|
|
{
|
|
struct stat s
|
|
{
|
|
};
|
|
if (do_stat(filename_, &s)) {
|
|
return S_ISREG(s.st_mode);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//: Returns TRUE if we are pointing to a directory or a symbolic link to
|
|
//: a directory.
|
|
bool FileInfo::is_dir() const
|
|
{
|
|
struct stat s
|
|
{
|
|
};
|
|
if (do_stat(filename_, &s)) {
|
|
return S_ISDIR(s.st_mode);
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//: Returns TRUE if we are pointing to a symbolic link
|
|
bool FileInfo::is_symlink() const
|
|
{
|
|
#if !defined(__SUP_WINDOWS__)
|
|
struct stat s
|
|
{
|
|
};
|
|
if (lstat(filename_.c_str(), &s) == 0) {
|
|
return S_ISLNK(s.st_mode);
|
|
}
|
|
#endif
|
|
return false;
|
|
}
|
|
|
|
//: Time of last data modification. See 'man stat(2)'
|
|
time_t FileInfo::modified() const
|
|
{
|
|
struct stat s
|
|
{
|
|
};
|
|
if (do_stat(filename_, &s)) {
|
|
return s.st_mtime;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//: Time of last access
|
|
time_t FileInfo::accessed() const
|
|
{
|
|
struct stat s
|
|
{
|
|
};
|
|
if (do_stat(filename_, &s)) {
|
|
return s.st_atime;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//: Time of last status change. (creation, chmod, ...)
|
|
time_t FileInfo::created() const
|
|
{
|
|
struct stat s
|
|
{
|
|
};
|
|
if (do_stat(filename_, &s)) {
|
|
return s.st_ctime;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//: File size in bytes. Only if is_file() == true
|
|
off_t FileInfo::size() const
|
|
{
|
|
struct stat s
|
|
{
|
|
};
|
|
if (do_stat(filename_, &s)) {
|
|
return s.st_size;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//: Returns the filename
|
|
std::string FileInfo::filename() const { return filename_; }
|
|
|
|
//: Sets the filename
|
|
void FileInfo::set_filename(const std::string &name)
|
|
{
|
|
filename_ = name;
|
|
readable_ = internal_access(filename_, R_OK);
|
|
exists_ = readable_ || internal_access(filename_, F_OK);
|
|
}
|
|
|
|
//: Sets the filename
|
|
void FileInfo::set_filename(const char *name)
|
|
{
|
|
filename_ = std::string(name);
|
|
readable_ = internal_access(filename_, R_OK);
|
|
exists_ = readable_ || internal_access(filename_, F_OK);
|
|
}
|
|
|
|
//: Returns the filename extension or the empty string if there is
|
|
//: no extension. Assumes extension is all characters following the
|
|
//: last period.
|
|
std::string FileInfo::extension() const
|
|
{
|
|
size_t ind = filename_.find_last_of('.', std::string::npos);
|
|
size_t inds = filename_.find_last_of('/', std::string::npos);
|
|
|
|
// Protect against './filename' returning /filename as extension
|
|
if (ind != std::string::npos && (inds == std::string::npos || inds < ind)) {
|
|
return filename_.substr(ind + 1, filename_.size());
|
|
}
|
|
|
|
return std::string();
|
|
}
|
|
|
|
std::string FileInfo::pathname() const
|
|
{
|
|
size_t ind = filename_.find_last_of('/', filename_.size());
|
|
if (ind != std::string::npos) {
|
|
return filename_.substr(0, ind);
|
|
}
|
|
|
|
return std::string();
|
|
}
|
|
|
|
std::string FileInfo::tailname() const
|
|
{
|
|
size_t ind = filename_.find_last_of('/', filename_.size());
|
|
if (ind != std::string::npos) {
|
|
return filename_.substr(ind + 1, filename_.size());
|
|
}
|
|
|
|
return filename_; // No path, just return the filename
|
|
}
|
|
|
|
std::string FileInfo::basename() const
|
|
{
|
|
std::string tail = tailname();
|
|
|
|
// Strip off the extension
|
|
size_t ind = tail.find_last_of('.', tail.size());
|
|
if (ind != std::string::npos) {
|
|
return tail.substr(0, ind);
|
|
}
|
|
|
|
return tail;
|
|
}
|
|
|
|
std::string FileInfo::realpath() const
|
|
{
|
|
#if defined(__SUP_WINDOWS__)
|
|
char *path = _fullpath(nullptr, filename_.c_str(), _MAX_PATH);
|
|
#else
|
|
char *path = ::realpath(filename_.c_str(), nullptr);
|
|
#endif
|
|
if (path != nullptr) {
|
|
std::string temp(path);
|
|
free(path);
|
|
return temp;
|
|
}
|
|
{
|
|
return filename_;
|
|
}
|
|
}
|
|
|
|
bool FileInfo::remove_file()
|
|
{
|
|
int success = std::remove(filename_.c_str());
|
|
return success == 0;
|
|
}
|
|
|
|
namespace {
|
|
bool internal_access(const std::string &name, int mode)
|
|
{
|
|
if (name.empty()) {
|
|
return false;
|
|
}
|
|
if (::access(name.c_str(), mode) != 0) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool do_stat(const std::string &filename, struct stat *s)
|
|
{
|
|
return (stat(filename.c_str(), s) == 0);
|
|
}
|
|
} // namespace
|
|
|