blob: 838f92d5bbf4d16ced54f4a54d91f13be0e45fae [file] [log] [blame]
// Windows/FileDir.cpp
#include "StdAfx.h"
#include "FileDir.h"
#include "FileName.h"
#include "FileFind.h"
#include "Defs.h"
#include "../Common/StringConvert.h"
#include "../Common/IntToString.h"
#define NEED_NAME_WINDOWS_TO_UNIX
#include "myPrivate.h"
#include "Windows/Synchronization.h"
#include <unistd.h> // rmdir
#include <errno.h>
#include <sys/stat.h> // mkdir
#include <sys/types.h>
#include <fcntl.h>
#include <utime.h>
// #define TRACEN(u) u;
#define TRACEN(u) /* */
class Umask
{
public:
mode_t current_umask;
mode_t mask;
Umask() {
current_umask = umask (0); /* get and set the umask */
umask(current_umask); /* restore the umask */
mask = 0777 & (~current_umask);
}
};
static Umask gbl_umask;
#ifdef _UNICODE
AString nameWindowToUnix2(LPCWSTR name) // FIXME : optimization ?
{
AString astr = UnicodeStringToMultiByte(name);
return AString(nameWindowToUnix((const char *)astr));
}
#endif
extern BOOLEAN WINAPI RtlTimeToSecondsSince1970( const LARGE_INTEGER *Time, DWORD *Seconds );
#ifdef _UNICODE
DWORD WINAPI GetFullPathName( LPCTSTR name, DWORD len, LPTSTR buffer, LPTSTR *lastpart ) { // FIXME
if (name == 0) return 0;
DWORD name_len = lstrlen(name);
if (name[0] == '/') {
DWORD ret = name_len+2;
if (ret >= len) {
TRACEN((printf("GetFullPathNameA(%ls,%d,)=0000 (case 0)\n",name, (int)len)))
return 0;
}
lstrcpy(buffer,L"c:");
lstrcat(buffer,name);
*lastpart=buffer;
TCHAR *ptr=buffer;
while (*ptr) {
if (*ptr == '/')
*lastpart=ptr+1;
ptr++;
}
TRACEN((printf("GetFullPathNameA(%s,%d,%ls,%ls)=%d\n",name, (int)len,buffer, *lastpart,(int)ret)))
return ret;
}
if (isascii(name[0]) && (name[1] == ':')) { // FIXME isascii
DWORD ret = name_len;
if (ret >= len) {
TRACEN((printf("GetFullPathNameA(%ls,%d,)=0000 (case 1)\n",name, (int)len)))
return 0;
}
lstrcpy(buffer,name);
*lastpart=buffer;
TCHAR *ptr=buffer;
while (*ptr) {
if (*ptr == '/')
*lastpart=ptr+1;
ptr++;
}
TRACEN((printf("GetFullPathNameA(%sl,%d,%ls,%ls)=%d\n",name, (int)len,buffer, *lastpart,(int)ret)))
return ret;
}
// name is a relative pathname.
//
if (len < 2) {
TRACEN((printf("GetFullPathNameA(%s,%d,)=0000 (case 2)\n",name, (int)len)))
return 0;
}
DWORD ret = 0;
char begin[MAX_PATHNAME_LEN];
/* DWORD begin_len = GetCurrentDirectoryA(MAX_PATHNAME_LEN,begin); */
DWORD begin_len = 0;
begin[0]='c';
begin[1]=':';
char * cret = getcwd(begin+2, MAX_PATHNAME_LEN - 3);
if (cret) {
begin_len = strlen(begin);
}
if (begin_len >= 1) {
// strlen(begin) + strlen("/") + strlen(name)
ret = begin_len + 1 + name_len;
if (ret >= len) {
TRACEN((printf("GetFullPathNameA(%s,%d,)=0000 (case 4)\n",name, (int)len)))
return 0;
}
UString wbegin = GetUnicodeString(begin);
lstrcpy(buffer,wbegin);
lstrcat(buffer,L"/");
lstrcat(buffer,name);
*lastpart=buffer + begin_len + 1;
TCHAR *ptr=buffer;
while (*ptr) {
if (*ptr == '/')
*lastpart=ptr+1;
ptr++;
}
TRACEN((printf("GetFullPathNameA(%s,%d,%s,%s)=%d\n",name, (int)len,buffer, *lastpart,(int)ret)))
} else {
ret = 0;
TRACEN((printf("GetFullPathNameA(%s,%d,)=0000 (case 5)\n",name, (int)len)))
}
return ret;
}
#endif
#if 0
DWORD WINAPI GetFullPathName( LPCSTR name, DWORD len, LPSTR buffer, LPSTR *lastpart ) {
if (name == 0) return 0;
DWORD name_len = strlen(name);
if (name[0] == '/') {
DWORD ret = name_len+2;
if (ret >= len) {
TRACEN((printf("GetFullPathNameA(%s,%d,)=0000 (case 0)\n",name, (int)len)))
return 0;
}
strcpy(buffer,"c:");
strcat(buffer,name);
*lastpart=buffer;
char *ptr=buffer;
while (*ptr) {
if (*ptr == '/')
*lastpart=ptr+1;
ptr++;
}
TRACEN((printf("GetFullPathNameA(%s,%d,%s,%s)=%d\n",name, (int)len,buffer, *lastpart,(int)ret)))
return ret;
}
if (isascii(name[0]) && (name[1] == ':')) {
DWORD ret = name_len;
if (ret >= len) {
TRACEN((printf("GetFullPathNameA(%s,%d,)=0000 (case 1)\n",name, (int)len)))
return 0;
}
strcpy(buffer,name);
*lastpart=buffer;
char *ptr=buffer;
while (*ptr) {
if (*ptr == '/')
*lastpart=ptr+1;
ptr++;
}
TRACEN((printf("GetFullPathNameA(%s,%d,%s,%s)=%d\n",name, (int)len,buffer, *lastpart,(int)ret)))
return ret;
}
// name is a relative pathname.
//
if (len < 2) {
TRACEN((printf("GetFullPathNameA(%s,%d,)=0000 (case 2)\n",name, (int)len)))
return 0;
}
DWORD ret = 0;
char begin[MAX_PATHNAME_LEN];
/* DWORD begin_len = GetCurrentDirectoryA(MAX_PATHNAME_LEN,begin); */
DWORD begin_len = 0;
begin[0]='c';
begin[1]=':';
char * cret = getcwd(begin+2, MAX_PATHNAME_LEN - 3);
if (cret) {
begin_len = strlen(begin);
}
if (begin_len >= 1) {
// strlen(begin) + strlen("/") + strlen(name)
ret = begin_len + 1 + name_len;
if (ret >= len) {
TRACEN((printf("GetFullPathNameA(%s,%d,)=0000 (case 4)\n",name, (int)len)))
return 0;
}
strcpy(buffer,begin);
strcat(buffer,"/");
strcat(buffer,name);
*lastpart=buffer + begin_len + 1;
char *ptr=buffer;
while (*ptr) {
if (*ptr == '/')
*lastpart=ptr+1;
ptr++;
}
TRACEN((printf("GetFullPathNameA(%s,%d,%s,%s)=%d\n",name, (int)len,buffer, *lastpart,(int)ret)))
} else {
ret = 0;
TRACEN((printf("GetFullPathNameA(%s,%d,)=0000 (case 5)\n",name, (int)len)))
}
return ret;
}
static BOOL WINAPI RemoveDirectory(LPCSTR path) {
if (!path || !*path) {
SetLastError(ERROR_PATH_NOT_FOUND);
return FALSE;
}
const char * name = nameWindowToUnix(path);
TRACEN((printf("RemoveDirectoryA(%s)\n",name)))
if (rmdir( name ) != 0) {
return FALSE;
}
return TRUE;
}
#endif
#ifdef _UNICODE
static BOOL WINAPI RemoveDirectory(LPCWSTR path) {
if (!path || !*path) {
SetLastError(ERROR_PATH_NOT_FOUND);
return FALSE;
}
AString name = nameWindowToUnix2(path);
TRACEN((printf("RemoveDirectoryA(%s)\n",(const char *)name)))
if (rmdir( (const char *)name ) != 0) {
return FALSE;
}
return TRUE;
}
#endif
static int copy_fd(int fin,int fout)
{
char buffer[16384];
ssize_t ret_in;
ssize_t ret_out;
do {
ret_out = -1;
do {
ret_in = read(fin, buffer,sizeof(buffer));
} while (ret_in < 0 && (errno == EINTR));
if (ret_in >= 1) {
do {
ret_out = write (fout, buffer, ret_in);
} while (ret_out < 0 && (errno == EINTR));
} else if (ret_in == 0) {
ret_out = 0;
}
} while (ret_out >= 1);
return ret_out;
}
static BOOL CopyFile(const char *src,const char *dst)
{
int ret = -1;
#ifdef O_BINARY
int flags = O_BINARY;
#else
int flags = 0;
#endif
#ifdef O_LARGEFILE
flags |= O_LARGEFILE;
#endif
int fout = open(dst,O_CREAT | O_WRONLY | O_EXCL | flags, 0600);
if (fout != -1)
{
int fin = open(src,O_RDONLY | flags , 0600);
if (fin != -1)
{
ret = copy_fd(fin,fout);
if (ret == 0) ret = close(fin);
else close(fin);
}
if (ret == 0) ret = close(fout);
else close(fout);
}
if (ret == 0) return TRUE;
return FALSE;
}
/*****************************************************************************************/
namespace NWindows {
namespace NFile {
namespace NDirectory {
bool MySetCurrentDirectory(LPCWSTR wpath)
{
AString path = UnicodeStringToMultiByte(wpath);
return chdir((const char*)path) == 0;
}
#ifdef _UNICODE
bool GetOnlyName(LPCTSTR fileName, CSysString &resultName)
{
int index;
if (!MyGetFullPathName(fileName, resultName, index))
return false;
resultName = resultName.Mid(index);
return true;
}
bool GetOnlyDirPrefix(LPCTSTR fileName, CSysString &resultName)
{
int index;
if (!MyGetFullPathName(fileName, resultName, index))
return false;
resultName = resultName.Left(index);
return true;
}
#endif
bool MyGetCurrentDirectory(CSysString &resultPath)
{
char begin[MAX_PATHNAME_LEN];
begin[0]='c';
begin[1]=':';
char * cret = getcwd(begin+2, MAX_PATHNAME_LEN - 3);
if (cret)
{
#ifdef _UNICODE
resultPath = GetUnicodeString(begin);
#else
resultPath = begin;
#endif
return true;
}
return false;
}
bool MyMoveFile( LPCTSTR fn1, LPCTSTR fn2 ) {
#ifdef _UNICODE
AString src = nameWindowToUnix2(fn1);
AString dst = nameWindowToUnix2(fn2);
#else
const char * src = nameWindowToUnix(fn1);
const char * dst = nameWindowToUnix(fn2);
#endif
TRACEN((printf("MoveFileW(%s,%s)\n",src,dst)))
int ret = rename(src,dst);
if (ret != 0)
{
if (errno == EXDEV) // FIXED : bug #1112167 (Temporary directory must be on same partition as target)
{
BOOL bret = CopyFile(src,dst);
if (bret == FALSE) return false;
struct stat info_file;
ret = stat(src,&info_file);
if (ret == 0) {
TRACEN((printf("##DBG chmod-1(%s,%o)\n",dst,(unsigned)info_file.st_mode & gbl_umask.mask)))
ret = chmod(dst,info_file.st_mode & gbl_umask.mask);
}
if (ret == 0) {
ret = unlink(src);
}
if (ret == 0) return true;
}
return false;
}
return true;
}
bool MyRemoveDirectory(LPCTSTR pathName)
{
return BOOLToBool(::RemoveDirectory(pathName));
}
bool SetDirTime(LPCWSTR fileName, const FILETIME * /* creationTime */ ,
const FILETIME *lpLastAccessTime, const FILETIME *lpLastWriteTime)
{
AString cfilename = UnicodeStringToMultiByte(fileName);
const char * unix_filename = nameWindowToUnix((const char *)cfilename);
struct utimbuf buf;
struct stat oldbuf;
int ret = stat(unix_filename,&oldbuf);
if (ret == 0) {
buf.actime = oldbuf.st_atime;
buf.modtime = oldbuf.st_mtime;
} else {
time_t current_time = time(0);
buf.actime = current_time;
buf.modtime = current_time;
}
if (lpLastAccessTime)
{
LARGE_INTEGER ltime;
DWORD dw;
ltime.QuadPart = lpLastAccessTime->dwHighDateTime;
ltime.QuadPart = (ltime.QuadPart << 32) | lpLastAccessTime->dwLowDateTime;
RtlTimeToSecondsSince1970( &ltime, &dw );
buf.actime = dw;
}
if (lpLastWriteTime)
{
LARGE_INTEGER ltime;
DWORD dw;
ltime.QuadPart = lpLastWriteTime->dwHighDateTime;
ltime.QuadPart = (ltime.QuadPart << 32) | lpLastWriteTime->dwLowDateTime;
RtlTimeToSecondsSince1970( &ltime, &dw );
buf.modtime = dw;
}
/* ret = */ utime(unix_filename, &buf);
return true;
}
#ifndef _UNICODE
bool MySetFileAttributes(LPCWSTR fileName, DWORD fileAttributes)
{
return MySetFileAttributes(UnicodeStringToMultiByte(fileName, CP_ACP), fileAttributes);
}
bool MyRemoveDirectory(LPCWSTR pathName)
{
return MyRemoveDirectory(UnicodeStringToMultiByte(pathName, CP_ACP));
}
bool MyMoveFile(LPCWSTR existFileName, LPCWSTR newFileName)
{
UINT codePage = CP_ACP;
return MyMoveFile(UnicodeStringToMultiByte(existFileName, codePage), UnicodeStringToMultiByte(newFileName, codePage));
}
#endif
static int convert_to_symlink(const char * name) {
FILE *file = fopen(name,"rb");
if (file) {
char buf[MAX_PATHNAME_LEN+1];
char * ret = fgets(buf,sizeof(buf)-1,file);
fclose(file);
if (ret) {
int ir = unlink(name);
if (ir == 0) {
ir = symlink(buf,name);
}
return ir;
}
}
return -1;
}
bool MySetFileAttributes(LPCTSTR fileName, DWORD fileAttributes)
{
if (!fileName) {
SetLastError(ERROR_PATH_NOT_FOUND);
TRACEN((printf("MySetFileAttributes(NULL,%d) : false-1\n",fileAttributes)))
return false;
}
#ifdef _UNICODE
AString name = nameWindowToUnix2(fileName);
#else
const char * name = nameWindowToUnix(fileName);
#endif
struct stat stat_info;
#ifdef ENV_HAVE_LSTAT
if (global_use_lstat) {
if(lstat(name,&stat_info)!=0) {
TRACEN((printf("MySetFileAttributes(%s,%d) : false-2-1\n",name,fileAttributes)))
return false;
}
} else
#endif
{
if(stat(name,&stat_info)!=0) {
TRACEN((printf("MySetFileAttributes(%s,%d) : false-2-2\n",name,fileAttributes)))
return false;
}
}
if (fileAttributes & FILE_ATTRIBUTE_UNIX_EXTENSION) {
stat_info.st_mode = fileAttributes >> 16;
#ifdef ENV_HAVE_LSTAT
if (S_ISLNK(stat_info.st_mode)) {
if ( convert_to_symlink(name) != 0) {
TRACEN((printf("MySetFileAttributes(%s,%d) : false-3\n",name,fileAttributes)))
return false;
}
} else
#endif
if (S_ISREG(stat_info.st_mode)) {
TRACEN((printf("##DBG chmod-2(%s,%o)\n",name,(unsigned)stat_info.st_mode & gbl_umask.mask)))
chmod(name,stat_info.st_mode & gbl_umask.mask);
} else if (S_ISDIR(stat_info.st_mode)) {
// user/7za must be able to create files in this directory
stat_info.st_mode |= (S_IRUSR | S_IWUSR | S_IXUSR);
TRACEN((printf("##DBG chmod-3(%s,%o)\n",name,(unsigned)stat_info.st_mode & gbl_umask.mask)))
chmod(name,stat_info.st_mode & gbl_umask.mask);
}
#ifdef ENV_HAVE_LSTAT
} else if (!S_ISLNK(stat_info.st_mode)) {
// do not use chmod on a link
#else
} else {
#endif
/* Only Windows Attributes */
if( S_ISDIR(stat_info.st_mode)) {
/* Remark : FILE_ATTRIBUTE_READONLY ignored for directory. */
TRACEN((printf("##DBG chmod-4(%s,%o)\n",name,(unsigned)stat_info.st_mode & gbl_umask.mask)))
chmod(name,stat_info.st_mode & gbl_umask.mask);
} else {
if (fileAttributes & FILE_ATTRIBUTE_READONLY) stat_info.st_mode &= ~0222; /* octal!, clear write permission bits */
TRACEN((printf("##DBG chmod-5(%s,%o)\n",name,(unsigned)stat_info.st_mode & gbl_umask.mask)))
chmod(name,stat_info.st_mode & gbl_umask.mask);
}
}
TRACEN((printf("MySetFileAttributes(%s,%d) : true\n",name,fileAttributes)))
return true;
}
bool MyCreateDirectory(LPCTSTR pathName)
{
if (!pathName || !*pathName) {
SetLastError(ERROR_PATH_NOT_FOUND);
return false;
}
#ifdef _UNICODE
AString name = nameWindowToUnix2(pathName);
#else
const char * name = nameWindowToUnix(pathName);
#endif
bool bret = false;
if (mkdir( name, 0700 ) == 0) bret = true;
TRACEN((printf("MyCreateDirectory(%s)=%d\n",name,(int)bret)))
return bret;
}
#ifndef _UNICODE
bool MyCreateDirectory(LPCWSTR pathName)
{
return MyCreateDirectory(UnicodeStringToMultiByte(pathName, CP_ACP));
}
#endif
bool CreateComplexDirectory(LPCTSTR _aPathName)
{
CSysString pathName = _aPathName;
int pos = pathName.ReverseFind(TEXT(CHAR_PATH_SEPARATOR));
if (pos > 0 && pos == pathName.Length() - 1)
{
if (pathName.Length() == 3 && pathName[1] == ':')
return true; // Disk folder;
pathName.Delete(pos);
}
CSysString pathName2 = pathName;
pos = pathName.Length();
while(true)
{
if(MyCreateDirectory(pathName))
break;
if(::GetLastError() == ERROR_ALREADY_EXISTS)
{
#ifdef _WIN32 // FIXED for supporting symbolic link instead of a directory
NFind::CFileInfo fileInfo;
if (!NFind::FindFile(pathName, fileInfo)) // For network folders
return true;
if (!fileInfo.IsDir())
return false;
#endif
break;
}
pos = pathName.ReverseFind(TEXT(CHAR_PATH_SEPARATOR));
if (pos < 0 || pos == 0)
return false;
if (pathName[pos - 1] == ':')
return false;
pathName = pathName.Left(pos);
}
pathName = pathName2;
while(pos < pathName.Length())
{
pos = pathName.Find(TEXT(CHAR_PATH_SEPARATOR), pos + 1);
if (pos < 0)
pos = pathName.Length();
if(!MyCreateDirectory(pathName.Left(pos)))
return false;
}
return true;
}
#ifndef _UNICODE
bool CreateComplexDirectory(LPCWSTR _aPathName)
{
UString pathName = _aPathName;
int pos = pathName.ReverseFind(WCHAR_PATH_SEPARATOR);
if (pos > 0 && pos == pathName.Length() - 1)
{
if (pathName.Length() == 3 && pathName[1] == L':')
return true; // Disk folder;
pathName.Delete(pos);
}
UString pathName2 = pathName;
pos = pathName.Length();
while(true)
{
if(MyCreateDirectory(pathName))
break;
if(::GetLastError() == ERROR_ALREADY_EXISTS)
{
#ifdef _WIN32 // FIXED for supporting symbolic link instead of a directory
NFind::CFileInfoW fileInfo;
if (!NFind::FindFile(pathName, fileInfo)) // For network folders
return true;
if (!fileInfo.IsDir())
return false;
#endif
break;
}
pos = pathName.ReverseFind(WCHAR_PATH_SEPARATOR);
if (pos < 0 || pos == 0)
return false;
if (pathName[pos - 1] == L':')
return false;
pathName = pathName.Left(pos);
}
pathName = pathName2;
while(pos < pathName.Length())
{
pos = pathName.Find(WCHAR_PATH_SEPARATOR, pos + 1);
if (pos < 0)
pos = pathName.Length();
if(!MyCreateDirectory(pathName.Left(pos)))
return false;
}
return true;
}
#endif
bool DeleteFileAlways(LPCTSTR name)
{
if (!name || !*name) {
SetLastError(ERROR_PATH_NOT_FOUND);
return false;
}
#ifdef _UNICODE
AString unixname = nameWindowToUnix2(name);
#else
const char * unixname = nameWindowToUnix(name);
#endif
bool bret = false;
if (remove(unixname) == 0) bret = true;
TRACEN((printf("DeleteFileAlways(%s)=%d\n",unixname,(int)bret)))
return bret;
}
#ifndef _UNICODE
bool DeleteFileAlways(LPCWSTR name)
{
return DeleteFileAlways(UnicodeStringToMultiByte(name, CP_ACP));
}
#endif
static bool RemoveDirectorySubItems2(const UString &pathPrefix, const NFind::CFileInfoW &fileInfo)
{
if (fileInfo.IsDir())
return RemoveDirectoryWithSubItems(pathPrefix + fileInfo.Name);
return DeleteFileAlways(pathPrefix + fileInfo.Name);
}
bool RemoveDirectoryWithSubItems(const UString &path)
{
NFind::CFileInfoW fileInfo;
UString pathPrefix = path + NName::kDirDelimiter;
{
NFind::CEnumeratorW enumerator(pathPrefix + TCHAR(NName::kAnyStringWildcard));
while (enumerator.Next(fileInfo))
if (!RemoveDirectorySubItems2(pathPrefix, fileInfo))
return false;
}
if (!MySetFileAttributes(path, 0))
return false;
return MyRemoveDirectory(path);
}
#ifndef _WIN32_WCE
bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath,
int &fileNamePartStartIndex)
{
LPTSTR fileNamePointer = 0;
LPTSTR buffer = resultPath.GetBuffer(MAX_PATH);
DWORD needLength = ::GetFullPathName(fileName, MAX_PATH + 1,
buffer, &fileNamePointer);
resultPath.ReleaseBuffer();
if (needLength == 0 || needLength >= MAX_PATH)
return false;
if (fileNamePointer == 0)
fileNamePartStartIndex = lstrlen(fileName);
else
fileNamePartStartIndex = fileNamePointer - buffer;
return true;
}
#ifndef _UNICODE
bool MyGetFullPathName(LPCWSTR fileName, UString &resultPath,
int &fileNamePartStartIndex)
{
const UINT currentPage = CP_ACP;
CSysString sysPath;
if (!MyGetFullPathName(UnicodeStringToMultiByte(fileName,
currentPage), sysPath, fileNamePartStartIndex))
return false;
UString resultPath1 = MultiByteToUnicodeString(
sysPath.Left(fileNamePartStartIndex), currentPage);
UString resultPath2 = MultiByteToUnicodeString(
sysPath.Mid(fileNamePartStartIndex), currentPage);
fileNamePartStartIndex = resultPath1.Length();
resultPath = resultPath1 + resultPath2;
return true;
}
#endif
bool MyGetFullPathName(LPCTSTR fileName, CSysString &path)
{
int index;
return MyGetFullPathName(fileName, path, index);
}
#ifndef _UNICODE
bool MyGetFullPathName(LPCWSTR fileName, UString &path)
{
int index;
return MyGetFullPathName(fileName, path, index);
}
#endif
#endif
/* needed to find .DLL/.so and SFX */
bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension, UString &resultPath)
{
if (path != 0) {
printf("NOT EXPECTED : MySearchPath : path != NULL\n");
exit(EXIT_FAILURE);
}
if (extension != 0) {
printf("NOT EXPECTED : MySearchPath : extension != NULL\n");
exit(EXIT_FAILURE);
}
if (fileName == 0) {
printf("NOT EXPECTED : MySearchPath : fileName == NULL\n");
exit(EXIT_FAILURE);
}
const char *p7zip_home_dir = getenv("P7ZIP_HOME_DIR");
if (p7zip_home_dir) {
AString file_path = p7zip_home_dir;
file_path += UnicodeStringToMultiByte(fileName, CP_ACP);
TRACEN((printf("MySearchPath() fopen(%s)\n",(const char *)file_path)))
FILE *file = fopen((const char *)file_path,"r");
if (file) {
// file is found
fclose(file);
resultPath = MultiByteToUnicodeString(file_path, CP_ACP);
return true;
}
}
return false;
}
#ifndef _UNICODE
bool MyGetTempPath(CSysString &path)
{
path = "c:/tmp/"; // final '/' is needed
return true;
}
#endif
bool MyGetTempPath(UString &path)
{
path = L"c:/tmp/"; // final '/' is needed
return true;
}
static NSynchronization::CCriticalSection g_CountCriticalSection;
static CSysString CSysConvertUInt32ToString(UInt32 value)
{
TCHAR buffer[32];
ConvertUInt32ToString(value, buffer);
return buffer;
}
UINT CTempFile::Create(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath)
{
static UInt32 memo_count = 0;
UInt32 count;
g_CountCriticalSection.Enter();
count = memo_count++;
g_CountCriticalSection.Leave();
Remove();
/* UINT number = ::GetTempFileName(dirPath, prefix, 0, path.GetBuffer(MAX_PATH)); */
UINT number = (UINT)getpid();
resultPath = dirPath;
resultPath += prefix;
resultPath += TEXT('#');
resultPath += CSysConvertUInt32ToString(number);
resultPath += TEXT('@');
resultPath += CSysConvertUInt32ToString(count);
resultPath += TEXT(".tmp");
_fileName = resultPath;
_mustBeDeleted = true;
return number;
}
bool CTempFile::Create(LPCTSTR prefix, CSysString &resultPath)
{
CSysString tempPath;
if (!MyGetTempPath(tempPath))
return false;
if (Create(tempPath, prefix, resultPath) != 0)
return true;
return false;
}
bool CTempFile::Remove()
{
if (!_mustBeDeleted)
return true;
_mustBeDeleted = !DeleteFileAlways(_fileName);
return !_mustBeDeleted;
}
bool CreateTempDirectory(LPCWSTR prefix, UString &dirName)
{
/*
CSysString prefix = tempPath + prefixChars;
CRandom random;
random.Init();
*/
for (;;)
{
{
CTempFileW tempFile;
if (!tempFile.Create(prefix, dirName))
return false;
if (!tempFile.Remove())
return false;
}
/*
UINT32 randomNumber = random.Generate();
TCHAR randomNumberString[32];
_stprintf(randomNumberString, _T("%04X"), randomNumber);
dirName = prefix + randomNumberString;
*/
if (NFind::DoesFileOrDirExist(dirName))
continue;
if (MyCreateDirectory(dirName))
return true;
if (::GetLastError() != ERROR_ALREADY_EXISTS)
return false;
}
}
bool CTempDirectory::Create(LPCTSTR prefix)
{
Remove();
return (_mustBeDeleted = CreateTempDirectory(prefix, _tempDir));
}
}}}