mirror of
https://github.com/aaru-dps/Aaru.Compression.Native.git
synced 2025-12-16 19:24:31 +00:00
Update to lzma 23.01.
This commit is contained in:
357
3rdparty/lzma/CPP/Windows/FileDir.cpp
vendored
357
3rdparty/lzma/CPP/Windows/FileDir.cpp
vendored
@@ -5,6 +5,7 @@
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <unistd.h>
|
||||
@@ -16,7 +17,6 @@
|
||||
|
||||
#include "../Common/StringConvert.h"
|
||||
#include "../Common/C_FileIO.h"
|
||||
#include "TimeUtils.h"
|
||||
#endif
|
||||
|
||||
#include "FileDir.h"
|
||||
@@ -31,6 +31,30 @@ using namespace NWindows;
|
||||
using namespace NFile;
|
||||
using namespace NName;
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
static bool FiTime_To_timespec(const CFiTime *ft, timespec &ts)
|
||||
{
|
||||
if (ft)
|
||||
{
|
||||
ts = *ft;
|
||||
return true;
|
||||
}
|
||||
// else
|
||||
{
|
||||
ts.tv_sec = 0;
|
||||
ts.tv_nsec =
|
||||
#ifdef UTIME_OMIT
|
||||
UTIME_OMIT; // -2 keep old timesptamp
|
||||
#else
|
||||
// UTIME_NOW; -1 // set to the current time
|
||||
0;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace NWindows {
|
||||
namespace NFile {
|
||||
namespace NDir {
|
||||
@@ -41,51 +65,60 @@ namespace NDir {
|
||||
|
||||
bool GetWindowsDir(FString &path)
|
||||
{
|
||||
UINT needLength;
|
||||
const unsigned kBufSize = MAX_PATH + 16;
|
||||
UINT len;
|
||||
#ifndef _UNICODE
|
||||
if (!g_IsNT)
|
||||
{
|
||||
TCHAR s[MAX_PATH + 2];
|
||||
TCHAR s[kBufSize + 1];
|
||||
s[0] = 0;
|
||||
needLength = ::GetWindowsDirectory(s, MAX_PATH + 1);
|
||||
len = ::GetWindowsDirectory(s, kBufSize);
|
||||
path = fas2fs(s);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
WCHAR s[MAX_PATH + 2];
|
||||
WCHAR s[kBufSize + 1];
|
||||
s[0] = 0;
|
||||
needLength = ::GetWindowsDirectoryW(s, MAX_PATH + 1);
|
||||
len = ::GetWindowsDirectoryW(s, kBufSize);
|
||||
path = us2fs(s);
|
||||
}
|
||||
return (needLength > 0 && needLength <= MAX_PATH);
|
||||
return (len != 0 && len < kBufSize);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
new DOCs for GetSystemDirectory:
|
||||
returned path does not end with a backslash unless the
|
||||
system directory is the root directory.
|
||||
*/
|
||||
|
||||
bool GetSystemDir(FString &path)
|
||||
{
|
||||
UINT needLength;
|
||||
const unsigned kBufSize = MAX_PATH + 16;
|
||||
UINT len;
|
||||
#ifndef _UNICODE
|
||||
if (!g_IsNT)
|
||||
{
|
||||
TCHAR s[MAX_PATH + 2];
|
||||
TCHAR s[kBufSize + 1];
|
||||
s[0] = 0;
|
||||
needLength = ::GetSystemDirectory(s, MAX_PATH + 1);
|
||||
len = ::GetSystemDirectory(s, kBufSize);
|
||||
path = fas2fs(s);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
WCHAR s[MAX_PATH + 2];
|
||||
WCHAR s[kBufSize + 1];
|
||||
s[0] = 0;
|
||||
needLength = ::GetSystemDirectoryW(s, MAX_PATH + 1);
|
||||
len = ::GetSystemDirectoryW(s, kBufSize);
|
||||
path = us2fs(s);
|
||||
}
|
||||
return (needLength > 0 && needLength <= MAX_PATH);
|
||||
return (len != 0 && len < kBufSize);
|
||||
}
|
||||
#endif // UNDER_CE
|
||||
|
||||
|
||||
bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime)
|
||||
bool SetDirTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime)
|
||||
{
|
||||
#ifndef _UNICODE
|
||||
if (!g_IsNT)
|
||||
@@ -99,7 +132,7 @@ bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const
|
||||
IF_USE_MAIN_PATH
|
||||
hDir = ::CreateFileW(fs2us(path), GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
||||
#ifdef WIN_LONG_PATH
|
||||
#ifdef Z7_LONG_PATH
|
||||
if (hDir == INVALID_HANDLE_VALUE && USE_SUPER_PATH)
|
||||
{
|
||||
UString superPath;
|
||||
@@ -134,7 +167,7 @@ bool SetFileAttrib(CFSTR path, DWORD attrib)
|
||||
IF_USE_MAIN_PATH
|
||||
if (::SetFileAttributesW(fs2us(path), attrib))
|
||||
return true;
|
||||
#ifdef WIN_LONG_PATH
|
||||
#ifdef Z7_LONG_PATH
|
||||
if (USE_SUPER_PATH)
|
||||
{
|
||||
UString superPath;
|
||||
@@ -171,7 +204,7 @@ bool RemoveDir(CFSTR path)
|
||||
IF_USE_MAIN_PATH
|
||||
if (::RemoveDirectoryW(fs2us(path)))
|
||||
return true;
|
||||
#ifdef WIN_LONG_PATH
|
||||
#ifdef Z7_LONG_PATH
|
||||
if (USE_SUPER_PATH)
|
||||
{
|
||||
UString superPath;
|
||||
@@ -200,7 +233,7 @@ bool MyMoveFile(CFSTR oldFile, CFSTR newFile)
|
||||
if (::MoveFileW(fs2us(oldFile), fs2us(newFile)))
|
||||
return true;
|
||||
}
|
||||
#ifdef WIN_LONG_PATH
|
||||
#ifdef Z7_LONG_PATH
|
||||
if (USE_SUPER_PATH_2)
|
||||
{
|
||||
UString d1, d2;
|
||||
@@ -237,8 +270,11 @@ bool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName)
|
||||
else
|
||||
#endif
|
||||
{
|
||||
Func_CreateHardLinkW my_CreateHardLinkW = (Func_CreateHardLinkW)
|
||||
(void *)::GetProcAddress(::GetModuleHandleW(L"kernel32.dll"), "CreateHardLinkW");
|
||||
const
|
||||
Func_CreateHardLinkW
|
||||
my_CreateHardLinkW = Z7_GET_PROC_ADDRESS(
|
||||
Func_CreateHardLinkW, ::GetModuleHandleW(L"kernel32.dll"),
|
||||
"CreateHardLinkW");
|
||||
if (!my_CreateHardLinkW)
|
||||
return false;
|
||||
IF_USE_MAIN_PATH_2(newFileName, existFileName)
|
||||
@@ -246,7 +282,7 @@ bool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName)
|
||||
if (my_CreateHardLinkW(fs2us(newFileName), fs2us(existFileName), NULL))
|
||||
return true;
|
||||
}
|
||||
#ifdef WIN_LONG_PATH
|
||||
#ifdef Z7_LONG_PATH
|
||||
if (USE_SUPER_PATH_2)
|
||||
{
|
||||
UString d1, d2;
|
||||
@@ -296,7 +332,7 @@ bool CreateDir(CFSTR path)
|
||||
IF_USE_MAIN_PATH
|
||||
if (::CreateDirectoryW(fs2us(path), NULL))
|
||||
return true;
|
||||
#ifdef WIN_LONG_PATH
|
||||
#ifdef Z7_LONG_PATH
|
||||
if ((!USE_MAIN_PATH || ::GetLastError() != ERROR_ALREADY_EXISTS) && USE_SUPER_PATH)
|
||||
{
|
||||
UString superPath;
|
||||
@@ -331,7 +367,7 @@ static bool CreateDir2(CFSTR path)
|
||||
IF_USE_MAIN_PATH
|
||||
if (::CreateDirectoryW(fs2us(path), NULL))
|
||||
return true;
|
||||
#ifdef WIN_LONG_PATH
|
||||
#ifdef Z7_LONG_PATH
|
||||
if ((!USE_MAIN_PATH || ::GetLastError() != ERROR_ALREADY_EXISTS) && USE_SUPER_PATH)
|
||||
{
|
||||
UString superPath;
|
||||
@@ -366,7 +402,7 @@ bool CreateComplexDir(CFSTR _path)
|
||||
#ifdef _WIN32
|
||||
|
||||
{
|
||||
DWORD attrib = NFind::GetFileAttrib(_path);
|
||||
const DWORD attrib = NFind::GetFileAttrib(_path);
|
||||
if (attrib != INVALID_FILE_ATTRIBUTES && (attrib & FILE_ATTRIBUTE_DIRECTORY) != 0)
|
||||
return true;
|
||||
}
|
||||
@@ -472,7 +508,7 @@ bool DeleteFileAlways(CFSTR path)
|
||||
IF_USE_MAIN_PATH
|
||||
if (::DeleteFileW(fs2us(path)))
|
||||
return true;
|
||||
#ifdef WIN_LONG_PATH
|
||||
#ifdef Z7_LONG_PATH
|
||||
if (USE_SUPER_PATH)
|
||||
{
|
||||
UString superPath;
|
||||
@@ -562,9 +598,12 @@ bool MyGetFullPathName(CFSTR path, FString &resFullPath)
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
/* Win10: SetCurrentDirectory() doesn't support long paths and
|
||||
doesn't support super prefix "\\?\", if long path behavior is not
|
||||
enabled in registry (LongPathsEnabled) and in manifest (longPathAware). */
|
||||
|
||||
bool SetCurrentDir(CFSTR path)
|
||||
{
|
||||
// SetCurrentDirectory doesn't support \\?\ prefix
|
||||
#ifndef _UNICODE
|
||||
if (!g_IsNT)
|
||||
{
|
||||
@@ -578,28 +617,74 @@ bool SetCurrentDir(CFSTR path)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
we use system function GetCurrentDirectory()
|
||||
new GetCurrentDirectory() DOCs:
|
||||
- If the function fails, the return value is zero.
|
||||
- If the function succeeds, the return value specifies
|
||||
the number of characters that are written to the buffer,
|
||||
not including the terminating null character.
|
||||
- If the buffer is not large enough, the return value specifies
|
||||
the required size of the buffer, in characters,
|
||||
including the null-terminating character.
|
||||
|
||||
GetCurrentDir() calls GetCurrentDirectory().
|
||||
GetCurrentDirectory() in win10 in tests:
|
||||
the returned (path) does not end with a backslash, if
|
||||
current directory is not root directory of drive.
|
||||
But that behavior is not guarantied in specification docs.
|
||||
*/
|
||||
|
||||
bool GetCurrentDir(FString &path)
|
||||
{
|
||||
const unsigned kBufSize = MAX_PATH + 16;
|
||||
path.Empty();
|
||||
|
||||
DWORD needLength;
|
||||
#ifndef _UNICODE
|
||||
if (!g_IsNT)
|
||||
{
|
||||
TCHAR s[MAX_PATH + 2];
|
||||
TCHAR s[kBufSize + 1];
|
||||
s[0] = 0;
|
||||
needLength = ::GetCurrentDirectory(MAX_PATH + 1, s);
|
||||
const DWORD len = ::GetCurrentDirectory(kBufSize, s);
|
||||
if (len == 0 || len >= kBufSize)
|
||||
return false;
|
||||
s[kBufSize] = 0; // optional guard
|
||||
path = fas2fs(s);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
WCHAR s[MAX_PATH + 2];
|
||||
s[0] = 0;
|
||||
needLength = ::GetCurrentDirectoryW(MAX_PATH + 1, s);
|
||||
path = us2fs(s);
|
||||
DWORD len;
|
||||
{
|
||||
WCHAR s[kBufSize + 1];
|
||||
s[0] = 0;
|
||||
len = ::GetCurrentDirectoryW(kBufSize, s);
|
||||
if (len == 0)
|
||||
return false;
|
||||
if (len < kBufSize)
|
||||
{
|
||||
s[kBufSize] = 0; // optional guard
|
||||
path = us2fs(s);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
UString temp;
|
||||
const DWORD len2 = ::GetCurrentDirectoryW(len, temp.GetBuf(len));
|
||||
if (len2 == 0)
|
||||
return false;
|
||||
temp.ReleaseBuf_CalcLen(len);
|
||||
if (temp.Len() != len2 || len - 1 != len2)
|
||||
{
|
||||
/* it's unexpected case, if current dir of process
|
||||
was changed between two function calls,
|
||||
or some unexpected function implementation */
|
||||
// SetLastError((DWORD)E_FAIL); // we can set some error code
|
||||
return false;
|
||||
}
|
||||
path = us2fs(temp);
|
||||
return true;
|
||||
}
|
||||
return (needLength > 0 && needLength <= MAX_PATH);
|
||||
}
|
||||
|
||||
#endif // _WIN32
|
||||
@@ -624,41 +709,59 @@ bool GetOnlyDirPrefix(CFSTR path, FString &resDirPrefix)
|
||||
return GetFullPathAndSplit(path, resDirPrefix, resFileName);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool MyGetTempPath(FString &path)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
path.Empty();
|
||||
DWORD needLength;
|
||||
|
||||
/*
|
||||
new DOCs for GetTempPathW():
|
||||
- The returned string ends with a backslash.
|
||||
- The maximum possible return value is MAX_PATH+1 (261).
|
||||
*/
|
||||
|
||||
const unsigned kBufSize = MAX_PATH + 16;
|
||||
DWORD len;
|
||||
#ifndef _UNICODE
|
||||
if (!g_IsNT)
|
||||
{
|
||||
TCHAR s[MAX_PATH + 2];
|
||||
TCHAR s[kBufSize + 1];
|
||||
s[0] = 0;
|
||||
needLength = ::GetTempPath(MAX_PATH + 1, s);
|
||||
len = ::GetTempPath(kBufSize, s);
|
||||
path = fas2fs(s);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
WCHAR s[MAX_PATH + 2];
|
||||
WCHAR s[kBufSize + 1];
|
||||
s[0] = 0;
|
||||
needLength = ::GetTempPathW(MAX_PATH + 1, s);;
|
||||
len = ::GetTempPathW(kBufSize, s);
|
||||
path = us2fs(s);
|
||||
}
|
||||
return (needLength > 0 && needLength <= MAX_PATH);
|
||||
/* win10: GetTempPathW() doesn't set backslash at the end of path,
|
||||
if (buffer_size == len_of(path_with_backslash)).
|
||||
So we normalize path here: */
|
||||
NormalizeDirPathPrefix(path);
|
||||
return (len != 0 && len < kBufSize);
|
||||
|
||||
#else
|
||||
#else // !_WIN32
|
||||
|
||||
// FIXME: improve that code
|
||||
path = "/tmp/";
|
||||
if (!NFind::DoesDirExist_FollowLink(path))
|
||||
path = "./";
|
||||
path = STRING_PATH_SEPARATOR "tmp";
|
||||
const char *s;
|
||||
if (NFind::DoesDirExist_FollowLink(path))
|
||||
s = STRING_PATH_SEPARATOR "tmp" STRING_PATH_SEPARATOR;
|
||||
else
|
||||
s = "." STRING_PATH_SEPARATOR;
|
||||
path = s;
|
||||
return true;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static bool CreateTempFile(CFSTR prefix, bool addRandom, FString &path, NIO::COutFile *outFile)
|
||||
bool CreateTempFile2(CFSTR prefix, bool addRandom, AString &postfix, NIO::COutFile *outFile)
|
||||
{
|
||||
UInt32 d =
|
||||
#ifdef _WIN32
|
||||
@@ -669,7 +772,7 @@ static bool CreateTempFile(CFSTR prefix, bool addRandom, FString &path, NIO::COu
|
||||
|
||||
for (unsigned i = 0; i < 100; i++)
|
||||
{
|
||||
path = prefix;
|
||||
postfix.Empty();
|
||||
if (addRandom)
|
||||
{
|
||||
char s[16];
|
||||
@@ -677,14 +780,14 @@ static bool CreateTempFile(CFSTR prefix, bool addRandom, FString &path, NIO::COu
|
||||
unsigned k;
|
||||
for (k = 0; k < 8; k++)
|
||||
{
|
||||
unsigned t = val & 0xF;
|
||||
const unsigned t = val & 0xF;
|
||||
val >>= 4;
|
||||
s[k] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10)));
|
||||
}
|
||||
s[k] = '\0';
|
||||
if (outFile)
|
||||
path += '.';
|
||||
path += s;
|
||||
postfix.Add_Dot();
|
||||
postfix += s;
|
||||
UInt32 step = GetTickCount() + 2;
|
||||
if (step == 0)
|
||||
step = 1;
|
||||
@@ -692,7 +795,9 @@ static bool CreateTempFile(CFSTR prefix, bool addRandom, FString &path, NIO::COu
|
||||
}
|
||||
addRandom = true;
|
||||
if (outFile)
|
||||
path += ".tmp";
|
||||
postfix += ".tmp";
|
||||
FString path (prefix);
|
||||
path += postfix;
|
||||
if (NFind::DoesFileOrDirExist(path))
|
||||
{
|
||||
SetLastError(ERROR_ALREADY_EXISTS);
|
||||
@@ -708,12 +813,12 @@ static bool CreateTempFile(CFSTR prefix, bool addRandom, FString &path, NIO::COu
|
||||
if (CreateDir(path))
|
||||
return true;
|
||||
}
|
||||
DWORD error = GetLastError();
|
||||
const DWORD error = GetLastError();
|
||||
if (error != ERROR_FILE_EXISTS &&
|
||||
error != ERROR_ALREADY_EXISTS)
|
||||
break;
|
||||
}
|
||||
path.Empty();
|
||||
postfix.Empty();
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -721,8 +826,12 @@ bool CTempFile::Create(CFSTR prefix, NIO::COutFile *outFile)
|
||||
{
|
||||
if (!Remove())
|
||||
return false;
|
||||
if (!CreateTempFile(prefix, false, _path, outFile))
|
||||
_path.Empty();
|
||||
AString postfix;
|
||||
if (!CreateTempFile2(prefix, false, postfix, outFile))
|
||||
return false;
|
||||
_path = prefix;
|
||||
_path += postfix;
|
||||
_mustBeDeleted = true;
|
||||
return true;
|
||||
}
|
||||
@@ -731,11 +840,16 @@ bool CTempFile::CreateRandomInTempFolder(CFSTR namePrefix, NIO::COutFile *outFil
|
||||
{
|
||||
if (!Remove())
|
||||
return false;
|
||||
_path.Empty();
|
||||
FString tempPath;
|
||||
if (!MyGetTempPath(tempPath))
|
||||
return false;
|
||||
if (!CreateTempFile(tempPath + namePrefix, true, _path, outFile))
|
||||
AString postfix;
|
||||
tempPath += namePrefix;
|
||||
if (!CreateTempFile2(tempPath, true, postfix, outFile))
|
||||
return false;
|
||||
_path = tempPath;
|
||||
_path += postfix;
|
||||
_mustBeDeleted = true;
|
||||
return true;
|
||||
}
|
||||
@@ -778,11 +892,16 @@ bool CTempDir::Create(CFSTR prefix)
|
||||
{
|
||||
if (!Remove())
|
||||
return false;
|
||||
_path.Empty();
|
||||
FString tempPath;
|
||||
if (!MyGetTempPath(tempPath))
|
||||
return false;
|
||||
if (!CreateTempFile(tempPath + prefix, true, _path, NULL))
|
||||
tempPath += prefix;
|
||||
AString postfix;
|
||||
if (!CreateTempFile2(tempPath, true, postfix, NULL))
|
||||
return false;
|
||||
_path = tempPath;
|
||||
_path += postfix;
|
||||
_mustBeDeleted = true;
|
||||
return true;
|
||||
}
|
||||
@@ -806,7 +925,7 @@ bool RemoveDir(CFSTR path)
|
||||
}
|
||||
|
||||
|
||||
static BOOL My__CopyFile(CFSTR oldFile, CFSTR newFile)
|
||||
static BOOL My_CopyFile(CFSTR oldFile, CFSTR newFile)
|
||||
{
|
||||
NWindows::NFile::NIO::COutFile outFile;
|
||||
if (!outFile.Create(newFile, false))
|
||||
@@ -841,7 +960,7 @@ bool MyMoveFile(CFSTR oldFile, CFSTR newFile)
|
||||
if (errno != EXDEV) // (oldFile and newFile are not on the same mounted filesystem)
|
||||
return false;
|
||||
|
||||
if (My__CopyFile(oldFile, newFile) == FALSE)
|
||||
if (My_CopyFile(oldFile, newFile) == FALSE)
|
||||
return false;
|
||||
|
||||
struct stat info_file;
|
||||
@@ -882,48 +1001,48 @@ bool GetCurrentDir(FString &path)
|
||||
{
|
||||
path.Empty();
|
||||
|
||||
#define MY__PATH_MAX PATH_MAX
|
||||
// #define MY__PATH_MAX 1024
|
||||
#define MY_PATH_MAX PATH_MAX
|
||||
// #define MY_PATH_MAX 1024
|
||||
|
||||
char s[MY__PATH_MAX + 1];
|
||||
char *res = getcwd(s, MY__PATH_MAX);
|
||||
if (!res)
|
||||
char s[MY_PATH_MAX + 1];
|
||||
char *res = getcwd(s, MY_PATH_MAX);
|
||||
if (res)
|
||||
{
|
||||
// if (errno != ERANGE)
|
||||
return false;
|
||||
path = fas2fs(s);
|
||||
return true;
|
||||
}
|
||||
path = fas2fs(s);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
static void FILETME_To_timespec(const FILETIME *ft, timespec &ts)
|
||||
{
|
||||
if (ft)
|
||||
{
|
||||
const Int64 sec = NTime::FileTimeToUnixTime64(*ft);
|
||||
// time_t is long
|
||||
const time_t sec2 = (time_t)sec;
|
||||
if (sec2 == sec)
|
||||
// if (errno != ERANGE) return false;
|
||||
#if defined(__GLIBC__) || defined(__APPLE__)
|
||||
/* As an extension to the POSIX.1-2001 standard, glibc's getcwd()
|
||||
allocates the buffer dynamically using malloc(3) if buf is NULL. */
|
||||
res = getcwd(NULL, 0);
|
||||
if (res)
|
||||
{
|
||||
ts.tv_sec = sec2;
|
||||
const UInt64 winTime = (((UInt64)ft->dwHighDateTime) << 32) + ft->dwLowDateTime;
|
||||
ts.tv_nsec = (long)((winTime % 10000000) * 100);
|
||||
return;
|
||||
path = fas2fs(res);
|
||||
::free(res);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// else
|
||||
{
|
||||
ts.tv_sec = 0;
|
||||
// ts.tv_nsec = UTIME_NOW; // set to the current time
|
||||
ts.tv_nsec = UTIME_OMIT; // keep old timesptamp
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// #undef UTIME_OMIT // to debug
|
||||
|
||||
bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const FILETIME *mTime)
|
||||
#ifndef UTIME_OMIT
|
||||
/* we can define UTIME_OMIT for debian and another systems.
|
||||
Is it OK to define UTIME_OMIT to -2 here, if UTIME_OMIT is not defined? */
|
||||
// #define UTIME_OMIT -2
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
bool SetDirTime(CFSTR path, const CFiTime *cTime, const CFiTime *aTime, const CFiTime *mTime)
|
||||
{
|
||||
// need testing
|
||||
/*
|
||||
@@ -968,9 +1087,19 @@ bool SetDirTime(CFSTR path, const FILETIME *cTime, const FILETIME *aTime, const
|
||||
struct timespec times[2];
|
||||
UNUSED_VAR(cTime)
|
||||
|
||||
FILETME_To_timespec(aTime, times[0]);
|
||||
FILETME_To_timespec(mTime, times[1]);
|
||||
bool needChange;
|
||||
needChange = FiTime_To_timespec(aTime, times[0]);
|
||||
needChange |= FiTime_To_timespec(mTime, times[1]);
|
||||
|
||||
/*
|
||||
if (mTime)
|
||||
{
|
||||
printf("\n time = %ld.%9ld\n", mTime->tv_sec, mTime->tv_nsec);
|
||||
}
|
||||
*/
|
||||
|
||||
if (!needChange)
|
||||
return true;
|
||||
const int flags = 0; // follow link
|
||||
// = AT_SYMLINK_NOFOLLOW; // don't follow link
|
||||
return utimensat(AT_FDCWD, path, times, flags) == 0;
|
||||
@@ -1001,15 +1130,19 @@ static C_umask g_umask;
|
||||
#define PRF(x)
|
||||
|
||||
#define TRACE_SetFileAttrib(msg) \
|
||||
PRF(printf("\nSetFileAttrib(%s, %x) : %s\n", (const char *)path, attrib, msg));
|
||||
PRF(printf("\nSetFileAttrib(%s, %x) : %s\n", (const char *)path, attrib, msg);)
|
||||
|
||||
#define TRACE_chmod(s, mode) \
|
||||
PRF(printf("\n chmod(%s, %o)\n", (const char *)path, (unsigned)(mode)));
|
||||
PRF(printf("\n chmod(%s, %o)\n", (const char *)path, (unsigned)(mode));)
|
||||
|
||||
int my_chown(CFSTR path, uid_t owner, gid_t group)
|
||||
{
|
||||
return chown(path, owner, group);
|
||||
}
|
||||
|
||||
bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib)
|
||||
{
|
||||
TRACE_SetFileAttrib("");
|
||||
TRACE_SetFileAttrib("")
|
||||
|
||||
struct stat st;
|
||||
|
||||
@@ -1018,21 +1151,23 @@ bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib)
|
||||
{
|
||||
if (lstat(path, &st) != 0)
|
||||
{
|
||||
TRACE_SetFileAttrib("bad lstat()");
|
||||
TRACE_SetFileAttrib("bad lstat()")
|
||||
return false;
|
||||
}
|
||||
// TRACE_chmod("lstat", st.st_mode);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (stat(path, &st) != 0)
|
||||
{
|
||||
TRACE_SetFileAttrib("bad stat()");
|
||||
TRACE_SetFileAttrib("bad stat()")
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (attrib & FILE_ATTRIBUTE_UNIX_EXTENSION)
|
||||
{
|
||||
TRACE_SetFileAttrib("attrib & FILE_ATTRIBUTE_UNIX_EXTENSION")
|
||||
st.st_mode = attrib >> 16;
|
||||
if (S_ISDIR(st.st_mode))
|
||||
{
|
||||
@@ -1044,12 +1179,15 @@ bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib)
|
||||
}
|
||||
else if (S_ISLNK(st.st_mode))
|
||||
{
|
||||
// change it
|
||||
SetLastError(ENOSYS);
|
||||
return false;
|
||||
/* for most systems: permissions for symlinks are fixed to rwxrwxrwx.
|
||||
so we don't need chmod() for symlinks. */
|
||||
return true;
|
||||
// SetLastError(ENOSYS);
|
||||
// return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE_SetFileAttrib("Only Windows Attributes")
|
||||
// Only Windows Attributes
|
||||
if (S_ISDIR(st.st_mode)
|
||||
|| (attrib & FILE_ATTRIBUTE_READONLY) == 0)
|
||||
@@ -1057,17 +1195,30 @@ bool SetFileAttrib_PosixHighDetect(CFSTR path, DWORD attrib)
|
||||
st.st_mode &= ~(mode_t)(S_IWUSR | S_IWGRP | S_IWOTH); // octal: ~0222; // disable write permissions
|
||||
}
|
||||
|
||||
TRACE_chmod(path, (st.st_mode) & g_umask.mask);
|
||||
int res = chmod(path, (st.st_mode) & g_umask.mask);
|
||||
|
||||
// TRACE_SetFileAttrib("OK")
|
||||
int res;
|
||||
/*
|
||||
if (S_ISLNK(st.st_mode))
|
||||
{
|
||||
printf("\nfchmodat()\n");
|
||||
TRACE_chmod(path, (st.st_mode) & g_umask.mask)
|
||||
// AT_SYMLINK_NOFOLLOW is not implemted still in Linux.
|
||||
res = fchmodat(AT_FDCWD, path, (st.st_mode) & g_umask.mask,
|
||||
S_ISLNK(st.st_mode) ? AT_SYMLINK_NOFOLLOW : 0);
|
||||
}
|
||||
else
|
||||
*/
|
||||
{
|
||||
TRACE_chmod(path, (st.st_mode) & g_umask.mask)
|
||||
res = chmod(path, (st.st_mode) & g_umask.mask);
|
||||
}
|
||||
// TRACE_SetFileAttrib("End")
|
||||
return (res == 0);
|
||||
}
|
||||
|
||||
|
||||
bool MyCreateHardLink(CFSTR newFileName, CFSTR existFileName)
|
||||
{
|
||||
PRF(printf("\nhard link() %s -> %s\n", newFileName, existFileName));
|
||||
PRF(printf("\nhard link() %s -> %s\n", newFileName, existFileName);)
|
||||
return (link(existFileName, newFileName) == 0);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user