def acquire(self): """Acquire the lock""" open_mode = os.O_RDWR | os.O_CREAT | os.O_TRUNC fd = None try: # Under Windows, filesystem.open will raise directly an EACCES error # if the lock file is already locked. fd = filesystem.open(self._path, open_mode, 0o600) # The need for this "type: ignore" was fixed in # https://github.com/python/typeshed/pull/3607 and included in # newer versions of mypy so it can be removed when mypy is # upgraded. msvcrt.locking(fd, msvcrt.LK_NBLCK, 1) # type: ignore except (IOError, OSError) as err: if fd: os.close(fd) # Anything except EACCES is unexpected. Raise directly the error in that case. if err.errno != errno.EACCES: raise logger.debug('A lock on %s is held by another process.', self._path) raise errors.LockError( 'Another instance of Certbot is already running.') self._fd = fd
def acquire(self): """Acquire the lock""" open_mode = os.O_RDWR | os.O_CREAT | os.O_TRUNC fd = None try: # Under Windows, filesystem.open will raise directly an EACCES error # if the lock file is already locked. fd = filesystem.open(self._path, open_mode, 0o600) # This "type: ignore" is currently needed because msvcrt methods # are only defined on Windows. See # https://github.com/python/typeshed/blob/16ae4c61201cd8b96b8b22cdfb2ab9e89ba5bcf2/stdlib/msvcrt.pyi. msvcrt.locking(fd, msvcrt.LK_NBLCK, 1) # type: ignore except (IOError, OSError) as err: if fd: os.close(fd) # Anything except EACCES is unexpected. Raise directly the error in that case. if err.errno != errno.EACCES: raise logger.debug('A lock on %s is held by another process.', self._path) raise errors.LockError( 'Another instance of Certbot is already running.') self._fd = fd
def _create_file(path, mode=0o777): file_desc = None try: file_desc = filesystem.open(path, flags=os.O_CREAT, mode=mode) finally: if file_desc: os.close(file_desc)
def test_not_executable(self): file_path = os.path.join(self.tempdir, "foo") # On Windows a file created within Certbot will always have all permissions to the # Administrators group set. Since the unit tests are typically executed under elevated # privileges, it means that current user will always have effective execute rights on the # hook script, and so the test will fail. To prevent that and represent a file created # outside Certbot as typically a hook file is, we mock the _generate_dacl function in # certbot.compat.filesystem to give rights only to the current user. This implies removing # all ACEs except the first one from the DACL created by original _generate_dacl function. from certbot.compat.filesystem import _generate_dacl def _execute_mock(user_sid, mode): dacl = _generate_dacl(user_sid, mode) for _ in range(1, dacl.GetAceCount()): dacl.DeleteAce( 1 ) # DeleteAce dynamically updates the internal index mapping. return dacl # create a non-executable file with mock.patch("certbot.compat.filesystem._generate_dacl", side_effect=_execute_mock): os.close( filesystem.open(file_path, os.O_CREAT | os.O_WRONLY, 0o666)) self.assertFalse(filesystem.is_executable(file_path))
def test_not_executable(self): file_path = os.path.join(self.tempdir, "foo") # create a non-executable file os.close(os.open(file_path, os.O_CREAT | os.O_WRONLY, 0o666)) # prevent unnecessary modifications to PATH with mock.patch("certbot.hooks.plug_util.path_surgery"): self.assertRaises(errors.HookCommandNotFound, self._call, file_path, "foo")
def test_new_file_correct_permissions(self): path = os.path.join(self.tempdir, 'file') desc = filesystem.open(path, os.O_CREAT | os.O_EXCL | os.O_RDWR, 0o700) os.close(desc) dacl = _get_security_dacl(path).GetSecurityDescriptorDacl() everybody = win32security.ConvertStringSidToSid(EVERYBODY_SID) self.assertFalse([dacl.GetAce(index) for index in range(0, dacl.GetAceCount()) if dacl.GetAce(index)[2] == everybody])
def _test_one_creation(self, num, file_exist, flags): one_file = os.path.join(self.tempdir, str(num)) if file_exist and not os.path.exists(one_file): with open(one_file, 'w'): pass handler = None try: handler = filesystem.open(one_file, flags) finally: if handler: os.close(handler)
def _test_one_creation(self, num, file_exist, flags): one_file = os.path.join(self.tempdir, str(num)) if file_exist and not os.path.exists(one_file): open(one_file, 'w').close() handler = None try: handler = filesystem.open(one_file, flags) except BaseException as err: if handler: os.close(handler) raise err
def acquire(self) -> None: """Acquire the lock.""" while self._fd is None: # Open the file fd = filesystem.open(self._path, os.O_CREAT | os.O_WRONLY, 0o600) try: self._try_lock(fd) if self._lock_success(fd): self._fd = fd finally: # Close the file if it is not the required one if self._fd is None: os.close(fd)
def release(self): """Release the lock.""" try: msvcrt.locking(self._fd, msvcrt.LK_UNLCK, 1) os.close(self._fd) try: os.remove(self._path) except OSError as e: # If the lock file cannot be removed, it is not a big deal. # Likely another instance is acquiring the lock we just released. logger.debug(str(e)) finally: self._fd = None
def acquire(self): # type: () -> None """Acquire the lock.""" while self._fd is None: # Open the file fd = os.open(self._path, os.O_CREAT | os.O_WRONLY, 0o600) try: self._try_lock(fd) if self._lock_success(fd): self._fd = fd finally: # Close the file if it is not the required one if self._fd is None: os.close(fd)
def acquire(self): """Acquire the lock""" open_mode = os.O_RDWR | os.O_CREAT | os.O_TRUNC fd = os.open(self._path, open_mode, 0o600) try: msvcrt.locking(fd, msvcrt.LK_NBLCK, 1) except (IOError, OSError) as err: os.close(fd) # Anything except EACCES is unexpected. Raise directly the error in that case. if err.errno != errno.EACCES: raise logger.debug('A lock on %s is held by another process.', self._path) raise errors.LockError('Another instance of Certbot is already running.') self._fd = fd
def release(self): """Release the lock.""" try: # This "type: ignore" is currently needed because msvcrt methods # are only defined on Windows. See # https://github.com/python/typeshed/blob/16ae4c61201cd8b96b8b22cdfb2ab9e89ba5bcf2/stdlib/msvcrt.pyi. msvcrt.locking(self._fd, msvcrt.LK_UNLCK, 1) # type: ignore os.close(self._fd) try: os.remove(self._path) except OSError as e: # If the lock file cannot be removed, it is not a big deal. # Likely another instance is acquiring the lock we just released. logger.debug(str(e)) finally: self._fd = None
def acquire(self): """Acquire the lock""" open_mode = os.O_RDWR | os.O_CREAT | os.O_TRUNC fd = os.open(self._path, open_mode, 0o600) try: msvcrt.locking(fd, msvcrt.LK_NBLCK, 1) except (IOError, OSError) as err: os.close(fd) # Anything except EACCES is unexpected. Raise directly the error in that case. if err.errno != errno.EACCES: raise logger.debug('A lock on %s is held by another process.', self._path) raise errors.LockError( 'Another instance of Certbot is already running.') self._fd = fd
def release(self): """Release the lock.""" try: # The need for this "type: ignore" was fixed in # https://github.com/python/typeshed/pull/3607 and included in # newer versions of mypy so it can be removed when mypy is # upgraded. msvcrt.locking(self._fd, msvcrt.LK_UNLCK, 1) # type: ignore os.close(self._fd) try: os.remove(self._path) except OSError as e: # If the lock file cannot be removed, it is not a big deal. # Likely another instance is acquiring the lock we just released. logger.debug(str(e)) finally: self._fd = None
def release(self) -> None: """Remove, close, and release the lock file.""" # It is important the lock file is removed before it's released, # otherwise: # # process A: open lock file # process B: release lock file # process A: lock file # process A: check device and inode # process B: delete file # process C: open and lock a different file at the same path try: os.remove(self._path) finally: # Following check is done to make mypy happy: it ensure that self._fd, marked # as Optional[int] is effectively int to make it compatible with os.close signature. if self._fd is None: # pragma: no cover raise TypeError('Error, self._fd is None.') try: os.close(self._fd) finally: self._fd = None
def release(self): # type: () -> None """Remove, close, and release the lock file.""" # It is important the lock file is removed before it's released, # otherwise: # # process A: open lock file # process B: release lock file # process A: lock file # process A: check device and inode # process B: delete file # process C: open and lock a different file at the same path try: os.remove(self._path) finally: # Following check is done to make mypy happy: it ensure that self._fd, marked # as Optional[int] is effectively int to make it compatible with os.close signature. if self._fd is None: # pragma: no cover raise TypeError('Error, self._fd is None.') try: os.close(self._fd) finally: self._fd = None