diff options
| author | Sébastien Marie <semarie@online.fr> | 2022-02-25 12:32:34 +0000 |
|---|---|---|
| committer | Sébastien Marie <semarie@online.fr> | 2022-02-25 12:32:34 +0000 |
| commit | 0a9099440370c902a6d3a08493f6c02363874be5 (patch) | |
| tree | adfdeae954d0a568b671732e9c7f457c6175b598 | |
| parent | 00c138ce9f75b7c4911042a32fbc34a7335f2739 (diff) | |
provide a simple gb_file_copy() implementation
permit to not require sendfile(2) syscall for gb_file_copy()
| -rw-r--r-- | src/gb/gb.h | 48 |
1 files changed, 44 insertions, 4 deletions
diff --git a/src/gb/gb.h b/src/gb/gb.h index 293e5063a..b72a893f7 100644 --- a/src/gb/gb.h +++ b/src/gb/gb.h @@ -243,9 +243,6 @@ extern "C" { #include <stdio.h> #include <pthread_np.h> #define lseek64 lseek - - // XXX OpenBSD - #define sendfile(out, in, offset, count) (-1) #endif #if defined(GB_SYSTEM_UNIX) @@ -6069,7 +6066,7 @@ gbFileTime gb_file_last_write_time(char const *filepath) { gb_inline b32 gb_file_copy(char const *existing_filename, char const *new_filename, b32 fail_if_exists) { #if defined(GB_SYSTEM_OSX) return copyfile(existing_filename, new_filename, NULL, COPYFILE_DATA) == 0; -#else +#elif defined(GB_SYSTEM_LINUX) || defined(GB_SYSTEM_FREEBSD) isize size; int existing_fd = open(existing_filename, O_RDONLY, 0); int new_fd = open(new_filename, O_WRONLY|O_CREAT, 0666); @@ -6086,6 +6083,49 @@ gb_inline b32 gb_file_copy(char const *existing_filename, char const *new_filena close(existing_fd); return size == stat_existing.st_size; +#else + int new_flags = O_WRONLY | O_CREAT; + if (fail_if_exists) { + new_flags |= O_EXCL; + } + int existing_fd = open(existing_filename, O_RDONLY, 0); + int new_fd = open(new_filename, new_flags, 0666); + + struct stat stat_existing; + if (fstat(existing_fd, &stat_existing) == -1) { + return 0; + } + + size_t bsize = stat_existing.st_blksize > BUFSIZ ? stat_existing.st_blksize : BUFSIZ; + char *buf = (char *)malloc(bsize); + if (buf == NULL) { + close(new_fd); + close(existing_fd); + return 0; + } + + isize size = 0; + ssize_t nread, nwrite, offset; + while ((nread = read(existing_fd, buf, bsize)) != -1 && nread != 0) { + for (offset = 0; nread; nread -= nwrite, offset += nwrite) { + if ((nwrite = write(new_fd, buf + offset, nread)) == -1 || nwrite == 0) { + free(buf); + close(new_fd); + close(existing_fd); + return 0; + } + size += nwrite; + } + } + + free(buf); + close(new_fd); + close(existing_fd); + + if (nread == -1) { + return 0; + } + return size == stat_existing.st_size; #endif } |