/usr/lib/python3/dist-packages/skytools/fileutil.py is in python3-skytools 3.3-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 | """File utilities
>>> import tempfile, os
>>> pidfn = tempfile.mktemp('.pid')
>>> write_atomic(pidfn, "1")
>>> write_atomic(pidfn, "2")
>>> os.remove(pidfn)
>>> write_atomic(pidfn, "1", '.bak')
>>> write_atomic(pidfn, "2", '.bak')
>>> os.remove(pidfn)
"""
from __future__ import division, absolute_import, print_function
import sys
import os
import errno
__all__ = ['write_atomic', 'signal_pidfile']
try:
unicode
except NameError:
unicode = str # noqa
# non-win32
def write_atomic_unix(fn, data, bakext=None, mode='b'):
"""Write file with rename."""
if mode not in ['', 'b', 't']:
raise ValueError("unsupported fopen mode")
if mode == 'b' and isinstance(data, unicode):
data = data.encode('utf8')
# write new data to tmp file
fn2 = fn + '.new'
f = open(fn2, 'w' + mode)
f.write(data)
f.close()
# link old data to bak file
if bakext:
if bakext.find('/') >= 0:
raise ValueError("invalid bakext")
fnb = fn + bakext
try:
os.unlink(fnb)
except OSError as e:
if e.errno != errno.ENOENT:
raise
try:
os.link(fn, fnb)
except OSError as e:
if e.errno != errno.ENOENT:
raise
# win32 does not like replace
if sys.platform == 'win32':
try:
os.remove(fn)
except:
pass
# atomically replace file
os.rename(fn2, fn)
def signal_pidfile(pidfile, sig):
"""Send a signal to process whose ID is located in pidfile.
Read only first line of pidfile to support multiline
pidfiles like postmaster.pid.
Returns True is successful, False if pidfile does not exist
or process itself is dead. Any other errors will passed
as exceptions."""
ln = ''
try:
f = open(pidfile, 'r')
ln = f.readline().strip()
f.close()
pid = int(ln)
if sig == 0 and sys.platform == 'win32':
return win32_detect_pid(pid)
os.kill(pid, sig)
return True
except (IOError, OSError) as ex:
if ex.errno not in (errno.ESRCH, errno.ENOENT):
raise
except ValueError as ex:
# this leaves slight race when someone is just creating the file,
# but more common case is old empty file.
if not ln:
return False
raise ValueError('Corrupt pidfile: %s' % pidfile)
return False
def win32_detect_pid(pid):
"""Process detection for win32."""
# avoid pywin32 dependecy, use ctypes instead
import ctypes
# win32 constants
PROCESS_QUERY_INFORMATION = 1024
STILL_ACTIVE = 259
ERROR_INVALID_PARAMETER = 87
ERROR_ACCESS_DENIED = 5
# Load kernel32.dll
k = ctypes.windll.kernel32
OpenProcess = k.OpenProcess
OpenProcess.restype = ctypes.c_void_p
# query pid exit code
h = OpenProcess(PROCESS_QUERY_INFORMATION, 0, pid)
if h is None:
err = k.GetLastError()
if err == ERROR_INVALID_PARAMETER:
return False
if err == ERROR_ACCESS_DENIED:
return True
raise OSError(errno.EFAULT, "Unknown win32error: " + str(err))
code = ctypes.c_int()
k.GetExitCodeProcess(h, ctypes.byref(code))
k.CloseHandle(h)
return code.value == STILL_ACTIVE
def win32_write_atomic(fn, data, bakext=None, mode='b'):
"""Write file with rename for win32."""
if mode not in ['', 'b', 't']:
raise ValueError("unsupported fopen mode")
# write new data to tmp file
fn2 = fn + '.new'
f = open(fn2, 'w' + mode)
f.write(data)
f.close()
# move old data to bak file
if bakext:
if bakext.find('/') >= 0:
raise ValueError("invalid bakext")
fnb = fn + bakext
try:
os.remove(fnb)
except OSError as e:
if e.errno != errno.ENOENT:
raise
try:
os.rename(fn, fnb)
except OSError as e:
if e.errno != errno.ENOENT:
raise
else:
try:
os.remove(fn)
except:
pass
# replace file
os.rename(fn2, fn)
if sys.platform == 'win32':
write_atomic = win32_write_atomic
else:
write_atomic = write_atomic_unix
|