2 // This file is part of the aMule Project.
4 // Copyright (c) 2008-2011 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 #include "PlatformSpecific.h"
28 // NTFS Sparse Files (only for MSW)
30 #include "common/Format.h"
34 #ifndef FSCTL_SET_SPARSE
35 # define FSCTL_SET_SPARSE CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 49, METHOD_BUFFERED, FILE_SPECIAL_ACCESS)
37 #ifndef FSCTL_SET_ZERO_DATA
38 # define FSCTL_SET_ZERO_DATA CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 50, METHOD_BUFFERED, FILE_WRITE_DATA)
41 // Create a message from a Windows error code
42 static wxString
SystemError()
44 WCHAR
* lpMsgBuf
= NULL
;
47 FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
,
50 0, // Default language
56 wxString
ret(lpMsgBuf
);
61 // Create a file in sparse mode
62 bool PlatformSpecific::CreateSparseFile(const CPath
& name
, uint64_t size
)
64 DWORD dwReturnedBytes
=0;
66 HANDLE hd
= CreateFileW(name
.GetRaw().c_str(),
67 GENERIC_READ
| GENERIC_WRITE
,
68 0, // share - not shareable
69 NULL
, // security - not inheritable
71 FILE_ATTRIBUTE_ARCHIVE
,
73 if (hd
== INVALID_HANDLE_VALUE
) {
74 AddDebugLogLineC(logPartFile
, CFormat(wxT("converting %s to sparse failed (OPEN): %s ")) % name
% SystemError());
78 if (!DeviceIoControl(hd
, FSCTL_SET_SPARSE
, NULL
, 0, NULL
, 0, &dwReturnedBytes
, NULL
)) {
79 AddDebugLogLineC(logPartFile
, CFormat(wxT("converting %s to sparse failed (SET_SPARSE): %s ")) % name
% SystemError());
81 // FILE_ZERO_DATA_INFORMATION is not defined here
84 uint64 BeyondFinalZero
;
87 fzdi
.BeyondFinalZero
= size
;
89 largo
.QuadPart
= size
;
92 if (!DeviceIoControl(hd
, FSCTL_SET_ZERO_DATA
, (LPVOID
) &fzdi
, sizeof(fzdi
), NULL
, 0, &dwReturnedBytes
, NULL
)) {
93 AddDebugLogLineC(logPartFile
, CFormat(wxT("converting %s to sparse failed (ZERO): %s")) % name
% SystemError());
94 } else if (!SetFilePointerEx(hd
, largo
, NULL
, FILE_BEGIN
) || !SetEndOfFile(hd
)) {
95 AddDebugLogLineC(logPartFile
, CFormat(wxT("converting %s to sparse failed (SEEK): %s")) % name
% SystemError());
102 #else // non Windows systems don't need all this
105 bool PlatformSpecific::CreateSparseFile(const CPath
& name
, uint64_t WXUNUSED(size
))
108 return f
.Create(name
.GetRaw(), true) && f
.Close();
114 #include <wx/msw/registry.h>
115 #include <wx/utils.h>
117 // Get the max number of connections that the OS supports, or -1 for default
118 int PlatformSpecific::GetMaxConnections()
121 // Try to get the max connection value in the registry
122 wxRegKey
key( wxT("HKEY_LOCAL_MACHINE\\System\\CurrentControlSet\\Services\\VxD\\MSTCP\\MaxConnections") );
124 if ( key
.Exists() ) {
125 value
= key
.QueryDefaultValue();
127 if ( !value
.IsEmpty() && value
.IsNumber() ) {
132 switch (wxGetOsVersion()) {
133 case wxOS_WINDOWS_9X
:
134 // This includes all Win9x versions
137 case wxOS_WINDOWS_NT
:
138 // This includes NT based windows
142 // Anything else. Let aMule decide...
156 static PlatformSpecific::EFSType
doGetFilesystemType(const CPath
& path
)
158 wxWritableWCharBuffer
pathRaw(path
.GetRaw().wchar_str());
159 LPWSTR volume
= pathRaw
;
160 if (!PathStripToRootW(volume
)) {
161 return PlatformSpecific::fsOther
;
163 PathAddBackslashW(volume
);
165 DWORD maximumComponentLength
= 0;
166 DWORD filesystemFlags
= 0;
167 WCHAR filesystemNameBuffer
[128];
168 if (!GetVolumeInformationW(volume
, NULL
, 0, NULL
, &maximumComponentLength
, &filesystemFlags
, filesystemNameBuffer
, 128)) {
169 return PlatformSpecific::fsOther
;
171 if (wxStrnicmp(filesystemNameBuffer
, wxT("FAT"), 3) == 0) {
172 return PlatformSpecific::fsFAT
;
173 } else if (wxStrcmp(filesystemNameBuffer
, wxT("NTFS")) == 0) {
174 return PlatformSpecific::fsNTFS
;
176 return PlatformSpecific::fsOther
;
179 #elif defined(HAVE_GETMNTENT) && defined(HAVE_MNTENT_H)
183 #ifndef _PATH_MOUNTED
184 # define _PATH_MOUNTED "/etc/mtab"
186 #include <common/StringFunctions.h>
188 static PlatformSpecific::EFSType
doGetFilesystemType(const CPath
& path
)
190 struct mntent
*entry
= NULL
;
191 PlatformSpecific::EFSType retval
= PlatformSpecific::fsOther
;
192 FILE *mnttab
= fopen(_PATH_MOUNTED
, "r");
193 unsigned bestPrefixLen
= 0;
195 if (mnttab
== NULL
) {
196 return PlatformSpecific::fsOther
;
199 while ((entry
= getmntent(mnttab
)) != NULL
) {
200 if (entry
->mnt_dir
) {
201 wxString dir
= char2unicode(entry
->mnt_dir
);
202 if (dir
== path
.GetRaw().Mid(0, dir
.Length())) {
203 if (dir
.Length() >= bestPrefixLen
) {
204 if (entry
->mnt_type
== NULL
) {
206 } else if (!strcmp(entry
->mnt_type
, "ntfs")) {
207 retval
= PlatformSpecific::fsNTFS
;
208 } else if (!strcmp(entry
->mnt_type
, "msdos") ||
209 !strcmp(entry
->mnt_type
, "umsdos") ||
210 !strcmp(entry
->mnt_type
, "vfat") ||
211 !strncmp(entry
->mnt_type
, "fat", 3)) {
212 retval
= PlatformSpecific::fsFAT
;
213 } else if (!strcmp(entry
->mnt_type
, "hfs")) {
214 retval
= PlatformSpecific::fsHFS
;
215 } else if (!strcmp(entry
->mnt_type
, "hpfs")) {
216 retval
= PlatformSpecific::fsHPFS
;
217 } else if (!strcmp(entry
->mnt_type
, "minix")) {
218 retval
= PlatformSpecific::fsMINIX
;
219 } /* Add more filesystem types here */
220 else if (dir
.Length() > bestPrefixLen
) {
221 retval
= PlatformSpecific::fsOther
;
223 bestPrefixLen
= dir
.Length();
232 #elif defined(HAVE_GETMNTENT) && defined(HAVE_SYS_MNTENT_H) && defined(HAVE_SYS_MNTTAB_H)
235 #include <sys/mntent.h>
236 #include <sys/mnttab.h>
238 # define MNTTAB "/etc/mnttab"
240 #include <common/StringFunctions.h>
242 static PlatformSpecific::EFSType
doGetFilesystemType(const CPath
& path
)
244 struct mnttab entryStatic
;
245 struct mnttab
*entry
= &entryStatic
;
246 PlatformSpecific::EFSType retval
= PlatformSpecific::fsOther
;
247 FILE *fmnttab
= fopen(MNTTAB
, "r");
248 unsigned bestPrefixLen
= 0;
250 if (fmnttab
== NULL
) {
251 return PlatformSpecific::fsOther
;
254 while (getmntent(fmnttab
, entry
) == 0) {
255 if (entry
->mnt_mountp
) {
256 wxString dir
= char2unicode(entry
->mnt_mountp
);
257 if (dir
== path
.GetRaw().Mid(0, dir
.Length())) {
258 if (dir
.Length() >= bestPrefixLen
) {
259 if (entry
->mnt_fstype
== NULL
) {
261 } else if (!strcmp(entry
->mnt_fstype
, MNTTYPE_PCFS
)) {
262 retval
= PlatformSpecific::fsFAT
;
263 } else if (hasmntopt(entry
, MNTOPT_NOLARGEFILES
)) {
264 // MINIX is a file system that can handle special chars but has no large files.
265 retval
= PlatformSpecific::fsMINIX
;
266 } else if (dir
.Length() > bestPrefixLen
) {
267 retval
= PlatformSpecific::fsOther
;
269 bestPrefixLen
= dir
.Length();
280 // No way to determine filesystem type, no restrictions apply.
281 static inline PlatformSpecific::EFSType
doGetFilesystemType(const CPath
& WXUNUSED(path
))
283 return PlatformSpecific::fsOther
;
289 #include <wx/thread.h>
291 PlatformSpecific::EFSType
PlatformSpecific::GetFilesystemType(const CPath
& path
)
293 typedef std::map
<wxString
, EFSType
> FSMap
;
294 // Caching previous results, to speed up further checks.
295 static FSMap s_fscache
;
296 // Lock used to ensure the integrity of the cache.
297 static wxMutex s_lock
;
299 wxCHECK_MSG(path
.IsOk(), fsOther
, wxT("Invalid path in GetFilesystemType()"));
301 wxMutexLocker
locker(s_lock
);
303 FSMap::iterator it
= s_fscache
.find(path
.GetRaw());
304 if (it
!= s_fscache
.end()) {
308 return s_fscache
[path
.GetRaw()] = doGetFilesystemType(path
);
312 // Power event vetoing
314 static bool m_preventingSleepMode
= false;
316 #if defined(__WXMAC__) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 1050 // 10.5 only
317 #include <IOKit/pwr_mgt/IOPMLib.h>
318 static IOPMAssertionID assertionID
;
321 void PlatformSpecific::PreventSleepMode()
323 if (!m_preventingSleepMode
) {
325 SetThreadExecutionState(ES_CONTINUOUS
| ES_SYSTEM_REQUIRED
);
326 m_preventingSleepMode
= true;
328 // IOPMAssertionCreate has been introduced in Leopard (10.5) but deprecated starting from Snow Leopard(10.6)
329 // For more details see:
330 // - http://developer.apple.com/library/mac/#qa/qa1340/_index.html
331 // - http://www.cimgf.com/2009/10/14/the-journey-to-disabling-sleep-with-iokit/
332 #elif defined(__WXMAC__) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 1060 // 10.6 only
333 CFStringRef reasonForActivity
= CFSTR("Prevent Display Sleep");
334 IOReturn success
= IOPMAssertionCreateWithName(kIOPMAssertionTypeNoDisplaySleep
,
335 kIOPMAssertionLevelOn
, reasonForActivity
, &assertionID
);
336 if (success
== kIOReturnSuccess
) {
337 // Correctly vetoed, flag so we don't do it again.
338 m_preventingSleepMode
= true;
340 // May be should be better to trace in log?
343 #elif defined(__WXMAC__) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 1050 // 10.5 only
344 IOReturn success
= IOPMAssertionCreate(kIOPMAssertionTypeNoDisplaySleep
,
345 kIOPMAssertionLevelOn
, &assertionID
);
346 if (success
== kIOReturnSuccess
) {
347 // Correctly vetoed, flag so we don't do it again.
348 m_preventingSleepMode
= true;
353 //#warning Power event vetoing not implemented.
359 void PlatformSpecific::AllowSleepMode()
361 if (m_preventingSleepMode
) {
363 SetThreadExecutionState(ES_CONTINUOUS
); // Clear the system request flag.
364 m_preventingSleepMode
= false;
365 #elif defined(__WXMAC__) && __MAC_OS_X_VERSION_MAX_ALLOWED >= 1050 // 10.5 only
366 IOReturn success
= IOPMAssertionRelease(assertionID
);
367 if (success
== kIOReturnSuccess
) {
368 // Correctly restored, flag so we don't do it again.
369 m_preventingSleepMode
= false;