00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include "Poco/File_WIN32.h"
00038 #include "Poco/Exception.h"
00039 #include "Poco/String.h"
00040 #include "Poco/UnWindows.h"
00041
00042
00043 namespace Poco {
00044
00045
00046 class FileHandle
00047 {
00048 public:
00049 FileHandle(const std::string& path, DWORD access, DWORD share, DWORD disp)
00050 {
00051 _h = CreateFileA(path.c_str(), access, share, 0, disp, 0, 0);
00052 if (!_h) FileImpl::handleLastErrorImpl(path);
00053 }
00054
00055 ~FileHandle()
00056 {
00057 if (_h) CloseHandle(_h);
00058 }
00059
00060 HANDLE get() const
00061 {
00062 return _h;
00063 }
00064
00065 private:
00066 HANDLE _h;
00067 };
00068
00069
00070 FileImpl::FileImpl()
00071 {
00072 }
00073
00074
00075 FileImpl::FileImpl(const std::string& path): _path(path)
00076 {
00077 std::string::size_type n = _path.size();
00078 if (n > 1 && (_path[n - 1] == '\\' || _path[n - 1] == '/') && !((n == 3 && _path[1]==':')))
00079 {
00080 _path.resize(n - 1);
00081 }
00082 }
00083
00084
00085 FileImpl::~FileImpl()
00086 {
00087 }
00088
00089
00090 void FileImpl::swapImpl(FileImpl& file)
00091 {
00092 std::swap(_path, file._path);
00093 }
00094
00095
00096 void FileImpl::setPathImpl(const std::string& path)
00097 {
00098 _path = path;
00099 std::string::size_type n = _path.size();
00100 if (n > 1 && (_path[n - 1] == '\\' || _path[n - 1] == '/') && !((n == 3 && _path[1]==':')))
00101 {
00102 _path.resize(n - 1);
00103 }
00104 }
00105
00106
00107 bool FileImpl::existsImpl() const
00108 {
00109 poco_assert (!_path.empty());
00110
00111 DWORD attr = GetFileAttributes(_path.c_str());
00112 if (attr == 0xFFFFFFFF)
00113 {
00114 switch (GetLastError())
00115 {
00116 case ERROR_FILE_NOT_FOUND:
00117 case ERROR_PATH_NOT_FOUND:
00118 case ERROR_NOT_READY:
00119 case ERROR_INVALID_DRIVE:
00120 return false;
00121 default:
00122 handleLastErrorImpl(_path);
00123 }
00124 }
00125 return true;
00126 }
00127
00128
00129 bool FileImpl::canReadImpl() const
00130 {
00131 poco_assert (!_path.empty());
00132
00133 DWORD attr = GetFileAttributes(_path.c_str());
00134 if (attr == 0xFFFFFFFF)
00135 {
00136 switch (GetLastError())
00137 {
00138 case ERROR_ACCESS_DENIED:
00139 return false;
00140 default:
00141 handleLastErrorImpl(_path);
00142 }
00143 }
00144 return true;
00145 }
00146
00147
00148 bool FileImpl::canWriteImpl() const
00149 {
00150 poco_assert (!_path.empty());
00151
00152 DWORD attr = GetFileAttributes(_path.c_str());
00153 if (attr == 0xFFFFFFFF)
00154 handleLastErrorImpl(_path);
00155 return (attr & FILE_ATTRIBUTE_READONLY) == 0;
00156 }
00157
00158
00159 bool FileImpl::canExecuteImpl() const
00160 {
00161 Path p(_path);
00162 return icompare(p.getExtension(), "exe") == 0;
00163 }
00164
00165
00166 bool FileImpl::isFileImpl() const
00167 {
00168 return !isDirectoryImpl() && !isDeviceImpl();
00169 }
00170
00171
00172 bool FileImpl::isDirectoryImpl() const
00173 {
00174 poco_assert (!_path.empty());
00175
00176 DWORD attr = GetFileAttributes(_path.c_str());
00177 if (attr == 0xFFFFFFFF)
00178 handleLastErrorImpl(_path);
00179 return (attr & FILE_ATTRIBUTE_DIRECTORY) != 0;
00180 }
00181
00182
00183 bool FileImpl::isLinkImpl() const
00184 {
00185 return false;
00186 }
00187
00188
00189 bool FileImpl::isDeviceImpl() const
00190 {
00191 poco_assert (!_path.empty());
00192
00193 FileHandle fh(_path, GENERIC_READ, 0, OPEN_EXISTING);
00194 DWORD type = GetFileType(fh.get());
00195 if (type == FILE_TYPE_CHAR)
00196 return true;
00197 else if (type == FILE_TYPE_UNKNOWN && GetLastError() != NO_ERROR)
00198 handleLastErrorImpl(_path);
00199 return false;
00200 }
00201
00202
00203 bool FileImpl::isHiddenImpl() const
00204 {
00205 poco_assert (!_path.empty());
00206
00207 DWORD attr = GetFileAttributes(_path.c_str());
00208 if (attr == 0xFFFFFFFF)
00209 handleLastErrorImpl(_path);
00210 return (attr & FILE_ATTRIBUTE_HIDDEN) != 0;
00211 }
00212
00213
00214 Timestamp FileImpl::createdImpl() const
00215 {
00216 poco_assert (!_path.empty());
00217
00218 WIN32_FILE_ATTRIBUTE_DATA fad;
00219 if (GetFileAttributesEx(_path.c_str(), GetFileExInfoStandard, &fad) == 0)
00220 handleLastErrorImpl(_path);
00221 return Timestamp::fromFileTimeNP(fad.ftCreationTime.dwLowDateTime, fad.ftCreationTime.dwHighDateTime);
00222 }
00223
00224
00225 Timestamp FileImpl::getLastModifiedImpl() const
00226 {
00227 poco_assert (!_path.empty());
00228
00229 WIN32_FILE_ATTRIBUTE_DATA fad;
00230 if (GetFileAttributesEx(_path.c_str(), GetFileExInfoStandard, &fad) == 0)
00231 handleLastErrorImpl(_path);
00232 return Timestamp::fromFileTimeNP(fad.ftLastWriteTime.dwLowDateTime, fad.ftLastWriteTime.dwHighDateTime);
00233 }
00234
00235
00236 void FileImpl::setLastModifiedImpl(const Timestamp& ts)
00237 {
00238 poco_assert (!_path.empty());
00239
00240 UInt32 low;
00241 UInt32 high;
00242 ts.toFileTimeNP(low, high);
00243 FILETIME ft;
00244 ft.dwLowDateTime = low;
00245 ft.dwHighDateTime = high;
00246 FileHandle fh(_path, FILE_ALL_ACCESS, FILE_SHARE_READ | FILE_SHARE_WRITE, OPEN_EXISTING);
00247 if (SetFileTime(fh.get(), 0, &ft, &ft) == 0)
00248 handleLastErrorImpl(_path);
00249 }
00250
00251
00252 FileImpl::FileSizeImpl FileImpl::getSizeImpl() const
00253 {
00254 poco_assert (!_path.empty());
00255
00256 WIN32_FILE_ATTRIBUTE_DATA fad;
00257 if (GetFileAttributesEx(_path.c_str(), GetFileExInfoStandard, &fad) == 0)
00258 handleLastErrorImpl(_path);
00259 LARGE_INTEGER li;
00260 li.LowPart = fad.nFileSizeLow;
00261 li.HighPart = fad.nFileSizeHigh;
00262 return li.QuadPart;
00263 }
00264
00265
00266 void FileImpl::setSizeImpl(FileSizeImpl size)
00267 {
00268 poco_assert (!_path.empty());
00269
00270 FileHandle fh(_path, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, OPEN_EXISTING);
00271 LARGE_INTEGER li;
00272 li.QuadPart = size;
00273 if (SetFilePointer(fh.get(), li.LowPart, &li.HighPart, FILE_BEGIN) == -1)
00274 handleLastErrorImpl(_path);
00275 if (SetEndOfFile(fh.get()) == 0)
00276 handleLastErrorImpl(_path);
00277 }
00278
00279
00280 void FileImpl::setWriteableImpl(bool flag)
00281 {
00282 poco_assert (!_path.empty());
00283
00284 DWORD attr = GetFileAttributes(_path.c_str());
00285 if (attr == -1)
00286 handleLastErrorImpl(_path);
00287 if (flag)
00288 attr &= ~FILE_ATTRIBUTE_READONLY;
00289 else
00290 attr |= FILE_ATTRIBUTE_READONLY;
00291 if (SetFileAttributes(_path.c_str(), attr) == 0)
00292 handleLastErrorImpl(_path);
00293 }
00294
00295
00296 void FileImpl::setExecutableImpl(bool flag)
00297 {
00298
00299 }
00300
00301
00302 void FileImpl::copyToImpl(const std::string& path) const
00303 {
00304 poco_assert (!_path.empty());
00305
00306 if (CopyFileA(_path.c_str(), path.c_str(), FALSE) != 0)
00307 {
00308 FileImpl copy(path);
00309 copy.setWriteableImpl(true);
00310 }
00311 else handleLastErrorImpl(_path);
00312 }
00313
00314
00315 void FileImpl::renameToImpl(const std::string& path)
00316 {
00317 poco_assert (!_path.empty());
00318
00319 if (MoveFileA(_path.c_str(), path.c_str()) == 0)
00320 handleLastErrorImpl(_path);
00321 }
00322
00323
00324 void FileImpl::removeImpl()
00325 {
00326 poco_assert (!_path.empty());
00327
00328 if (isDirectoryImpl())
00329 {
00330 if (RemoveDirectoryA(_path.c_str()) == 0)
00331 handleLastErrorImpl(_path);
00332 }
00333 else
00334 {
00335 if (DeleteFileA(_path.c_str()) == 0)
00336 handleLastErrorImpl(_path);
00337 }
00338 }
00339
00340
00341 bool FileImpl::createFileImpl()
00342 {
00343 poco_assert (!_path.empty());
00344
00345 HANDLE hFile = CreateFileA(_path.c_str(), GENERIC_WRITE, 0, 0, CREATE_NEW, 0, 0);
00346 if (hFile != INVALID_HANDLE_VALUE)
00347 {
00348 CloseHandle(hFile);
00349 return true;
00350 }
00351 else if (GetLastError() == ERROR_FILE_EXISTS)
00352 return false;
00353 else
00354 handleLastErrorImpl(_path);
00355 return false;
00356 }
00357
00358
00359 bool FileImpl::createDirectoryImpl()
00360 {
00361 poco_assert (!_path.empty());
00362
00363 if (existsImpl() && isDirectoryImpl())
00364 return false;
00365 if (CreateDirectoryA(_path.c_str(), 0) == 0)
00366 handleLastErrorImpl(_path);
00367 return true;
00368 }
00369
00370
00371 void FileImpl::handleLastErrorImpl(const std::string& path)
00372 {
00373 switch (GetLastError())
00374 {
00375 case ERROR_FILE_NOT_FOUND:
00376 throw FileNotFoundException(path);
00377 case ERROR_PATH_NOT_FOUND:
00378 case ERROR_BAD_NETPATH:
00379 case ERROR_CANT_RESOLVE_FILENAME:
00380 case ERROR_INVALID_DRIVE:
00381 throw PathNotFoundException(path);
00382 case ERROR_ACCESS_DENIED:
00383 throw FileAccessDeniedException(path);
00384 case ERROR_ALREADY_EXISTS:
00385 case ERROR_FILE_EXISTS:
00386 throw FileExistsException(path);
00387 case ERROR_INVALID_NAME:
00388 case ERROR_DIRECTORY:
00389 case ERROR_FILENAME_EXCED_RANGE:
00390 case ERROR_BAD_PATHNAME:
00391 throw PathSyntaxException(path);
00392 case ERROR_FILE_READ_ONLY:
00393 throw FileReadOnlyException(path);
00394 case ERROR_CANNOT_MAKE:
00395 throw CreateFileException(path);
00396 case ERROR_DIR_NOT_EMPTY:
00397 throw FileException("directory not empty", path);
00398 case ERROR_WRITE_FAULT:
00399 throw WriteFileException(path);
00400 case ERROR_READ_FAULT:
00401 throw ReadFileException(path);
00402 case ERROR_SHARING_VIOLATION:
00403 throw FileException("sharing violation", path);
00404 case ERROR_LOCK_VIOLATION:
00405 throw FileException("lock violation", path);
00406 case ERROR_HANDLE_EOF:
00407 throw ReadFileException("EOF reached", path);
00408 case ERROR_HANDLE_DISK_FULL:
00409 case ERROR_DISK_FULL:
00410 throw WriteFileException("disk is full", path);
00411 case ERROR_NEGATIVE_SEEK:
00412 throw FileException("negative seek", path);
00413 default:
00414 throw FileException(path);
00415 }
00416 }
00417
00418
00419 }