3 * Copyright (c) 2002 Frodo
4 * Portions Copyright (c) by the authors of ffmpeg and xvid
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include "utils/AliasShortcutUtils.h"
32 #include <sys/ioctl.h>
35 #include "utils/CharsetConverter.h"
36 #include "utils/URIUtils.h"
38 #include "utils/log.h"
41 using namespace XFILE;
43 //////////////////////////////////////////////////////////////////////
44 // Construction/Destruction
45 //////////////////////////////////////////////////////////////////////
47 //*********************************************************************************************
49 : m_hFile(INVALID_HANDLE_VALUE)
52 //*********************************************************************************************
55 if (m_hFile != INVALID_HANDLE_VALUE) Close();
57 //*********************************************************************************************
58 CStdString CHDFile::GetLocal(const CURL &url)
60 CStdString path( url.GetFileName() );
62 if( url.GetProtocol().Equals("file", false) )
64 // file://drive[:]/path
65 // file:///drive:/path
66 CStdString host( url.GetHostName() );
70 if(host.Right(1) == ":")
71 path = host + "/" + path;
73 path = host + ":/" + path;
78 path.Replace('/', '\\');
81 if (IsAliasShortcut(path))
82 TranslateAliasShortcut(path);
87 //*********************************************************************************************
88 bool CHDFile::Open(const CURL& url)
90 CStdString strFile = GetLocal(url);
94 g_charsetConverter.utf8ToW(strFile, strWFile, false);
95 m_hFile.attach(CreateFileW(strWFile.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL));
97 m_hFile.attach(CreateFile(strFile.c_str(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL));
99 if (!m_hFile.isValid()) return false;
107 bool CHDFile::Exists(const CURL& url)
109 struct __stat64 buffer;
110 CStdString strFile = GetLocal(url);
113 CStdStringW strWFile;
114 URIUtils::RemoveSlashAtEnd(strFile);
115 g_charsetConverter.utf8ToW(strFile, strWFile, false);
116 return (_wstat64(strWFile.c_str(), &buffer)==0);
118 return (_stat64(strFile.c_str(), &buffer)==0);
122 int CHDFile::Stat(struct __stat64* buffer)
125 return _fstat64((*m_hFile).fd, buffer);
127 // Duplicate the handle, as retrieving and closing a matching crt handle closes the crt handle AND the original Windows handle.
129 if (0 == DuplicateHandle(GetCurrentProcess(), (HANDLE)m_hFile, GetCurrentProcess(), &hFileDup, 0, FALSE, DUPLICATE_SAME_ACCESS))
131 CLog::Log(LOGERROR, __FUNCTION__" - DuplicateHandle()");
136 fd = _open_osfhandle((intptr_t)((HANDLE)hFileDup), 0);
139 CLog::Log(LOGERROR, "Stat: fd == -1");
142 int result = _fstat64(fd, buffer);
148 int CHDFile::Stat(const CURL& url, struct __stat64* buffer)
150 CStdString strFile = GetLocal(url);
153 CStdStringW strWFile;
154 // win32 can only stat root drives with a slash at the end
155 if(strFile.length() == 2 && strFile[1] ==':')
156 URIUtils::AddSlashAtEnd(strFile);
157 /* _wstat64 calls FindFirstFileEx. According to MSDN, the path should not end in a trailing backslash.
158 Remove it before calling _wstat64 */
159 if (strFile.length() > 3 && URIUtils::HasSlashAtEnd(strFile))
160 URIUtils::RemoveSlashAtEnd(strFile);
161 g_charsetConverter.utf8ToW(strFile, strWFile, false);
162 return _wstat64(strWFile.c_str(), buffer);
164 return _stat64(strFile.c_str(), buffer);
168 bool CHDFile::SetHidden(const CURL &url, bool hidden)
172 g_charsetConverter.utf8ToW(GetLocal(url), path, false);
173 DWORD attributes = hidden ? FILE_ATTRIBUTE_HIDDEN : FILE_ATTRIBUTE_NORMAL;
174 if (SetFileAttributesW(path.c_str(), attributes))
180 //*********************************************************************************************
181 bool CHDFile::OpenForWrite(const CURL& url, bool bOverWrite)
183 // make sure it's a legal FATX filename (we are writing to the harddisk)
184 CStdString strPath = GetLocal(url);
187 CStdStringW strWPath;
188 g_charsetConverter.utf8ToW(strPath, strWPath, false);
189 m_hFile.attach(CreateFileW(strWPath.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, bOverWrite ? CREATE_ALWAYS : OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL));
191 m_hFile.attach(CreateFile(strPath.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, bOverWrite ? CREATE_ALWAYS : OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL));
193 if (!m_hFile.isValid())
202 //*********************************************************************************************
203 unsigned int CHDFile::Read(void *lpBuf, int64_t uiBufSize)
205 if (!m_hFile.isValid()) return 0;
207 if ( ReadFile((HANDLE)m_hFile, lpBuf, (DWORD)uiBufSize, &nBytesRead, NULL) )
209 m_i64FilePos += nBytesRead;
215 //*********************************************************************************************
216 int CHDFile::Write(const void *lpBuf, int64_t uiBufSize)
218 if (!m_hFile.isValid())
222 if ( WriteFile((HANDLE)m_hFile, (void*) lpBuf, (DWORD)uiBufSize, &nBytesWriten, NULL) )
228 //*********************************************************************************************
229 void CHDFile::Close()
234 //*********************************************************************************************
235 int64_t CHDFile::Seek(int64_t iFilePosition, int iWhence)
237 LARGE_INTEGER lPos, lNewPos;
238 lPos.QuadPart = iFilePosition;
244 bSuccess = SetFilePointerEx((HANDLE)m_hFile, lPos, &lNewPos, FILE_BEGIN);
248 bSuccess = SetFilePointerEx((HANDLE)m_hFile, lPos, &lNewPos, FILE_CURRENT);
252 bSuccess = SetFilePointerEx((HANDLE)m_hFile, lPos, &lNewPos, FILE_END);
260 m_i64FilePos = lNewPos.QuadPart;
267 //*********************************************************************************************
268 int64_t CHDFile::GetLength()
270 if(m_i64FileLen <= m_i64FilePos || m_i64FileLen == 0)
272 LARGE_INTEGER i64Size;
273 if(GetFileSizeEx((HANDLE)m_hFile, &i64Size))
274 m_i64FileLen = i64Size.QuadPart;
276 CLog::Log(LOGERROR, "CHDFile::GetLength - GetFileSizeEx failed with error %d", GetLastError());
281 //*********************************************************************************************
282 int64_t CHDFile::GetPosition()
287 bool CHDFile::Delete(const CURL& url)
289 CStdString strFile=GetLocal(url);
292 CStdStringW strWFile;
293 g_charsetConverter.utf8ToW(strFile, strWFile, false);
294 return ::DeleteFileW(strWFile.c_str()) ? true : false;
296 return ::DeleteFile(strFile.c_str()) ? true : false;
300 bool CHDFile::Rename(const CURL& url, const CURL& urlnew)
302 CStdString strFile=GetLocal(url);
303 CStdString strNewFile=GetLocal(urlnew);
306 CStdStringW strWFile;
307 CStdStringW strWNewFile;
308 g_charsetConverter.utf8ToW(strFile, strWFile, false);
309 g_charsetConverter.utf8ToW(strNewFile, strWNewFile, false);
310 return ::MoveFileW(strWFile.c_str(), strWNewFile.c_str()) ? true : false;
312 return ::MoveFile(strFile.c_str(), strNewFile.c_str()) ? true : false;
316 void CHDFile::Flush()
318 ::FlushFileBuffers(m_hFile);
321 int CHDFile::IoControl(EIoControl request, void* param)
324 if(request == IOCTRL_NATIVE && param)
326 SNativeIoControl* s = (SNativeIoControl*)param;
327 return ioctl((*m_hFile).fd, s->request, s->param);
333 int CHDFile::Truncate(int64_t size)
336 // Duplicate the handle, as retrieving and closing a matching crt handle closes the crt handle AND the original Windows handle.
338 if (0 == DuplicateHandle(GetCurrentProcess(), (HANDLE)m_hFile, GetCurrentProcess(), &hFileDup, 0, FALSE, DUPLICATE_SAME_ACCESS))
340 CLog::Log(LOGERROR, __FUNCTION__" - DuplicateHandle()");
345 fd = _open_osfhandle((intptr_t)((HANDLE)hFileDup), 0);
348 CLog::Log(LOGERROR, "Stat: fd == -1");
351 int result = _chsize_s(fd, (long) size);
355 return ftruncate((*m_hFile).fd, (off_t) size);