How to open (read-write) or create a file with truncation allowed?

According to OpenGroup:

O_TRUNC

If the file exists and is a regular file, and the file is successfully
opened O_RDWR or O_WRONLY, its length is truncated to 0 and the mode
and owner are unchanged. It will have no effect on FIFO special files
or terminal device files. Its effect on other file types is
implementation-dependent. The result of using O_TRUNC with O_RDONLY is
undefined.

So, O_TRUNC is probably passed when opening a file with “w” or “w+”. This gives “truncation” a different meaning, not what I want.

With python the solution seems to open file at low-level I/O with os.open() function.

The following python function:

def touchopen(filename, *args, **kwargs):
    # Open the file in R/W and create if it doesn't exist. *Don't* pass O_TRUNC
    fd = os.open(filename, os.O_RDWR | os.O_CREAT)

    # Encapsulate the low-level file descriptor in a python file object
    return os.fdopen(fd, *args, **kwargs)

has the behavior I wanted. You can use it like this (it’s in fact my use case):

# Open an existing file or create if it doesn't exist
with touchopen("./tool.run", "r+") as doing_fd:

    # Acquire a non-blocking exclusive lock
    fcntl.lockf(doing_fd, fcntl.LOCK_EX)

    # Read a previous value if present
    previous_value = doing_fd.read()
    print previous_value 

    # Write the new value and truncate
    doing_fd.seek(0)
    doing_fd.write("new value")
    doing_fd.truncate()

Leave a Comment