diff options
Diffstat (limited to 'src/libs/7zip/unix/CPP/Windows/FileDir.cpp')
-rw-r--r-- | src/libs/7zip/unix/CPP/Windows/FileDir.cpp | 898 |
1 files changed, 431 insertions, 467 deletions
diff --git a/src/libs/7zip/unix/CPP/Windows/FileDir.cpp b/src/libs/7zip/unix/CPP/Windows/FileDir.cpp index 838f92d5b..9915bd8b8 100644 --- a/src/libs/7zip/unix/CPP/Windows/FileDir.cpp +++ b/src/libs/7zip/unix/CPP/Windows/FileDir.cpp @@ -2,10 +2,14 @@ #include "StdAfx.h" +#ifndef _UNICODE +#include "../Common/StringConvert.h" +#endif + #include "FileDir.h" -#include "FileName.h" #include "FileFind.h" -#include "Defs.h" +#include "FileName.h" + #include "../Common/StringConvert.h" #include "../Common/IntToString.h" @@ -25,6 +29,10 @@ // #define TRACEN(u) u; #define TRACEN(u) /* */ +int g_filedir = 1; + +static NWindows::NSynchronization::CCriticalSection g_CountCriticalSection; + class Umask { public: @@ -34,10 +42,12 @@ class Umask current_umask = umask (0); /* get and set the umask */ umask(current_umask); /* restore the umask */ mask = 0777 & (~current_umask); - } + } }; static Umask gbl_umask; +extern BOOLEAN WINAPI RtlTimeToSecondsSince1970( const LARGE_INTEGER *Time, DWORD *Seconds ); + #ifdef _UNICODE AString nameWindowToUnix2(LPCWSTR name) // FIXME : optimization ? @@ -47,10 +57,7 @@ AString nameWindowToUnix2(LPCWSTR name) // FIXME : optimization ? } #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 +DWORD WINAPI GetFullPathNameW( LPCTSTR name, DWORD len, LPTSTR buffer, LPTSTR *lastpart ) { // FIXME if (name == 0) return 0; DWORD name_len = lstrlen(name); @@ -71,7 +78,7 @@ DWORD WINAPI GetFullPathName( LPCTSTR name, DWORD len, LPTSTR buffer, LPTSTR *la *lastpart=ptr+1; ptr++; } - TRACEN((printf("GetFullPathNameA(%s,%d,%ls,%ls)=%d\n",name, (int)len,buffer, *lastpart,(int)ret))) + TRACEN((printf("GetFullPathNameA(%ls,%d,%ls,%ls)=%d\n",name, (int)len,buffer, *lastpart,(int)ret))) return ret; } if (isascii(name[0]) && (name[1] == ':')) { // FIXME isascii @@ -89,14 +96,14 @@ DWORD WINAPI GetFullPathName( LPCTSTR name, DWORD len, LPTSTR buffer, LPTSTR *la *lastpart=ptr+1; ptr++; } - TRACEN((printf("GetFullPathNameA(%sl,%d,%ls,%ls)=%d\n",name, (int)len,buffer, *lastpart,(int)ret))) + TRACEN((printf("GetFullPathNameA(%ls,%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))) + TRACEN((printf("GetFullPathNameA(%ls,%d,)=0000 (case 2)\n",name, (int)len))) return 0; } @@ -110,13 +117,13 @@ DWORD WINAPI GetFullPathName( LPCTSTR name, DWORD len, LPTSTR buffer, LPTSTR *la 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))) + TRACEN((printf("GetFullPathNameA(%ls,%d,)=0000 (case 4)\n",name, (int)len))) return 0; } UString wbegin = GetUnicodeString(begin); @@ -131,136 +138,14 @@ DWORD WINAPI GetFullPathName( LPCTSTR name, DWORD len, LPTSTR buffer, LPTSTR *la *lastpart=ptr+1; ptr++; } - TRACEN((printf("GetFullPathNameA(%s,%d,%s,%s)=%d\n",name, (int)len,buffer, *lastpart,(int)ret))) + TRACEN((printf("GetFullPathNameA(%ls,%d,%ls,%ls)=%d\n",name, (int)len,buffer, *lastpart,(int)ret))) } else { ret = 0; - TRACEN((printf("GetFullPathNameA(%s,%d,)=0000 (case 5)\n",name, (int)len))) + TRACEN((printf("GetFullPathNameA(%ls,%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]; @@ -297,6 +182,7 @@ static BOOL CopyFile(const char *src,const char *dst) flags |= O_LARGEFILE; #endif + // printf("##DBG CopyFile(%s,%s)\n",src,dst); int fout = open(dst,O_CREAT | O_WRONLY | O_EXCL | flags, 0600); if (fout != -1) { @@ -314,102 +200,76 @@ static BOOL CopyFile(const char *src,const char *dst) return FALSE; } -/*****************************************************************************************/ +#ifndef _UNICODE +extern bool g_IsNT; +#endif namespace NWindows { namespace NFile { -namespace NDirectory { +// SetCurrentDirectory doesn't support \\?\ prefix -bool MySetCurrentDirectory(LPCWSTR wpath) -{ - AString path = UnicodeStringToMultiByte(wpath); +#ifdef WIN_LONG_PATH +bool GetLongPathBase(CFSTR fileName, UString &res); +bool GetLongPath(CFSTR fileName, UString &res); +#endif - return chdir((const char*)path) == 0; -} +namespace NDir { -#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 +#ifdef _WIN32 +#ifndef UNDER_CE -bool MyGetCurrentDirectory(CSysString &resultPath) +bool MyGetWindowsDirectory(FString &path) { - char begin[MAX_PATHNAME_LEN]; - begin[0]='c'; - begin[1]=':'; - char * cret = getcwd(begin+2, MAX_PATHNAME_LEN - 3); - if (cret) + UINT needLength; + #ifndef _UNICODE + if (!g_IsNT) { -#ifdef _UNICODE - resultPath = GetUnicodeString(begin); -#else - resultPath = begin; -#endif - return true; + TCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetWindowsDirectory(s, MAX_PATH + 1); + path = fas2fs(s); } - 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) + else + #endif { - 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; + WCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetWindowsDirectoryW(s, MAX_PATH + 1); + path = us2fs(s); } - return true; + return (needLength > 0 && needLength <= MAX_PATH); } -bool MyRemoveDirectory(LPCTSTR pathName) + +bool MyGetSystemDirectory(FString &path) { - return BOOLToBool(::RemoveDirectory(pathName)); + UINT needLength; + #ifndef _UNICODE + if (!g_IsNT) + { + TCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetSystemDirectory(s, MAX_PATH + 1); + path = fas2fs(s); + } + else + #endif + { + WCHAR s[MAX_PATH + 2]; + s[0] = 0; + needLength = ::GetSystemDirectoryW(s, MAX_PATH + 1); + path = us2fs(s); + } + return (needLength > 0 && needLength <= MAX_PATH); } +#endif +#endif // _WIN32 -bool SetDirTime(LPCWSTR fileName, const FILETIME * /* creationTime */ , - const FILETIME *lpLastAccessTime, const FILETIME *lpLastWriteTime) +bool SetDirTime(CFSTR fileName, const FILETIME * /* cTime */ , const FILETIME *aTime, const FILETIME *mTime) { AString cfilename = UnicodeStringToMultiByte(fileName); const char * unix_filename = nameWindowToUnix((const char *)cfilename); @@ -427,22 +287,22 @@ bool SetDirTime(LPCWSTR fileName, const FILETIME * /* creationTime */ , buf.modtime = current_time; } - if (lpLastAccessTime) + if (aTime) { LARGE_INTEGER ltime; DWORD dw; - ltime.QuadPart = lpLastAccessTime->dwHighDateTime; - ltime.QuadPart = (ltime.QuadPart << 32) | lpLastAccessTime->dwLowDateTime; + ltime.QuadPart = aTime->dwHighDateTime; + ltime.QuadPart = (ltime.QuadPart << 32) | aTime->dwLowDateTime; RtlTimeToSecondsSince1970( <ime, &dw ); buf.actime = dw; } - if (lpLastWriteTime) + if (mTime) { LARGE_INTEGER ltime; DWORD dw; - ltime.QuadPart = lpLastWriteTime->dwHighDateTime; - ltime.QuadPart = (ltime.QuadPart << 32) | lpLastWriteTime->dwLowDateTime; + ltime.QuadPart = mTime->dwHighDateTime; + ltime.QuadPart = (ltime.QuadPart << 32) | mTime->dwLowDateTime; RtlTimeToSecondsSince1970( <ime, &dw ); buf.modtime = dw; } @@ -452,25 +312,20 @@ bool SetDirTime(LPCWSTR fileName, const FILETIME * /* creationTime */ , 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)); +#ifdef WIN_LONG_PATH +bool GetLongPaths(CFSTR s1, CFSTR s2, UString &d1, UString &d2) +{ + if (!GetLongPathBase(s1, d1) || + !GetLongPathBase(s2, d2)) + return false; + if (d1.IsEmpty() && d2.IsEmpty()) + return false; + if (d1.IsEmpty()) d1 = fs2us(s1); + if (d2.IsEmpty()) d2 = fs2us(s2); + return true; } #endif - static int convert_to_symlink(const char * name) { FILE *file = fopen(name,"rb"); if (file) { @@ -482,17 +337,17 @@ static int convert_to_symlink(const char * name) { if (ir == 0) { ir = symlink(buf,name); } - return ir; + return ir; } } return -1; } -bool MySetFileAttributes(LPCTSTR fileName, DWORD fileAttributes) +bool SetFileAttrib(CFSTR fileName, DWORD fileAttributes) { if (!fileName) { SetLastError(ERROR_PATH_NOT_FOUND); - TRACEN((printf("MySetFileAttributes(NULL,%d) : false-1\n",fileAttributes))) + TRACEN((printf("SetFileAttrib(NULL,%d) : false-1\n",fileAttributes))) return false; } #ifdef _UNICODE @@ -504,14 +359,14 @@ bool MySetFileAttributes(LPCTSTR fileName, DWORD fileAttributes) #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))) + TRACEN((printf("SetFileAttrib(%s,%d) : false-2-1\n",(const char *)name,fileAttributes))) return false; } } else #endif { if(stat(name,&stat_info)!=0) { - TRACEN((printf("MySetFileAttributes(%s,%d) : false-2-2\n",name,fileAttributes))) + TRACEN((printf("SetFileAttrib(%s,%d) : false-2-2\n",(const char *)name,fileAttributes))) return false; } } @@ -521,18 +376,18 @@ bool MySetFileAttributes(LPCTSTR fileName, DWORD fileAttributes) #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))) + TRACEN((printf("SetFileAttrib(%s,%d) : false-3\n",(const char *)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))) + TRACEN((printf("##DBG chmod-2(%s,%o)\n",(const char *)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))) + TRACEN((printf("##DBG chmod-3(%s,%o)\n",(const char *)name,(unsigned)stat_info.st_mode & gbl_umask.mask))) chmod(name,stat_info.st_mode & gbl_umask.mask); } #ifdef ENV_HAVE_LSTAT @@ -545,121 +400,123 @@ bool MySetFileAttributes(LPCTSTR fileName, DWORD fileAttributes) /* 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))) + TRACEN((printf("##DBG chmod-4(%s,%o)\n",(const char *)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))) + TRACEN((printf("##DBG chmod-5(%s,%o)\n",(const char *)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))) + TRACEN((printf("SetFileAttrib(%s,%d) : true\n",(const char *)name,fileAttributes))) return true; } -bool MyCreateDirectory(LPCTSTR pathName) -{ - if (!pathName || !*pathName) { +bool RemoveDir(CFSTR path) +{ + if (!path || !*path) { SetLastError(ERROR_PATH_NOT_FOUND); - return false; + return FALSE; } + AString name = nameWindowToUnix2(path); + TRACEN((printf("RemoveDirectoryA(%s)\n",(const char *)name))) + + if (rmdir( (const char *)name ) != 0) { + return FALSE; + } + return TRUE; +} +bool MyMoveFile(CFSTR existFileName, CFSTR newFileName) +{ #ifdef _UNICODE - AString name = nameWindowToUnix2(pathName); + AString src = nameWindowToUnix2(existFileName); + AString dst = nameWindowToUnix2(newFileName); #else - const char * name = nameWindowToUnix(pathName); + const char * src = nameWindowToUnix(existFileName); + const char * dst = nameWindowToUnix(newFileName); #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 + TRACEN((printf("MyMoveFile(%s,%s)\n",(const char *)src,(const char *)dst))) -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) + int ret = rename(src,dst); + if (ret != 0) { - if(MyCreateDirectory(pathName)) - break; - if(::GetLastError() == ERROR_ALREADY_EXISTS) + if (errno == EXDEV) // FIXED : bug #1112167 (Temporary directory must be on same partition as target) { -#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; + 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",(const char *)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; } - 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 false; } return true; } -#ifndef _UNICODE +bool CreateDir(CFSTR path) +{ + if (!path || !*path) { + SetLastError(ERROR_PATH_NOT_FOUND); + return false; + } -bool CreateComplexDirectory(LPCWSTR _aPathName) +#ifdef _UNICODE + AString name = nameWindowToUnix2(path); +#else + const char * name = nameWindowToUnix(path); +#endif + bool bret = false; + if (mkdir( name, 0700 ) == 0) bret = true; + + TRACEN((printf("CreateDir(%s)=%d\n",(const char *)name,(int)bret))) + return bret; +} + +bool CreateComplexDir(CFSTR _aPathName) { - UString pathName = _aPathName; - int pos = pathName.ReverseFind(WCHAR_PATH_SEPARATOR); - if (pos > 0 && pos == pathName.Length() - 1) + AString name = nameWindowToUnix2(_aPathName); + TRACEN((printf("CreateComplexDir(%s)\n",(const char *)name))) + + + FString pathName = _aPathName; + int pos = pathName.ReverseFind(FCHAR_PATH_SEPARATOR); + if (pos > 0 && pos == pathName.Len() - 1) { - if (pathName.Length() == 3 && pathName[1] == L':') + if (pathName.Len() == 3 && pathName[1] == L':') return true; // Disk folder; pathName.Delete(pos); } - UString pathName2 = pathName; - pos = pathName.Length(); - while(true) + FString pathName2 = pathName; + pos = pathName.Len(); + TRACEN((printf("CreateComplexDir(%s) pathName2=%ls\n",(const char *)name,(CFSTR)pathName2))) + for (;;) { - if(MyCreateDirectory(pathName)) + if (CreateDir(pathName)) break; - if(::GetLastError() == ERROR_ALREADY_EXISTS) + TRACEN((printf("CreateComplexDir(%s) GetLastError=%d (ERROR_ALREADY_EXISTS=%d)\n",(const char *)name,::GetLastError(), ERROR_ALREADY_EXISTS))) + 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 + NFind::CFileInfo fileInfo; + if (!fileInfo.Find(pathName)) // For network folders return true; if (!fileInfo.IsDir()) return false; #endif break; } - pos = pathName.ReverseFind(WCHAR_PATH_SEPARATOR); + pos = pathName.ReverseFind(FCHAR_PATH_SEPARATOR); if (pos < 0 || pos == 0) return false; if (pathName[pos - 1] == L':') @@ -667,20 +524,18 @@ bool CreateComplexDirectory(LPCWSTR _aPathName) pathName = pathName.Left(pos); } pathName = pathName2; - while(pos < pathName.Length()) + while (pos < pathName.Len()) { - pos = pathName.Find(WCHAR_PATH_SEPARATOR, pos + 1); + pos = pathName.Find(FCHAR_PATH_SEPARATOR, pos + 1); if (pos < 0) - pos = pathName.Length(); - if(!MyCreateDirectory(pathName.Left(pos))) + pos = pathName.Len(); + if (!CreateDir(pathName.Left(pos))) return false; } return true; } -#endif - -bool DeleteFileAlways(LPCTSTR name) +bool DeleteFileAlways(CFSTR name) { if (!name || !*name) { SetLastError(ERROR_PATH_NOT_FOUND); @@ -693,235 +548,344 @@ bool DeleteFileAlways(LPCTSTR name) #endif bool bret = false; if (remove(unixname) == 0) bret = true; - TRACEN((printf("DeleteFileAlways(%s)=%d\n",unixname,(int)bret))) + TRACEN((printf("DeleteFileAlways(%s)=%d\n",(const char *)unixname,(int)bret))) return bret; } -#ifndef _UNICODE -bool DeleteFileAlways(LPCWSTR name) -{ - return DeleteFileAlways(UnicodeStringToMultiByte(name, CP_ACP)); +bool RemoveDirWithSubItems(const FString &path) +{ + bool needRemoveSubItems = true; + { + NFind::CFileInfo fi; + if (!fi.Find(path)) + return false; + if (!fi.IsDir()) + { + ::SetLastError(ERROR_DIRECTORY); + return false; + } + if (fi.HasReparsePoint()) + needRemoveSubItems = false; + } + + if (needRemoveSubItems) + { + FString s = path; + s += FCHAR_PATH_SEPARATOR; + unsigned prefixSize = s.Len(); + s += FCHAR_ANY_MASK; + NFind::CEnumerator enumerator(s); + NFind::CFileInfo fi; + while (enumerator.Next(fi)) + { + s.DeleteFrom(prefixSize); + s += fi.Name; + if (fi.IsDir()) + { + if (!RemoveDirWithSubItems(s)) + return false; + } + else if (!DeleteFileAlways(s)) + return false; + } + } + + if (!SetFileAttrib(path, 0)) + return false; + return RemoveDir(path); } -#endif -static bool RemoveDirectorySubItems2(const UString &pathPrefix, const NFind::CFileInfoW &fileInfo) +bool RemoveDirectoryWithSubItems(const FString &path); // FIXME +static bool RemoveDirectorySubItems2(const FString pathPrefix, const NFind::CFileInfo &fileInfo) { if (fileInfo.IsDir()) return RemoveDirectoryWithSubItems(pathPrefix + fileInfo.Name); return DeleteFileAlways(pathPrefix + fileInfo.Name); } - -bool RemoveDirectoryWithSubItems(const UString &path) +bool RemoveDirectoryWithSubItems(const FString &path) { - NFind::CFileInfoW fileInfo; - UString pathPrefix = path + NName::kDirDelimiter; + NFind::CFileInfo fileInfo; + FString pathPrefix = path + FCHAR_PATH_SEPARATOR; { - NFind::CEnumeratorW enumerator(pathPrefix + TCHAR(NName::kAnyStringWildcard)); + NFind::CEnumerator enumerator(pathPrefix + FCHAR_ANY_MASK); while (enumerator.Next(fileInfo)) if (!RemoveDirectorySubItems2(pathPrefix, fileInfo)) return false; } - if (!MySetFileAttributes(path, 0)) + if (!SetFileAttrib(path, 0)) return false; - return MyRemoveDirectory(path); + return RemoveDir(path); } -#ifndef _WIN32_WCE +#ifdef UNDER_CE -bool MyGetFullPathName(LPCTSTR fileName, CSysString &resultPath, - int &fileNamePartStartIndex) +bool MyGetFullPathName(CFSTR fileName, FString &resFullPath) { - 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; + resFullPath = fileName; 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 +#else +#ifdef WIN_LONG_PATH -bool MyGetFullPathName(LPCTSTR fileName, CSysString &path) +static FString GetLastPart(CFSTR path) { - int index; - return MyGetFullPathName(fileName, path, index); + int i = MyStringLen(path); + for (; i > 0; i--) + { + FChar c = path[i - 1]; + if (c == FCHAR_PATH_SEPARATOR || c == '/') + break; + } + return path + i; } -#ifndef _UNICODE -bool MyGetFullPathName(LPCWSTR fileName, UString &path) +static void AddTrailingDots(CFSTR oldPath, FString &newPath) { - int index; - return MyGetFullPathName(fileName, path, index); + int len = MyStringLen(oldPath); + int i; + for (i = len; i > 0 && oldPath[i - 1] == '.'; i--); + if (i == 0 || i == len) + return; + FString oldName = GetLastPart(oldPath); + FString newName = GetLastPart(newPath); + int nonDotsLen = oldName.Len() - (len - i); + if (nonDotsLen == 0 || newName.CompareNoCase(oldName.Left(nonDotsLen)) != 0) + return; + for (; i != len; i++) + newPath += '.'; } -#endif #endif -/* needed to find .DLL/.so and SFX */ -bool MySearchPath(LPCWSTR path, LPCWSTR fileName, LPCWSTR extension, UString &resultPath) + +bool MyGetFullPathName(CFSTR fileName, FString &resFullPath) { - if (path != 0) { - printf("NOT EXPECTED : MySearchPath : path != NULL\n"); - exit(EXIT_FAILURE); + resFullPath.Empty(); + #ifndef _UNICODE + if (!g_IsNT) + { + TCHAR s[MAX_PATH + 2]; + s[0] = 0; + LPTSTR fileNamePointer = 0; + DWORD needLength = ::GetFullPathName(fs2fas(fileName), MAX_PATH + 1, s, &fileNamePointer); + if (needLength == 0 || needLength > MAX_PATH) + return false; + resFullPath = fas2fs(s); + return true; } - - if (extension != 0) { - printf("NOT EXPECTED : MySearchPath : extension != NULL\n"); - exit(EXIT_FAILURE); + else + #endif + { + LPWSTR fileNamePointer = 0; + WCHAR s[MAX_PATH + 2]; + s[0] = 0; + DWORD needLength = ::GetFullPathNameW(fs2us(fileName), MAX_PATH + 1, s, &fileNamePointer); + if (needLength == 0) + return false; + if (needLength <= MAX_PATH) + { + resFullPath = us2fs(s); + return true; + } + #ifdef WIN_LONG_PATH + needLength++; + UString temp; + LPWSTR buffer = temp.GetBuffer(needLength + 1); + buffer[0] = 0; + DWORD needLength2 = ::GetFullPathNameW(fs2us(fileName), needLength, buffer, &fileNamePointer); + temp.ReleaseBuffer(); + if (needLength2 > 0 && needLength2 <= needLength) + { + resFullPath = us2fs(temp); + AddTrailingDots(fileName, resFullPath); + return true; + } + #endif + return false; } +} - if (fileName == 0) { - printf("NOT EXPECTED : MySearchPath : fileName == NULL\n"); - exit(EXIT_FAILURE); - } +bool SetCurrentDir(CFSTR path) +{ + AString apath = UnicodeStringToMultiByte(path); - 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); + return chdir((const char*)apath) == 0; +} - 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; - } +bool GetCurrentDir(FString &path) +{ + char begin[MAX_PATHNAME_LEN]; + begin[0]='c'; + begin[1]=':'; + char * cret = getcwd(begin+2, MAX_PATHNAME_LEN - 3); + if (cret) + { +#ifdef _UNICODE + path = GetUnicodeString(begin); +#else + path = begin; +#endif + return true; } return false; } -#ifndef _UNICODE -bool MyGetTempPath(CSysString &path) -{ - path = "c:/tmp/"; // final '/' is needed - return true; -} #endif -bool MyGetTempPath(UString &path) +bool GetFullPathAndSplit(CFSTR path, FString &resDirPrefix, FString &resFileName) { - path = L"c:/tmp/"; // final '/' is needed - return true; + bool res = MyGetFullPathName(path, resDirPrefix); + if (!res) + resDirPrefix = path; + int pos = resDirPrefix.ReverseFind(FCHAR_PATH_SEPARATOR); + resFileName = resDirPrefix.Ptr(pos + 1); + resDirPrefix.DeleteFrom(pos + 1); + return res; } -static NSynchronization::CCriticalSection g_CountCriticalSection; +bool GetOnlyDirPrefix(CFSTR path, FString &resDirPrefix) +{ + FString resFileName; + return GetFullPathAndSplit(path, resDirPrefix, resFileName); +} -static CSysString CSysConvertUInt32ToString(UInt32 value) +bool MyGetTempPath(FString &path) { - TCHAR buffer[32]; - ConvertUInt32ToString(value, buffer); - return buffer; + path = L"c:/tmp/"; // final '/' is needed + return true; } -UINT CTempFile::Create(LPCTSTR dirPath, LPCTSTR prefix, CSysString &resultPath) +static bool CreateTempFile(CFSTR prefix, bool addRandom, FString &path, NIO::COutFile *outFile) { +#ifdef _WIN32 + UInt32 d = (GetTickCount() << 12) ^ (GetCurrentThreadId() << 14) ^ GetCurrentProcessId(); +#else 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; + UInt32 d = (GetTickCount() << 12) ^ (count << 14) ^ number; +#endif + for (unsigned i = 0; i < 100; i++) + { + path = prefix; + if (addRandom) + { + FChar s[16]; + UInt32 value = d; + unsigned k; + for (k = 0; k < 8; k++) + { + unsigned t = value & 0xF; + value >>= 4; + s[k] = (char)((t < 10) ? ('0' + t) : ('A' + (t - 10))); + } + s[k] = '\0'; + if (outFile) + path += FChar('.'); + path += s; + UInt32 step = GetTickCount() + 2; + if (step == 0) + step = 1; + d += step; + } + addRandom = true; + if (outFile) + path += FTEXT(".tmp"); + if (NFind::DoesFileOrDirExist(path)) + { + SetLastError(ERROR_ALREADY_EXISTS); + continue; + } + if (outFile) + { + if (outFile->Create(path, false)) + return true; + } + else + { + if (CreateDir(path)) + return true; + } + DWORD error = GetLastError(); + if (error != ERROR_FILE_EXISTS && + error != ERROR_ALREADY_EXISTS) + break; + } + path.Empty(); + return false; +} + +bool CTempFile::Create(CFSTR prefix, NIO::COutFile *outFile) +{ + if (!Remove()) + return false; + if (!CreateTempFile(prefix, false, _path, outFile)) + return false; _mustBeDeleted = true; - - return number; + return true; } -bool CTempFile::Create(LPCTSTR prefix, CSysString &resultPath) +bool CTempFile::CreateRandomInTempFolder(CFSTR namePrefix, NIO::COutFile *outFile) { - CSysString tempPath; + if (!Remove()) + return false; + FString tempPath; if (!MyGetTempPath(tempPath)) return false; - if (Create(tempPath, prefix, resultPath) != 0) - return true; - return false; + if (!CreateTempFile(tempPath + namePrefix, true, _path, outFile)) + return false; + _mustBeDeleted = true; + return true; } - bool CTempFile::Remove() { if (!_mustBeDeleted) return true; - _mustBeDeleted = !DeleteFileAlways(_fileName); + _mustBeDeleted = !DeleteFileAlways(_path); return !_mustBeDeleted; } -bool CreateTempDirectory(LPCWSTR prefix, UString &dirName) +bool CTempFile::MoveTo(CFSTR name, bool deleteDestBefore) { - /* - CSysString prefix = tempPath + prefixChars; - CRandom random; - random.Init(); - */ - for (;;) - { - { - CTempFileW tempFile; - if (!tempFile.Create(prefix, dirName)) - return false; - if (!tempFile.Remove()) + if (deleteDestBefore) + if (NFind::DoesFileExist(name)) + if (!DeleteFileAlways(name)) 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; - } + DisableDeleting(); + return MyMoveFile(_path, name); } -bool CTempDirectory::Create(LPCTSTR prefix) +bool CTempDir::Create(CFSTR prefix) { - Remove(); - return (_mustBeDeleted = CreateTempDirectory(prefix, _tempDir)); + if (!Remove()) + return false; + FString tempPath; + if (!MyGetTempPath(tempPath)) + return false; + if (!CreateTempFile(tempPath + prefix, true, _path, NULL)) + return false; + _mustBeDeleted = true; + return true; } +bool CTempDir::Remove() +{ + if (!_mustBeDeleted) + return true; + _mustBeDeleted = !RemoveDirectoryWithSubItems(_path); + return !_mustBeDeleted; +} }}} + + + |