def win32_fstat_llimpl(fd): handle = rwin32.get_osfhandle(fd) filetype = win32traits.GetFileType(handle) if filetype == win32traits.FILE_TYPE_CHAR: # console or LPT device return make_stat_result( (win32traits._S_IFCHR, 0, 0, 0, 0, 0, 0, 0, 0, 0)) elif filetype == win32traits.FILE_TYPE_PIPE: # socket or named pipe return make_stat_result( (win32traits._S_IFIFO, 0, 0, 0, 0, 0, 0, 0, 0, 0)) elif filetype == win32traits.FILE_TYPE_UNKNOWN: error = rwin32.GetLastError_saved() if error != 0: raise WindowsError(error, "os_fstat failed") # else: unknown but valid file # normal disk file (FILE_TYPE_DISK) info = lltype.malloc(win32traits.BY_HANDLE_FILE_INFORMATION, flavor='raw', zero=True) try: res = win32traits.GetFileInformationByHandle(handle, info) if res == 0: raise WindowsError(rwin32.GetLastError_saved(), "os_fstat failed") return by_handle_info_to_stat(info) finally: lltype.free(info, flavor='raw')
def fstat(fd): if not _WIN32: with lltype.scoped_alloc(STAT_STRUCT.TO) as stresult: handle_posix_error('fstat', c_fstat(fd, stresult)) return build_stat_result(stresult) else: handle = rwin32.get_osfhandle(fd) win32traits = make_win32_traits(string_traits) filetype = win32traits.GetFileType(handle) if filetype == win32traits.FILE_TYPE_CHAR: # console or LPT device return make_stat_result( (win32traits._S_IFCHR, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) elif filetype == win32traits.FILE_TYPE_PIPE: # socket or named pipe return make_stat_result( (win32traits._S_IFIFO, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) elif filetype == win32traits.FILE_TYPE_UNKNOWN: error = rwin32.GetLastError_saved() if error != 0: raise WindowsError(error, "os_fstat failed") # else: unknown but valid file # normal disk file (FILE_TYPE_DISK) info = lltype.malloc(win32traits.BY_HANDLE_FILE_INFORMATION, flavor='raw', zero=True) try: res = win32traits.GetFileInformationByHandle(handle, info) if res == 0: raise WindowsError(rwin32.GetLastError_saved(), "os_fstat failed") return win32_by_handle_info_to_stat(win32traits, info) finally: lltype.free(info, flavor='raw')
def listdir_llimpl(path): mask = make_listdir_mask(path) filedata = lltype.malloc(win32traits.WIN32_FIND_DATA, flavor='raw') try: result = [] hFindFile = win32traits.FindFirstFile(mask, filedata) if hFindFile == rwin32.INVALID_HANDLE_VALUE: error = rwin32.GetLastError_saved() if error == win32traits.ERROR_FILE_NOT_FOUND: return result else: raise WindowsError(error, "FindFirstFile failed") while True: name = traits.charp2str( rffi.cast(traits.CCHARP, filedata.c_cFileName)) if not skip_listdir(name): result.append(name) if not win32traits.FindNextFile(hFindFile, filedata): break # FindNextFile sets error to ERROR_NO_MORE_FILES if # it got to the end of the directory error = rwin32.GetLastError_saved() win32traits.FindClose(hFindFile) if error == win32traits.ERROR_NO_MORE_FILES: return result else: raise WindowsError(error, "FindNextFile failed") finally: lltype.free(filedata, flavor='raw')
def win32_xstat(traits, path, traverse=False): win32traits = make_win32_traits(traits) with lltype.scoped_alloc( win32traits.WIN32_FILE_ATTRIBUTE_DATA) as data: res = win32traits.GetFileAttributesEx( path, win32traits.GetFileExInfoStandard, data) if res == 0: errcode = rwin32.GetLastError_saved() if errcode == win32traits.ERROR_SHARING_VIOLATION: res = win32_attributes_from_dir(win32traits, path, data) if res == 0: errcode = rwin32.GetLastError_saved() raise WindowsError(errcode, "os_stat failed") return win32_attribute_data_to_stat(win32traits, data)
def dlopenex(name): res = rwin32.LoadLibraryExA(name) if not res: err = rwin32.GetLastError_saved() ustr, lgt = rwin32.FormatErrorW(err) raise DLOpenError(ustr) return res
def dlopen(name, mode=-1): # mode is unused on windows, but a consistant signature res = rwin32.LoadLibrary(name) if not res: err = rwin32.GetLastError_saved() raise DLOpenError(rwin32.FormatError(err)) return res
def utf8_encode_code_page(cp, s, errors, errorhandler): """Encode a utf8 string s using code page cp and the given errors/errorhandler. Returns a encoded byte string """ name = _code_page_name(cp) lgt = len(s) if lgt == 0: return '' flags = _encode_code_page_flags(cp, errors) if cp in (rwin32.CP_UTF8, rwin32.CP_UTF7): used_default_p = lltype.nullptr(BOOLP.TO) else: used_default_p = lltype.malloc(BOOLP.TO, 1, flavor='raw') # Encode one codpoint at a time to allow the errorhandlers to do # their thing chars = lltype.malloc(rffi.CWCHARP.TO, 2, flavor='raw') res = StringBuilder(lgt) try: with rffi.scoped_alloc_buffer(4) as buf: pos = 0 # TODO: update s if obj != s is returned from an errorhandler for uni in Utf8StringIterator(s): if used_default_p: used_default_p[0] = rffi.cast(rwin32.BOOL, False) if uni < 0x10000: chars[0] = rffi.cast(lltype.UniChar, uni) charsize = 1 else: chars[0] = Py_UNICODE_HIGH_SURROGATE(uni) chars[1] = Py_UNICODE_LOW_SURROGATE(uni) charsize = 2 # first get the size of the result outsize = WideCharToMultiByte(cp, flags, chars, charsize, buf.raw, 4, None, used_default_p) if outsize > 0: if not (used_default_p and used_default_p[0]): r = buf.str(outsize) assert r is not None res.append(r) pos += 1 continue elif rwin32.GetLastError_saved( ) != rwin32.ERROR_NO_UNICODE_TRANSLATION: raise rwin32.lastSavedWindowsError() # If we used a default char, then we failed! r, pos, retype, obj = errorhandler(errors, name, "invalid character", s, pos, pos + 1) res.append(r) pos += 1 finally: lltype.free(chars, flavor='raw') if used_default_p: lltype.free(used_default_p, flavor='raw') return res.build()
def dlopenex(name): res = rwin32.LoadLibraryExA(name) if not res: err = rwin32.GetLastError_saved() ustr = rwin32.FormatErrorW(err) # DLOpenError unicode msg breaks translation of cpyext create_extension_module raise DLOpenError(ustr.encode('utf-8')) return res
def create_semaphore(space, name, val, max): rwin32.SetLastError_saved(0) handle = _CreateSemaphore(rffi.NULL, val, max, rffi.NULL) # On Windows we should fail on ERROR_ALREADY_EXISTS err = rwin32.GetLastError_saved() if err != 0: raise WindowsError(err, "CreateSemaphore") return handle
def win32_stat_llimpl(path): data = lltype.malloc(win32traits.WIN32_FILE_ATTRIBUTE_DATA, flavor='raw') try: l_path = traits.str2charp(path) res = win32traits.GetFileAttributesEx( l_path, win32traits.GetFileExInfoStandard, data) errcode = rwin32.GetLastError_saved() if res == 0: if errcode == win32traits.ERROR_SHARING_VIOLATION: res = attributes_from_dir(l_path, data) errcode = rwin32.GetLastError_saved() traits.free_charp(l_path) if res == 0: raise WindowsError(errcode, "os_stat failed") return attribute_data_to_stat(data) finally: lltype.free(data, flavor='raw')
def dlopenU(name, mode=-1): # mode is unused on windows, but a consistant signature res = rwin32.LoadLibraryW(name) if not res: err = rwin32.GetLastError_saved() ustr = rwin32.FormatErrorW(err) # DLOpenError unicode msg breaks translation of cpyext create_extension_module raise DLOpenError(ustr.encode('utf-8')) return res
def semlock_release(self, space): if not _ReleaseSemaphore(self.handle, 1, lltype.nullptr( rffi.LONGP.TO)): err = rwin32.GetLastError_saved() if err == 0x0000012a: # ERROR_TOO_MANY_POSTS raise oefmt(space.w_ValueError, "semaphore or lock released too many times") else: raise WindowsError(err, "ReleaseSemaphore")
def dlopenex(name, flags=rwin32.LOAD_WITH_ALTERED_SEARCH_PATH): # Don't display a message box when Python can't load a DLL */ old_mode = rwin32.SetErrorMode(rwin32.SEM_FAILCRITICALERRORS) res = rwin32.LoadLibraryExA(name, flags) rwin32.SetErrorMode(old_mode) if not res: err = rwin32.GetLastError_saved() ustr, lgt = rwin32.FormatErrorW(err) raise DLOpenError(ustr) return res
def do_recv_string(self, space, buflength, maxlength): from _multiprocess.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_saved() 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.lastSavedWindowsError()) length = intmask(read_ptr[0]) + intmask(left_ptr[0]) if length > maxlength: # bad message, close connection self.flags &= ~READABLE if self.flags == 0: self.close() raise oefmt(space.w_IOError, "bad message length") newbuf = lltype.malloc(rffi.CCHARP.TO, length + 1, flavor='raw') length_read = intmask(read_ptr[0]) for i in range(length_read): newbuf[i] = self.buffer[i] result = _ReadFile(self.handle, rffi.ptradd(newbuf, length_read), left_ptr[0], read_ptr, rffi.NULL) if not result: rffi.free_charp(newbuf) raise wrap_windowserror(space, rwin32.lastSavedWindowsError()) assert r_uint(read_ptr[0]) == r_uint(left_ptr[0]) return length, newbuf finally: lltype.free(read_ptr, flavor='raw') lltype.free(left_ptr, flavor='raw')
def _decode_cp_error(s, errorhandler, encoding, errors, final, start, end): # late import to avoid circular import from pypy.interpreter.unicodehelper import _str_decode_utf8_slowpath if rwin32.GetLastError_saved() == rwin32.ERROR_NO_UNICODE_TRANSLATION: msg = ("No mapping for the Unicode character exists in the target " "multi-byte code page.") r, ignore1, ignore2 = _str_decode_utf8_slowpath( s[start:end], errors, final, errorhandler, False) return r, end else: raise rwin32.lastSavedWindowsError()
def win32_xstat3(traits, path, traverse=False): # This is the Python3 version of os.stat() or lstat(). # XXX 'traverse' is ignored, and everything related to # the "reparse points" is missing win32traits = make_win32_traits(traits) hFile = win32traits.CreateFile( path, win32traits.FILE_READ_ATTRIBUTES, 0, lltype.nullptr(rwin32.LPSECURITY_ATTRIBUTES.TO), win32traits.OPEN_EXISTING, win32traits.FILE_ATTRIBUTE_NORMAL | win32traits.FILE_FLAG_BACKUP_SEMANTICS | 0, # win32traits.FILE_FLAG_OPEN_REPARSE_POINT, rwin32.NULL_HANDLE) if hFile == rwin32.INVALID_HANDLE_VALUE: errcode = rwin32.GetLastError_saved() if (errcode != win32traits.ERROR_ACCESS_DENIED and errcode != win32traits.ERROR_SHARING_VIOLATION): raise WindowsError(errcode, "os_stat failed") with lltype.scoped_alloc( win32traits.WIN32_FILE_ATTRIBUTE_DATA) as data: if win32_attributes_from_dir(win32traits, path, data) == 0: raise WindowsError(rwin32.GetLastError_saved(), "win32_attributes_from_dir failed") return win32_attribute_data_to_stat(win32traits, data) with lltype.scoped_alloc(win32traits.BY_HANDLE_FILE_INFORMATION, zero=True) as data: res = win32traits.GetFileInformationByHandle(hFile, data) errcode = rwin32.GetLastError_saved() rwin32.CloseHandle(hFile) if res == 0: raise WindowsError(errcode, "GetFileInformationByHandle failed") return win32_by_handle_info_to_stat(win32traits, data)
def opendir(path): if len(path) == 0: path = u'.' if path[-1] not in (u'\\', u'/', u':'): mask = path + u'\\*.*' else: mask = path + u'*.*' dirp = lltype.malloc(SCANDIRP.TO, flavor='raw') hFindFile = win32traits.FindFirstFile(mask, dirp.filedata) if hFindFile == rwin32.INVALID_HANDLE_VALUE: error = rwin32.GetLastError_saved() lltype.free(dirp, flavor='raw') raise WindowsError(error, "FindFirstFileW failed") dirp.hFindFile = hFindFile dirp.first_time = True return dirp
def nextentry(dirp): """Read the next entry and returns an opaque object. Use the methods has_xxx() and get_xxx() to read from that opaque object. The opaque object is valid until the next time nextentry() or closedir() is called. This may raise WindowsError, or return NULL when exhausted. Note that this doesn't filter out the "." and ".." entries. """ if dirp.first_time: dirp.first_time = False else: if not win32traits.FindNextFile(dirp.hFindFile, dirp.filedata): # error or no more files error = rwin32.GetLastError_saved() if error == win32traits.ERROR_NO_MORE_FILES: return lltype.nullptr(win32traits.WIN32_FIND_DATA) raise WindowsError(error, "FindNextFileW failed") return dirp.filedata
def do_send_string(self, space, buf, offset, size): from pypy.module._multiprocessing.interp_win32 import ( _WriteFile, ERROR_NO_SYSTEM_RESOURCES) from rpython.rlib import rwin32 with rffi.scoped_view_charp(buf) as charp: written_ptr = lltype.malloc(rffi.CArrayPtr(rwin32.DWORD).TO, 1, flavor='raw') try: result = _WriteFile(self.handle, rffi.ptradd(charp, offset), size, written_ptr, rffi.NULL) if (result == 0 and rwin32.GetLastError_saved() == ERROR_NO_SYSTEM_RESOURCES): raise oefmt(space.w_ValueError, "Cannot send %d bytes over connection", size) finally: lltype.free(written_ptr, flavor='raw')
def opendir(path, lgt): if lgt == 0: path = '.' if path[-1] not in ('\\', '/', ':'): mask = path + '\\*.*' lgt += 4 else: mask = path + '*.*' lgt += 3 dirp = lltype.malloc(SCANDIRP.TO, flavor='raw') with rffi.scoped_utf82wcharp(mask, lgt) as src_buf: hFindFile = win32traits.FindFirstFile(src_buf, dirp.filedata) if hFindFile == rwin32.INVALID_HANDLE_VALUE: error = rwin32.GetLastError_saved() lltype.free(dirp, flavor='raw') raise WindowsError(error, "FindFirstFileW failed") dirp.hFindFile = hFindFile dirp.first_time = True return dirp
def _get_file_size(handle): # XXX use native Windows types like WORD high_ref = lltype.malloc(LPDWORD.TO, 1, flavor='raw') try: low = GetFileSize(handle, high_ref) low = rffi.cast(lltype.Signed, low) # XXX should be propagate the real type, allowing # for 2*sys.maxint? high = high_ref[0] high = rffi.cast(lltype.Signed, high) # low might just happen to have the value INVALID_FILE_SIZE # so we need to check the last error also INVALID_FILE_SIZE = -1 if low == INVALID_FILE_SIZE: err = rwin32.GetLastError_saved() if err: raise WindowsError(err, "mmap") return low, high finally: lltype.free(high_ref, flavor='raw')
def write_w(self, space, w_data): if self.handle == rwin32.INVALID_HANDLE_VALUE: raise err_closed(space) if not self.writable: raise err_mode(space, "writing") utf8 = space.utf8_w(w_data) if not len(utf8): return space.newint(0) # TODO: break up the encoding into chunks to save memory state = space.fromcache(CodecState) errh = state.encode_error_handler utf16 = utf8_encode_utf_16(utf8, 'strict', errh, allow_surrogates=False) wlen = len(utf16) // 2 with lltype.scoped_alloc(rwin32.LPDWORD.TO, 1) as n: with rffi.scoped_nonmovingbuffer(utf16) as dataptr: # skip BOM, start at 1 offset = 1 while offset < wlen: res = rwin32.WriteConsoleW( self.handle, rffi.cast(rwin32.LPVOID, rffi.ptradd(dataptr, offset * 2)), wlen - offset, n, rffi.cast(rwin32.LPVOID, 0)) if not res: err = rwin32.GetLastError_saved() raise OperationError(space.w_WindowsError, space.newint(err)) nwrote = intmask(n[0]) offset += nwrote return space.newint(offset - 1)
def get_last_error(space): return space.wrap(rwin32.GetLastError_saved())
def read_console_wide(space, handle, maxlen): """ Make a blocking call to ReadConsoleW, returns wchar-encoded bytes """ err = 0 sig = 0 # Windows uses a 16-bit wchar_t, we mimic that with bytes buf = ByteBuffer((maxlen + 2) * 2) addr = buf.get_raw_address() off = 0 # offset from the beginning of buf, in wchar # readlen is in 16 bits, readlen_b is in 8-bit bytes readlen = readlen_b = 0 bufsize = BUFSIZ with lltype.scoped_alloc(rwin32.LPDWORD.TO, 1) as n: while readlen_b < maxlen: neg_one = rffi.cast(rwin32.DWORD, -1) n[0] = neg_one length = min(maxlen - off, bufsize) rwin32.SetLastError_saved(0) res = rwin32.ReadConsoleW( handle, rffi.cast(rwin32.LPWSTR, rffi.ptradd(addr, readlen_b)), length, n, rffi.cast(rwin32.LPVOID, 0)) nread = intmask(n[0]) err = rwin32.GetLastError_saved() if not res: break if nread == -1 and err == rwin32.ERROR_OPERATION_ABORTED: break if nread == 0: if err != rwin32.ERROR_OPERATION_ABORTED: break err = 0 # This will only catch CTRL-C on the main thread sleep(space, space.newfloat(0.1)) continue readlen += nread readlen_b = 2 * readlen # We didn't manage to read the whole buffer # don't try again as it will just block if nread < length: break if buf.getitem(readlen_b - 2) == '\n': # We read a new line break # If the buffer ends with a high surrogate, take an extra character. if (readlen_b + 1) >= maxlen: with lltype.scoped_alloc(rwin32.LPWORD.TO, 1) as char_type: ptr = rffi.cast(rffi.CWCHARP, rffi.ptradd(addr, +1)) rwin32.GetStringTypeW(rwin32.CT_CTYPE3, ptr, 1, char_type) if intmask(char_type[0]) == intmask( rwin32.C3_HIGHSURROGATE): readlen_b += 2 break if err: raise OperationError(space.w_WindowsError, space.newint(err)) if readlen_b <= 0 or buf.getitem(0) == '\x1a': return '' else: return buf.getslice(0, 1, readlen_b)
def descr_init(self, space, w_nameobj, mode='r', closefd=True, w_opener=None): name = rffi.cast(rffi.CWCHARP, 0) self.fd = -1 self.handle = rwin32.INVALID_HANDLE_VALUE self.readable = False self.writable = False self.blksize = 0 rwa = False console_type = '\0' self.buf = '' if space.isinstance_w(w_nameobj, space.w_int): self.fd = space.int_w(w_nameobj) if self.fd < 0: raise oefmt(space.w_ValueError, "negative file descriptor") # make the flow analysis happy,otherwise it thinks w_path # is undefined later w_path = w_nameobj if self.fd < 0: from pypy.module.posix.interp_posix import fspath w_path = fspath(space, w_nameobj) console_type = _pyio_get_console_type(space, w_path) if not console_type: raise oefmt(space.w_ValueError, "Invalid console type") if console_type == '\0': raise oefmt(space.w_ValueError, "Cannot open non-console file") self.mode = 'u' for char in mode: if char in "+ax": # OK do nothing pass elif char == "b": self.mode = 'b' elif char == "r": if rwa: raise oefmt(space.w_ValueError, "invalid mode: %s", mode) rwa = True self.readable = True if console_type == "x": console_type = "r" elif char == "w": if rwa: raise oefmt(space.w_ValueError, "invalid mode: %s", mode) rwa = True self.writable = True if console_type == 'x': console_type = 'w' else: raise oefmt(space.w_ValueError, "invalid mode: %s", mode) if not rwa: raise oefmt(space.w_ValueError, "Must have exactly one of read or write mode") if self.fd >= 0: self.handle = rwin32.get_osfhandle(self.fd) self.closehandle = False else: access = rwin32.GENERIC_READ self.closehandle = True if not closefd: raise oefmt(space.w_ValueError, "Cannot use closefd=False with a file name") if self.writable: access = rwin32.GENERIC_WRITE traits = _preferred_traits(space.realunicode_w(w_path)) if not (traits.str is unicode): raise oefmt(space.w_ValueError, "Non-unicode string name %s", traits.str) win32traits = make_win32_traits(traits) pathlen = space.len_w(w_path) name = rffi.utf82wcharp(space.utf8_w(w_path), pathlen) self.handle = win32traits.CreateFile( name, rwin32.GENERIC_READ | rwin32.GENERIC_WRITE, rwin32.FILE_SHARE_READ | rwin32.FILE_SHARE_WRITE, rffi.NULL, win32traits.OPEN_EXISTING, 0, rffi.cast(rwin32.HANDLE, 0)) if self.handle == rwin32.INVALID_HANDLE_VALUE: self.handle = win32traits.CreateFile( name, access, rwin32.FILE_SHARE_READ | rwin32.FILE_SHARE_WRITE, rffi.NULL, win32traits.OPEN_EXISTING, 0, rffi.cast(rwin32.HANDLE, 0)) lltype.free(name, flavor='raw') if self.handle == rwin32.INVALID_HANDLE_VALUE: raise WindowsError(rwin32.GetLastError_saved(), "Failed to open handle") if console_type == '\0': console_type = _get_console_type(self.handle) if console_type == '\0': raise oefmt(space.w_ValueError, "Cannot open non-console file") if self.writable and console_type != 'w': raise oefmt(space.w_ValueError, "Cannot open input buffer for writing") if self.readable and console_type != 'r': raise oefmt(space.w_ValueError, "Cannot open output buffer for reading") self.blksize = DEFAULT_BUFFER_SIZE
def GetLastError(space): return space.wrap(rwin32.GetLastError_saved())
def GetLastError(space): return space.newint(rwin32.GetLastError_saved())
def GetLastError(space): """NOTE: don't use this. See issue #2658""" return space.newint(rwin32.GetLastError_saved())