PR #23830 opened by John_Smith_LYI URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23830 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23830.patch
## Summary When an output file already exists and overwrite is refused, ffmpeg currently returns `AVERROR_EXIT`. The top-level ffmpeg exit path maps `AVERROR_EXIT` to status 0, which makes `-n` and an interactive "no" look successful to scripts. This patch changes only the overwrite-refusal branches in `assert_file_overwrite()` to return `AVERROR(EEXIST)`. Normal `AVERROR_EXIT` paths such as help/version output remain unchanged. The change is limited to the `fftools` command-line program and does not affect public API or ABI. ## Reproduction Before this patch: ```sh touch existing.wav ffmpeg -nostdin -n -f lavfi -i anullsrc -f wav existing.wav echo $? ``` The command reports that the file already exists, but exits with status 0. After this patch, the same refusal exits non-zero and reports `File exists`. ## Test Coverage Added `fate-ffmpeg-no-overwrite`, which creates an existing output file and checks that `ffmpeg -n` exits non-zero. Validated locally on commit `1dae8f89b24ff23565be29b689c061a2d499bbeb` with the default configure path after installing `nasm`: ```sh ./configure make -j$(nproc) fate-ffmpeg-no-overwrite V=1 make -j$(nproc) \ fate-ffmpeg-filter-in-eof \ fate-ffmpeg-filter_complex \ fate-ffmpeg-filter_complex_audio \ fate-ffmpeg-lavfi \ fate-ffmpeg-loopback-decoding \ fate-ffmpeg-no-overwrite \ fate-ffmpeg-streamcopy-t rsync -vrltLW --timeout=60 --contimeout=60 \ rsync://fate-suite.ffmpeg.org/fate-suite/cover_art \ /tmp/ffmpeg-fate-samples/ rsync -vrltLW --timeout=60 --contimeout=60 \ rsync://fate-suite.ffmpeg.org/fate-suite/qt-surge-suite \ /tmp/ffmpeg-fate-samples/ make -j$(nproc) TARGET_SAMPLES=/tmp/ffmpeg-fate-samples fate git diff --check git diff | ./tools/patcheck - printf '%s\n\n%s\n' \ 'fftools/ffmpeg_opt: return an error when refusing overwrite' \ 'Return EEXIST when output overwrite is refused so ffmpeg exits with a non-zero status for -n and interactive no responses.' \ | sh ./tools/check_commit_msg.sh ``` Interactive stdin check: ```sh touch tests/data/fate/interactive-refusal.wav printf 'n\n' | ./ffmpeg -f lavfi -i anullsrc -f wav tests/data/fate/interactive-refusal.wav echo $? ``` The interactive refusal exits non-zero. The non-interactive `-n` refusal path is covered by FATE. The interactive refusal path was verified with stdin prompt input because it depends on prompt handling. ## Notes - `./configure` detected `standalone assembly yes` and `x86 assembler nasm`. - Full local `make fate` passed with `TARGET_SAMPLES=/tmp/ffmpeg-fate-samples`. Only the sample directories needed by locally enabled MOV metadata tests were synced; full external FATE was not enabled with `SAMPLES=...`. - `tools/patcheck` only reported "Missing changelog entry", treated as ignorable for this small CLI error-code fix. - User-visible behavior changes only when overwrite is refused; scripts now get a failure status instead of status 0. From 529320deba513aa3a4ccee020e85e5855805d017 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E6=B0=B8=E9=B9=8F?= <[email protected]> Date: Thu, 16 Jul 2026 18:49:06 +0800 Subject: [PATCH] fftools/ffmpeg_opt: return an error when refusing overwrite MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Return EEXIST when output overwrite is refused so ffmpeg exits with a non-zero status for -n and interactive no responses. Signed-off-by: 张永鹏 <[email protected]> --- fftools/ffmpeg_opt.c | 5 +++-- tests/fate/ffmpeg.mak | 4 ++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/fftools/ffmpeg_opt.c b/fftools/ffmpeg_opt.c index 4e05e2c56b..823486d3fb 100644 --- a/fftools/ffmpeg_opt.c +++ b/fftools/ffmpeg_opt.c @@ -20,6 +20,7 @@ #include "config.h" +#include <errno.h> #include <stdint.h> #if HAVE_SYS_RESOURCE_H @@ -831,13 +832,13 @@ int assert_file_overwrite(const char *filename) signal(SIGINT, SIG_DFL); if (!read_yesno()) { av_log(NULL, AV_LOG_FATAL, "Not overwriting - exiting\n"); - return AVERROR_EXIT; + return AVERROR(EEXIST); } term_init(); } else { av_log(NULL, AV_LOG_FATAL, "File '%s' already exists. Exiting.\n", filename); - return AVERROR_EXIT; + return AVERROR(EEXIST); } } } diff --git a/tests/fate/ffmpeg.mak b/tests/fate/ffmpeg.mak index db6a171898..ca13073208 100644 --- a/tests/fate/ffmpeg.mak +++ b/tests/fate/ffmpeg.mak @@ -244,6 +244,10 @@ fate-ffmpeg-error-rate-fail: CMD = ffmpeg -i $(TARGET_SAMPLES)/mkv/h264_tta_unde fate-ffmpeg-error-rate-pass: CMD = ffmpeg -i $(TARGET_SAMPLES)/mkv/h264_tta_undecodable.mkv -c:v copy -f null - -max_error_rate 1 FATE_SAMPLES_FFMPEG-$(call ENCDEC, PCM_S16LE TTA, NULL MATROSKA) += fate-ffmpeg-error-rate-fail fate-ffmpeg-error-rate-pass +fate-ffmpeg-no-overwrite: CMP = null +fate-ffmpeg-no-overwrite: CMD = out=tests/data/fate/no-overwrite.wav; touch $$out; ffmpeg -f lavfi -i anullsrc -t 0.01 -c:a pcm_u8 -f wav -n $$out; ret=$$?; rm -f $$out; test $$ret -ne 0 +FATE_FFMPEG-$(call ALLYES, LAVFI_INDEV ANULLSRC_FILTER PCM_U8_DECODER PCM_U8_ENCODER WAV_MUXER FILE_PROTOCOL) += fate-ffmpeg-no-overwrite + # test input -bsf # use -stream_loop, because it tests flushing bsfs fate-ffmpeg-bsf-input: CMD = framecrc -stream_loop 2 -bsf setts=PTS*2 -i $(TARGET_SAMPLES)/hevc/extradata-reload-multi-stsd.mov -c copy -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
