You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							106 lines
						
					
					
						
							3.4 KiB
						
					
					
				
			
		
		
	
	
							106 lines
						
					
					
						
							3.4 KiB
						
					
					
				# -*- 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: (c) 2014 by the Werkzeug Team, see AUTHORS for more details.
 | 
						|
    :license: BSD, see LICENSE for more details.
 | 
						|
"""
 | 
						|
import sys
 | 
						|
import os
 | 
						|
import errno
 | 
						|
import time
 | 
						|
import random
 | 
						|
 | 
						|
from ._compat import to_unicode
 | 
						|
from .filesystem import get_filesystem_encoding
 | 
						|
 | 
						|
 | 
						|
can_rename_open_file = False
 | 
						|
if os.name == 'nt':  # pragma: no cover
 | 
						|
    _rename = lambda src, dst: False
 | 
						|
    _rename_atomic = lambda src, dst: False
 | 
						|
 | 
						|
    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:
 | 
						|
        pass
 | 
						|
 | 
						|
    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.maxint))
 | 
						|
            os.rename(dst, old)
 | 
						|
            os.rename(src, dst)
 | 
						|
            try:
 | 
						|
                os.unlink(old)
 | 
						|
            except Exception:
 | 
						|
                pass
 | 
						|
else:
 | 
						|
    rename = os.rename
 | 
						|
    can_rename_open_file = True
 | 
						|
 |