This is an automated email from the git hooks/post-receive script.
Git pushed a commit to branch master
in repository ffmpeg.
The following commit(s) were added to refs/heads/master by this push:
new 94ff335d76 avformat/os_support: fix return value of win32_rename
94ff335d76 is described below
commit 94ff335d762ad08f2557a320def57f287d74e2a5
Author: Christopher Decker <[email protected]>
AuthorDate: Thu Jul 23 11:01:30 2026 -0400
Commit: Daniel Verkamp <[email protected]>
CommitDate: Tue Jul 28 04:59:01 2026 +0000
avformat/os_support: fix return value of win32_rename
The return value of MoveFileExW was not being correctly interpreted,
see
https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-movefileexw.
On Windows a failed rename over the file: protocol now surfaces as failed
to rename file %s to %s:
Operation not permitted (ff_rename, libavformat/avio.c:867) plus an
AVERROR(EPERM) return, where previously the muxer
reported success and the user was left with a missing or stale output file
and no diagnostic. This affects the
write-to-temp-then-rename paths in hlsenc, dashenc, hdsenc,
smoothstreamingenc, segment, and img2enc (e.g. HLS/DASH
playlist updates, -write_temp_file, segment list finalization).
Also, added unit tests to exercise the rename function.
Signed-off-by: Christopher Decker <[email protected]>
---
libavformat/Makefile | 1 +
libavformat/os_support.h | 4 +-
libavformat/tests/rename.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++
tests/fate/libavformat.mak | 5 +++
4 files changed, 105 insertions(+), 2 deletions(-)
diff --git a/libavformat/Makefile b/libavformat/Makefile
index 2a7fbecf96..45084227a6 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -781,6 +781,7 @@ SKIPHEADERS-$(CONFIG_NETWORK) += network.h rtsp.h
TESTPROGS = id3v2 \
mkdir \
+ rename \
seek \
url \
seek_utils
diff --git a/libavformat/os_support.h b/libavformat/os_support.h
index 8479163f70..4fa5ca3c52 100644
--- a/libavformat/os_support.h
+++ b/libavformat/os_support.h
@@ -279,7 +279,7 @@ static inline int win32_rename(const char *src_utf8, const
char *dest_utf8)
goto fallback;
}
- ret = MoveFileExW(src_w, dest_w, MOVEFILE_REPLACE_EXISTING);
+ ret = (MoveFileExW(src_w, dest_w, MOVEFILE_REPLACE_EXISTING) == 0) ? -1 :
0;
av_free(src_w);
av_free(dest_w);
// Lacking proper mapping from GetLastError() error codes to errno codes
@@ -290,7 +290,7 @@ static inline int win32_rename(const char *src_utf8, const
char *dest_utf8)
fallback:
/* filename may be be in CP_ACP */
#if !HAVE_UWP
- ret = MoveFileExA(src_utf8, dest_utf8, MOVEFILE_REPLACE_EXISTING);
+ ret = (MoveFileExA(src_utf8, dest_utf8, MOVEFILE_REPLACE_EXISTING) == 0) ?
-1 : 0;
if (ret)
errno = EPERM;
#else
diff --git a/libavformat/tests/rename.c b/libavformat/tests/rename.c
new file mode 100644
index 0000000000..8f3aa44ff8
--- /dev/null
+++ b/libavformat/tests/rename.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2026 Christopher Decker
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "libavutil/random_seed.h"
+
+#include "libavformat/os_support.h"
+
+static int create_file(const char *path)
+{
+ FILE *f = fopen(path, "wb");
+ if (!f)
+ return -1;
+ fputs("ffmpeg rename test\n", f);
+ fclose(f);
+ return 0;
+}
+
+static int file_exists(const char *path)
+{
+ FILE *f = fopen(path, "rb");
+ if (!f)
+ return 0;
+ fclose(f);
+ return 1;
+}
+
+int main(void)
+{
+ char src[64];
+ char dst[64];
+ unsigned seed = av_get_random_seed();
+ int ret = 0;
+
+ snprintf(src, sizeof(src), "ff-rename-test-%08x.src", seed);
+ snprintf(dst, sizeof(dst), "ff-rename-test-%08x.dst", seed);
+
+ if (create_file(src) < 0) {
+ perror("create src");
+ return 1;
+ }
+
+ /* rename() must follow POSIX semantics and return 0 on success. */
+ if (rename(src, dst) != 0) {
+ perror("rename");
+ ret = 1;
+ goto cleanup;
+ }
+
+ if (file_exists(src)) {
+ fprintf(stderr, "source still exists after rename\n");
+ ret = 1;
+ goto cleanup;
+ }
+
+ if (!file_exists(dst)) {
+ fprintf(stderr, "destination missing after rename\n");
+ ret = 1;
+ goto cleanup;
+ }
+
+ /* Renaming a nonexistent source must fail with a -1 return. */
+ if (rename(src, dst) != -1) {
+ fprintf(stderr, "rename of nonexistent source unexpectedly
succeeded\n");
+ ret = 1;
+ goto cleanup;
+ }
+
+cleanup:
+ unlink(src);
+ unlink(dst);
+ return ret;
+}
diff --git a/tests/fate/libavformat.mak b/tests/fate/libavformat.mak
index 989515a646..7bd20cf9c8 100644
--- a/tests/fate/libavformat.mak
+++ b/tests/fate/libavformat.mak
@@ -7,6 +7,11 @@ fate-mkdir: libavformat/tests/mkdir$(EXESUF)
fate-mkdir: CMD = run libavformat/tests/mkdir$(EXESUF)
fate-mkdir: CMP = null
+FATE_LIBAVFORMAT += fate-rename
+fate-rename: libavformat/tests/rename$(EXESUF)
+fate-rename: CMD = run libavformat/tests/rename$(EXESUF)
+fate-rename: CMP = null
+
FATE_LIBAVFORMAT-$(CONFIG_NETWORK) += fate-noproxy
fate-noproxy: libavformat/tests/noproxy$(EXESUF)
fate-noproxy: CMD = run libavformat/tests/noproxy$(EXESUF)
_______________________________________________
ffmpeg-cvslog mailing list -- [email protected]
To unsubscribe send an email to [email protected]