def chdir_llimpl(path): """This is a reimplementation of the C library's chdir function, but one that produces Win32 errors instead of DOS error codes. chdir is essentially a wrapper around SetCurrentDirectory; however, it also needs to set "magic" environment variables indicating the per-drive current directory, which are of the form =<drive>: """ if not win32traits.SetCurrentDirectory(path): raise rwin32.lastWindowsError() MAX_PATH = rwin32.MAX_PATH assert MAX_PATH > 0 with traits.scoped_alloc_buffer(MAX_PATH) as path: res = win32traits.GetCurrentDirectory(MAX_PATH + 1, path.raw) if not res: raise rwin32.lastWindowsError() res = rffi.cast(lltype.Signed, res) assert res > 0 if res <= MAX_PATH + 1: new_path = path.str(res) else: with traits.scoped_alloc_buffer(res) as path: res = win32traits.GetCurrentDirectory(res, path.raw) if not res: raise rwin32.lastWindowsError() res = rffi.cast(lltype.Signed, res) assert res > 0 new_path = path.str(res) if isUNC(new_path): return if not win32traits.SetEnvironmentVariable(magic_envvar(new_path), new_path): raise rwin32.lastWindowsError()
def os_utime_llimpl(path, tp): hFile = CreateFile(path, FILE_WRITE_ATTRIBUTES, 0, None, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, rwin32.NULL_HANDLE) if hFile == rwin32.INVALID_HANDLE_VALUE: raise rwin32.lastWindowsError() ctime = lltype.nullptr(rwin32.FILETIME) atime = lltype.malloc(rwin32.FILETIME, flavor='raw') mtime = lltype.malloc(rwin32.FILETIME, flavor='raw') try: if tp is None: now = lltype.malloc(rwin32.SYSTEMTIME, flavor='raw') try: GetSystemTime(now) if (not SystemTimeToFileTime(now, atime) or not SystemTimeToFileTime(now, mtime)): raise rwin32.lastWindowsError() finally: lltype.free(now, flavor='raw') else: actime, modtime = tp time_t_to_FILE_TIME(actime, atime) time_t_to_FILE_TIME(modtime, mtime) if not SetFileTime(hFile, ctime, atime, mtime): raise rwin32.lastWindowsError() finally: rwin32.CloseHandle(hFile) lltype.free(atime, flavor='raw') lltype.free(mtime, flavor='raw')
def do_poll(self, space, timeout): from pypy.module._multiprocessing.interp_win32 import ( _PeekNamedPipe, _GetTickCount, _Sleep) from rpython.rlib import rwin32 from pypy.interpreter.error import wrap_windowserror bytes_ptr = lltype.malloc(rffi.CArrayPtr(rwin32.DWORD).TO, 1, flavor='raw') try: if not _PeekNamedPipe(self.handle, rffi.NULL, 0, lltype.nullptr(rwin32.LPDWORD.TO), bytes_ptr, lltype.nullptr(rwin32.LPDWORD.TO)): raise wrap_windowserror(space, rwin32.lastWindowsError()) bytes = bytes_ptr[0] finally: lltype.free(bytes_ptr, flavor='raw') if timeout == 0.0: return bytes > 0 block = timeout < 0 if not block: # XXX does not check for overflow deadline = intmask(_GetTickCount()) + int(1000 * timeout + 0.5) else: deadline = 0 _Sleep(0) delay = 1 while True: bytes_ptr = lltype.malloc(rffi.CArrayPtr(rwin32.DWORD).TO, 1, flavor='raw') try: if not _PeekNamedPipe(self.handle, rffi.NULL, 0, lltype.nullptr(rwin32.LPDWORD.TO), bytes_ptr, lltype.nullptr(rwin32.LPDWORD.TO)): raise wrap_windowserror(space, rwin32.lastWindowsError()) bytes = bytes_ptr[0] finally: lltype.free(bytes_ptr, flavor='raw') if bytes > 0: return True if not block: now = intmask(_GetTickCount()) if now > deadline: return False diff = deadline - now if delay > diff: delay = diff else: delay += 1 if delay >= 20: delay = 20 _Sleep(delay)
def chmod_llimpl(path, mode): attr = win32traits.GetFileAttributes(path) if attr == win32traits.INVALID_FILE_ATTRIBUTES: raise rwin32.lastWindowsError() if mode & 0200: # _S_IWRITE attr &= ~win32traits.FILE_ATTRIBUTE_READONLY else: attr |= win32traits.FILE_ATTRIBUTE_READONLY if not win32traits.SetFileAttributes(path, attr): raise rwin32.lastWindowsError()
def do_recv_string(self, space, buflength, maxlength): from pypy.module._multiprocessing.interp_win32 import ( _ReadFile, _PeekNamedPipe, ERROR_BROKEN_PIPE, ERROR_MORE_DATA) from rpython.rlib import rwin32 from pypy.interpreter.error import wrap_windowserror read_ptr = lltype.malloc(rffi.CArrayPtr(rwin32.DWORD).TO, 1, flavor='raw') left_ptr = lltype.malloc(rffi.CArrayPtr(rwin32.DWORD).TO, 1, flavor='raw') try: result = _ReadFile(self.handle, self.buffer, min(self.BUFFER_SIZE, buflength), read_ptr, rffi.NULL) if result: return intmask(read_ptr[0]), lltype.nullptr(rffi.CCHARP.TO) err = rwin32.GetLastError() if err == ERROR_BROKEN_PIPE: raise OperationError(space.w_EOFError, space.w_None) elif err != ERROR_MORE_DATA: raise wrap_windowserror(space, WindowsError(err, "_ReadFile")) # More data... if not _PeekNamedPipe(self.handle, rffi.NULL, 0, lltype.nullptr(rwin32.LPDWORD.TO), lltype.nullptr(rwin32.LPDWORD.TO), left_ptr): raise wrap_windowserror(space, rwin32.lastWindowsError()) length = intmask(read_ptr[0] + left_ptr[0]) if length > maxlength: # bad message, close connection self.flags &= ~READABLE if self.flags == 0: self.close() raise OperationError(space.w_IOError, space.wrap( "bad message length")) newbuf = lltype.malloc(rffi.CCHARP.TO, length + 1, flavor='raw') for i in range(read_ptr[0]): newbuf[i] = self.buffer[i] result = _ReadFile(self.handle, rffi.ptradd(newbuf, read_ptr[0]), left_ptr[0], read_ptr, rffi.NULL) if not result: rffi.free_charp(newbuf) raise wrap_windowserror(space, rwin32.lastWindowsError()) assert read_ptr[0] == left_ptr[0] return length, newbuf finally: lltype.free(read_ptr, flavor='raw') lltype.free(left_ptr, flavor='raw')
def ExpandEnvironmentStrings(source): with rffi.scoped_unicode2wcharp(source) as src_buf: size = _ExpandEnvironmentStringsW(src_buf, lltype.nullptr(rffi.CWCHARP.TO), 0) if size == 0: raise rwin32.lastWindowsError("ExpandEnvironmentStrings") size = intmask(size) with rffi.scoped_alloc_unicodebuffer(size) as dest_buf: if _ExpandEnvironmentStringsW(src_buf, dest_buf.raw, size) == 0: raise rwin32.lastWindowsError("ExpandEnvironmentStrings") return dest_buf.str(size - 1) # remove trailing \0
def ConnectNamedPipe(space, w_handle, w_overlapped): handle = handle_w(space, w_handle) overlapped = space.int_w(w_overlapped) if overlapped: raise OperationError(space.w_NotImplementedError, space.wrap("expected a NULL pointer")) if not _ConnectNamedPipe(handle, rffi.NULL): raise wrap_windowserror(space, rwin32.lastWindowsError())
def resize(self, newsize): if _POSIX: if not has_mremap: raise RValueError("mmap: resizing not available--no mremap()") # resize the underlying file first os.ftruncate(self.fd, self.offset + newsize) # now resize the mmap newdata = c_mremap(self.getptr(0), self.size, newsize, MREMAP_MAYMOVE or 0) self.setdata(newdata, newsize) elif _MS_WINDOWS: # disconnect the mapping self.unmap() rwin32.CloseHandle(self.map_handle) # move to the desired EOF position if _64BIT: newsize_high = (self.offset + newsize) >> 32 newsize_low = (self.offset + newsize) & 0xFFFFFFFF offset_high = self.offset >> 32 offset_low = self.offset & 0xFFFFFFFF else: newsize_high = 0 newsize_low = self.offset + newsize offset_high = 0 offset_low = self.offset FILE_BEGIN = 0 high_ref = lltype.malloc(PLONG.TO, 1, flavor='raw') try: high_ref[0] = rffi.cast(LONG, newsize_high) SetFilePointer(self.file_handle, newsize_low, high_ref, FILE_BEGIN) finally: lltype.free(high_ref, flavor='raw') # resize the file SetEndOfFile(self.file_handle) # create another mapping object and remap the file view res = CreateFileMapping(self.file_handle, NULL, PAGE_READWRITE, newsize_high, newsize_low, self.tagname) self.map_handle = res if self.map_handle: data = MapViewOfFile(self.map_handle, FILE_MAP_WRITE, offset_high, offset_low, newsize) if data: # XXX we should have a real LPVOID which must always be casted charp = rffi.cast(LPCSTR, data) self.setdata(charp, newsize) return winerror = rwin32.lastWindowsError() if self.map_handle: rwin32.CloseHandle(self.map_handle) self.map_handle = INVALID_HANDLE raise winerror
def urandom(context, n): provider = context[0] if not provider: # This handle is never explicitly released. The operating # system will release it when the process terminates. if not CryptAcquireContext( context, None, None, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT): raise rwin32.lastWindowsError("CryptAcquireContext") provider = context[0] # TODO(win64) This is limited to 2**31 with lltype.scoped_alloc(rffi.CArray(rwin32.BYTE), n, zero=True, # zero seed ) as buf: if not CryptGenRandom(provider, n, buf): raise rwin32.lastWindowsError("CryptGenRandom") return rffi.charpsize2str(rffi.cast(rffi.CCHARP, buf), n)
def semlock_getvalue(self, space): if rwin32.WaitForSingleObject(self.handle, 0) == rwin32.WAIT_TIMEOUT: return 0 previous_ptr = lltype.malloc(rffi.LONGP.TO, 1, flavor='raw') try: if not _ReleaseSemaphore(self.handle, 1, previous_ptr): raise rwin32.lastWindowsError("ReleaseSemaphore") return previous_ptr[0] + 1 finally: lltype.free(previous_ptr, flavor='raw')
def getfullpathname_llimpl(path): nBufferLength = rwin32.MAX_PATH + 1 lpBuffer = lltype.malloc(traits.CCHARP.TO, nBufferLength, flavor='raw') try: res = win32traits.GetFullPathName( path, rffi.cast(rwin32.DWORD, nBufferLength), lpBuffer, lltype.nullptr(win32traits.LPSTRP.TO)) if res == 0: raise rwin32.lastWindowsError("_getfullpathname failed") result = traits.charp2str(lpBuffer) return result finally: lltype.free(lpBuffer, flavor='raw')
def CreateNamedPipe(space, name, openmode, pipemode, maxinstances, outputsize, inputsize, timeout, w_security): security = space.int_w(w_security) if security: raise OperationError(space.w_NotImplementedError, space.wrap("expected a NULL pointer")) handle = _CreateNamedPipe( name, openmode, pipemode, maxinstances, outputsize, inputsize, timeout, rffi.NULL) if handle == rwin32.INVALID_HANDLE_VALUE: raise wrap_windowserror(space, rwin32.lastWindowsError()) return w_handle(space, handle)
def CreateFile(space, filename, access, share, w_security, disposition, flags, w_templatefile): security = space.int_w(w_security) templatefile = space.int_w(w_templatefile) if security or templatefile: raise OperationError(space.w_NotImplementedError, space.wrap("expected a NULL pointer")) handle = _CreateFile(filename, access, share, rffi.NULL, disposition, flags, rwin32.NULL_HANDLE) if handle == rwin32.INVALID_HANDLE_VALUE: raise wrap_windowserror(space, rwin32.lastWindowsError()) return w_handle(space, handle)
class GlobalState: def __init__(self): self.init() def init(self): self.interrupt_event = rwin32.NULL_HANDLE def startup(self, space): # Initialize the event handle used to signal Ctrl-C try: globalState.interrupt_event = rwin32.CreateEvent( rffi.NULL, True, False, rffi.NULL) except WindowsError, e: raise wrap_windowserror(space, e) if not _setCtrlHandlerRoutine(globalState.interrupt_event): raise wrap_windowserror( space, rwin32.lastWindowsError("SetConsoleCtrlHandler"))
def SetNamedPipeHandleState(space, w_handle, w_pipemode, w_maxinstances, w_timeout): handle = handle_w(space, w_handle) state = lltype.malloc(rffi.CArrayPtr(rffi.UINT).TO, 3, flavor='raw') statep = lltype.malloc(rffi.CArrayPtr(rffi.UINTP).TO, 3, flavor='raw', zero=True) try: if not space.is_w(w_pipemode, space.w_None): state[0] = space.uint_w(w_pipemode) statep[0] = rffi.ptradd(state, 0) if not space.is_w(w_maxinstances, space.w_None): state[1] = space.uint_w(w_maxinstances) statep[1] = rffi.ptradd(state, 1) if not space.is_w(w_timeout, space.w_None): state[2] = space.uint_w(w_timeout) statep[2] = rffi.ptradd(state, 2) if not _SetNamedPipeHandleState(handle, statep[0], statep[1], statep[2]): raise wrap_windowserror(space, rwin32.lastWindowsError()) finally: lltype.free(state, flavor='raw') lltype.free(statep, flavor='raw')
def WaitNamedPipe(space, name, timeout): # Careful: zero means "default value specified by CreateNamedPipe()" if not _WaitNamedPipe(name, timeout): raise wrap_windowserror(space, rwin32.lastWindowsError())
def CloseHandle(space, w_handle): handle = handle_w(space, w_handle) if not rwin32.CloseHandle(handle): raise wrap_windowserror(space, rwin32.lastWindowsError())
def mmap(fileno, length, tagname="", access=_ACCESS_DEFAULT, offset=0): # XXX flags is or-ed into access by now. flags = 0 # check size boundaries _check_map_size(length) map_size = length if offset < 0: raise RValueError("negative offset") flProtect = 0 dwDesiredAccess = 0 fh = NULL_HANDLE if access == ACCESS_READ: flProtect = PAGE_READONLY dwDesiredAccess = FILE_MAP_READ elif access == _ACCESS_DEFAULT or access == ACCESS_WRITE: flProtect = PAGE_READWRITE dwDesiredAccess = FILE_MAP_WRITE elif access == ACCESS_COPY: flProtect = PAGE_WRITECOPY dwDesiredAccess = FILE_MAP_COPY else: raise RValueError("mmap invalid access parameter.") # assume -1 and 0 both mean invalid file descriptor # to 'anonymously' map memory. if fileno != -1 and fileno != 0: fh = rwin32.get_osfhandle(fileno) # Win9x appears to need us seeked to zero # SEEK_SET = 0 # libc._lseek(fileno, 0, SEEK_SET) # check file size try: low, high = _get_file_size(fh) except OSError: pass # ignore non-seeking files and errors and trust map_size else: if not high and low <= sys.maxint: size = low else: # not so sure if the signed/unsigned strictness is a good idea: high = rffi.cast(lltype.Unsigned, high) low = rffi.cast(lltype.Unsigned, low) size = (high << 32) + low size = rffi.cast(lltype.Signed, size) if map_size == 0: if size == 0: raise RValueError("cannot mmap an empty file") if offset > size: raise RValueError( "mmap offset is greater than file size") map_size = int(size - offset) if map_size != size - offset: raise RValueError("mmap length is too large") elif offset + map_size > size: raise RValueError("mmap length is greater than file size") m = MMap(access, offset) m.file_handle = INVALID_HANDLE m.map_handle = INVALID_HANDLE if fh: # it is necessary to duplicate the handle, so the # Python code can close it on us handle_ref = lltype.malloc(LPHANDLE.TO, 1, flavor='raw') handle_ref[0] = m.file_handle try: res = DuplicateHandle(GetCurrentProcess(), # source process handle fh, # handle to be duplicated GetCurrentProcess(), # target process handle handle_ref, # result 0, # access - ignored due to options value False, # inherited by child procs? DUPLICATE_SAME_ACCESS) # options if not res: raise rwin32.lastWindowsError() m.file_handle = handle_ref[0] finally: lltype.free(handle_ref, flavor='raw') if not map_size: low, high = _get_file_size(fh) if _64BIT: map_size = (low << 32) + 1 else: if high: # file is too large to map completely map_size = -1 else: map_size = low if tagname: m.tagname = tagname # DWORD is a 4-byte int. If int > 4-byte it must be divided if _64BIT: size_hi = (map_size + offset) >> 32 size_lo = (map_size + offset) & 0xFFFFFFFF offset_hi = offset >> 32 offset_lo = offset & 0xFFFFFFFF else: size_hi = 0 size_lo = map_size + offset offset_hi = 0 offset_lo = offset flProtect |= flags m.map_handle = CreateFileMapping(m.file_handle, NULL, flProtect, size_hi, size_lo, m.tagname) if m.map_handle: data = MapViewOfFile(m.map_handle, dwDesiredAccess, offset_hi, offset_lo, length) if data: # XXX we should have a real LPVOID which must always be casted charp = rffi.cast(LPCSTR, data) m.setdata(charp, map_size) return m winerror = rwin32.lastWindowsError() if m.map_handle: rwin32.CloseHandle(m.map_handle) m.map_handle = INVALID_HANDLE raise winerror