# (c) Copyright 2014-2015. CodeWeavers, Inc.
import os
import sys
import cxwhich
import systeminfo
try:
MAXFD = os.sysconf("SC_OPEN_MAX")
except:
MAXFD = 256
def _compress_log_file(fileno, compressors, *arguments):
for compressor in compressors:
path = cxwhich.which(os.environ['PATH'], compressor)
if path:
break
else:
return fileno
read_pipe, write_pipe = os.pipe()
exitcode = 1
# double fork to prevent zombies
cpid = os.fork()
if cpid == 0: # pylint: disable=R1702
# child process
try:
os.dup2(read_pipe, 0)
os.dup2(fileno, 1)
os.closerange(3, MAXFD)
gcpid = os.fork()
if gcpid == 0:
# grandchild process
try:
os.execl(path, path, *arguments)
except OSError:
os.write(sys.stderr.fileno(), '_compress_log_file grandchild error: '+str(sys.exc_info()[1]) + '\n')
finally:
os._exit(exitcode) # pylint: disable=W0212
exitcode = 0
except OSError:
os.write(sys.stderr.fileno(), '_compress_log_file child error: '+str(sys.exc_info()[1]) + '\n')
finally:
os._exit(exitcode) # pylint: disable=W0212
# parent process
_pid, exitcode = os.waitpid(cpid, 0)
if exitcode != 0:
os.close(read_pipe)
os.close(write_pipe)
return fileno
os.close(fileno)
os.close(read_pipe)
return write_pipe
# creates the specified file, writes header_text and system info, and returns a file object
# writes must be <= 512 bytes to be atomic
def create_log_file(filename, header_text='', overwrite=True):
fileno = os.open(filename, os.O_WRONLY|os.O_APPEND|os.O_CREAT|(os.O_TRUNC if overwrite else os.O_EXCL), 0o666)
if filename.endswith('.gz'):
fileno = _compress_log_file(fileno, ('pigz', 'gzip'), '-2')
elif filename.endswith('.bz2'):
fileno = _compress_log_file(fileno, ('pbzip2', 'bzip2'), '-9')
elif filename.endswith('.z'):
fileno = _compress_log_file(fileno, ('compress',))
result = os.fdopen(fileno, 'a', 0)
result.write(header_text)
result.write(systeminfo.system_info_string() + '\n')
return result