1 // TortoiseGitMerge - a Windows shell extension for easy version control
3 // Copyright (C) 2003-2012 - TortoiseSVN
5 // This program is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU General Public License
7 // as published by the Free Software Foundation; either version 2
8 // of the License, or (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software Foundation,
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 #include "PathUtils.h"
22 #include "DirFileEnum.h"
23 #include "SmartHandle.h"
25 CTempFiles::CTempFiles(void)
29 CTempFiles::~CTempFiles(void)
31 m_TempFileList
.DeleteAllFiles(false, false);
34 CTempFiles
& CTempFiles::Instance()
36 static CTempFiles instance
;
40 CTGitPath
CTempFiles::ConstructTempPath(const CTGitPath
& path
)
42 DWORD len
= ::GetTempPath(0, nullptr);
43 auto temppath
= std::make_unique
<TCHAR
[]>(len
+ 1);
44 auto tempF
= std::make_unique
<TCHAR
[]>(len
+ 50);
45 ::GetTempPath (len
+1, temppath
.get());
47 CString possibletempfile
;
50 ::GetTempFileName(temppath
.get(), L
"tsm", 0, tempF
.get());
51 tempfile
= CTGitPath (tempF
.get());
58 // use the UI path, which does unescaping for urls
59 CString filename
= path
.GetUIFileOrDirectoryName();
60 // remove illegal chars which could be present in urls
67 // the inner loop assures that the resulting path is < MAX_PATH
68 // if that's not possible without reducing the 'filename' to less than 5 chars, use a path
69 // that's longer than MAX_PATH (in that case, we can't really do much to avoid longer paths)
72 possibletempfile
.Format(L
"%s%s.tsm%3.3x.tmp%s", temppath
.get(), (LPCTSTR
)filename
, i
, (LPCTSTR
)path
.GetFileExtension());
73 tempfile
.SetFromWin(possibletempfile
);
74 filename
= filename
.Left(filename
.GetLength()-1);
75 } while ( (filename
.GetLength() > 4)
76 && (tempfile
.GetWinPathString().GetLength() >= MAX_PATH
));
78 } while (PathFileExists(tempfile
.GetWinPath()));
81 // caller has to actually grab the file path
86 CTGitPath
CTempFiles::CreateTempPath (bool bRemoveAtEnd
, const CTGitPath
& path
, bool directory
)
88 bool succeeded
= false;
89 for (int retryCount
= 0; retryCount
< MAX_RETRIES
; ++retryCount
)
91 CTGitPath tempfile
= ConstructTempPath (path
);
93 // now create the temp file / directory, so that subsequent calls to GetTempFile() return
94 // different filenames.
95 // Handle races, i.e. name collisions.
99 DeleteFile(tempfile
.GetWinPath());
100 if (CreateDirectory(tempfile
.GetWinPath(), nullptr) == FALSE
)
102 if (GetLastError() != ERROR_ALREADY_EXISTS
)
110 CAutoFile hFile
= CreateFile(tempfile
.GetWinPath(), GENERIC_READ
, FILE_SHARE_READ
, nullptr, CREATE_ALWAYS
, FILE_ATTRIBUTE_TEMPORARY
, nullptr);
113 if (GetLastError() != ERROR_ALREADY_EXISTS
)
127 m_TempFileList
.AddPath(tempfile
);
138 CTGitPath
CTempFiles::GetTempFilePath(bool bRemoveAtEnd
, const CTGitPath
& path
/* = CTGitPath() */)
140 return CreateTempPath (bRemoveAtEnd
, path
, false);
143 CString
CTempFiles::GetTempFilePathString()
145 return CreateTempPath (true, CTGitPath(), false).GetWinPathString();
148 CTGitPath
CTempFiles::GetTempDirPath(bool bRemoveAtEnd
, const CTGitPath
& path
/* = CTGitPath() */)
150 return CreateTempPath (bRemoveAtEnd
, path
, true);
153 void CTempFiles::DeleteOldTempFiles(LPCTSTR wildCard
)
155 DWORD len
= ::GetTempPath(0, nullptr);
156 auto path
= std::make_unique
<TCHAR
[]>(len
+ 100);
157 len
= ::GetTempPath (len
+100, path
.get());
161 CSimpleFileFind finder
= CSimpleFileFind(path
.get(), wildCard
);
163 ::GetSystemTimeAsFileTime(&systime_
);
164 __int64 systime
= (__int64
)systime_
.dwLowDateTime
| (__int64
)systime_
.dwHighDateTime
<< 32LL;
165 while (finder
.FindNextFileNoDirectories())
167 CString filepath
= finder
.GetFilePath();
169 FILETIME createtime_
= finder
.GetCreateTime();
170 __int64 createtime
= (__int64
)createtime_
.dwLowDateTime
| (__int64
)createtime_
.dwHighDateTime
<< 32LL;
171 createtime
+= 864000000000LL; //only delete files older than a day
172 if (createtime
< systime
)
174 ::SetFileAttributes(filepath
, FILE_ATTRIBUTE_NORMAL
);
175 ::DeleteFile(filepath
);