ssize_t lisp_write(HANDLE hfile, void *buf, ssize_t count) { HANDLE hevent; OVERLAPPED overlapped; DWORD err, nwritten, wait_result; pending_io pending; TCR *tcr = (TCR *)get_tcr(1); hevent = (HANDLE)TCR_AUX(tcr)->io_datum; if (hfile == (HANDLE)1) { hfile = GetStdHandle(STD_OUTPUT_HANDLE); } else if (hfile == (HANDLE) 2) { hfile = GetStdHandle(STD_ERROR_HANDLE); } memset(&overlapped,0,sizeof(overlapped)); if (GetFileType(hfile) == FILE_TYPE_DISK) { overlapped.Offset = SetFilePointer(hfile, 0, &(overlapped.OffsetHigh), FILE_CURRENT); } pending.h = hfile; pending.o = &overlapped; TCR_AUX(tcr)->pending_io_info = &pending; overlapped.hEvent = hevent; ResetEvent(hevent); if (WriteFile(hfile, buf, count, &nwritten, &overlapped)) { TCR_AUX(tcr)->pending_io_info = NULL; return nwritten; } err = GetLastError(); if (err != ERROR_IO_PENDING) { _dosmaperr(err); TCR_AUX(tcr)->pending_io_info = NULL; return -1; } err = 0; wait_result = WaitForSingleObjectEx(hevent, INFINITE, true); TCR_AUX(tcr)->pending_io_info = NULL; if (wait_result == WAIT_OBJECT_0) { err = overlapped.Internal; if (err) { _dosmaperr(err); return -1; } return overlapped.InternalHigh; } if (wait_result == WAIT_IO_COMPLETION) { CancelIo(hfile); errno = EINTR; return -1; } err = GetLastError(); _dosmaperr(err); return -1; }
int __cdecl _tchmod ( const _TSCHAR *path, int mode ) { DWORD attr; attr = GetFileAttributes((LPTSTR)path); if (attr == 0xffffffff) { /* error occured -- map error code and return */ _dosmaperr(GetLastError()); return -1; } if (mode & _S_IWRITE) { /* clear read only bit */ attr &= ~FILE_ATTRIBUTE_READONLY; } else { /* set read only bit */ attr |= FILE_ATTRIBUTE_READONLY; } /* set new attribute */ if (!SetFileAttributes((LPTSTR)path, attr)) { /* error occured -- map error code and return */ _dosmaperr(GetLastError()); return -1; } return 0; }
/******************************************************************//** @file api/api0misc.c Create a temporary file in Windows. @return file descriptor, or -1 */ static int ib_win_create_tempfile( /*===================*/ const char* prefix) /*!< in: temp file prefix */ { ulint ret; TCHAR path[WIN_MAX_PATH]; TCHAR tempname[WIN_MAX_PATH]; int fh = -1; ret = GetTempPath(sizeof(path), path); if (ret > sizeof(path) || ret == 0) { _dosmaperr(GetLastError()); } else if (!GetTempFileName(path, prefix, 0, tempname)) { _dosmaperr(GetLastError()); } else { HANDLE handle; /* Create the actual file with the relevant attributes. */ handle = CreateFile( tempname, GENERIC_READ | GENERIC_WRITE | DELETE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE | FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_SEQUENTIAL_SCAN, NULL); if (handle == INVALID_HANDLE_VALUE) { _dosmaperr(GetLastError()); } else { do { DWORD oserr; fh = _open_osfhandle((intptr_t) handle, 0); /* We need to map the Windows OS error number (if any) to errno. */ oserr = GetLastError(); if (oserr) { _dosmaperr(oserr); } } while (fh == -1 && errno == EINTR); if (fh == -1) { _dosmaperr(GetLastError()); CloseHandle(handle); } } } return(fh); }
int __cdecl rename( const char *oldname, const char *newname ) { /* We want to use MoveFileExW but not MoveFileExA (or MoveFile). So convert the strings to Unicode representation and call _wrename. Note that minwin does not support OEM CP for conversion via the FileAPIs APIs. So we unconditionally use the ACP for conversion */ int oldnamelen; int newnamelen; wchar_t *widenamesbuffer = NULL; wchar_t *oldnamew = NULL; wchar_t *newnamew = NULL; int retval; UINT codePage = CP_ACP; #if !(defined (_CORESYS) || defined (_CRT_APP) || defined (_KERNELX)) if (!__crtIsPackagedApp() && !AreFileApisANSI()) codePage = CP_OEMCP; #endif /* !(defined (_CORESYS) || defined (_CRT_APP) || defined (_KERNELX)) */ if ( ( (oldnamelen = MultiByteToWideChar(codePage, 0, oldname, -1, 0, 0) ) == 0 ) || ( (newnamelen = MultiByteToWideChar(codePage, 0, newname, -1, 0, 0) ) == 0 ) ) { _dosmaperr(GetLastError()); return -1; } /* allocate enough space for both */ if ( (widenamesbuffer = (wchar_t*)_malloc_crt( (oldnamelen+newnamelen) * sizeof(wchar_t) ) ) == NULL ) { /* errno is set by _malloc */ return -1; } /* now do the conversion */ oldnamew = widenamesbuffer; newnamew = widenamesbuffer + oldnamelen; if ( ( MultiByteToWideChar(codePage, 0, oldname, -1, oldnamew, oldnamelen) == 0 ) || ( MultiByteToWideChar(codePage, 0, newname, -1, newnamew, newnamelen) == 0 ) ) { _free_crt(widenamesbuffer); _dosmaperr(GetLastError()); return -1; } /* and event call the wide-character variant */ retval = _wrename(oldnamew,newnamew); _free_crt(widenamesbuffer); /* _free_crt leaves errno alone if everything completes as expected */ return retval; }
/* now define normal version */ int __cdecl _close ( int fh ) { ParamBlockRec parm; OSErr osErr = 0; /* validate file handle */ if ((unsigned)fh >= (unsigned)_nfile || !(_osfile[fh] & FOPEN)) { /* bad file handle, set errno and abort */ errno = EBADF; _macerrno = 0; return -1; } if (!(_osfile[fh] & FDEV)) /*no need to close console*/ { if (_osfhnd[fh] == -1 ) { /*an open file with a -1 handle indicates a pseudo open for stdin, stdout, or stderr -- close with no error*/ _osfhnd[fh] = 0; /*only allowed to close once*/ } else { parm.ioParam.ioRefNum = _osfhnd[fh]; parm.ioParam.ioNamePtr = NULL; osErr = PBCloseSync(&parm); if (osErr) { _dosmaperr(osErr); return -1; } memset(&parm, 0, sizeof(ParamBlockRec)); parm.ioParam.ioVRefNum = _osVRefNum[fh]; osErr = PBFlushVolSync(&parm); } } _osfile[fh] = 0; /* clear file flags */ if (osErr) { _dosmaperr(osErr); return -1; } return 0; /* good return */ }
/* * Make a path to the argument directory, printing a message if something * goes wrong. */ void CFileAccess::_tmake_directories(const char *name, const TCHAR *fn) { DWORD fa; TCHAR *dir; TCHAR *cp; fa = GetFileAttributes(fn); if(fa!=0xFFFFFFFF) { if(!(fa&FILE_ATTRIBUTE_DIRECTORY)) CServerIo::error (0, 0, "%s already exists but is not a directory", name); else { return; } } if (!CreateDirectory(fn,NULL)) { DWORD dwErr = GetLastError(); if(dwErr!=ERROR_PATH_NOT_FOUND) { _dosmaperr(dwErr); CServerIo::error (0, errno, "cannot make directory %s", name); return; } } else return; dir = _tcsdup(fn); for(cp=dir+_tcslen(dir);cp>dir && !ISDIRSEP(*cp); --cp) ; if(cp==dir) { free(dir); return; } *cp = '\0'; _tmake_directories (name,dir); *cp++ = '/'; if (*cp == '\0') { free(dir); return; } if (!CreateDirectory(dir,NULL)) { _dosmaperr(GetLastError()); CServerIo::error (0, errno, "cannot make directory %s", name); free(dir); return; } free(dir); }
extern "C" float _CRTIMP __cdecl _wcstof_l ( const wchar_t *nptr, wchar_t **endptr, _locale_t plocinfo ) { int len; char * str = NULL; /* get the buffer size needed for conversion */ if ( (len = WideCharToMultiByte(CP_ACP, 0 /* Use default flags */, nptr, -1, 0, 0, NULL, NULL) ) == 0 ) { _dosmaperr(GetLastError()); return 0; } /* allocate enough space for conversion */ if ( (str = (char*)_malloc_crt( len * sizeof(char) ) ) == NULL ) { /* malloc should set the errno */ return 0; } /* now do the conversion */ if ( WideCharToMultiByte(CP_ACP, 0 /* Use default flags */, nptr, -1, str, len, NULL, NULL) == 0 ) { _dosmaperr(GetLastError()); _free_crt(str); return 0; } _CRT_FLOAT ret; char *local_end_ptr = NULL; __crt_atoflt_l(&ret, str, plocinfo, &local_end_ptr); if (endptr != NULL) { if (local_end_ptr != NULL) { *endptr = (wchar_t*)(nptr + (local_end_ptr - str)); } else { *endptr = NULL; } } _free_crt(str); return ret.f; }
__int64 lisp_ftruncate(HANDLE hfile, off_t new_size) { __int64 cureof,curpos; int e; curpos = lisp_lseek(hfile, 0, SEEK_CUR); cureof = lisp_lseek(hfile, 0, SEEK_END); lisp_lseek(hfile, 0, SEEK_CUR); if (cureof == -1) { return 0; } if (cureof < new_size) { char buf[4096]; __int64 n = new_size-cureof; DWORD nwritten, to_write; lisp_lseek(hfile, cureof, SEEK_SET); memset(buf,0,sizeof(buf)); while(n) { if (n > 4096LL) { to_write = 4096; } else { to_write = n; } if (!WriteFile(hfile,buf,to_write,&nwritten,NULL)) { _dosmaperr(GetLastError()); e = errno; lisp_lseek(hfile,curpos,SEEK_SET); errno = e; return -1; } n -= nwritten; } lisp_lseek(hfile,curpos,SEEK_SET); return 0; } lisp_lseek(hfile, new_size, SEEK_SET); if (SetEndOfFile(hfile)) { lisp_lseek(hfile,curpos,SEEK_SET); return 0; } _dosmaperr(GetLastError()); e = errno; lisp_lseek(hfile,curpos,SEEK_SET); errno = e; return -1; }
/* * @implemented */ int CDECL _pclose(FILE* file) { HANDLE h; DWORD i; if (!MSVCRT_CHECK_PMT(file != NULL)) return -1; _mlock(_POPEN_LOCK); for(i=0; i<popen_handles_size; i++) { if (popen_handles[i].f == file) break; } if(i == popen_handles_size) { _munlock(_POPEN_LOCK); *_errno() = EBADF; return -1; } h = popen_handles[i].proc; popen_handles[i].f = NULL; _munlock(_POPEN_LOCK); fclose(file); if(WaitForSingleObject(h, INFINITE)==WAIT_FAILED || !GetExitCodeProcess(h, &i)) { _dosmaperr(GetLastError()); CloseHandle(h); return -1; } CloseHandle(h); return i; }
int __cdecl _mkdir ( const char *path ) { /* ask OS to create directory */ HParamBlockRec hparamBlock; char st[256]; OSErr osErr; if (!*path) { errno = ENOENT; return -1; } strcpy(st, path); hparamBlock.fileParam.ioNamePtr = _c2pstr(st); hparamBlock.fileParam.ioVRefNum = 0; hparamBlock.fileParam.ioDirID = 0; osErr = PBDirCreateSync(&hparamBlock); if (osErr) { /* error occured -- map error code and return */ _dosmaperr(osErr); return -1; } return 0; }
/* signal sending */ int pgkill(int pid, int sig) { char pipename[128]; BYTE sigData = sig; BYTE sigRet = 0; DWORD bytes; /* we allow signal 0 here, but it will be ignored in pg_queue_signal */ if (sig >= PG_SIGNAL_COUNT || sig < 0) { errno = EINVAL; return -1; } if (pid <= 0) { /* No support for process groups */ errno = EINVAL; return -1; } /* special case for SIGKILL: just ask the system to terminate the target */ if (sig == SIGKILL) { HANDLE prochandle; if ((prochandle = OpenProcess(PROCESS_TERMINATE, FALSE, (DWORD) pid)) == NULL) { errno = ESRCH; return -1; } if (!TerminateProcess(prochandle, 255)) { _dosmaperr(GetLastError()); CloseHandle(prochandle); return -1; } CloseHandle(prochandle); return 0; } snprintf(pipename, sizeof(pipename), "\\\\.\\pipe\\pgsignal_%u", pid); if (CallNamedPipe(pipename, &sigData, 1, &sigRet, 1, &bytes, 1000)) { if (bytes != 1 || sigRet != sig) { errno = ESRCH; return -1; } return 0; } if (GetLastError() == ERROR_FILE_NOT_FOUND) errno = ESRCH; else if (GetLastError() == ERROR_ACCESS_DENIED) errno = EPERM; else errno = EINVAL; return -1; }
static int uart_errno(uart_ctx_t* ctx) { int error = GetLastError(); _dosmaperr(error); ctx->error = errno; return errno; }
ssize_t console_read(HANDLE hfile, void *buf, unsigned int count) { DWORD err, eventcount, i, n; INPUT_RECORD ir; do { err = WaitForSingleObjectEx(hfile, INFINITE, TRUE); switch (err) { case WAIT_OBJECT_0: eventcount = 0; GetNumberOfConsoleInputEvents(hfile, &eventcount); for (i = 0; i < eventcount; i++) { PeekConsoleInput(hfile, &ir, 1, &n); if (ir.EventType == KEY_EVENT) { return lisp_standard_read(hfile, buf, count); } else { ReadConsoleInput(hfile, &ir, 1, &n); } } break; case WAIT_IO_COMPLETION: errno = EINTR; return -1; break; case WAIT_FAILED: _dosmaperr(GetLastError()); return -1; break; } } while (1); }
int __cdecl _chdrive ( int drive ) { char newdrive[3]; if (drive < 1 || drive > 31) { errno = EACCES; _doserrno = ERROR_INVALID_DRIVE; return -1; } _mlock(_ENV_LOCK); newdrive[0] = (char)('A' + (char)drive - (char)1); newdrive[1] = ':'; newdrive[2] = '\0'; /* * Set new drive. If current directory on new drive exists, it * will become the cwd. Otherwise defaults to root directory. */ if ( SetCurrentDirectory((LPSTR)newdrive) ) { _munlock(_ENV_LOCK); return 0; } else { _dosmaperr(GetLastError()); _munlock(_ENV_LOCK); return -1; } }
/* * @implemented */ int _dup(int handle) { HANDLE hFile; HANDLE hProcess = GetCurrentProcess(); BOOL result; int fd; hFile = _get_osfhandle(handle); if (hFile == INVALID_HANDLE_VALUE) { __set_errno(EBADF); return -1; } result = DuplicateHandle(hProcess, hFile, hProcess, &hFile, 0, TRUE, DUPLICATE_SAME_ACCESS); if (result == FALSE) { _dosmaperr(GetLastError()); return -1; } fd = __fileno_alloc(hFile, __fileno_getmode(handle)); if (fd < 0) { CloseHandle(hFile); } return fd; }
ssize_t pipe_read(HANDLE hfile, void *buf, unsigned int count) { DWORD navail, err;; do { navail = 0; if (PeekNamedPipe(hfile, NULL, 0, NULL, &navail, NULL) == 0) { err = GetLastError(); if (err = ERROR_HANDLE_EOF) { return 0; } else { _dosmaperr(err); return -1; } } if (navail != 0) { return lisp_standard_read(hfile, buf, count); } if (SleepEx(50, TRUE) == WAIT_IO_COMPLETION) { errno = EINTR; return -1; } } while (1); }
struct dirent * readdir(DIR *d) { WIN32_FIND_DATA fd; if (d->handle == INVALID_HANDLE_VALUE) { d->handle = FindFirstFile(d->dirname, &fd); if (d->handle == INVALID_HANDLE_VALUE) { errno = ENOENT; return NULL; } } else { if (!FindNextFile(d->handle, &fd)) { if (GetLastError() == ERROR_NO_MORE_FILES) { /* No more files, force errno=0 (unlike mingw) */ errno = 0; return NULL; } _dosmaperr(GetLastError()); return NULL; } } strcpy(d->ret.d_name, fd.cFileName); /* Both strings are MAX_PATH * long */ d->ret.d_namlen = strlen(d->ret.d_name); return &d->ret; }
/* * Returns the current user name. */ static char * get_username(void) { char *ret; #ifndef WIN32 struct passwd *pw; pw = getpwuid(geteuid()); ret = (pw ? pw->pw_name : NULL); #else static char username[128]; /* remains after function execute */ DWORD len = sizeof(username) - 1; if (GetUserNameA(username, &len)) ret = username; else { _dosmaperr(GetLastError()); ret = NULL; } #endif if (ret == NULL) ereport(ERROR, (errcode_errno(), errmsg("could not get current user name: "))); return ret; }
/* * Worker thread to transfer data from the pipe to the current logfile. * * We need this because on Windows, WaitForSingleObject does not work on * unnamed pipes: it always reports "signaled", so the blocking ReadFile won't * allow for SIGHUP; and select is for sockets only. */ static unsigned int __stdcall pipeThread(void *arg) { DWORD bytesRead; char logbuffer[1024]; for (;;) { if (!ReadFile(syslogPipe[0], logbuffer, sizeof(logbuffer), &bytesRead, 0)) { DWORD error = GetLastError(); if (error == ERROR_HANDLE_EOF || error == ERROR_BROKEN_PIPE) break; _dosmaperr(error); ereport(LOG, (errcode_for_file_access(), errmsg("could not read from logger pipe: %m"))); } else if (bytesRead > 0) write_syslogger_file_binary(logbuffer, bytesRead); } /* We exit the above loop only upon detecting pipe EOF */ pipe_eof_seen = true; _endthread(); return 0; }
/* * The stat() function in win32 is not guaranteed to update the st_size * field when run. So we define our own version that uses the Win32 API * to update this field. */ int pgwin32_safestat(const char *path, struct stat *buf) { int r; WIN32_FILE_ATTRIBUTE_DATA attr; r = stat(path, buf); if (r < 0) return r; // MPP-24774: just return if path refer to a windows named pipe file. // no need to get size of a windows named pipe file if (strlen(path) >2) { if (path[0] == '\\' && path[1] == '\\') { return r; } } if (!GetFileAttributesEx(path, GetFileExInfoStandard, &attr)) { _dosmaperr(GetLastError()); return -1; } /* * XXX no support for large files here, but we don't do that in * general on Win32 yet. */ buf->st_size = attr.nFileSizeLow; return 0; }
/* * Returns the current user name. */ static const char * get_username(void) { const char *ret; #ifndef WIN32 struct passwd *pw; pw = getpwuid(geteuid()); ret = (pw ? pw->pw_name : NULL); #else static char username[128]; /* remains after function exit */ DWORD len = sizeof(username) - 1; if (GetUserName(username, &len)) ret = username; else { _dosmaperr(GetLastError()); ret = NULL; } #endif if (ret == NULL) ereport(ERROR, (errcode(ERROR_SYSTEM), errmsg("%s: could not get current user name: %s", PROGRAM_NAME, strerror(errno)))); return ret; }
int pgut_flock(int fd, int operation) { BOOL ret; HANDLE handle = (HANDLE) _get_osfhandle(fd); DWORD lo = 0; DWORD hi = 0; if (operation & LOCK_UN) { ret = UnlockFileEx(handle, 0, lo, hi, NULL); } else { DWORD flags = 0; if (operation & LOCK_EX) flags |= LOCKFILE_EXCLUSIVE_LOCK; if (operation & LOCK_NB) flags |= LOCKFILE_FAIL_IMMEDIATELY; ret = LockFileEx(handle, flags, 0, lo, hi, NULL); } if (!ret) { _dosmaperr(GetLastError()); return -1; } return 0; }
/* * getErrorText() * * Returns the text of the error message for the given error number * * This feature is factored into a separate function because it is * system-dependent. */ const char * getErrorText(int errNum) { #ifdef WIN32 _dosmaperr(GetLastError()); #endif return strdup(strerror(errNum)); }
/* * @implemented */ int _trmdir(const _TCHAR* _path) { if (!RemoveDirectory(_path)) { _dosmaperr(GetLastError()); return -1; } return 0; }
int FileRead(File file, char *buffer, int amount) { int returnCode; Assert(FileIsValid(file)); DO_DB(elog(LOG, "FileRead: %d (%s) " INT64_FORMAT " %d %p", file, VfdCache[file].fileName, VfdCache[file].seekPos, amount, buffer)); if (Debug_filerep_print) (elog(LOG, "FileRead: %d (%s) " INT64_FORMAT " %d %p", file, VfdCache[file].fileName, VfdCache[file].seekPos, amount, buffer)); returnCode = FileAccess(file); if (returnCode < 0) return returnCode; retry: returnCode = read(VfdCache[file].fd, buffer, amount); if (returnCode >= 0) VfdCache[file].seekPos += returnCode; else { /* * Windows may run out of kernel buffers and return "Insufficient * system resources" error. Wait a bit and retry to solve it. * * It is rumored that EINTR is also possible on some Unix filesystems, * in which case immediate retry is indicated. */ #ifdef WIN32 DWORD error = GetLastError(); switch (error) { case ERROR_NO_SYSTEM_RESOURCES: pg_usleep(1000L); errno = EINTR; break; default: _dosmaperr(error); break; } #endif /* OK to retry if interrupted */ if (errno == EINTR) goto retry; /* Trouble, so assume we don't know the file position anymore */ VfdCache[file].seekPos = FileUnknownPos; } return returnCode; }
/********************************************************************* * _heapchk (MSVCRT.@) */ int CDECL _heapchk(void) { if (!HeapValidate( GetProcessHeap(), 0, NULL)) { _dosmaperr(GetLastError()); return _HEAPBADNODE; } return _HEAPOK; }
/* * @implemented */ int _wunlink(const wchar_t* filename) { DPRINT("_wunlink('%S')\n", filename); if (!DeleteFileW(filename)) { _dosmaperr(GetLastError()); return -1; } return 0; }
/* * getErrorText() * * Returns the text of the error message for the given error number * * This feature is factored into a separate function because it is * system-dependent. */ const char * getErrorText(int errNum) { #ifdef WIN32 _dosmaperr(GetLastError()); /* _dosmaperr sets errno, so we copy errno here */ errNum = errno; #endif return pg_strdup(strerror(errNum)); }
/********************************************************************* * _heapmin (MSVCRT.@) */ int CDECL _heapmin(void) { if (!HeapCompact( GetProcessHeap(), 0 )) { if (GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) _dosmaperr(GetLastError()); return -1; } return 0; }
int __cdecl _chdir ( const char *path ) { WDPBRec wdPB; char st[256]; OSErr osErr; ParamBlockRec parm; if (!*path) { errno = ENOENT; return -1; } strcpy(st, path); wdPB.ioNamePtr = _c2pstr(st); wdPB.ioVRefNum = 0; wdPB.ioWDDirID = 0; osErr = PBHSetVolSync(&wdPB); if (osErr) { /* error occured -- map error code and return */ _dosmaperr(osErr); return -1; } osErr = PBHGetVolSync(&wdPB); if (osErr) { /* error occured -- map error code and return */ _dosmaperr(osErr); return -1; } CurDirStore = wdPB.ioWDDirID; SFSaveDisk = wdPB.ioWDVRefNum; memset(&parm, 0, sizeof(ParamBlockRec)); osErr = PBSetVolSync(&parm); return 0; }