2 // This file is part of the aMule Project.
4 // Copyright (c) 2008 aMule Team ( admin@amule.org / http://www.amule.org )
6 // Any parts of this program derived from the xMule, lMule or eMule project,
7 // or contributed by third-party developers are copyrighted by their
10 // This program is free software; you can redistribute it and/or modify
11 // it under the terms of the GNU General Public License as published by
12 // the Free Software Foundation; either version 2 of the License, or
13 // (at your option) any later version.
15 // This program is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU General Public License for more details.
20 // You should have received a copy of the GNU General Public License
21 // along with this program; if not, write to the Free Software
22 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 // MP: This define needs to be kept here, before the .h include because wxWidgets will include the WinIoCtl.h
26 // file with a different value, and we'll never get the FSCTL_SET_SPARSE
27 #define _WIN32_WINNT 0x0500
29 #include "PlatformSpecific.h"
35 // NTFS Sparse Files (only for MSW)
37 #include "common/Format.h"
41 # include <ddk/ntifs.h>
43 # include <winioctl.h>
46 // Create a message from a Windows error code
47 static wxString
SystemError()
49 WCHAR
* lpMsgBuf
= NULL
;
52 FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
,
55 0, // Default language
61 wxString
ret(lpMsgBuf
);
66 // Create a file in sparse mode
67 bool PlatformSpecific::CreateSparseFile(const CPath
& name
, uint64_t size
)
69 DWORD dwReturnedBytes
=0;
71 HANDLE hd
= CreateFileW(name
.GetRaw().c_str(),
72 GENERIC_READ
| GENERIC_WRITE
,
73 0, // share - not shareable
74 NULL
, // security - not inheritable
76 FILE_ATTRIBUTE_ARCHIVE
,
78 if (hd
== INVALID_HANDLE_VALUE
) {
79 AddDebugLogLineM(true, logPartFile
, CFormat(wxT("converting %s to sparse failed (OPEN): %s ")) % name
% SystemError());
83 if (!DeviceIoControl(hd
, FSCTL_SET_SPARSE
, NULL
, 0, NULL
, 0, &dwReturnedBytes
, NULL
)) {
84 AddDebugLogLineM(true, logPartFile
, CFormat(wxT("converting %s to sparse failed (SET_SPARSE): %s ")) % name
% SystemError());
86 // FILE_ZERO_DATA_INFORMATION is not defined here
89 uint64 BeyondFinalZero
;
92 fzdi
.BeyondFinalZero
= size
;
94 largo
.QuadPart
= size
;
97 if (!DeviceIoControl(hd
, FSCTL_SET_ZERO_DATA
, (LPVOID
) &fzdi
, sizeof(fzdi
), NULL
, 0, &dwReturnedBytes
, NULL
)) {
98 AddDebugLogLineM(true, logPartFile
, CFormat(wxT("converting %s to sparse failed (ZERO): %s")) % name
% SystemError());
99 } else if (!SetFilePointerEx(hd
, largo
, NULL
, FILE_BEGIN
) || !SetEndOfFile(hd
)) {
100 AddDebugLogLineM(true, logPartFile
, CFormat(wxT("converting %s to sparse failed (SEEK): %s")) % name
% SystemError());
107 #else // non Windows systems don't need all this
110 bool PlatformSpecific::CreateSparseFile(const CPath
& name
, uint64_t WXUNUSED(size
))
113 return f
.Create(name
.GetRaw(), true) && f
.Close();
119 #include <wx/msw/registry.h>
120 #include <wx/utils.h>
122 // Get the max number of connections that the OS supports, or -1 for default
123 int PlatformSpecific::GetMaxConnections()
126 // Try to get the max connection value in the registry
127 wxRegKey
key( wxT("HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Services\\VxD\\MSTCP\\MaxConnections") );
129 if ( key
.Exists() ) {
130 value
= key
.QueryDefaultValue();
132 if ( !value
.IsEmpty() && value
.IsNumber() ) {
137 switch (wxGetOsVersion()) {
138 case wxOS_WINDOWS_9X
:
139 // This includes all Win9x versions
142 case wxOS_WINDOWS_NT
:
143 // This includes NT based windows
147 // Anything else. Let aMule decide...
161 static PlatformSpecific::EFSType
doGetFilesystemType(const CPath
& path
)
163 wxWritableWCharBuffer
pathRaw(path
.GetRaw());
164 LPWSTR volume
= pathRaw
;
165 if (!PathStripToRootW(volume
)) {
166 return PlatformSpecific::fsOther
;
168 PathAddBackslashW(volume
);
170 DWORD maximumComponentLength
= 0;
171 DWORD filesystemFlags
= 0;
172 WCHAR filesystemNameBuffer
[128];
173 if (!GetVolumeInformationW(volume
, NULL
, 0, NULL
, &maximumComponentLength
, &filesystemFlags
, filesystemNameBuffer
, 128)) {
174 return PlatformSpecific::fsOther
;
176 if (wxStrnicmp(filesystemNameBuffer
, wxT("FAT"), 3) == 0) {
177 return PlatformSpecific::fsFAT
;
178 } else if (wxStrcmp(filesystemNameBuffer
, wxT("NTFS")) == 0) {
179 return PlatformSpecific::fsNTFS
;
181 return PlatformSpecific::fsOther
;
184 #elif defined(HAVE_GETMNTENT)
188 #ifndef _PATH_MOUNTED
189 # define _PATH_MOUNTED "/etc/mtab"
191 #include <common/StringFunctions.h>
193 static PlatformSpecific::EFSType
doGetFilesystemType(const CPath
& path
)
195 struct mntent
*entry
= NULL
;
196 PlatformSpecific::EFSType retval
= PlatformSpecific::fsOther
;
197 FILE *mnttab
= fopen(_PATH_MOUNTED
, "r");
198 unsigned bestPrefixLen
= 0;
200 if (mnttab
== NULL
) {
201 return PlatformSpecific::fsOther
;
204 while ((entry
= getmntent(mnttab
)) != NULL
) {
205 if (entry
->mnt_dir
) {
206 wxString dir
= char2unicode(entry
->mnt_dir
);
207 if (dir
== path
.GetRaw().Mid(0, dir
.Length())) {
208 if (dir
.Length() >= bestPrefixLen
) {
209 if (entry
->mnt_type
== NULL
) {
211 } else if (!strcmp(entry
->mnt_type
, "ntfs")) {
212 retval
= PlatformSpecific::fsNTFS
;
213 } else if (!strcmp(entry
->mnt_type
, "msdos") ||
214 !strcmp(entry
->mnt_type
, "umsdos") ||
215 !strcmp(entry
->mnt_type
, "vfat") ||
216 !strncmp(entry
->mnt_type
, "fat", 3)) {
217 retval
= PlatformSpecific::fsFAT
;
218 } else if (!strcmp(entry
->mnt_type
, "hfs")) {
219 retval
= PlatformSpecific::fsHFS
;
220 } else if (!strcmp(entry
->mnt_type
, "hpfs")) {
221 retval
= PlatformSpecific::fsHPFS
;
222 } else if (!strcmp(entry
->mnt_type
, "minix")) {
223 retval
= PlatformSpecific::fsMINIX
;
224 } /* Add more filesystem types here */
225 else if (dir
.Length() > bestPrefixLen
) {
226 retval
= PlatformSpecific::fsOther
;
228 bestPrefixLen
= dir
.Length();
239 // No way to determine filesystem type, all restrictions apply.
240 static inline PlatformSpecific::EFSType
doGetFilesystemType(const CPath
& WXUNUSED(path
))
242 return PlatformSpecific::fsOther
;
248 #include <wx/thread.h>
250 PlatformSpecific::EFSType
PlatformSpecific::GetFilesystemType(const CPath
& path
)
252 typedef std::map
<wxString
, EFSType
> FSMap
;
253 // Caching previous results, to speed up further checks.
254 static FSMap s_fscache
;
255 // Lock used to ensure the integrity of the cache.
256 static wxMutex s_lock
;
258 wxCHECK_MSG(path
.IsOk(), fsOther
, wxT("Invalid path in GetFilesystemType()"));
260 wxMutexLocker
locker(s_lock
);
262 FSMap::iterator it
= s_fscache
.find(path
.GetRaw());
263 if (it
!= s_fscache
.end()) {
267 return s_fscache
[path
.GetRaw()] = doGetFilesystemType(path
);