| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 | # -*- coding: utf-8 -*-r"""    werkzeug.posixemulation    ~~~~~~~~~~~~~~~~~~~~~~~    Provides a POSIX emulation for some features that are relevant to    web applications.  The main purpose is to simplify support for    systems such as Windows NT that are not 100% POSIX compatible.    Currently this only implements a :func:`rename` function that    follows POSIX semantics.  Eg: if the target file already exists it    will be replaced without asking.    This module was introduced in 0.6.1 and is not a public interface.    It might become one in later versions of Werkzeug.    :copyright: 2007 Pallets    :license: BSD-3-Clause"""import errnoimport osimport randomimport sysimport timefrom ._compat import to_unicodefrom .filesystem import get_filesystem_encodingcan_rename_open_file = Falseif os.name == "nt":    try:        import ctypes        _MOVEFILE_REPLACE_EXISTING = 0x1        _MOVEFILE_WRITE_THROUGH = 0x8        _MoveFileEx = ctypes.windll.kernel32.MoveFileExW        def _rename(src, dst):            src = to_unicode(src, get_filesystem_encoding())            dst = to_unicode(dst, get_filesystem_encoding())            if _rename_atomic(src, dst):                return True            retry = 0            rv = False            while not rv and retry < 100:                rv = _MoveFileEx(                    src, dst, _MOVEFILE_REPLACE_EXISTING | _MOVEFILE_WRITE_THROUGH                )                if not rv:                    time.sleep(0.001)                    retry += 1            return rv        # new in Vista and Windows Server 2008        _CreateTransaction = ctypes.windll.ktmw32.CreateTransaction        _CommitTransaction = ctypes.windll.ktmw32.CommitTransaction        _MoveFileTransacted = ctypes.windll.kernel32.MoveFileTransactedW        _CloseHandle = ctypes.windll.kernel32.CloseHandle        can_rename_open_file = True        def _rename_atomic(src, dst):            ta = _CreateTransaction(None, 0, 0, 0, 0, 1000, "Werkzeug rename")            if ta == -1:                return False            try:                retry = 0                rv = False                while not rv and retry < 100:                    rv = _MoveFileTransacted(                        src,                        dst,                        None,                        None,                        _MOVEFILE_REPLACE_EXISTING | _MOVEFILE_WRITE_THROUGH,                        ta,                    )                    if rv:                        rv = _CommitTransaction(ta)                        break                    else:                        time.sleep(0.001)                        retry += 1                return rv            finally:                _CloseHandle(ta)    except Exception:        def _rename(src, dst):            return False        def _rename_atomic(src, dst):            return False    def rename(src, dst):        # Try atomic or pseudo-atomic rename        if _rename(src, dst):            return        # Fall back to "move away and replace"        try:            os.rename(src, dst)        except OSError as e:            if e.errno != errno.EEXIST:                raise            old = "%s-%08x" % (dst, random.randint(0, sys.maxsize))            os.rename(dst, old)            os.rename(src, dst)            try:                os.unlink(old)            except Exception:                passelse:    rename = os.rename    can_rename_open_file = True
 |