common/msvc_posix_wrapper.cc

Go to the documentation of this file.
00001 /* msvc_posix_wrapper.cc: Provides wrappers with POSIX semantics under MSVC.
00002  *
00003  * (misnamed, this isn't MSVC specific, but __WIN32__-specific)
00004  *
00005  * Copyright (C) 2007 Lemur Consulting Ltd
00006  * Copyright (C) 2007 Olly Betts
00007  *
00008  * This program is free software; you can redistribute it and/or modify
00009  * it under the terms of the GNU General Public License as published by
00010  * the Free Software Foundation; either version 2 of the License, or
00011  * (at your option) any later version.
00012  *
00013  * This program is distributed in the hope that it will be useful,
00014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00016  * GNU General Public License for more details.
00017  *
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program; if not, write to the Free Software
00020  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
00021  */
00022 
00023 #include <config.h>
00024 
00025 #ifdef __WIN32__ /* Ignore the whole file except for __WIN32__ */
00026 
00027 #include <io.h>
00028 
00029 #include "safeerrno.h"
00030 #include "safefcntl.h"
00031 #include "safewindows.h"
00032 
00034 static int
00035 msvc_set_errno_from_getlasterror()
00036 {
00037     int e;
00038     unsigned long winerr = GetLastError();
00039     switch (winerr) {
00040         case ERROR_FILENAME_EXCED_RANGE:
00041         case ERROR_FILE_NOT_FOUND:
00042         case ERROR_PATH_NOT_FOUND:
00043         case ERROR_INVALID_DRIVE:
00044         case ERROR_NO_MORE_FILES:
00045         case ERROR_BAD_NETPATH:
00046         case ERROR_BAD_NET_NAME:
00047         case ERROR_BAD_PATHNAME:
00048             e = ENOENT;
00049             break;
00050         case ERROR_ARENA_TRASHED:
00051         case ERROR_NOT_ENOUGH_MEMORY:
00052         case ERROR_INVALID_BLOCK:
00053         case ERROR_NOT_ENOUGH_QUOTA:
00054             e = ENOMEM;
00055             break;
00056         case ERROR_LOCK_VIOLATION:
00057         case ERROR_LOCK_FAILED:
00058         case ERROR_SEEK_ON_DEVICE:
00059         case ERROR_NETWORK_ACCESS_DENIED:
00060         case ERROR_NOT_LOCKED:
00061         case ERROR_ACCESS_DENIED:
00062         case ERROR_CANNOT_MAKE:
00063         case ERROR_FAIL_I24:
00064         case ERROR_DRIVE_LOCKED:
00065         case ERROR_CURRENT_DIRECTORY:
00066             e = EACCES;
00067             break;
00068         case ERROR_INVALID_FUNCTION:
00069         case ERROR_INVALID_ACCESS:
00070         case ERROR_NEGATIVE_SEEK:
00071         case ERROR_INVALID_DATA:
00072         case ERROR_INVALID_PARAMETER:
00073             e = EINVAL;
00074             break;
00075         case ERROR_NO_PROC_SLOTS:
00076         case ERROR_NESTING_NOT_ALLOWED:
00077         case ERROR_MAX_THRDS_REACHED:
00078             e = EAGAIN;
00079             break;
00080         case ERROR_INVALID_HANDLE:
00081         case ERROR_INVALID_TARGET_HANDLE:
00082         case ERROR_DIRECT_ACCESS_HANDLE:
00083             e = EBADF;
00084             break;
00085         case ERROR_ALREADY_EXISTS:
00086         case ERROR_FILE_EXISTS:
00087             e = EEXIST;
00088             break;
00089         case ERROR_BROKEN_PIPE:
00090             e = EPIPE;
00091             break;
00092         case ERROR_DISK_FULL:
00093             e = ENOSPC;
00094             break;
00095         case ERROR_TOO_MANY_OPEN_FILES:
00096             e = EMFILE;
00097             break;
00098         case ERROR_WAIT_NO_CHILDREN:
00099         case ERROR_CHILD_NOT_COMPLETE:
00100             e = ECHILD;
00101             break;
00102         case ERROR_DIR_NOT_EMPTY:
00103             e = ENOTEMPTY;
00104             break;
00105         case ERROR_BAD_ENVIRONMENT:
00106             e = E2BIG;
00107             break;
00108         case ERROR_BAD_FORMAT:
00109             e = ENOEXEC;
00110             break;
00111         case ERROR_NOT_SAME_DEVICE:
00112             e = EXDEV;
00113             break;
00114         default:
00115             if (winerr >= ERROR_WRITE_PROTECT && winerr <= ERROR_SHARING_BUFFER_EXCEEDED)
00116                 e = EACCES;
00117             else if (winerr >= ERROR_INVALID_STARTING_CODESEG && winerr <= ERROR_INFLOOP_IN_RELOC_CHAIN)
00118                 e = ENOEXEC;
00119             else
00120                 e = EINVAL;
00121             break;
00122     }
00123     /* Some versions of Microsoft's C++ compiler earlier than 2005 do not have
00124      * _set_errno(). */
00125 #ifdef _set_errno
00126     _set_errno(e);
00127 #else
00128     errno = e;
00129 #endif
00130     return -1;
00131 }
00132 
00137 int
00138 msvc_posix_unlink(const char * filename)
00139 {
00140     /* We must use DeleteFile as this can delete files that are open. */
00141     if (DeleteFile(filename) != 0) {
00142         return 0;
00143     }
00144 
00145     return msvc_set_errno_from_getlasterror();
00146 }
00147 
00149 int
00150 msvc_posix_open(const char *filename, int flags)
00151 {
00152     /* Translate ANSI read mode to Windows access mode */
00153     DWORD dwDesiredAccess = GENERIC_READ;
00154     switch (flags & (O_RDONLY | O_RDWR | O_WRONLY))
00155     {
00156         case O_RDONLY:
00157             dwDesiredAccess = GENERIC_READ;
00158             break;
00159         case O_RDWR:
00160             dwDesiredAccess = GENERIC_READ | GENERIC_WRITE;
00161             break;
00162         case O_WRONLY:
00163             dwDesiredAccess = GENERIC_WRITE;
00164             break;
00165     }
00166     /* Subsequent operations may open this file to read, write or delete it */
00167     DWORD dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;
00168 
00169     /* Translate ANSI creation mode to Windows creation mode */
00170     DWORD dwCreationDisposition = OPEN_EXISTING;
00171     switch (flags & (O_CREAT | O_TRUNC | O_EXCL))
00172     {
00173         case O_EXCL:
00174             dwCreationDisposition = OPEN_EXISTING;
00175             break;
00176 
00177         case O_CREAT:
00178             dwCreationDisposition = OPEN_ALWAYS;
00179             break;
00180 
00181         case O_CREAT | O_TRUNC:
00182             dwCreationDisposition = CREATE_ALWAYS;
00183             break;
00184 
00185         case O_CREAT | O_EXCL:
00186         case O_CREAT | O_TRUNC | O_EXCL:
00187             dwCreationDisposition = CREATE_NEW;
00188             break;
00189 
00190         case O_TRUNC:
00191         case O_TRUNC | O_EXCL:
00192             dwCreationDisposition = TRUNCATE_EXISTING;
00193             break;
00194     }
00195 
00196     HANDLE handleWin =
00197         CreateFile(filename,
00198                 dwDesiredAccess,
00199                 dwShareMode,
00200                 NULL,
00201                 dwCreationDisposition,
00202                 FILE_ATTRIBUTE_NORMAL,
00203                 NULL);
00204     if (handleWin == INVALID_HANDLE_VALUE) {
00205         return msvc_set_errno_from_getlasterror();
00206     }
00207 
00208     /* Return a standard file descriptor. */
00209     return _open_osfhandle((intptr_t)handleWin, flags);
00210 }
00211 
00213 int msvc_posix_rename(const char *from, const char *to)
00214 {
00215     if (MoveFileEx(from, to, MOVEFILE_REPLACE_EXISTING) != 0) {
00216         return 0;
00217     }
00218 
00219     return msvc_set_errno_from_getlasterror();
00220 }
00221 
00222 #endif // __WIN32__

Documentation for Xapian (version 1.0.10).
Generated on 24 Dec 2008 by Doxygen 1.5.2.