_RANDOM_UUID_FILE = "/proc/sys/kernel/random/uuid"
-def ReadFile(file_name, size=-1):
+def ReadFile(file_name, size=-1, preread=None):
"""Reads a file.
@type size: int
@param size: Read at most size bytes (if negative, entire file)
+ @type preread: callable receiving file handle as single parameter
+ @param preread: Function called before file is read
@rtype: str
@return: the (possibly partial) content of the file
"""
f = open(file_name, "r")
try:
+ if preread:
+ preread(f)
+
return f.read(size)
finally:
f.close()
if backup and not dry_run and os.path.isfile(file_name):
CreateBackup(file_name)
- dir_name, base_name = os.path.split(file_name)
- fd, new_name = tempfile.mkstemp('.new', base_name, dir_name)
+ # Whether temporary file needs to be removed (e.g. if any error occurs)
do_remove = True
- # here we need to make sure we remove the temp file, if any error
- # leaves it in place
+
+ # Function result
+ result = None
+
+ (dir_name, base_name) = os.path.split(file_name)
+ (fd, new_name) = tempfile.mkstemp(suffix=".new", prefix=base_name,
+ dir=dir_name)
try:
- if uid != -1 or gid != -1:
- os.chown(new_name, uid, gid)
- if mode:
- os.chmod(new_name, mode)
- if callable(prewrite):
- prewrite(fd)
- if data is not None:
- os.write(fd, data)
- else:
- fn(fd)
- if callable(postwrite):
- postwrite(fd)
- os.fsync(fd)
- if atime is not None and mtime is not None:
- os.utime(new_name, (atime, mtime))
+ try:
+ if uid != -1 or gid != -1:
+ os.chown(new_name, uid, gid)
+ if mode:
+ os.chmod(new_name, mode)
+ if callable(prewrite):
+ prewrite(fd)
+ if data is not None:
+ if isinstance(data, unicode):
+ data = data.encode()
+ assert isinstance(data, str)
+ to_write = len(data)
+ offset = 0
+ while offset < to_write:
+ written = os.write(fd, buffer(data, offset))
+ assert written >= 0
+ assert written <= to_write - offset
+ offset += written
+ assert offset == to_write
+ else:
+ fn(fd)
+ if callable(postwrite):
+ postwrite(fd)
+ os.fsync(fd)
+ if atime is not None and mtime is not None:
+ os.utime(new_name, (atime, mtime))
+ finally:
+ # Close file unless the file descriptor should be returned
+ if close:
+ os.close(fd)
+ else:
+ result = fd
+
+ # Rename file to destination name
if not dry_run:
os.rename(new_name, file_name)
+ # Successful, no need to remove anymore
do_remove = False
finally:
- if close:
- os.close(fd)
- result = None
- else:
- result = fd
if do_remove:
RemoveFile(new_name)
(os.path.basename(file_name), TimestampForFilename()))
dir_name = os.path.dirname(file_name)
- fsrc = open(file_name, 'rb')
+ fsrc = open(file_name, "rb")
try:
(fd, backup_name) = tempfile.mkstemp(prefix=prefix, dir=dir_name)
- fdst = os.fdopen(fd, 'wb')
+ fdst = os.fdopen(fd, "wb")
try:
logging.debug("Backing up %s at %s", file_name, backup_name)
shutil.copyfileobj(fsrc, fdst)
try:
fd.seek(0, 2)
pos = fd.tell()
- pos = max(0, pos-4096)
+ pos = max(0, pos - 4096)
fd.seek(pos, 0)
raw_data = fd.read()
finally:
key_fields = key.split()
if isinstance(file_obj, basestring):
- f = open(file_obj, 'a+')
+ f = open(file_obj, "a+")
else:
f = file_obj
# Ignore whitespace changes
if line.split() == key_fields:
break
- nl = line.endswith('\n')
+ nl = line.endswith("\n")
else:
if not nl:
f.write("\n")
- f.write(key.rstrip('\r\n'))
+ f.write(key.rstrip("\r\n"))
f.write("\n")
f.flush()
finally:
fd, tmpname = tempfile.mkstemp(dir=os.path.dirname(file_name))
try:
- out = os.fdopen(fd, 'w')
+ out = os.fdopen(fd, "w")
try:
- f = open(file_name, 'r')
+ f = open(file_name, "r")
try:
for line in f:
# Ignore whitespace changes while comparing lines
return fd_pidfile
-def RemovePidFile(pidfile):
- """Remove the current process pidfile.
-
- Any errors are ignored.
-
- @type pidfile: string
- @param pidfile: Path to the file to be removed
-
- """
- # TODO: we could check here that the file contains our pid
- try:
- RemoveFile(pidfile)
- except Exception: # pylint: disable-msg=W0703
- pass
-
-
def ReadWatcherPauseFile(filename, now=None, remove_after=3600):
"""Reads the watcher pause file.