xref: /qemu/include/glib-compat.h (revision 8905770b)
1d63c9477SAnthony Liguori /*
2d63c9477SAnthony Liguori  * GLIB Compatibility Functions
3d63c9477SAnthony Liguori  *
4d63c9477SAnthony Liguori  * Copyright IBM, Corp. 2013
5d63c9477SAnthony Liguori  *
6d63c9477SAnthony Liguori  * Authors:
7d63c9477SAnthony Liguori  *  Anthony Liguori   <aliguori@us.ibm.com>
886946a2dSMichael Tokarev  *  Michael Tokarev   <mjt@tls.msk.ru>
986946a2dSMichael Tokarev  *  Paolo Bonzini     <pbonzini@redhat.com>
10d63c9477SAnthony Liguori  *
11d63c9477SAnthony Liguori  * This work is licensed under the terms of the GNU GPL, version 2 or later.
12d63c9477SAnthony Liguori  * See the COPYING file in the top-level directory.
13d63c9477SAnthony Liguori  *
14d63c9477SAnthony Liguori  */
15d63c9477SAnthony Liguori 
16d63c9477SAnthony Liguori #ifndef QEMU_GLIB_COMPAT_H
17d63c9477SAnthony Liguori #define QEMU_GLIB_COMPAT_H
18d63c9477SAnthony Liguori 
19e71e8cc0SDaniel P. Berrangé /* Ask for warnings for anything that was marked deprecated in
20e71e8cc0SDaniel P. Berrangé  * the defined version, or before. It is a candidate for rewrite.
21e71e8cc0SDaniel P. Berrangé  */
22b4c6036fSDaniel P. Berrangé #define GLIB_VERSION_MIN_REQUIRED GLIB_VERSION_2_56
23e71e8cc0SDaniel P. Berrangé 
24e71e8cc0SDaniel P. Berrangé /* Ask for warnings if code tries to use function that did not
25e71e8cc0SDaniel P. Berrangé  * exist in the defined version. These risk breaking builds
26e71e8cc0SDaniel P. Berrangé  */
27b4c6036fSDaniel P. Berrangé #define GLIB_VERSION_MAX_ALLOWED GLIB_VERSION_2_56
28e71e8cc0SDaniel P. Berrangé 
29e71e8cc0SDaniel P. Berrangé #pragma GCC diagnostic push
30e71e8cc0SDaniel P. Berrangé #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
31e71e8cc0SDaniel P. Berrangé 
32d63c9477SAnthony Liguori #include <glib.h>
336d593ab4SMarc-André Lureau #if defined(G_OS_UNIX)
346d593ab4SMarc-André Lureau #include <glib-unix.h>
356d593ab4SMarc-André Lureau #include <sys/types.h>
366d593ab4SMarc-André Lureau #include <pwd.h>
376d593ab4SMarc-André Lureau #endif
38d63c9477SAnthony Liguori 
39e71e8cc0SDaniel P. Berrangé /*
40e71e8cc0SDaniel P. Berrangé  * Note that because of the GLIB_VERSION_MAX_ALLOWED constant above, allowing
41e71e8cc0SDaniel P. Berrangé  * use of functions from newer GLib via this compat header needs a little
42e71e8cc0SDaniel P. Berrangé  * trickery to prevent warnings being emitted.
43e71e8cc0SDaniel P. Berrangé  *
44e71e8cc0SDaniel P. Berrangé  * Consider a function from newer glib-X.Y that we want to use
45e71e8cc0SDaniel P. Berrangé  *
46e71e8cc0SDaniel P. Berrangé  *    int g_foo(const char *wibble)
47e71e8cc0SDaniel P. Berrangé  *
48e71e8cc0SDaniel P. Berrangé  * We must define a static inline function with the same signature that does
493918fe16SAlex Bennée  * what we need, but with a "_compat" suffix e.g.
50e71e8cc0SDaniel P. Berrangé  *
513918fe16SAlex Bennée  * static inline void g_foo_compat(const char *wibble)
52e71e8cc0SDaniel P. Berrangé  * {
53e71e8cc0SDaniel P. Berrangé  *     #if GLIB_CHECK_VERSION(X, Y, 0)
54e71e8cc0SDaniel P. Berrangé  *        g_foo(wibble)
55e71e8cc0SDaniel P. Berrangé  *     #else
56e71e8cc0SDaniel P. Berrangé  *        g_something_equivalent_in_older_glib(wibble);
57e71e8cc0SDaniel P. Berrangé  *     #endif
58e71e8cc0SDaniel P. Berrangé  * }
59e71e8cc0SDaniel P. Berrangé  *
60e71e8cc0SDaniel P. Berrangé  * The #pragma at the top of this file turns off -Wdeprecated-declarations,
61e71e8cc0SDaniel P. Berrangé  * ensuring this wrapper function impl doesn't trigger the compiler warning
62e71e8cc0SDaniel P. Berrangé  * about using too new glib APIs. Finally we can do
63e71e8cc0SDaniel P. Berrangé  *
643918fe16SAlex Bennée  *   #define g_foo(a) g_foo_compat(a)
65e71e8cc0SDaniel P. Berrangé  *
66e71e8cc0SDaniel P. Berrangé  * So now the code elsewhere in QEMU, which *does* have the
67e71e8cc0SDaniel P. Berrangé  * -Wdeprecated-declarations warning active, can call g_foo(...) as normal,
68e71e8cc0SDaniel P. Berrangé  * without generating warnings.
69e71e8cc0SDaniel P. Berrangé  */
70e71e8cc0SDaniel P. Berrangé 
712c674fadSPhilippe Mathieu-Daudé /*
722c674fadSPhilippe Mathieu-Daudé  * g_memdup2_qemu:
732c674fadSPhilippe Mathieu-Daudé  * @mem: (nullable): the memory to copy.
742c674fadSPhilippe Mathieu-Daudé  * @byte_size: the number of bytes to copy.
752c674fadSPhilippe Mathieu-Daudé  *
762c674fadSPhilippe Mathieu-Daudé  * Allocates @byte_size bytes of memory, and copies @byte_size bytes into it
772c674fadSPhilippe Mathieu-Daudé  * from @mem. If @mem is %NULL it returns %NULL.
782c674fadSPhilippe Mathieu-Daudé  *
792c674fadSPhilippe Mathieu-Daudé  * This replaces g_memdup(), which was prone to integer overflows when
802c674fadSPhilippe Mathieu-Daudé  * converting the argument from a #gsize to a #guint.
812c674fadSPhilippe Mathieu-Daudé  *
822c674fadSPhilippe Mathieu-Daudé  * This static inline version is a backport of the new public API from
832c674fadSPhilippe Mathieu-Daudé  * GLib 2.68, kept internal to GLib for backport to older stable releases.
842c674fadSPhilippe Mathieu-Daudé  * See https://gitlab.gnome.org/GNOME/glib/-/issues/2319.
852c674fadSPhilippe Mathieu-Daudé  *
862c674fadSPhilippe Mathieu-Daudé  * Returns: (nullable): a pointer to the newly-allocated copy of the memory,
872c674fadSPhilippe Mathieu-Daudé  *          or %NULL if @mem is %NULL.
882c674fadSPhilippe Mathieu-Daudé  */
g_memdup2_qemu(gconstpointer mem,gsize byte_size)892c674fadSPhilippe Mathieu-Daudé static inline gpointer g_memdup2_qemu(gconstpointer mem, gsize byte_size)
902c674fadSPhilippe Mathieu-Daudé {
912c674fadSPhilippe Mathieu-Daudé #if GLIB_CHECK_VERSION(2, 68, 0)
922c674fadSPhilippe Mathieu-Daudé     return g_memdup2(mem, byte_size);
932c674fadSPhilippe Mathieu-Daudé #else
942c674fadSPhilippe Mathieu-Daudé     gpointer new_mem;
952c674fadSPhilippe Mathieu-Daudé 
962c674fadSPhilippe Mathieu-Daudé     if (mem && byte_size != 0) {
972c674fadSPhilippe Mathieu-Daudé         new_mem = g_malloc(byte_size);
982c674fadSPhilippe Mathieu-Daudé         memcpy(new_mem, mem, byte_size);
992c674fadSPhilippe Mathieu-Daudé     } else {
1002c674fadSPhilippe Mathieu-Daudé         new_mem = NULL;
1012c674fadSPhilippe Mathieu-Daudé     }
1022c674fadSPhilippe Mathieu-Daudé 
1032c674fadSPhilippe Mathieu-Daudé     return new_mem;
1042c674fadSPhilippe Mathieu-Daudé #endif
1052c674fadSPhilippe Mathieu-Daudé }
1062c674fadSPhilippe Mathieu-Daudé #define g_memdup2(m, s) g_memdup2_qemu(m, s)
1072c674fadSPhilippe Mathieu-Daudé 
1086d593ab4SMarc-André Lureau #if defined(G_OS_UNIX)
1096d593ab4SMarc-André Lureau /*
1106d593ab4SMarc-André Lureau  * Note: The fallback implementation is not MT-safe, and it returns a copy of
1116d593ab4SMarc-André Lureau  * the libc passwd (must be g_free() after use) but not the content. Because of
1126d593ab4SMarc-André Lureau  * these important differences the caller must be aware of, it's not #define for
1136d593ab4SMarc-André Lureau  * GLib API substitution.
1146d593ab4SMarc-André Lureau  */
1156d593ab4SMarc-André Lureau static inline struct passwd *
g_unix_get_passwd_entry_qemu(const gchar * user_name,GError ** error)1166d593ab4SMarc-André Lureau g_unix_get_passwd_entry_qemu(const gchar *user_name, GError **error)
1176d593ab4SMarc-André Lureau {
1186d593ab4SMarc-André Lureau #if GLIB_CHECK_VERSION(2, 64, 0)
1196d593ab4SMarc-André Lureau     return g_unix_get_passwd_entry(user_name, error);
1206d593ab4SMarc-André Lureau #else
1216d593ab4SMarc-André Lureau     struct passwd *p = getpwnam(user_name);
1226d593ab4SMarc-André Lureau     if (!p) {
1236d593ab4SMarc-André Lureau         g_set_error_literal(error, G_UNIX_ERROR, 0, g_strerror(errno));
1246d593ab4SMarc-André Lureau         return NULL;
1256d593ab4SMarc-André Lureau     }
1266d593ab4SMarc-André Lureau     return (struct passwd *)g_memdup(p, sizeof(*p));
1276d593ab4SMarc-André Lureau #endif
1286d593ab4SMarc-André Lureau }
1296d593ab4SMarc-André Lureau #endif /* G_OS_UNIX */
1306d593ab4SMarc-André Lureau 
1319ba5db49SPaolo Bonzini static inline bool
qemu_g_test_slow(void)1329ba5db49SPaolo Bonzini qemu_g_test_slow(void)
1339ba5db49SPaolo Bonzini {
1349ba5db49SPaolo Bonzini     static int cached = -1;
1359ba5db49SPaolo Bonzini     if (cached == -1) {
1369ba5db49SPaolo Bonzini         cached = g_test_slow() || getenv("G_TEST_SLOW") != NULL;
1379ba5db49SPaolo Bonzini     }
1389ba5db49SPaolo Bonzini     return cached;
1399ba5db49SPaolo Bonzini }
1409ba5db49SPaolo Bonzini 
1419ba5db49SPaolo Bonzini #undef g_test_slow
1429ba5db49SPaolo Bonzini #undef g_test_thorough
1439ba5db49SPaolo Bonzini #undef g_test_quick
1449ba5db49SPaolo Bonzini #define g_test_slow() qemu_g_test_slow()
1459ba5db49SPaolo Bonzini #define g_test_thorough() qemu_g_test_slow()
1469ba5db49SPaolo Bonzini #define g_test_quick() (!qemu_g_test_slow())
1479ba5db49SPaolo Bonzini 
148e71e8cc0SDaniel P. Berrangé #pragma GCC diagnostic pop
149e71e8cc0SDaniel P. Berrangé 
150*8905770bSMarc-André Lureau #ifndef G_NORETURN
151*8905770bSMarc-André Lureau #define G_NORETURN G_GNUC_NORETURN
152*8905770bSMarc-André Lureau #endif
153*8905770bSMarc-André Lureau 
154d63c9477SAnthony Liguori #endif
155