Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 470
Unknown123 Avatar asked Oct 29 '22 16:10

Unknown123


1 Answers

With stream I/O, neither rewind() nor fsetpos() overrides the append mode — any more than fseek() does. The implicit seek for append mode happens when the write occurs; the positioning operation is separate and only affects where the implicit seek starts from, not where the write occurs.

With file descriptor I/O, pwrite() — positioned write — does override append mode but other operations do not. POSIX states: The pwrite() function shall be equivalent to write(), except that it writes into a given position and does not change the file offset (regardless of whether O_APPEND is set).

like image 169
Jonathan Leffler Avatar answered Nov 15 '22 06:11

Jonathan Leffler