1 /*
   2  * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 #include <stdio.h>
  27 #include <stdlib.h>
  28 #include <linux/fb.h>
  29 #include <fcntl.h>
  30 #ifndef __USE_GNU       // required for dladdr() & Dl_info
  31 #define __USE_GNU
  32 #endif
  33 #include <dlfcn.h>
  34 #include <sys/ioctl.h>
  35 
  36 #include <string.h>
  37 #include <strings.h>
  38 
  39 #include <assert.h>
  40 
  41 #include <gio/gio.h>
  42 
  43 #include "glass_wrapper.h"
  44 
  45 static GSettingsSchemaSource *(*_g_settings_schema_source_get_default) ();
  46 static GSettingsSchema *(*_g_settings_schema_source_lookup) (
  47                         GSettingsSchemaSource *source,
  48                         const gchar *schema_id,
  49                         gboolean recursive);
  50 static gboolean (*_g_settings_schema_has_key) (
  51                         GSettingsSchema *schema,
  52                         const gchar *name);
  53 static GSettings *(*_g_settings_new) (const gchar *schema_id);
  54 static guint (*_g_settings_get_uint) (GSettings *settings,
  55                         const gchar *key);
  56 
  57 /***************************************************************************/
  58 
  59 #define PRELOAD_SYMBOL_GIO_OPT(x) \
  60     _##x = dlsym(libgio, #x); \
  61     if (!_##x && wrapper_debug) { \
  62         symbol_load_missing++; \
  63         fprintf(stderr, "did not find %s\n", #x); \
  64     } else if (wrapper_debug) { \
  65         fprintf(stderr, "found %s = 0x%08lx\n", #x, (long)_##x); \
  66     }
  67 
  68 int wrapper_load_symbols_gio (void *libgio)
  69 {
  70     int symbol_load_missing = 0;
  71     int symbol_load_errors = 0;
  72 
  73     PRELOAD_SYMBOL_GIO_OPT (g_settings_schema_source_get_default);
  74     PRELOAD_SYMBOL_GIO_OPT (g_settings_schema_source_lookup);
  75     PRELOAD_SYMBOL_GIO_OPT (g_settings_schema_has_key);
  76     PRELOAD_SYMBOL_GIO_OPT (g_settings_new);
  77     PRELOAD_SYMBOL_GIO_OPT (g_settings_get_uint);
  78 
  79     if (symbol_load_errors && wrapper_debug) {
  80         fprintf (stderr, "failed to load %d required gio symbols\n", symbol_load_errors);
  81     }
  82 
  83     if (symbol_load_missing && wrapper_debug) {
  84         fprintf (stderr, "missing %d optional gio symbols\n", symbol_load_missing);
  85     }
  86 
  87     return symbol_load_errors;
  88 }
  89 
  90 #define CHECK_LOAD_SYMBOL_GIO(x) \
  91     { \
  92         if (!_##x) { \
  93             if (wrapper_debug) fprintf(stderr, "missing %s\n", #x); \
  94             assert(_##x); \
  95         } else { \
  96             if (wrapper_debug) { \
  97                fprintf(stderr, "using %s\n", #x); \
  98                fflush(stderr); \
  99             } \
 100         } \
 101     }
 102 
 103 #define CHECK_LOAD_SYMBOL_GIO_OPT(x, retval) \
 104     { \
 105         if (!_##x) { \
 106             if (wrapper_debug) fprintf(stderr, "missing optional %s\n", #x); \
 107             return retval; \
 108         } else { \
 109             if (wrapper_debug) { \
 110                fprintf(stderr, "using %s\n", #x); \
 111                fflush(stderr); \
 112             } \
 113         } \
 114     }
 115 
 116 GSettingsSchemaSource *g_settings_schema_source_get_default ()
 117 {
 118     CHECK_LOAD_SYMBOL_GIO_OPT(g_settings_schema_source_get_default, NULL)
 119     return (*_g_settings_schema_source_get_default) ();
 120 }
 121 
 122 GSettingsSchema *g_settings_schema_source_lookup (
 123                     GSettingsSchemaSource *source,
 124                     const gchar *schema_id,
 125                     gboolean recursive)
 126 {
 127     CHECK_LOAD_SYMBOL_GIO_OPT(g_settings_schema_source_lookup, NULL)
 128     if (source == NULL) {
 129         return NULL;
 130     }
 131     return (*_g_settings_schema_source_lookup) (source, schema_id, recursive);
 132 }
 133 
 134 gboolean g_settings_schema_has_key (GSettingsSchema *schema,
 135                     const gchar *name)
 136 {
 137     CHECK_LOAD_SYMBOL_GIO_OPT(g_settings_schema_has_key, FALSE)
 138     return (*_g_settings_schema_has_key) (schema, name);
 139 }
 140 
 141 GSettings *g_settings_new (const gchar *schema_id)
 142 {
 143     CHECK_LOAD_SYMBOL_GIO (g_settings_new)
 144     return (*_g_settings_new) (schema_id);
 145 }
 146 
 147 guint g_settings_get_uint (GSettings *settings,
 148                         const gchar *key)
 149 {
 150     CHECK_LOAD_SYMBOL_GIO (g_settings_get_uint)
 151     return (*_g_settings_get_uint) (settings, key);
 152 }
 153 
 154 //--------------------------------------------------------------------------------------
 155 
 156 guint glass_settings_get_guint_opt (const gchar *schema_name,
 157                     const gchar *key_name,
 158                     int defval)
 159 {
 160     GSettingsSchemaSource *default_schema_source =
 161             g_settings_schema_source_get_default();
 162     if (default_schema_source == NULL) {
 163         if (wrapper_debug) {
 164             fprintf(stderr, "No schema source dir found!\n");
 165         }
 166         return defval;
 167     }
 168     GSettingsSchema *the_schema =
 169             g_settings_schema_source_lookup(default_schema_source, schema_name, TRUE);
 170     if (the_schema == NULL) {
 171         if (wrapper_debug) {
 172             fprintf(stderr, "schema '%s' not found!\n", schema_name);
 173         }
 174         return defval;
 175     }
 176     if (!g_settings_schema_has_key(the_schema, key_name)) {
 177         if (wrapper_debug) {
 178             fprintf(stderr, "key '%s' not found in schema '%s'!\n", key_name, schema_name);
 179         }
 180         return defval;
 181     }
 182     if (wrapper_debug) {
 183         fprintf(stderr, "found schema '%s' and key '%s'\n", schema_name, key_name);
 184     }
 185     GSettings *gset = g_settings_new(schema_name);
 186     return g_settings_get_uint(gset, key_name);
 187 }