Search code examples
winformsfilewinapimsvcrt

How can I determine if a file was opened for append on Windows?


In UNIX if I open a file in append mode like

fd = open("filename", O_APPEND);

then given such a file descriptor one can easily find out what flags it was opened with using fcntl:

fcntl(fd, F_GETFL) & O_APPEND

I know that fcntl is not available on Windows, but I wonder if there is some way to determine this. Windows does clearly support an append mode for example when creating a file with CreateFile and passing in the FILE_APPEND_DATA flag.

But if all I have is a handle to an already opened file I cannot for the life of me find a way to determine what access rights were requested when the file was first opened. This question provides a basic recipe for checking the access rights to a specific file, but that doesn't seem to help. I tried it and even if I open a file with read-only mode it still tells me I have the FILE_APPEND_DATA access to the file, if I were to request it. In other words, this method only tells me what access rights the process has to a particular file (as inherited from the user who started the process). It says nothing about what exact access was requested when the file was opened.

This has nothing to do with how Windows keeps track of whether the file should only be appended to. And it's that latter question that I can't find an answer to anywhere. The closest thing I've found is GetFileInformationByHandleEx but after combing through the docs there's not one file attribute that can be returned through that API that suggests "append mode".

Update: To clarify my question a bit better, this question really just applies to the MS VC runtime library--files opened with the POSIX-like functions _open and written to with fwrite and the like. It appears that the native win32 file handles have no notion of "append mode".


Solution

  • Self-answering, with thanks to @mehrdad and @HansPassant for pointing me in the right direction. Indeed, MSVCRT exports an array of arrays of a structure called ioinfo in which it stores information about each open file handle in the process.

    The exact contents of the structure depend on the VC version and some defines, but in general its first two members are defined:

    typedef struct {
            intptr_t osfhnd;    /* underlying OS file HANDLE */
            char osfile;        /* attributes of file (e.g., open in text mode?) */
            ....
    } ioinfo;
    

    The osfile member is the interesting one--if the file is opened with _O_APPEND the flag called FAPPEND defined as 0x20 is set on this.

    I wrote a little utility function in Python based on similar code in CPython's posixmodule that can perform this check: https://gist.github.com/embray/6444262