This is an automated email from the git hooks/post-receive script.

Git pushed a commit to branch release/9.0
in repository ffmpeg.

commit b0692eb266b9f0132a0afc7d3a698e1e6ceb8c6f
Author:     Christopher Decker <[email protected]>
AuthorDate: Thu Jul 23 11:01:30 2026 -0400
Commit:     Michael Niedermayer <[email protected]>
CommitDate: Sun Aug 2 06:24:00 2026 +0200

    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]>
    (cherry picked from commit 94ff335d762ad08f2557a320def57f287d74e2a5)
    Co-Authored-by: Fable 5
---
 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 e76dc35c31..0d2e757b27 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -779,6 +779,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]

Reply via email to