611 lines
17 KiB
C++
611 lines
17 KiB
C++
/*
|
||
PIP - Platform Independent Primitives
|
||
File
|
||
Ivan Pelipenko peri4ko@yandex.ru
|
||
|
||
This program is free software: you can redistribute it and/or modify
|
||
it under the terms of the GNU Lesser General Public License as published by
|
||
the Free Software Foundation, either version 3 of the License, or
|
||
(at your option) any later version.
|
||
|
||
This program is distributed in the hope that it will be useful,
|
||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
GNU Lesser General Public License for more details.
|
||
|
||
You should have received a copy of the GNU Lesser General Public License
|
||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||
*/
|
||
|
||
#include "piincludes_p.h"
|
||
#include "pifile.h"
|
||
#include "pidir.h"
|
||
#include "piiostream.h"
|
||
#include "pitime_win.h"
|
||
#ifdef WINDOWS
|
||
# undef S_IFDIR
|
||
# undef S_IFREG
|
||
# undef S_IFLNK
|
||
# undef S_IFBLK
|
||
# undef S_IFCHR
|
||
# undef S_IFSOCK
|
||
# define S_IFDIR 0x01
|
||
# define S_IFREG 0x02
|
||
# define S_IFLNK 0x04
|
||
# define S_IFBLK 0x08
|
||
# define S_IFCHR 0x10
|
||
# define S_IFSOCK 0x20
|
||
#else
|
||
# include <sys/stat.h>
|
||
# include <sys/time.h>
|
||
# include <fcntl.h>
|
||
# include <utime.h>
|
||
#endif
|
||
#define S_IFHDN 0x40
|
||
#if defined(QNX) || defined(ANDROID) || defined(FREERTOS)
|
||
# define _fopen_call_ fopen
|
||
# define _fseek_call_ fseek
|
||
# define _ftell_call_ ftell
|
||
# define _stat_struct_ struct stat
|
||
# define _stat_call_ stat
|
||
# define _stat_link_ lstat
|
||
#else
|
||
# if defined(MAC_OS)
|
||
# define _fopen_call_ fopen
|
||
# define _fseek_call_ fseek
|
||
# define _ftell_call_ ftell
|
||
# else
|
||
# ifdef CC_GCC
|
||
# define _fopen_call_ fopen64
|
||
# define _fseek_call_ fseeko64
|
||
# define _ftell_call_ ftello64
|
||
# else
|
||
# define _fopen_call_ fopen
|
||
# define _fseek_call_ fseek
|
||
# define _ftell_call_ ftell
|
||
# endif
|
||
# endif
|
||
# define _stat_struct_ struct stat64
|
||
# define _stat_call_ stat64
|
||
# define _stat_link_ lstat64
|
||
#endif
|
||
|
||
|
||
//! \class PIFile pifile.h
|
||
//! \details
|
||
//! \~english \section PIFile_sec0 Synopsis
|
||
//! \~russian \section PIFile_sec0 Краткий обзор
|
||
//! \~english
|
||
//!
|
||
//! This class provide access to local file. You can manipulate
|
||
//! binary content or use this class as text stream. To binary
|
||
//! access there are function \a read(), \a write(), and many
|
||
//! \a writeBinary() functions. For write and read variables to file in
|
||
//! their text representation there are many "<<" and ">>" operators.
|
||
//!
|
||
//! \~russian
|
||
//! Этот класс предоставляет доступ к локальному файлу. Можно
|
||
//! работать на байтовом уровне, либо использовать его как
|
||
//! текстовый поток. Для байтового доступа используются методы
|
||
//! \a read(), \a write(), и много \a writeBinary() методов.
|
||
//! Для записи и чтения переменных в текстовом представлении
|
||
//! используются операторы "<<" и ">>".
|
||
//!
|
||
//! \~english \section PIFile_sec1 Position
|
||
//! \~russian \section PIFile_sec1 Позиция
|
||
//! \~english
|
||
//! Each opened file has a read/write position - logical position
|
||
//! in the file content you read from or you write to. You can
|
||
//! find out current position with function \a pos(). Function
|
||
//! \a seek(llong position) move position to position "position",
|
||
//! \a seekToBegin() move position to the begin of file,
|
||
//! \a seekToEnd() move position to the end of file.
|
||
//!
|
||
//! \~russian
|
||
//! Каждый файл имеет позицию чтения/записи - логическое положение
|
||
//! в содержимом файла, откуда производится чтение или запись.
|
||
//! Узнать текущую позицию можно с помощью метода \a pos().
|
||
//! Метод \a seek(llong position) перемещает позицию на указанную,
|
||
//! \a seekToBegin() перемещает её в начало файла, а \a seekToEnd() - в конец.
|
||
//!
|
||
|
||
REGISTER_DEVICE(PIFile)
|
||
|
||
PRIVATE_DEFINITION_START(PIFile)
|
||
FILE * fd = nullptr;
|
||
PRIVATE_DEFINITION_END(PIFile)
|
||
|
||
|
||
PIString PIFile::FileInfo::name() const {
|
||
if (path.isEmpty()) return PIString();
|
||
return path.mid(path.findLast(PIDir::separator) + 1);
|
||
}
|
||
|
||
|
||
PIString PIFile::FileInfo::baseName() const {
|
||
if (path.isEmpty()) return PIString();
|
||
PIString n = name(), e = extension();
|
||
if (e.isEmpty()) return n;
|
||
return n.cutRight(e.size_s() + 1);
|
||
}
|
||
|
||
|
||
PIString PIFile::FileInfo::extension() const {
|
||
PIString n = name();
|
||
if (n.isEmpty()) return PIString();
|
||
while (n.startsWith("."))
|
||
n.pop_front();
|
||
if (n.isEmpty()) return PIString();
|
||
int i = n.findLast(".");
|
||
if (i < 0) return PIString();
|
||
return n.mid(i + 1);
|
||
}
|
||
|
||
|
||
PIString PIFile::FileInfo::dir() const {
|
||
if (path.isEmpty()) return PIString();
|
||
int ind = path.findLast(PIDir::separator);
|
||
PIString ret;
|
||
if (ind >= 0) ret = path.mid(0, ind);
|
||
if (ret.isEmpty()) ret = ".";
|
||
return ret + PIDir::separator;
|
||
}
|
||
|
||
|
||
|
||
|
||
PIFile::PIFile(): PIIODevice() {
|
||
}
|
||
|
||
|
||
PIFile::PIFile(const PIString & path, PIIODevice::DeviceMode mode): PIIODevice(path, mode) {
|
||
if (!path.isEmpty()) open();
|
||
}
|
||
|
||
|
||
bool PIFile::openTemporary(PIIODevice::DeviceMode mode) {
|
||
PIString tp;
|
||
#ifdef WINDOWS
|
||
tp = PIDir::temporary().path() + PIDir::separator + "file" + PIString::fromNumber(randomi());
|
||
#else
|
||
char * rc = tmpnam(0);
|
||
if (!rc) return false;
|
||
tp = rc;
|
||
#endif
|
||
while (isExists(tp)) {
|
||
tp += PIString::fromNumber(randomi() % 10);
|
||
}
|
||
return open(tp, mode);
|
||
}
|
||
|
||
|
||
PIFile::~PIFile() {
|
||
stop();
|
||
close();
|
||
}
|
||
|
||
|
||
bool PIFile::openDevice() {
|
||
close();
|
||
PIString p = path();
|
||
if (p.isEmpty()) return false;
|
||
if ((mode_ & PIIODevice::WriteOnly) == PIIODevice::WriteOnly) {
|
||
if (!isExists(p)) {
|
||
FILE * fd = fopen(p.data(), "w");
|
||
if (fd != 0) fclose(fd);
|
||
}
|
||
}
|
||
PRIVATE->fd = _fopen_call_(p.data(), strType(mode_).data());
|
||
//piCout << "fopen " << path() << ": " << strType(mode_).data() << PRIVATE->fd;
|
||
bool opened = (PRIVATE->fd != 0);
|
||
if (opened) {
|
||
fdi = fileno(PRIVATE->fd);
|
||
#ifndef WINDOWS
|
||
fcntl(fdi, F_SETFL, O_NONBLOCK);
|
||
#endif
|
||
if (mode_ == PIIODevice::ReadOnly) {
|
||
_fseek_call_(PRIVATE->fd, 0, SEEK_END);
|
||
_size = _ftell_call_(PRIVATE->fd);
|
||
}
|
||
_fseek_call_(PRIVATE->fd, 0, SEEK_SET);
|
||
clearerr(PRIVATE->fd);
|
||
}
|
||
//piCout << "open file" << PRIVATE->fd << opened_;
|
||
return opened;
|
||
}
|
||
|
||
|
||
bool PIFile::closeDevice() {
|
||
//piCout << "close file" << PRIVATE->fd << opened_;
|
||
if (isClosed() || PRIVATE->fd == 0) return true;
|
||
bool cs = (fclose(PRIVATE->fd) == 0);
|
||
if (cs) PRIVATE->fd = 0;
|
||
fdi = -1;
|
||
_size = -1;
|
||
//piCout << "closed file" << PRIVATE->fd << opened_;
|
||
return cs;
|
||
}
|
||
|
||
|
||
llong PIFile::readAll(void * data) {
|
||
llong cp = pos(), s = size(), i = -1;
|
||
seekToBegin();
|
||
if (s < 0) {
|
||
while (!isEnd())
|
||
read(&(((char*)data)[++i]), 1);
|
||
} else
|
||
read((char * )data, s);
|
||
seek(cp);
|
||
return s;
|
||
}
|
||
|
||
|
||
PIByteArray PIFile::readAll(bool forceRead) {
|
||
PIByteArray a;
|
||
llong cp = pos();
|
||
if (forceRead) {
|
||
seekToBegin();
|
||
while (!isEnd())
|
||
a.push_back(readChar());
|
||
seek(cp);
|
||
return a;
|
||
}
|
||
llong s = size();
|
||
if (s < 0) return a;
|
||
a.resize(s);
|
||
seekToBegin();
|
||
fread(a.data(), 1, s, PRIVATE->fd);
|
||
seek(cp);
|
||
if (s >= 0) a.resize(s);
|
||
return a;
|
||
}
|
||
|
||
|
||
llong PIFile::size() const {
|
||
if (isClosed()) return -1;
|
||
llong s, cp = pos();
|
||
_fseek_call_(PRIVATE->fd, 0, SEEK_END); clearerr(PRIVATE->fd);
|
||
s = pos();
|
||
_fseek_call_(PRIVATE->fd, cp, SEEK_SET); clearerr(PRIVATE->fd);
|
||
return s;
|
||
}
|
||
|
||
|
||
void PIFile::resize(llong new_size, uchar fill_) {
|
||
llong ds = new_size - size();
|
||
if (ds == 0) return;
|
||
if (ds > 0) {
|
||
uchar * buff = new uchar[ds];
|
||
memset(buff, fill_, ds);
|
||
write(buff, ds);
|
||
delete[] buff;
|
||
return;
|
||
}
|
||
if (new_size == 0) {
|
||
clear();
|
||
return;
|
||
}
|
||
piCoutObj << "Downsize is not supported yet :-(";
|
||
}
|
||
|
||
|
||
|
||
bool PIFile::isExists(const PIString & path) {
|
||
FILE * f = _fopen_call_(PIString(path).data(), "r");
|
||
bool ok = (f != 0);
|
||
if (ok) fclose(f);
|
||
return ok;
|
||
}
|
||
|
||
|
||
bool PIFile::remove(const PIString & path) {
|
||
#ifdef WINDOWS
|
||
if (PIDir::isExists(path))
|
||
return RemoveDirectory(path.data()) > 0;
|
||
else
|
||
#endif
|
||
return ::remove(path.data()) == 0;
|
||
}
|
||
|
||
|
||
bool PIFile::rename(const PIString & from, const PIString & to) {
|
||
return ::rename(from.data(), to.data()) == 0;
|
||
}
|
||
|
||
|
||
PIString PIFile::constructFullPathDevice() const {
|
||
return path();
|
||
}
|
||
|
||
|
||
void PIFile::configureFromFullPathDevice(const PIString & full_path) {
|
||
setPath(full_path);
|
||
}
|
||
|
||
|
||
PIPropertyStorage PIFile::constructVariantDevice() const {
|
||
PIPropertyStorage ret;
|
||
PIVariantTypes::File f;
|
||
f.file = path();
|
||
ret.addProperty("path", f);
|
||
return ret;
|
||
}
|
||
|
||
|
||
void PIFile::configureFromVariantDevice(const PIPropertyStorage & d) {
|
||
setPath(d.propertyValueByName("path").toString());
|
||
}
|
||
|
||
|
||
PIString PIFile::strType(const PIIODevice::DeviceMode type) {
|
||
switch (type) {
|
||
case PIIODevice::ReadOnly: return "rb";
|
||
case PIIODevice::ReadWrite:
|
||
case PIIODevice::WriteOnly: return "r+b";
|
||
}
|
||
return "rb";
|
||
}
|
||
|
||
|
||
void PIFile::flush() {
|
||
if (isOpened()) fflush(PRIVATE->fd);
|
||
}
|
||
|
||
|
||
void PIFile::seek(llong position) {
|
||
if (isClosed()) return;
|
||
if (position == pos()) return;
|
||
_fseek_call_(PRIVATE->fd, position, SEEK_SET);
|
||
clearerr(PRIVATE->fd);
|
||
}
|
||
|
||
|
||
void PIFile::seekToBegin() {
|
||
if (isClosed()) return;
|
||
_fseek_call_(PRIVATE->fd, 0, SEEK_SET);
|
||
clearerr(PRIVATE->fd);
|
||
}
|
||
|
||
|
||
void PIFile::seekToEnd() {
|
||
if (isClosed()) return;
|
||
_fseek_call_(PRIVATE->fd, 0, SEEK_END);
|
||
clearerr(PRIVATE->fd);
|
||
}
|
||
|
||
|
||
void PIFile::seekToLine(llong line) {
|
||
if (isClosed()) return;
|
||
seekToBegin();
|
||
PIIOTextStream ts(this);
|
||
piForTimes (line) ts.readLine();
|
||
clearerr(PRIVATE->fd);
|
||
}
|
||
|
||
|
||
void PIFile::skip(llong bytes) {
|
||
if (isClosed() || (bytes == 0)) return;
|
||
_fseek_call_(PRIVATE->fd, bytes, SEEK_CUR);
|
||
}
|
||
|
||
|
||
char PIFile::readChar() {
|
||
return (char)fgetc(PRIVATE->fd);
|
||
}
|
||
|
||
|
||
void PIFile::setPath(const PIString & path) {
|
||
PIIODevice::setPath(path);
|
||
if (isOpened()) open();
|
||
}
|
||
|
||
|
||
llong PIFile::pos() const {
|
||
if (isClosed()) return -1;
|
||
return _ftell_call_(PRIVATE->fd);
|
||
}
|
||
|
||
|
||
bool PIFile::isEnd() const {
|
||
if (isClosed()) return true;
|
||
bool ret = (feof(PRIVATE->fd) || ferror(PRIVATE->fd));
|
||
if (!ret && (_size >= 0)) {
|
||
if (pos() > _size)
|
||
ret = true;
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
|
||
PIFile & PIFile::put(const PIByteArray & v) {
|
||
int sz = (int)v.size_s();
|
||
write(createMemoryBlock(&sz));
|
||
write(v);
|
||
return *this;
|
||
}
|
||
|
||
|
||
PIByteArray PIFile::get() {
|
||
PIByteArray ret;
|
||
int sz(0);
|
||
read(createMemoryBlock(&sz));
|
||
if (sz > 0) {
|
||
ret.resize(sz);
|
||
read(ret.data(), sz);
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
|
||
ssize_t PIFile::readDevice(void * read_to, ssize_t max_size) {
|
||
if (!canRead() || PRIVATE->fd == 0) return -1;
|
||
ssize_t ret = fread(read_to, 1, max_size, PRIVATE->fd);
|
||
return ret;
|
||
}
|
||
|
||
|
||
ssize_t PIFile::writeDevice(const void * data, ssize_t max_size) {
|
||
if (!canWrite() || PRIVATE->fd == 0) return -1;
|
||
return fwrite(data, 1, max_size, PRIVATE->fd);
|
||
}
|
||
|
||
|
||
void PIFile::clear() {
|
||
close();
|
||
PRIVATE->fd = fopen(path().data(), "w");
|
||
if (PRIVATE->fd != 0) fclose(PRIVATE->fd);
|
||
PRIVATE->fd = 0;
|
||
opened_ = false;
|
||
open();
|
||
}
|
||
|
||
|
||
void PIFile::remove() {
|
||
close();
|
||
::remove(path().data());
|
||
}
|
||
|
||
|
||
|
||
|
||
PIFile::FileInfo PIFile::fileInfo(const PIString & path) {
|
||
FileInfo ret;
|
||
if (path.isEmpty()) return ret;
|
||
ret.path = path.replacedAll("\\", PIDir::separator);
|
||
PIString n = ret.name();
|
||
//piCout << "open" << path;
|
||
#ifdef WINDOWS
|
||
DWORD attr = GetFileAttributes((LPCTSTR)(path.data()));
|
||
if (attr == 0xFFFFFFFF) return ret;
|
||
HANDLE hFile = 0;
|
||
if ((attr & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY) {
|
||
hFile = CreateFile(path.data(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
||
} else {
|
||
hFile = CreateFile(path.data(), GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
|
||
}
|
||
if (!hFile) return ret;
|
||
BY_HANDLE_FILE_INFORMATION fi;
|
||
memset(&fi, 0, sizeof(fi));
|
||
if (GetFileInformationByHandle(hFile, &fi) != 0) {
|
||
LARGE_INTEGER filesize;
|
||
filesize.LowPart = filesize.HighPart = 0;
|
||
if (fi.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) ret.flags |= FileInfo::Hidden;
|
||
if (fi.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ret.flags |= FileInfo::Dir;
|
||
else {
|
||
ret.flags |= FileInfo::File;
|
||
filesize.LowPart = fi.nFileSizeLow;
|
||
filesize.HighPart = fi.nFileSizeHigh;
|
||
}
|
||
PIString ext = ret.extension();
|
||
ret.perm_user = FileInfo::Permissions(true, (attr & FILE_ATTRIBUTE_READONLY) != FILE_ATTRIBUTE_READONLY, ext == "bat" || ext == "exe");
|
||
ret.perm_group = ret.perm_other = ret.perm_user;
|
||
ret.size = filesize.QuadPart;
|
||
ret.time_access = FILETIME2PIDateTime(fi.ftLastAccessTime);
|
||
ret.time_modification = FILETIME2PIDateTime(fi.ftLastWriteTime);
|
||
}
|
||
CloseHandle(hFile);
|
||
#else
|
||
_stat_struct_ fs;
|
||
memset(&fs, 0, sizeof(fs));
|
||
_stat_call_(path.data(), &fs);
|
||
int mode = fs.st_mode;
|
||
ret.size = fs.st_size;
|
||
ret.id_user = fs.st_uid;
|
||
ret.id_group = fs.st_gid;
|
||
#ifdef ANDROID
|
||
ret.time_access = PIDateTime::fromSystemTime(PISystemTime(fs.st_atime, fs.st_atime_nsec));
|
||
ret.time_modification = PIDateTime::fromSystemTime(PISystemTime(fs.st_mtime, fs.st_mtime_nsec));
|
||
#else
|
||
# if defined(QNX) || defined(FREERTOS)
|
||
ret.time_access = PIDateTime::fromSecondSinceEpoch(fs.st_atime);
|
||
ret.time_modification = PIDateTime::fromSecondSinceEpoch(fs.st_mtime);
|
||
# else
|
||
# ifdef MAC_OS
|
||
# define ATIME st_atimespec
|
||
# define MTIME st_ctimespec
|
||
# else
|
||
# define ATIME st_atim
|
||
# define MTIME st_mtim
|
||
# endif
|
||
ret.time_access = PIDateTime::fromSystemTime(PISystemTime(fs.ATIME.tv_sec, fs.ATIME.tv_nsec));
|
||
ret.time_modification = PIDateTime::fromSystemTime(PISystemTime(fs.MTIME.tv_sec, fs.MTIME.tv_nsec));
|
||
# endif
|
||
#endif
|
||
#ifndef MICRO_PIP
|
||
ret.perm_user = FileInfo::Permissions((mode & S_IRUSR) == S_IRUSR, (mode & S_IWUSR) == S_IWUSR, (mode & S_IXUSR) == S_IXUSR);
|
||
ret.perm_group = FileInfo::Permissions((mode & S_IRGRP) == S_IRGRP, (mode & S_IWGRP) == S_IWGRP, (mode & S_IXGRP) == S_IXGRP);
|
||
ret.perm_other = FileInfo::Permissions((mode & S_IROTH) == S_IROTH, (mode & S_IWOTH) == S_IWOTH, (mode & S_IXOTH) == S_IXOTH);
|
||
memset(&fs, 0, sizeof(fs));
|
||
_stat_link_(path.data(), &fs);
|
||
mode &= ~S_IFLNK;
|
||
mode |= S_IFLNK & fs.st_mode;
|
||
if (n.startsWith(".")) mode |= S_IFHDN;
|
||
if ((mode & S_IFDIR) == S_IFDIR) ret.flags |= FileInfo::Dir;
|
||
if ((mode & S_IFREG) == S_IFREG) ret.flags |= FileInfo::File;
|
||
if ((mode & S_IFLNK) == S_IFLNK) ret.flags |= FileInfo::SymbolicLink;
|
||
if ((mode & S_IFHDN) == S_IFHDN) ret.flags |= FileInfo::Hidden;
|
||
#endif
|
||
#endif
|
||
if (n == ".") ret.flags = FileInfo::Dir | FileInfo::Dot;
|
||
if (n == "..") ret.flags = FileInfo::Dir | FileInfo::DotDot;
|
||
return ret;
|
||
}
|
||
|
||
|
||
bool PIFile::applyFileInfo(const PIString & path, const PIFile::FileInfo & info) {
|
||
if (path.isEmpty()) return false;
|
||
PIString fp(path);
|
||
if (fp.endsWith(PIDir::separator)) fp.pop_back();
|
||
#ifdef WINDOWS
|
||
DWORD attr = GetFileAttributes((LPCTSTR)(path.data()));
|
||
if (attr == 0xFFFFFFFF) return false;
|
||
attr &= ~(FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_READONLY);
|
||
if (info.isHidden()) attr |= FILE_ATTRIBUTE_HIDDEN;
|
||
if (!info.perm_user.write) attr |= FILE_ATTRIBUTE_READONLY;
|
||
if (SetFileAttributes((LPCTSTR)(fp.data()), attr) == 0) {
|
||
piCout << "[PIFile] applyFileInfo: \"SetFileAttributes\" error:" << errorString();
|
||
}
|
||
HANDLE hFile = 0;
|
||
if ((attr & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY) {
|
||
hFile = CreateFile(path.data(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
|
||
} else {
|
||
hFile = CreateFile(path.data(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, 0, OPEN_EXISTING, 0, 0);
|
||
}
|
||
if (!hFile) return false;
|
||
FILETIME atime = PIDateTime2FILETIME(info.time_access), mtime = PIDateTime2FILETIME(info.time_modification);
|
||
if (SetFileTime(hFile, 0, &atime, &mtime) == 0) {
|
||
piCout << "[PIFile] applyFileInfo: \"SetFileTime\" error:" << errorString();
|
||
return false;
|
||
}
|
||
CloseHandle(hFile);
|
||
#else
|
||
int mode(0);
|
||
if (info.perm_user.read) mode |= S_IRUSR;
|
||
if (info.perm_user.write) mode |= S_IWUSR;
|
||
if (info.perm_user.exec) mode |= S_IXUSR;
|
||
if (info.perm_group.read) mode |= S_IRGRP;
|
||
if (info.perm_group.write) mode |= S_IWGRP;
|
||
if (info.perm_group.exec) mode |= S_IXGRP;
|
||
if (info.perm_other.read) mode |= S_IROTH;
|
||
if (info.perm_other.write) mode |= S_IWOTH;
|
||
if (info.perm_other.exec) mode |= S_IXOTH;
|
||
if (chmod(fp.data(), mode) != 0) {
|
||
piCout << "[PIFile] applyFileInfo: \"chmod\" error:" << errorString();
|
||
}
|
||
if (chown(fp.data(), info.id_user, info.id_group) != 0) {
|
||
piCout << "[PIFile] applyFileInfo: \"chown\" error:" << errorString();
|
||
}
|
||
struct timeval tm[2];
|
||
PISystemTime st = info.time_access.toSystemTime();
|
||
tm[0].tv_sec = st.seconds;
|
||
tm[0].tv_usec = st.nanoseconds / 1000;
|
||
st = info.time_modification.toSystemTime();
|
||
tm[1].tv_sec = st.seconds;
|
||
tm[1].tv_usec = st.nanoseconds / 1000;
|
||
if (utimes(fp.data(), tm) != 0) {
|
||
piCout << "[PIFile] applyFileInfo: \"utimes\" error:" << errorString();
|
||
}
|
||
#endif
|
||
return true;
|
||
}
|