cfileappendstandardsmode

Does rewind and fsetpos can also intervene the C file append mode subsequent writes?


C11 Working Draft Standard N1570 said that on page 306 at "7.21.5.3 The fopen function" section

Opening a file with append mode ('a' as the first character in the mode argument) causes all subsequent writes to the file to be forced to the then current end-of-file, regardless of intervening calls to the fseek function. ...

Can anybody confirms that not only fseek function but also other file positioning function such as fsetpos and rewind can't intervene the append mode?

Well, the standard on page 338 said that rewind does a similar thing with (void)fseek(stream, 0L, SEEK_SET) except that the error indicator for the stream is also cleared. But as far as I have read on page 337 the standard does not state that fsetpos similar to fseek.


Source Code to illustrate this problem

#include <stdio.h>

// Declare the File Pointer
    FILE *fp;

// Declare the test integer variable
    int TEST;

// declare the test position variable for fsetpos test
    fpos_t POSITION;

void WriteData(int choice){
    // Clear the file content
        fp = fopen("test.bin", "wb"); fclose(fp);

    // Reopen the file with ab
        fp = fopen("test.bin", "ab");

    // Initialize the test integer variable
        TEST = 100;

    // Write five sample data
        int i;
        for(i = 1; i <= 5; i++) {

            fwrite(&TEST, sizeof(TEST), 1, fp);

            // If two data were written then save the position
            if( i == 2 ) 
                fgetpos(fp, &POSITION);
        }

    //  Change the data
        TEST = 54321;   

    // Declare the test case
        switch(choice){
            case 1 : fseek(fp, (long) 2*sizeof(TEST), SEEK_SET); break;
            case 2 : rewind(fp); break;
            case 3 : fsetpos(fp, &POSITION); break;
        }

    // Write the data again
        fwrite(&TEST, sizeof(TEST), 1, fp);

    // Close the file
        fclose(fp);
}


void ReadData(){
    // Open the file for read
        fp = fopen("test.bin", "rb");

        printf("\n [OUTPUT]");
    // while the data can be read then print it to the console
        while( fread(&TEST, sizeof(TEST), 1, fp) == 1)
            printf("\n %d", TEST);

    // Close the file
        fclose(fp);
}

int main(){

    /* Test Case Process */
        printf("\n\n Intervene using fseek(fp, (long) 2*sizeof(TEST), SEEK_SET);");
        WriteData(1);
        ReadData();

        printf("\n\n Intervene using rewind(fp);");
        WriteData(2);
        ReadData();

        printf("\n\n Intervene using fsetpos(fp, &POSITION);");
        WriteData(3);
        ReadData();




    return 0;
}

The desired output:

 Intervene using fseek(fp, (long) 2*sizeof(TEST), SEEK_SET);
 [OUTPUT]
 100
 100
 100
 100
 100
 54321

 Intervene using rewind(fp);
 [OUTPUT]
 100
 100
 100
 100
 100
 54321

 Intervene using fsetpos(fp, &POSITION);
 [OUTPUT]
 100
 100
 100
 100
 100
 54321

If the output were like that, then the standard does confirms that not only fseek function that can't intervene the subsequent writes, but also rewind and fsetpos. Else if the output were not like that, then the standard does not confirms it.

I have test it on windows 10 using tdm-gcc 4.9.2 and on Ubuntu 16.04 gcc 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.4). The result is that three of them can't intervene, but I'm not sure in other platform whether it can't intervene or not.

Finally, If I might re-ask my question again. Does the standard also confirms that not only fseek function that can't intervene the seubsequent writes, but also rewind and fsetpos?

If the standard confirms then please explain where does the statement which indicate the confirmation.

Else if the standard does not confirms then please explain where does the statement which indicate the denial.

About my question, what I need to know is the certainty that standard does confirms the compiler writer must exactly do this or do that etc. in order to confirms the standard, nothing more


Solution

  • ISO C17 (ISO/IEC 9899:2017 - N2176 working draft)

    7.21.5.3 The fopen function
    ...
    6 Opening a file with append mode (’a’ as the first character in the mode argument) causes all subsequent writes to the file to be forced to the then current end-of-file, regardless of intervening calls to the fseek function. ...
    ...


    ISO C23 (ISO/IEC 9899:2024 - N3220 working draft)

    7.23.5.3 The fopen function
    ...
    6 Opening a file with append mode (’a’ as the first character in the mode argument) causes all subse-quent writes to the file to be forced to the then current end-of-file at the point of buffer flush or actual write, regardless of intervening calls to the fseek, fsetpos, or rewind functions. ...
    ...


    [wg14/wg21 liaison] fopen 'x', 'a' and 'p'

    From: Niall Douglas <s_sourceforge_at_[hidden]>
    Date: Fri, 27 May 2022 13:23:43 +0000
    ...
    fopen("a"):

    Opening a file with append mode (\code{'a'} as the first character in the mode argument) causes all subsequent writes to the file to be forced to the current end-of-file at the point of buffer flush or actual write}, regardless of intervening calls to the \code{fseek}, \code{fsetpos}, or \code{rewind} functions. Incrementing the current end-of-file by the amount of data written is atomic with respect to other threads writing to the same file provided the file was also opened in append mode. If the implementation is not capable of incrementing the current end-of-file atomically, it shall fail setting \code{errno} to \code{ENOTSUP} instead of performing non-atomic end-of-file writes.} In some implementations, opening a binary file with append mode (\code{'b'} as the second or third character in the above list of \code{mode} argument values) may initially position the file position indicator for the stream beyond the last data written, because of null character padding.

    [Main change: increment of end of file to become atomic]
    ...


    Although the C17 draft (N2176) strictly mentions only fseek. The C23 draft (N3220) and the liaison material explicitly broaden the wording to include fsetpos and rewind, making the specification unambiguous across all File-Positioning Functions.

    And despite the fact that the liaison material states that the “Main change” annotation highlights the atomicity addition, the wording change is undeniably present in the final proposal that WG14 moved forward with.

    So finally, the mystery has been solved many years later.