I rewrote a custom demo soft for this (see attachments).
# When trying to write data into a file on local filesystem
# All data are writen onto the disk

./write_into /tmp/file.txt 3
[fnFileSave] Will try to write 3 byte(s) into [/tmp/file.txt]
[fnFileSave] Opening first stream pointer on file [/tmp/file.txt]
[fnFileSave] Wanted to write 3 byte(s), and 3 were written
[fnFileSave] All data were written, but MAYBE not flushed yet (len <4k)
[fnCheckFileWritable?] Opening 2nd stream pointer on file [/tmp/file.txt] in 
APPEND mode.
[fnCheckFileWritable?] Closing 2nd stream pointer on file [/tmp/file.txt].
[fnFileSave] The flushing succeeded
[fnFileSave] The closing succeeded
[fnFileSave] stat() says that [/tmp/file.txt] size is : 3 byte(s)

./write_into /tmp/file.txt 5000
[fnFileSave] Will try to write 5000 byte(s) into [/tmp/file.txt]
[fnFileSave] Opening first stream pointer on file [/tmp/file.txt]
[fnFileSave] Wanted to write 5000 byte(s), and 5000 were written
[fnFileSave] All data were written, but probably only partially flushed (len > 
4k but not multiple of 4k)
[fnCheckFileWritable?] Opening 2nd stream pointer on file [/tmp/file.txt] in 
APPEND mode.
[fnCheckFileWritable?] Closing 2nd stream pointer on file [/tmp/file.txt].
[fnFileSave] The flushing succeeded
[fnFileSave] The closing succeeded
[fnFileSave] stat() says that [/tmp/file.txt] size is : 5000 byte(s)


# When using gvfs + sftp over the same location, only the data automatically
# flushed on write (each full block of 4kb) before the opening of the second
# file pointer succeed, the remainging data are lost

./write_into 
/run/user/1000/gvfs/sftp\:host\=localhost\,user\=nicolas/tmp/file.txt 3
[fnFileSave] Will try to write 3 byte(s) into 
[/run/user/1000/gvfs/sftp:host=localhost,user=nicolas/tmp/file.txt]
[fnFileSave] Opening first stream pointer on file 
[/run/user/1000/gvfs/sftp:host=localhost,user=nicolas/tmp/file.txt]
[fnFileSave] Wanted to write 3 byte(s), and 3 were written
[fnFileSave] All data were written, but MAYBE not flushed yet (len <4k)
[fnCheckFileWritable?] Opening 2nd stream pointer on file 
[/run/user/1000/gvfs/sftp:host=localhost,user=nicolas/tmp/file.txt] in APPEND 
mode.
[fnCheckFileWritable?] Closing 2nd stream pointer on file 
[/run/user/1000/gvfs/sftp:host=localhost,user=nicolas/tmp/file.txt].
[fnFileSave] The flushing failed, file is probably truncated
[fnFileSave]    -> fflush: Operation not supported
[fnFileSave] The closing succeeded
[fnFileSave] stat() says that 
[/run/user/1000/gvfs/sftp:host=localhost,user=nicolas/tmp/file.txt] size is : 0 
byte(s)

./write_into 
/run/user/1000/gvfs/sftp\:host\=localhost\,user\=nicolas/tmp/file.txt 4096
[fnFileSave] Will try to write 4096 byte(s) into 
[/run/user/1000/gvfs/sftp:host=localhost,user=nicolas/tmp/file.txt]
[fnFileSave] Opening first stream pointer on file 
[/run/user/1000/gvfs/sftp:host=localhost,user=nicolas/tmp/file.txt]
[fnFileSave] Wanted to write 4096 byte(s), and 4096 were written
[fnFileSave] All data were written, and probably flushed (len is multiple of 4k)
[fnCheckFileWritable?] Opening 2nd stream pointer on file 
[/run/user/1000/gvfs/sftp:host=localhost,user=nicolas/tmp/file.txt] in APPEND 
mode.
[fnCheckFileWritable?] Closing 2nd stream pointer on file 
[/run/user/1000/gvfs/sftp:host=localhost,user=nicolas/tmp/file.txt].
[fnFileSave] The flushing succeeded
[fnFileSave] The closing succeeded
[fnFileSave] stat() says that 
[/run/user/1000/gvfs/sftp:host=localhost,user=nicolas/tmp/file.txt] size is : 
4096 byte(s)

./write_into 
/run/user/1000/gvfs/sftp\:host\=localhost\,user\=nicolas/tmp/file.txt 5000
[fnFileSave] Will try to write 5000 byte(s) into 
[/run/user/1000/gvfs/sftp:host=localhost,user=nicolas/tmp/file.txt]
[fnFileSave] Opening first stream pointer on file 
[/run/user/1000/gvfs/sftp:host=localhost,user=nicolas/tmp/file.txt]
[fnFileSave] Wanted to write 5000 byte(s), and 5000 were written
[fnFileSave] All data were written, but probably only partially flushed (len > 
4k but not multiple of 4k)
[fnCheckFileWritable?] Opening 2nd stream pointer on file 
[/run/user/1000/gvfs/sftp:host=localhost,user=nicolas/tmp/file.txt] in APPEND 
mode.
[fnCheckFileWritable?] Closing 2nd stream pointer on file 
[/run/user/1000/gvfs/sftp:host=localhost,user=nicolas/tmp/file.txt].
[fnFileSave] The flushing failed, file is probably truncated
[fnFileSave]    -> fflush: Operation not supported
[fnFileSave] The closing succeeded
[fnFileSave] stat() says that 
[/run/user/1000/gvfs/sftp:host=localhost,user=nicolas/tmp/file.txt] size is : 
4096 byte(s)

./write_into 
/run/user/1000/gvfs/sftp\:host\=localhost\,user\=nicolas/tmp/file.txt 10000
[fnFileSave] Will try to write 10000 byte(s) into 
[/run/user/1000/gvfs/sftp:host=localhost,user=nicolas/tmp/file.txt]
[fnFileSave] Opening first stream pointer on file 
[/run/user/1000/gvfs/sftp:host=localhost,user=nicolas/tmp/file.txt]
[fnFileSave] Wanted to write 10000 byte(s), and 10000 were written
[fnFileSave] All data were written, but probably only partially flushed (len > 
4k but not multiple of 4k)
[fnCheckFileWritable?] Opening 2nd stream pointer on file 
[/run/user/1000/gvfs/sftp:host=localhost,user=nicolas/tmp/file.txt] in APPEND 
mode.
[fnCheckFileWritable?] Closing 2nd stream pointer on file 
[/run/user/1000/gvfs/sftp:host=localhost,user=nicolas/tmp/file.txt].
[fnFileSave] The flushing failed, file is probably truncated
[fnFileSave]    -> fflush: Operation not supported
[fnFileSave] The closing succeeded
[fnFileSave] stat() says that 
[/run/user/1000/gvfs/sftp:host=localhost,user=nicolas/tmp/file.txt] size is : 
8192 byte(s)
/*
 * Made to illustrate https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=680418
 * compile with : gcc write_info.c -o write_info
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>

/// Functions adapted from original leafpad source code (file.c)
/// opens a file in APPEND mode to see if it's writable, then closes it
int check_file_writable(char *filename)
{
	FILE *fp;
	printf("[fnCheckFileWritable?] Opening 2nd stream pointer on file [%s] in APPEND mode.\n", filename);
	if ((fp = fopen(filename, "a")) != NULL) {
		printf("[fnCheckFileWritable?] Closing 2nd stream pointer on file [%s].\n", filename);
		if (fclose(fp) != 0) {
			perror("[fnCheckFileWritable?] \t-> fclose");
		}
		return 1;
	}
	return 0;
}

int file_save(char* filename, int len)
{
	FILE *fp;
	char *str, *cstr;
	int written, result;
	struct stat filestats;

	printf("[fnFileSave] Will try to write %d byte(s) into [%s]\n", len, filename);

	str = (char*) malloc (len*sizeof(char));
	memset(str, 'X', len);

	printf("[fnFileSave] Opening first stream pointer on file [%s]\n", filename);
	fp = fopen(filename, "w");
	if (!fp) {
		printf("[fnFileSave] Can't open file to write\n");
		perror("[fnFileSave] \t-> fopen");
		return -1;
	}

	written = fwrite(str, 1, len, fp); // not flushed yet

	printf("[fnFileSave] Wanted to write %d byte(s), and %d were written\n", len, written);
	if (written != len) {
		printf("[fnFileSave] Some data were lost\n");
		perror("[fnFileSave] \t-> fwrite");
		return -1;
	} else {
		if(len < 4096)
			printf("[fnFileSave] All data were written, but MAYBE not flushed yet (len <4k)\n");
		else {
			if(len % 4096 == 0)
				printf("[fnFileSave] All data were written, and probably flushed (len is multiple of 4k)\n");
			else
				printf("[fnFileSave] All data were written, but probably only partially flushed (len > 4k but not multiple of 4k)\n");
		}
	}
	free(str);

	// As in leafpad 0.8.17,
	// a function opening a second handle on that file
	// in APPEND mode is called before the fclose().
	// Only used to display strange behaviour in some case.
	check_file_writable(filename);

	// fclose() that also causes the flushing of unwritten data
	result = fflush(fp);
	if (result != 0) {
		printf("[fnFileSave] The flushing failed, file is probably truncated\n");
		perror("[fnFileSave] \t-> fflush");
	} else {
		printf("[fnFileSave] The flushing succeeded\n");
	}

	result = fclose(fp);
	if (result != 0) {
		printf("[fnFileSave] The closing failed (%d)\n", result);
		perror("[fnFileSave] \t-> fclose");
	} else {
		printf("[fnFileSave] The closing succeeded\n");
	}

	if (stat(filename, &filestats) == -1) {
		perror("[fnFileSave] \t-> stat");
		return -1;
	}

	printf("[fnFileSave] stat() says that [%s] size is : %lld byte(s)\n",
			filename,
			(long long) filestats.st_size
	);

	return 0;
}

int main(int argc, char *argv[])
{

	if(argc != 3){
		printf("That code try to write some content into a file.");

	    printf("Syntax :\n");
	    printf("%s filename size\n", argv[0]);
	  }
	  else {
		char* filename = argv[1];
		int len = atoi(argv[2]);
		if(len < 0) {
			printf("The size should be strictly positive\n");
			exit(EXIT_FAILURE);
		}

		if(!file_save(filename, len))
			exit(EXIT_FAILURE);
	  }

	return EXIT_SUCCESS;
}

Reply via email to