##// END OF EJS Templates
branching: merge stable into default
branching: merge stable into default

File last commit:

r47575:d4ba4d51 default
r48007:bcafcd77 merge default
Show More
osutil.py
305 lines | 9.3 KiB | text/x-python | PythonLexer
Martin Geisler
pure/osutil: add copyright and license header
r8232 # osutil.py - pure Python version of osutil.c
#
Raphaël Gomès
contributor: change mentions of mpm to olivia...
r47575 # Copyright 2009 Olivia Mackall <olivia@selenic.com> and others
Martin Geisler
pure/osutil: add copyright and license header
r8232 #
# This software may be used and distributed according to the terms of the
Matt Mackall
Update license to GPLv2+
r10263 # GNU General Public License version 2 or any later version.
Martin Geisler
pure/osutil: add copyright and license header
r8232
Rodrigo Damazio Bovendorp
py3: use integer division for the value passed to xrange...
r42724 from __future__ import absolute_import, division
Gregory Szorc
osutil: use absolute_import
r27338
Yuya Nishihara
osutil: implement pure version of recvfds() for PyPy...
r27474 import ctypes
import ctypes.util
Martin Geisler
move mercurial.osutil to mercurial.pure.osutil
r7704 import os
Yuya Nishihara
osutil: implement pure version of recvfds() for PyPy...
r27474 import socket
Benoit Boissinot
style: use consistent variable names (*mod) with imports which would shadow
r10651 import stat as statmod
Martin Geisler
move mercurial.osutil to mercurial.pure.osutil
r7704
Gregory Szorc
py3: manually import getattr where it is needed...
r43359 from ..pycompat import getattr
Yuya Nishihara
osutil: switch to policy importer...
r32367 from .. import (
Matt Harbison
py3: fix str vs bytes in enough places to run `hg version` on Windows...
r39680 encoding,
Pulkit Goyal
py3: use pycompat.ossep at certain places...
r30304 pycompat,
)
Augie Fackler
formatting: blacken the codebase...
r43346
Martin Geisler
move mercurial.osutil to mercurial.pure.osutil
r7704 def _mode_to_kind(mode):
Benoit Boissinot
style: use consistent variable names (*mod) with imports which would shadow
r10651 if statmod.S_ISREG(mode):
return statmod.S_IFREG
if statmod.S_ISDIR(mode):
return statmod.S_IFDIR
if statmod.S_ISLNK(mode):
return statmod.S_IFLNK
if statmod.S_ISBLK(mode):
return statmod.S_IFBLK
if statmod.S_ISCHR(mode):
return statmod.S_IFCHR
if statmod.S_ISFIFO(mode):
return statmod.S_IFIFO
if statmod.S_ISSOCK(mode):
return statmod.S_IFSOCK
Martin Geisler
move mercurial.osutil to mercurial.pure.osutil
r7704 return mode
Augie Fackler
formatting: blacken the codebase...
r43346
Yuya Nishihara
cffi: split modules from pure...
r32512 def listdir(path, stat=False, skip=None):
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """listdir(path, stat=False) -> list_of_tuples
Martin Geisler
move mercurial.osutil to mercurial.pure.osutil
r7704
Return a sorted list containing information about the entries
in the directory.
If stat is True, each element is a 3-tuple:
(name, type, stat object)
Otherwise, each element is a 2-tuple:
(name, type)
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """
Martin Geisler
move mercurial.osutil to mercurial.pure.osutil
r7704 result = []
prefix = path
Pulkit Goyal
py3: use pycompat.ossep at certain places...
r30304 if not prefix.endswith(pycompat.ossep):
prefix += pycompat.ossep
Martin Geisler
move mercurial.osutil to mercurial.pure.osutil
r7704 names = os.listdir(path)
names.sort()
for fn in names:
st = os.lstat(prefix + fn)
Benoit Boissinot
style: use consistent variable names (*mod) with imports which would shadow
r10651 if fn == skip and statmod.S_ISDIR(st.st_mode):
Martin Geisler
move mercurial.osutil to mercurial.pure.osutil
r7704 return []
if stat:
result.append((fn, _mode_to_kind(st.st_mode), st))
else:
result.append((fn, _mode_to_kind(st.st_mode)))
return result
Sune Foldager
posixfile: remove posixfile_nt and fix import bug in windows.py...
r8421
Augie Fackler
formatting: blacken the codebase...
r43346
Jun Wu
codemod: use pycompat.iswindows...
r34646 if not pycompat.iswindows:
Adrian Buehlmann
pure: provide more correct implementation of posixfile for Windows...
r14413 posixfile = open
Yuya Nishihara
osutil: implement pure version of recvfds() for PyPy...
r27474
_SCM_RIGHTS = 0x01
_socklen_t = ctypes.c_uint
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 if pycompat.sysplatform.startswith(b'linux'):
Yuya Nishihara
osutil: implement pure version of recvfds() for PyPy...
r27474 # socket.h says "the type should be socklen_t but the definition of
# the kernel is incompatible with this."
_cmsg_len_t = ctypes.c_size_t
_msg_controllen_t = ctypes.c_size_t
_msg_iovlen_t = ctypes.c_size_t
else:
_cmsg_len_t = _socklen_t
_msg_controllen_t = _socklen_t
_msg_iovlen_t = ctypes.c_int
class _iovec(ctypes.Structure):
_fields_ = [
Pulkit Goyal
py3: use unicode literals in pure/osutil.py...
r29698 (u'iov_base', ctypes.c_void_p),
(u'iov_len', ctypes.c_size_t),
Yuya Nishihara
osutil: implement pure version of recvfds() for PyPy...
r27474 ]
class _msghdr(ctypes.Structure):
_fields_ = [
Pulkit Goyal
py3: use unicode literals in pure/osutil.py...
r29698 (u'msg_name', ctypes.c_void_p),
(u'msg_namelen', _socklen_t),
(u'msg_iov', ctypes.POINTER(_iovec)),
(u'msg_iovlen', _msg_iovlen_t),
(u'msg_control', ctypes.c_void_p),
(u'msg_controllen', _msg_controllen_t),
(u'msg_flags', ctypes.c_int),
Yuya Nishihara
osutil: implement pure version of recvfds() for PyPy...
r27474 ]
class _cmsghdr(ctypes.Structure):
_fields_ = [
Pulkit Goyal
py3: use unicode literals in pure/osutil.py...
r29698 (u'cmsg_len', _cmsg_len_t),
(u'cmsg_level', ctypes.c_int),
(u'cmsg_type', ctypes.c_int),
(u'cmsg_data', ctypes.c_ubyte * 0),
Yuya Nishihara
osutil: implement pure version of recvfds() for PyPy...
r27474 ]
Pulkit Goyal
py3: use unicode literals in pure/osutil.py...
r29698 _libc = ctypes.CDLL(ctypes.util.find_library(u'c'), use_errno=True)
Yuya Nishihara
osutil: do not abort loading pure module just because libc has no recvmsg()...
r27971 _recvmsg = getattr(_libc, 'recvmsg', None)
if _recvmsg:
_recvmsg.restype = getattr(ctypes, 'c_ssize_t', ctypes.c_long)
Augie Fackler
formatting: blacken the codebase...
r43346 _recvmsg.argtypes = (
ctypes.c_int,
ctypes.POINTER(_msghdr),
ctypes.c_int,
)
Yuya Nishihara
osutil: do not abort loading pure module just because libc has no recvmsg()...
r27971 else:
# recvmsg isn't always provided by libc; such systems are unsupported
def _recvmsg(sockfd, msg, flags):
Augie Fackler
formatting: byteify all mercurial/ and hgext/ string literals...
r43347 raise NotImplementedError(b'unsupported platform')
Yuya Nishihara
osutil: implement pure version of recvfds() for PyPy...
r27474
def _CMSG_FIRSTHDR(msgh):
if msgh.msg_controllen < ctypes.sizeof(_cmsghdr):
return
cmsgptr = ctypes.cast(msgh.msg_control, ctypes.POINTER(_cmsghdr))
return cmsgptr.contents
# The pure version is less portable than the native version because the
# handling of socket ancillary data heavily depends on C preprocessor.
# Also, some length fields are wrongly typed in Linux kernel.
def recvfds(sockfd):
"""receive list of file descriptors via socket"""
dummy = (ctypes.c_ubyte * 1)()
iov = _iovec(ctypes.cast(dummy, ctypes.c_void_p), ctypes.sizeof(dummy))
cbuf = ctypes.create_string_buffer(256)
Augie Fackler
formatting: blacken the codebase...
r43346 msgh = _msghdr(
None,
0,
ctypes.pointer(iov),
1,
ctypes.cast(cbuf, ctypes.c_void_p),
ctypes.sizeof(cbuf),
0,
)
Yuya Nishihara
osutil: implement pure version of recvfds() for PyPy...
r27474 r = _recvmsg(sockfd, ctypes.byref(msgh), 0)
if r < 0:
e = ctypes.get_errno()
raise OSError(e, os.strerror(e))
# assumes that the first cmsg has fds because it isn't easy to write
# portable CMSG_NXTHDR() with ctypes.
cmsg = _CMSG_FIRSTHDR(msgh)
if not cmsg:
return []
Augie Fackler
formatting: blacken the codebase...
r43346 if (
cmsg.cmsg_level != socket.SOL_SOCKET
or cmsg.cmsg_type != _SCM_RIGHTS
):
Yuya Nishihara
osutil: implement pure version of recvfds() for PyPy...
r27474 return []
rfds = ctypes.cast(cmsg.cmsg_data, ctypes.POINTER(ctypes.c_int))
Augie Fackler
formatting: blacken the codebase...
r43346 rfdscount = (
cmsg.cmsg_len - _cmsghdr.cmsg_data.offset
) // ctypes.sizeof(ctypes.c_int)
Gregory Szorc
global: use pycompat.xrange()...
r38806 return [rfds[i] for i in pycompat.xrange(rfdscount)]
Yuya Nishihara
osutil: implement pure version of recvfds() for PyPy...
r27474
Augie Fackler
formatting: blacken the codebase...
r43346
Adrian Buehlmann
pure: provide more correct implementation of posixfile for Windows...
r14413 else:
Gregory Szorc
osutil: use absolute_import
r27338 import msvcrt
Adrian Buehlmann
pure: provide more correct implementation of posixfile for Windows...
r14413
Matt Harbison
typing: disable module attribute warnings for properly conditionalized code...
r47544 _kernel32 = ctypes.windll.kernel32 # pytype: disable=module-attr
Adrian Buehlmann
pure: provide more correct implementation of posixfile for Windows...
r14413
_DWORD = ctypes.c_ulong
_LPCSTR = _LPSTR = ctypes.c_char_p
_HANDLE = ctypes.c_void_p
_INVALID_HANDLE_VALUE = _HANDLE(-1).value
Mads Kiilerich
check-code: catch trailing space in comments
r18959 # CreateFile
Adrian Buehlmann
pure: provide more correct implementation of posixfile for Windows...
r14413 _FILE_SHARE_READ = 0x00000001
_FILE_SHARE_WRITE = 0x00000002
_FILE_SHARE_DELETE = 0x00000004
_CREATE_ALWAYS = 2
_OPEN_EXISTING = 3
_OPEN_ALWAYS = 4
_GENERIC_READ = 0x80000000
_GENERIC_WRITE = 0x40000000
_FILE_ATTRIBUTE_NORMAL = 0x80
Mads Kiilerich
declare local constants instead of using magic values and comments
r17429 # open_osfhandle flags
Adrian Buehlmann
pure: provide more correct implementation of posixfile for Windows...
r14413 _O_RDONLY = 0x0000
_O_RDWR = 0x0002
_O_APPEND = 0x0008
_O_TEXT = 0x4000
_O_BINARY = 0x8000
# types of parameters of C functions used (required by pypy)
Augie Fackler
formatting: blacken the codebase...
r43346 _kernel32.CreateFileA.argtypes = [
_LPCSTR,
_DWORD,
_DWORD,
ctypes.c_void_p,
_DWORD,
_DWORD,
_HANDLE,
]
Adrian Buehlmann
pure: provide more correct implementation of posixfile for Windows...
r14413 _kernel32.CreateFileA.restype = _HANDLE
def _raiseioerror(name):
Matt Harbison
typing: disable module attribute warnings for properly conditionalized code...
r47544 err = ctypes.WinError() # pytype: disable=module-attr
Augie Fackler
formatting: blacken the codebase...
r43346 raise IOError(
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 err.errno, '%s: %s' % (encoding.strfromlocal(name), err.strerror)
Augie Fackler
formatting: blacken the codebase...
r43346 )
Adrian Buehlmann
pure: provide more correct implementation of posixfile for Windows...
r14413
class posixfile(object):
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """a file object aiming for POSIX-like semantics
Adrian Buehlmann
pure: provide more correct implementation of posixfile for Windows...
r14413
CPython's open() returns a file that was opened *without* setting the
_FILE_SHARE_DELETE flag, which causes rename and unlink to abort.
This even happens if any hardlinked copy of the file is in open state.
We set _FILE_SHARE_DELETE here, so files opened with posixfile can be
renamed and deleted while they are held open.
Note that if a file opened with posixfile is unlinked, the file
remains but cannot be opened again or be recreated under the same name,
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 until all reading processes have closed the file."""
Adrian Buehlmann
pure: provide more correct implementation of posixfile for Windows...
r14413
Matt Harbison
py3: fix str vs bytes in enough places to run `hg version` on Windows...
r39680 def __init__(self, name, mode=b'r', bufsize=-1):
if b'b' in mode:
Adrian Buehlmann
pure: provide more correct implementation of posixfile for Windows...
r14413 flags = _O_BINARY
else:
flags = _O_TEXT
Matt Harbison
py3: fix str vs bytes in enough places to run `hg version` on Windows...
r39680 m0 = mode[0:1]
if m0 == b'r' and b'+' not in mode:
Adrian Buehlmann
pure: provide more correct implementation of posixfile for Windows...
r14413 flags |= _O_RDONLY
access = _GENERIC_READ
else:
# work around http://support.microsoft.com/kb/899149 and
# set _O_RDWR for 'w' and 'a', even if mode has no '+'
flags |= _O_RDWR
access = _GENERIC_READ | _GENERIC_WRITE
Matt Harbison
py3: fix str vs bytes in enough places to run `hg version` on Windows...
r39680 if m0 == b'r':
Adrian Buehlmann
pure: provide more correct implementation of posixfile for Windows...
r14413 creation = _OPEN_EXISTING
Matt Harbison
py3: fix str vs bytes in enough places to run `hg version` on Windows...
r39680 elif m0 == b'w':
Adrian Buehlmann
pure: provide more correct implementation of posixfile for Windows...
r14413 creation = _CREATE_ALWAYS
Matt Harbison
py3: fix str vs bytes in enough places to run `hg version` on Windows...
r39680 elif m0 == b'a':
Adrian Buehlmann
pure: provide more correct implementation of posixfile for Windows...
r14413 creation = _OPEN_ALWAYS
flags |= _O_APPEND
else:
Augie Fackler
cleanup: remove pointless r-prefixes on double-quoted strings...
r43809 raise ValueError("invalid mode: %s" % pycompat.sysstr(mode))
Adrian Buehlmann
pure: provide more correct implementation of posixfile for Windows...
r14413
Augie Fackler
formatting: blacken the codebase...
r43346 fh = _kernel32.CreateFileA(
name,
access,
_FILE_SHARE_READ | _FILE_SHARE_WRITE | _FILE_SHARE_DELETE,
None,
creation,
_FILE_ATTRIBUTE_NORMAL,
None,
)
Adrian Buehlmann
pure: provide more correct implementation of posixfile for Windows...
r14413 if fh == _INVALID_HANDLE_VALUE:
_raiseioerror(name)
Matt Harbison
typing: disable module attribute warnings for properly conditionalized code...
r47544 fd = msvcrt.open_osfhandle(fh, flags) # pytype: disable=module-attr
Adrian Buehlmann
pure: provide more correct implementation of posixfile for Windows...
r14413 if fd == -1:
_kernel32.CloseHandle(fh)
_raiseioerror(name)
Pulkit Goyal
py3: convert the mode argument of os.fdopen to unicodes (2 of 2)
r30925 f = os.fdopen(fd, pycompat.sysstr(mode), bufsize)
Adrian Buehlmann
pure: provide more correct implementation of posixfile for Windows...
r14413 # unfortunately, f.name is '<fdopen>' at this point -- so we store
# the name on this wrapper. We cannot just assign to f.name,
# because that attribute is read-only.
Augie Fackler
cleanup: remove pointless r-prefixes on single-quoted strings...
r43906 object.__setattr__(self, 'name', name)
object.__setattr__(self, '_file', f)
Adrian Buehlmann
pure: provide more correct implementation of posixfile for Windows...
r14413
def __iter__(self):
return self._file
def __getattr__(self, name):
return getattr(self._file, name)
def __setattr__(self, name, value):
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """mimics the read-only attributes of Python file objects
Adrian Buehlmann
pure: provide more correct implementation of posixfile for Windows...
r14413 by raising 'TypeError: readonly attribute' if someone tries:
f = posixfile('foo.txt')
Augie Fackler
osutil: reformat triple-quoted string so black doesn't confuse itself...
r46553 f.name = 'bla'
Augie Fackler
formating: upgrade to black 20.8b1...
r46554 """
Adrian Buehlmann
pure: provide more correct implementation of posixfile for Windows...
r14413 return self._file.__setattr__(name, value)
Gregory Szorc
osutil: implement __enter__ and __exit__ on posixfile...
r27704
def __enter__(self):
Matt Harbison
windows: ensure pure posixfile fd doesn't escape by entering context manager...
r40976 self._file.__enter__()
return self
Gregory Szorc
osutil: implement __enter__ and __exit__ on posixfile...
r27704
def __exit__(self, exc_type, exc_value, exc_tb):
return self._file.__exit__(exc_type, exc_value, exc_tb)