Truncate locked file

393 views Asked by At

Even though I locked a file in a Java program

try (FileChannel channel = FileChannel.open(fileName, StandardOpenOption.READ);
        FileLock lock = channel.lock(0, Long.MAX_VALUE, false)) {
    // ... <-- Program waits here
}

I'm allowed to open this file with write access in a C program like that

FILE *file = fopen(filename, "wb");
assert(file != NULL);

Surprisingly these lines pass, the file will be opened and since it exists it will be happily truncated to the size zero.

However I'm not allowed to actually write content to it:

assert(fwrite("foo", 1, 3, file) == 3);
assert(fflush(file) == 0);

How dare I!

Question: Why is actually writing content to the file forbidden but truncating it to the size zero allowed? What is the purpose of such a file lock?

1

There are 1 answers

0
kxr On

This somewhat odd seeming behavior is on Linux / Unix too - independent of the language.

The meaning of a lock on an already open file is to lock specific bytes ranges, but not the file as it. In cooperative software you could in the other process / thread first try to gain the same kind of lock right after opening in append mode ("ab") or read+write mode ("rb+") - and not "wb", and ONLY THEN when you got the lock do a seek(0); truncate(0); write(...)

However if you simply want to lock the whole file on share-access level on Windows instead of doing byte-range locks , then simply do something like this right at the beginning when opening a file for reading:

fh = win32file.CreateFile(path, win32file.GENERIC_READ, win32file.FILE_SHARE_READ, None, 
                          win32file.OPEN_EXISTING, win32file.FILE_ATTRIBUTE_NORMAL, None)

(Python example using CreateFile; its a read-shared locking, which just blocks other writes during read; use "0" instead of FILE_SHARE_READ for a total lock against reading too, or when opening for writing)