[FFmpeg-cvslog] lavf: Don't try to update files atomically with renames on windows

Martin Storsjö git at videolan.org
Tue Nov 25 02:48:30 CET 2014


ffmpeg | branch: master | Martin Storsjö <martin at martin.st> | Tue Nov 18 14:06:19 2014 +0200| [b9d08c77a44390b0848c06f20bc0e9e951ba6a3c] | committer: Martin Storsjö

lavf: Don't try to update files atomically with renames on windows

On windows, rename(2) will fail if the target file exists. On
unix this trick is used to make sure that people reading the file
either will get the full previous file, or the full new version
of the file, but no intermediate version.

Signed-off-by: Martin Storsjö <martin at martin.st>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=b9d08c77a44390b0848c06f20bc0e9e951ba6a3c
---

 libavformat/dashenc.c            |   14 +++++++++-----
 libavformat/hdsenc.c             |   16 ++++++++++------
 libavformat/internal.h           |    6 ++++++
 libavformat/smoothstreamingenc.c |    8 +++++---
 4 files changed, 30 insertions(+), 14 deletions(-)

diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
index 0654661..57ce85f 100644
--- a/libavformat/dashenc.c
+++ b/libavformat/dashenc.c
@@ -296,13 +296,15 @@ static int write_manifest(AVFormatContext *s, int final)
     DASHContext *c = s->priv_data;
     AVIOContext *out;
     char temp_filename[1024];
+    const char *write_filename;
     int ret, i;
     AVDictionaryEntry *title = av_dict_get(s->metadata, "title", NULL, 0);
 
     snprintf(temp_filename, sizeof(temp_filename), "%s.tmp", s->filename);
-    ret = avio_open2(&out, temp_filename, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL);
+    write_filename = USE_RENAME_REPLACE ? temp_filename : s->filename;
+    ret = avio_open2(&out, write_filename, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL);
     if (ret < 0) {
-        av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", temp_filename);
+        av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", write_filename);
         return ret;
     }
     avio_printf(out, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
@@ -392,7 +394,7 @@ static int write_manifest(AVFormatContext *s, int final)
     avio_printf(out, "</MPD>\n");
     avio_flush(out);
     avio_close(out);
-    return ff_rename(temp_filename, s->filename);
+    return USE_RENAME_REPLACE ? ff_rename(temp_filename, s->filename) : 0;
 }
 
 static int dash_write_header(AVFormatContext *s)
@@ -605,6 +607,7 @@ static int dash_flush(AVFormatContext *s, int final, int stream)
     for (i = 0; i < s->nb_streams; i++) {
         OutputStream *os = &c->streams[i];
         char filename[1024] = "", full_path[1024], temp_path[1024];
+        const char *write_path;
         int64_t start_pos = avio_tell(os->ctx->pb);
         int range_length, index_length = 0;
 
@@ -627,7 +630,8 @@ static int dash_flush(AVFormatContext *s, int final, int stream)
             snprintf(filename, sizeof(filename), "chunk-stream%d-%05d.m4s", i, os->segment_index);
             snprintf(full_path, sizeof(full_path), "%s%s", c->dirname, filename);
             snprintf(temp_path, sizeof(temp_path), "%s.tmp", full_path);
-            ret = ffurl_open(&os->out, temp_path, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL);
+            write_path = USE_RENAME_REPLACE ? temp_path : full_path;
+            ret = ffurl_open(&os->out, write_path, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL);
             if (ret < 0)
                 break;
             write_styp(os->ctx->pb);
@@ -642,7 +646,7 @@ static int dash_flush(AVFormatContext *s, int final, int stream)
         } else {
             ffurl_close(os->out);
             os->out = NULL;
-            ret = ff_rename(temp_path, full_path);
+            ret = USE_RENAME_REPLACE ? ff_rename(temp_path, full_path) : 0;
             if (ret < 0)
                 break;
         }
diff --git a/libavformat/hdsenc.c b/libavformat/hdsenc.c
index d96a3d5..326f886 100644
--- a/libavformat/hdsenc.c
+++ b/libavformat/hdsenc.c
@@ -163,6 +163,7 @@ static int write_manifest(AVFormatContext *s, int final)
     HDSContext *c = s->priv_data;
     AVIOContext *out;
     char filename[1024], temp_filename[1024];
+    const char *write_filename;
     int ret, i;
     float duration = 0;
 
@@ -171,10 +172,11 @@ static int write_manifest(AVFormatContext *s, int final)
 
     snprintf(filename, sizeof(filename), "%s/index.f4m", s->filename);
     snprintf(temp_filename, sizeof(temp_filename), "%s/index.f4m.tmp", s->filename);
-    ret = avio_open2(&out, temp_filename, AVIO_FLAG_WRITE,
+    write_filename = USE_RENAME_REPLACE ? temp_filename : filename;
+    ret = avio_open2(&out, write_filename, AVIO_FLAG_WRITE,
                      &s->interrupt_callback, NULL);
     if (ret < 0) {
-        av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", temp_filename);
+        av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", write_filename);
         return ret;
     }
     avio_printf(out, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
@@ -204,7 +206,7 @@ static int write_manifest(AVFormatContext *s, int final)
     avio_printf(out, "</manifest>\n");
     avio_flush(out);
     avio_close(out);
-    return ff_rename(temp_filename, filename);
+    return USE_RENAME_REPLACE ? ff_rename(temp_filename, filename) : 0;
 }
 
 static void update_size(AVIOContext *out, int64_t pos)
@@ -223,6 +225,7 @@ static int write_abst(AVFormatContext *s, OutputStream *os, int final)
     HDSContext *c = s->priv_data;
     AVIOContext *out;
     char filename[1024], temp_filename[1024];
+    const char *write_filename;
     int i, ret;
     int64_t asrt_pos, afrt_pos;
     int start = 0, fragments;
@@ -240,10 +243,11 @@ static int write_abst(AVFormatContext *s, OutputStream *os, int final)
              "%s/stream%d.abst", s->filename, index);
     snprintf(temp_filename, sizeof(temp_filename),
              "%s/stream%d.abst.tmp", s->filename, index);
-    ret = avio_open2(&out, temp_filename, AVIO_FLAG_WRITE,
+    write_filename = USE_RENAME_REPLACE ? temp_filename : filename;
+    ret = avio_open2(&out, write_filename, AVIO_FLAG_WRITE,
                      &s->interrupt_callback, NULL);
     if (ret < 0) {
-        av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", temp_filename);
+        av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", write_filename);
         return ret;
     }
     avio_wb32(out, 0); // abst size
@@ -285,7 +289,7 @@ static int write_abst(AVFormatContext *s, OutputStream *os, int final)
     update_size(out, afrt_pos);
     update_size(out, 0);
     avio_close(out);
-    return ff_rename(temp_filename, filename);
+    return USE_RENAME_REPLACE ? ff_rename(temp_filename, filename) : 0;
 }
 
 static int init_file(AVFormatContext *s, OutputStream *os, int64_t start_ts)
diff --git a/libavformat/internal.h b/libavformat/internal.h
index d579db5..5feb0f8 100644
--- a/libavformat/internal.h
+++ b/libavformat/internal.h
@@ -365,4 +365,10 @@ static inline int ff_rename(const char *oldpath, const char *newpath)
     return 0;
 }
 
+#ifndef _WIN32
+#define USE_RENAME_REPLACE 1
+#else
+#define USE_RENAME_REPLACE 0
+#endif
+
 #endif /* AVFORMAT_INTERNAL_H */
diff --git a/libavformat/smoothstreamingenc.c b/libavformat/smoothstreamingenc.c
index ddd8da7..c0161b9 100644
--- a/libavformat/smoothstreamingenc.c
+++ b/libavformat/smoothstreamingenc.c
@@ -215,14 +215,16 @@ static int write_manifest(AVFormatContext *s, int final)
     SmoothStreamingContext *c = s->priv_data;
     AVIOContext *out;
     char filename[1024], temp_filename[1024];
+    const char *write_filename;
     int ret, i, video_chunks = 0, audio_chunks = 0, video_streams = 0, audio_streams = 0;
     int64_t duration = 0;
 
     snprintf(filename, sizeof(filename), "%s/Manifest", s->filename);
     snprintf(temp_filename, sizeof(temp_filename), "%s/Manifest.tmp", s->filename);
-    ret = avio_open2(&out, temp_filename, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL);
+    write_filename = USE_RENAME_REPLACE ? temp_filename : filename;
+    ret = avio_open2(&out, write_filename, AVIO_FLAG_WRITE, &s->interrupt_callback, NULL);
     if (ret < 0) {
-        av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", temp_filename);
+        av_log(s, AV_LOG_ERROR, "Unable to open %s for writing\n", write_filename);
         return ret;
     }
     avio_printf(out, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
@@ -283,7 +285,7 @@ static int write_manifest(AVFormatContext *s, int final)
     avio_printf(out, "</SmoothStreamingMedia>\n");
     avio_flush(out);
     avio_close(out);
-    return ff_rename(temp_filename, filename);
+    return USE_RENAME_REPLACE ? ff_rename(temp_filename, filename) : 0;
 }
 
 static int ism_write_header(AVFormatContext *s)



More information about the ffmpeg-cvslog mailing list