mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-02-17 11:45:25 +00:00
gst/gstregistrybinary.c: Don't use g_mkstmp() on win32, it's unsafe if glib is using a different libc.
Original commit message from CVS: * gst/gstregistrybinary.c: Don't use g_mkstmp() on win32, it's unsafe if glib is using a different libc. Fixes #544776.
This commit is contained in:
parent
6b16636203
commit
945bf1bdd3
2 changed files with 187 additions and 69 deletions
|
@ -1,3 +1,10 @@
|
||||||
|
2008-08-11 Michael Smith <msmith@songbirdnest.com>
|
||||||
|
|
||||||
|
* gst/gstregistrybinary.c:
|
||||||
|
Don't use g_mkstmp() on win32, it's unsafe if glib is using a different
|
||||||
|
libc.
|
||||||
|
Fixes #544776.
|
||||||
|
|
||||||
2008-08-11 Edward Hervey <edward.hervey@collabora.co.uk>
|
2008-08-11 Edward Hervey <edward.hervey@collabora.co.uk>
|
||||||
|
|
||||||
* libs/gst/base/gstbasetransform.c:
|
* libs/gst/base/gstbasetransform.c:
|
||||||
|
|
|
@ -215,15 +215,169 @@ _gst_crc32 (guint32 crc, const gchar * buf, guint len)
|
||||||
|
|
||||||
/* Registry saving */
|
/* Registry saving */
|
||||||
|
|
||||||
|
#ifdef G_OS_WIN32
|
||||||
|
/* On win32, we can't use g_mkstmp(), because of cross-DLL file I/O problems.
|
||||||
|
* So, we just create the entire binary registry in memory, then write it out
|
||||||
|
* with g_file_set_contents(), which creates a temporary file internally
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct BinaryRegistryCache
|
||||||
|
{
|
||||||
|
const char *location;
|
||||||
|
guint8 *mem;
|
||||||
|
gssize len;
|
||||||
|
} BinaryRegistryCache;
|
||||||
|
|
||||||
|
static BinaryRegistryCache *
|
||||||
|
gst_registry_binary_cache_init (GstRegistry * registry, const char *location)
|
||||||
|
{
|
||||||
|
BinaryRegistryCache *cache = g_new0 (BinaryRegistryCache, 1);
|
||||||
|
cache->location = location;
|
||||||
|
return cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
gst_registry_binary_cache_write (GstRegistry * registry,
|
||||||
|
BinaryRegistryCache * cache, unsigned long offset,
|
||||||
|
const void *data, int length)
|
||||||
|
{
|
||||||
|
cache->len = MAX (offset + length, cache->len);
|
||||||
|
cache->mem = g_realloc (cache->mem, cache->len);
|
||||||
|
|
||||||
|
memcpy (cache->mem + offset, data, length);
|
||||||
|
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_registry_binary_cache_finish (GstRegistry * registry,
|
||||||
|
BinaryRegistryCache * cache, gboolean success)
|
||||||
|
{
|
||||||
|
gboolean ret = TRUE;
|
||||||
|
GError *error = NULL;
|
||||||
|
if (!g_file_set_contents (cache->location, (const gchar *) cache->mem,
|
||||||
|
cache->len, &error)) {
|
||||||
|
GST_ERROR ("Failed to write to cache file: %s", error->message);
|
||||||
|
g_error_free (error);
|
||||||
|
ret = FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free (cache->mem);
|
||||||
|
g_free (cache);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
typedef struct BinaryRegistryCache
|
||||||
|
{
|
||||||
|
const char *location;
|
||||||
|
char *tmp_location;
|
||||||
|
unsigned long currentoffset;
|
||||||
|
} BinaryRegistryCache;
|
||||||
|
|
||||||
|
static BinaryRegistryCache *
|
||||||
|
gst_registry_binary_cache_init (GstRegistry * registry, const char *location)
|
||||||
|
{
|
||||||
|
BinaryRegistryCache *cache = g_new0 (BinaryRegistryCache, 1);
|
||||||
|
|
||||||
|
cache->location = location;
|
||||||
|
cache->tmp_location = g_strconcat (location, ".tmpXXXXXX", NULL);
|
||||||
|
registry->cache_file = g_mkstemp (cache->tmp_location);
|
||||||
|
if (registry->cache_file == -1) {
|
||||||
|
gchar *dir;
|
||||||
|
|
||||||
|
/* oops, I bet the directory doesn't exist */
|
||||||
|
dir = g_path_get_dirname (location);
|
||||||
|
g_mkdir_with_parents (dir, 0777);
|
||||||
|
g_free (dir);
|
||||||
|
|
||||||
|
/* the previous g_mkstemp call overwrote the XXXXXX placeholder ... */
|
||||||
|
g_free (cache->tmp_location);
|
||||||
|
cache->tmp_location = g_strconcat (location, ".tmpXXXXXX", NULL);
|
||||||
|
registry->cache_file = g_mkstemp (cache->tmp_location);
|
||||||
|
|
||||||
|
if (registry->cache_file == -1) {
|
||||||
|
GST_DEBUG ("g_mkstemp() failed: %s", g_strerror (errno));
|
||||||
|
g_free (cache->tmp_location);
|
||||||
|
g_free (cache);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
gst_registry_binary_cache_write (GstRegistry * registry,
|
||||||
|
BinaryRegistryCache * cache, unsigned long offset,
|
||||||
|
const void *data, int length)
|
||||||
|
{
|
||||||
|
long written;
|
||||||
|
if (offset != cache->currentoffset) {
|
||||||
|
if (lseek (registry->cache_file, offset, SEEK_SET) != 0) {
|
||||||
|
GST_ERROR ("Seeking to new offset failed");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
cache->currentoffset = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
written = write (registry->cache_file, data, length);
|
||||||
|
if (written != length) {
|
||||||
|
GST_ERROR ("Failed to write to cache file");
|
||||||
|
}
|
||||||
|
cache->currentoffset += written;
|
||||||
|
|
||||||
|
return written;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_registry_binary_cache_finish (GstRegistry * registry,
|
||||||
|
BinaryRegistryCache * cache, gboolean success)
|
||||||
|
{
|
||||||
|
if (close (registry->cache_file) < 0)
|
||||||
|
goto close_failed;
|
||||||
|
|
||||||
|
if (success) {
|
||||||
|
/* Only do the rename if we wrote the entire file successfully */
|
||||||
|
if (g_rename (cache->tmp_location, cache->location) < 0)
|
||||||
|
goto rename_failed;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_free (cache->tmp_location);
|
||||||
|
g_free (cache);
|
||||||
|
GST_INFO ("Wrote binary registry cache");
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
fail_after_close:
|
||||||
|
{
|
||||||
|
g_remove (cache->tmp_location);
|
||||||
|
g_free (cache->tmp_location);
|
||||||
|
g_free (cache);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
close_failed:
|
||||||
|
{
|
||||||
|
GST_ERROR ("close() failed: %s", g_strerror (errno));
|
||||||
|
goto fail_after_close;
|
||||||
|
}
|
||||||
|
rename_failed:
|
||||||
|
{
|
||||||
|
GST_ERROR ("g_rename() failed: %s", g_strerror (errno));
|
||||||
|
goto fail_after_close;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* gst_registry_binary_write:
|
* gst_registry_binary_write_chunk:
|
||||||
*
|
*
|
||||||
* Write from a memory location to the registry cache file
|
* Write from a memory location to the registry cache file
|
||||||
*
|
*
|
||||||
* Returns: %TRUE for success
|
* Returns: %TRUE for success
|
||||||
*/
|
*/
|
||||||
inline static gboolean
|
inline static gboolean
|
||||||
gst_registry_binary_write (GstRegistry * registry, const void *mem,
|
gst_registry_binary_write_chunk (GstRegistry * registry,
|
||||||
|
BinaryRegistryCache * cache, const void *mem,
|
||||||
const gssize size, unsigned long *file_position, gboolean align,
|
const gssize size, unsigned long *file_position, gboolean align,
|
||||||
guint32 * crc32)
|
guint32 * crc32)
|
||||||
{
|
{
|
||||||
|
@ -233,23 +387,26 @@ gst_registry_binary_write (GstRegistry * registry, const void *mem,
|
||||||
/* Padding to insert the struct that requiere word alignment */
|
/* Padding to insert the struct that requiere word alignment */
|
||||||
if ((align) && (alignment (*file_position) != 0)) {
|
if ((align) && (alignment (*file_position) != 0)) {
|
||||||
padsize = ALIGNMENT - alignment (*file_position);
|
padsize = ALIGNMENT - alignment (*file_position);
|
||||||
if (write (registry->cache_file, padder, padsize) != padsize) {
|
if (gst_registry_binary_cache_write (registry, cache, *file_position,
|
||||||
|
padder, padsize) != padsize) {
|
||||||
GST_ERROR ("Failed to write binary registry padder");
|
GST_ERROR ("Failed to write binary registry padder");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
if (padsize > 0)
|
if (padsize > 0)
|
||||||
*crc32 = _gst_crc32 (*crc32, padder, padsize);
|
*crc32 = _gst_crc32 (*crc32, padder, padsize);
|
||||||
*file_position = *file_position + padsize;
|
*file_position += padsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (write (registry->cache_file, mem, size) != size) {
|
if (gst_registry_binary_cache_write (registry, cache, *file_position,
|
||||||
|
mem, size) != size) {
|
||||||
GST_ERROR ("Failed to write binary registry element");
|
GST_ERROR ("Failed to write binary registry element");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
if (size > 0)
|
if (size > 0)
|
||||||
*crc32 = _gst_crc32 (*crc32, mem, size);
|
*crc32 = _gst_crc32 (*crc32, mem, size);
|
||||||
|
|
||||||
*file_position = *file_position + size;
|
*file_position += size;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -575,7 +732,6 @@ fail:
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gst_registry_binary_write_cache:
|
* gst_registry_binary_write_cache:
|
||||||
* @registry: a #GstRegistry
|
* @registry: a #GstRegistry
|
||||||
|
@ -589,35 +745,14 @@ gboolean
|
||||||
gst_registry_binary_write_cache (GstRegistry * registry, const char *location)
|
gst_registry_binary_write_cache (GstRegistry * registry, const char *location)
|
||||||
{
|
{
|
||||||
GList *walk;
|
GList *walk;
|
||||||
gchar *tmp_location;
|
|
||||||
GstBinaryRegistryMagic magic;
|
GstBinaryRegistryMagic magic;
|
||||||
GList *to_write = NULL;
|
GList *to_write = NULL;
|
||||||
unsigned long file_position = 0;
|
unsigned long file_position = 0;
|
||||||
|
BinaryRegistryCache *cache;
|
||||||
|
|
||||||
GST_INFO ("Building binary registry cache image");
|
GST_INFO ("Building binary registry cache image");
|
||||||
|
|
||||||
g_return_val_if_fail (GST_IS_REGISTRY (registry), FALSE);
|
g_return_val_if_fail (GST_IS_REGISTRY (registry), FALSE);
|
||||||
tmp_location = g_strconcat (location, ".tmpXXXXXX", NULL);
|
|
||||||
registry->cache_file = g_mkstemp (tmp_location);
|
|
||||||
if (registry->cache_file == -1) {
|
|
||||||
gchar *dir;
|
|
||||||
|
|
||||||
/* oops, I bet the directory doesn't exist */
|
|
||||||
dir = g_path_get_dirname (location);
|
|
||||||
g_mkdir_with_parents (dir, 0777);
|
|
||||||
g_free (dir);
|
|
||||||
|
|
||||||
/* the previous g_mkstemp call overwrote the XXXXXX placeholder ... */
|
|
||||||
g_free (tmp_location);
|
|
||||||
tmp_location = g_strconcat (location, ".tmpXXXXXX", NULL);
|
|
||||||
registry->cache_file = g_mkstemp (tmp_location);
|
|
||||||
|
|
||||||
if (registry->cache_file == -1) {
|
|
||||||
GST_DEBUG ("g_mkstemp() failed: %s", g_strerror (errno));
|
|
||||||
g_free (tmp_location);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!gst_registry_binary_initialize_magic (&magic))
|
if (!gst_registry_binary_initialize_magic (&magic))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -648,9 +783,14 @@ gst_registry_binary_write_cache (GstRegistry * registry, const char *location)
|
||||||
|
|
||||||
GST_INFO ("Writing binary registry cache");
|
GST_INFO ("Writing binary registry cache");
|
||||||
|
|
||||||
|
cache = gst_registry_binary_cache_init (registry, location);
|
||||||
|
if (!cache)
|
||||||
|
goto fail_free_list;
|
||||||
|
|
||||||
/* write magic */
|
/* write magic */
|
||||||
if (write (registry->cache_file, &magic,
|
if (gst_registry_binary_cache_write (registry, cache, file_position,
|
||||||
sizeof (GstBinaryRegistryMagic)) != sizeof (GstBinaryRegistryMagic)) {
|
&magic, sizeof (GstBinaryRegistryMagic)) !=
|
||||||
|
sizeof (GstBinaryRegistryMagic)) {
|
||||||
GST_ERROR ("Failed to write binary registry magic");
|
GST_ERROR ("Failed to write binary registry magic");
|
||||||
goto fail_free_list;
|
goto fail_free_list;
|
||||||
}
|
}
|
||||||
|
@ -660,7 +800,7 @@ gst_registry_binary_write_cache (GstRegistry * registry, const char *location)
|
||||||
for (walk = to_write; walk; walk = g_list_next (walk)) {
|
for (walk = to_write; walk; walk = g_list_next (walk)) {
|
||||||
GstBinaryChunk *cur = walk->data;
|
GstBinaryChunk *cur = walk->data;
|
||||||
|
|
||||||
if (!gst_registry_binary_write (registry, cur->data, cur->size,
|
if (!gst_registry_binary_write_chunk (registry, cache, cur->data, cur->size,
|
||||||
&file_position, cur->align, &magic.crc32)) {
|
&file_position, cur->align, &magic.crc32)) {
|
||||||
if (!(cur->flags & GST_BINARY_REGISTRY_FLAG_CONST))
|
if (!(cur->flags & GST_BINARY_REGISTRY_FLAG_CONST))
|
||||||
g_free (cur->data);
|
g_free (cur->data);
|
||||||
|
@ -675,29 +815,15 @@ gst_registry_binary_write_cache (GstRegistry * registry, const char *location)
|
||||||
}
|
}
|
||||||
g_list_free (to_write);
|
g_list_free (to_write);
|
||||||
|
|
||||||
if (lseek (registry->cache_file, 0, SEEK_SET) != 0) {
|
if (gst_registry_binary_cache_write (registry, cache, 0, &magic,
|
||||||
GST_ERROR ("Seeking to rewrite the binary registry CRC32 failed");
|
sizeof (GstBinaryRegistryMagic)) != sizeof (GstBinaryRegistryMagic)) {
|
||||||
} else {
|
|
||||||
if (write (registry->cache_file, &magic,
|
|
||||||
sizeof (GstBinaryRegistryMagic)) != sizeof (GstBinaryRegistryMagic))
|
|
||||||
GST_ERROR ("Failed to rewrite binary registry magic");
|
GST_ERROR ("Failed to rewrite binary registry magic");
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (close (registry->cache_file) < 0)
|
if (!gst_registry_binary_cache_finish (registry, cache, TRUE))
|
||||||
goto close_failed;
|
return FALSE;
|
||||||
|
|
||||||
if (g_file_test (tmp_location, G_FILE_TEST_EXISTS)) {
|
|
||||||
#ifdef WIN32
|
|
||||||
g_remove (location);
|
|
||||||
#endif
|
|
||||||
if (g_rename (tmp_location, location) < 0)
|
|
||||||
goto rename_failed;
|
|
||||||
} else {
|
|
||||||
/* FIXME: shouldn't we return FALSE here? */
|
|
||||||
}
|
|
||||||
|
|
||||||
g_free (tmp_location);
|
|
||||||
GST_INFO ("Wrote binary registry cache");
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
/* Errors */
|
/* Errors */
|
||||||
|
@ -711,29 +837,14 @@ fail_free_list:
|
||||||
g_free (cur);
|
g_free (cur);
|
||||||
}
|
}
|
||||||
g_list_free (to_write);
|
g_list_free (to_write);
|
||||||
|
|
||||||
|
(void) gst_registry_binary_cache_finish (registry, cache, FALSE);
|
||||||
/* fall through */
|
/* fall through */
|
||||||
}
|
}
|
||||||
fail:
|
fail:
|
||||||
{
|
{
|
||||||
(void) close (registry->cache_file);
|
|
||||||
/* fall through */
|
|
||||||
}
|
|
||||||
fail_after_close:
|
|
||||||
{
|
|
||||||
g_remove (tmp_location);
|
|
||||||
g_free (tmp_location);
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
close_failed:
|
|
||||||
{
|
|
||||||
GST_ERROR ("close() failed: %s", g_strerror (errno));
|
|
||||||
goto fail_after_close;
|
|
||||||
}
|
|
||||||
rename_failed:
|
|
||||||
{
|
|
||||||
GST_ERROR ("g_rename() failed: %s", g_strerror (errno));
|
|
||||||
goto fail_after_close;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue