mirror of
https://github.com/s3fs-fuse/s3fs-fuse.git
synced 2024-11-18 02:05:13 +00:00
03d84a07d1
nautilus does this when you drag and drop to overwrite a file: 1) create .goutputstream-XXXXXX to write to 2) fsync the fd for .goutputstream-XXXXXX 3) rename .goutputstream-XXXXXX to target file 4) close the fd for .goutputstream-XXXXXX previously, doing this on s3fs would result in an empty target file because after the rename, s3fs would not flush the content of .goutputstream-XXXXXX to target file. this change moves the FdEntity from the old path to the new path whenever rename happens. On flush s3fs would now flush the correct content to the rename target.
68 lines
1.3 KiB
C
68 lines
1.3 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <unistd.h>
|
|
|
|
static const char FILE_CONTENT[] = "XXXX";
|
|
|
|
static char *
|
|
filename_to_mkstemp_template(const char *file)
|
|
{
|
|
size_t len = strlen(file);
|
|
static const char suffix[] = ".XXXXXX";
|
|
size_t new_len = len + sizeof(suffix);
|
|
char *ret_str = calloc(1, new_len);
|
|
int ret = snprintf(ret_str, new_len, "%s%s", file, suffix);
|
|
assert(ret == new_len - 1);
|
|
assert(ret_str[new_len] == '\0');
|
|
return ret_str;
|
|
}
|
|
|
|
static off_t
|
|
get_file_size(const char *file)
|
|
{
|
|
struct stat ss;
|
|
int ret = lstat(file, &ss);
|
|
assert(ret == 0);
|
|
return ss.st_size;
|
|
}
|
|
|
|
static void
|
|
test_rename_before_close(const char *file)
|
|
{
|
|
char *template = filename_to_mkstemp_template(file);
|
|
int fd = mkstemp(template);
|
|
assert(fd >= 0);
|
|
|
|
int ret = write(fd, FILE_CONTENT, sizeof(FILE_CONTENT));
|
|
assert(ret == sizeof(FILE_CONTENT));
|
|
|
|
ret = fsync(fd);
|
|
assert(ret == 0);
|
|
|
|
assert(get_file_size(template) == sizeof(FILE_CONTENT));
|
|
|
|
ret = rename(template, file);
|
|
assert(ret == 0);
|
|
|
|
ret = close(fd);
|
|
assert(ret == 0);
|
|
|
|
assert(get_file_size(file) == sizeof(FILE_CONTENT));
|
|
}
|
|
|
|
int
|
|
main(int argc, char *argv[])
|
|
{
|
|
if (argc < 2) {
|
|
printf("Usage: %s <file>", argv[0]);
|
|
return 1;
|
|
}
|
|
|
|
test_rename_before_close(argv[1]);
|
|
return 0;
|
|
}
|