Home | History | Annotate | Line # | Download | only in utils
      1 /* Common utility code for interacting with libXfont from test utilities
      2  *
      3  * Note that this code is designed for test programs, and thus uses assert()
      4  * and fatal err() calls in places that real code would do error handling,
      5  * since the goal is to catch bugs faster, not help users get past problems.
      6  */
      7 
      8 /*
      9  * Copyright (c) 2015, 2019, Oracle and/or its affiliates.
     10  *
     11  * Permission is hereby granted, free of charge, to any person obtaining a
     12  * copy of this software and associated documentation files (the "Software"),
     13  * to deal in the Software without restriction, including without limitation
     14  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     15  * and/or sell copies of the Software, and to permit persons to whom the
     16  * Software is furnished to do so, subject to the following conditions:
     17  *
     18  * The above copyright notice and this permission notice (including the next
     19  * paragraph) shall be included in all copies or substantial portions of the
     20  * Software.
     21  *
     22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     23  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     24  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     25  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     26  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     27  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     28  * DEALINGS IN THE SOFTWARE.
     29  */
     30 
     31 /* Based on code from xorg-server/dix/dixfont.c covered by this notice:
     32 
     33 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
     34 
     35                         All Rights Reserved
     36 
     37 Permission to use, copy, modify, and distribute this software and its
     38 documentation for any purpose and without fee is hereby granted,
     39 provided that the above copyright notice appear in all copies and that
     40 both that copyright notice and this permission notice appear in
     41 supporting documentation, and that the name of Digital not be
     42 used in advertising or publicity pertaining to distribution of the
     43 software without specific, written prior permission.
     44 
     45 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
     46 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
     47 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
     48 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
     49 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
     50 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
     51 SOFTWARE.
     52 
     53  */
     54 
     55 #include "font-test-utils.h"
     56 #include "src/util/replace.h"
     57 #include <stdio.h>
     58 #include <stdlib.h>
     59 #include <limits.h>
     60 #include <assert.h>
     61 #ifdef HAVE_ERR_H
     62 #include <err.h>
     63 #endif
     64 #include "src/util/replace.h"
     65 #include <X11/X.h>
     66 
     67 static unsigned long server_generation;
     68 static xfont2_fpe_funcs_rec const **fpe_functions;
     69 static int num_fpe_types;
     70 
     71 static int
     72 test_client_auth_generation(ClientPtr client)
     73 {
     74     err(BadImplementation, "%s called but not yet implemented", __func__);
     75 }
     76 
     77 static Bool
     78 test_client_signal(ClientPtr client)
     79 {
     80     err(BadImplementation, "%s called but not yet implemented", __func__);
     81 }
     82 
     83 static void
     84 test_delete_font_client_id(Font id)
     85 {
     86     err(BadImplementation, "%s called but not yet implemented", __func__);
     87 }
     88 
     89 static void _X_ATTRIBUTE_PRINTF(1,0)
     90 test_verrorf(const char *f, va_list ap)
     91 {
     92     vwarn(f, ap);
     93 }
     94 
     95 static FontPtr
     96 test_find_old_font(FSID id)
     97 {
     98     err(BadImplementation, "%s called but not yet implemented", __func__);
     99 }
    100 
    101 static FontResolutionPtr
    102 test_get_client_resolutions(int *num)
    103 {
    104     *num = 0;
    105     return NULL;
    106 }
    107 
    108 static int
    109 test_get_default_point_size(void)
    110 {
    111     return 120;
    112 }
    113 
    114 static Font
    115 test_get_new_font_client_id(void)
    116 {
    117     err(BadImplementation, "%s called but not yet implemented", __func__);
    118 }
    119 
    120 static uint32_t
    121 test_get_time_in_millis(void)
    122 {
    123     return 0;
    124 }
    125 
    126 static int
    127 test_init_fs_handlers(FontPathElementPtr fpe,
    128 		      FontBlockHandlerProcPtr block_handler)
    129 {
    130     /* Font server connections are not available in test programs.
    131      * Return success to allow initialization to complete. */
    132     return Successful;
    133 }
    134 
    135 /* Callback from libXfont when each fpe handler is registered */
    136 static int
    137 test_register_fpe_funcs(const xfont2_fpe_funcs_rec *funcs)
    138 {
    139     xfont2_fpe_funcs_rec const **new;
    140 
    141     /* grow the list */
    142     new = reallocarray(fpe_functions, (num_fpe_types + 1),
    143 		       sizeof(xfont2_fpe_funcs_ptr));
    144     assert (new != NULL);
    145     fpe_functions = new;
    146 
    147     fpe_functions[num_fpe_types] = funcs;
    148 
    149     return num_fpe_types++;
    150 }
    151 
    152 static void
    153 test_remove_fs_handlers(FontPathElementPtr fpe,
    154 			FontBlockHandlerProcPtr block_handler, Bool all)
    155 {
    156     err(BadImplementation, "%s called but not yet implemented", __func__);
    157 }
    158 
    159 static void *
    160 test_get_server_client(void)
    161 {
    162     err(BadImplementation, "%s called but not yet implemented", __func__);
    163 }
    164 
    165 static int
    166 test_set_font_authorizations(char **authorizations, int *authlen, void *client)
    167 {
    168     err(BadImplementation, "%s called but not yet implemented", __func__);
    169 }
    170 
    171 static int
    172 test_store_font_client_font(FontPtr pfont, Font id)
    173 {
    174     err(BadImplementation, "%s called but not yet implemented", __func__);
    175 }
    176 
    177 /* Atom stubs: return NULL to let libxfontstubs fall back to the
    178  * internal atom implementation (__libxfont_internal__MakeAtom etc.)
    179  * which is linked into libXfont2.  This avoids fatal err() calls
    180  * when test code exercises paths that use atoms (e.g. bitmap scaling). */
    181 
    182 static unsigned long
    183 test_get_server_generation(void)
    184 {
    185     return server_generation;
    186 }
    187 
    188 static int
    189 test_add_fs_fd(int fd, FontFdHandlerProcPtr handler, void *data)
    190 {
    191     err(BadImplementation, "%s called but not yet implemented", __func__);
    192 }
    193 
    194 static void
    195 test_remove_fs_fd(int fd)
    196 {
    197     err(BadImplementation, "%s called but not yet implemented", __func__);
    198 }
    199 
    200 static void
    201 test_adjust_fs_wait_for_delay(void *wt, unsigned long newdelay)
    202 {
    203     err(BadImplementation, "%s called but not yet implemented", __func__);
    204 }
    205 
    206 static const xfont2_client_funcs_rec xfont2_client_funcs = {
    207     .version = XFONT2_CLIENT_FUNCS_VERSION,
    208     .client_auth_generation = test_client_auth_generation,
    209     .client_signal = test_client_signal,
    210     .delete_font_client_id = test_delete_font_client_id,
    211     .verrorf = test_verrorf,
    212     .find_old_font = test_find_old_font,
    213     .get_client_resolutions = test_get_client_resolutions,
    214     .get_default_point_size = test_get_default_point_size,
    215     .get_new_font_client_id = test_get_new_font_client_id,
    216     .get_time_in_millis = test_get_time_in_millis,
    217     .init_fs_handlers = test_init_fs_handlers,
    218     .register_fpe_funcs = test_register_fpe_funcs,
    219     .remove_fs_handlers = test_remove_fs_handlers,
    220     .get_server_client = test_get_server_client,
    221     .set_font_authorizations = test_set_font_authorizations,
    222     .store_font_client_font = test_store_font_client_font,
    223     .make_atom = NULL,
    224     .valid_atom = NULL,
    225     .name_for_atom = NULL,
    226     .get_server_generation = test_get_server_generation,
    227     .add_fs_fd = test_add_fs_fd,
    228     .remove_fs_fd = test_remove_fs_fd,
    229     .adjust_fs_wait_for_delay = test_adjust_fs_wait_for_delay,
    230 };
    231 
    232 
    233 xfont2_fpe_funcs_rec const **
    234 init_font_handlers(int *fpe_function_count)
    235 {
    236     server_generation++;
    237     xfont2_init(&xfont2_client_funcs);
    238     /* make sure our callbacks were called & worked */
    239     assert (fpe_functions != NULL);
    240     assert (num_fpe_types > 0);
    241     *fpe_function_count = num_fpe_types;
    242     return fpe_functions;
    243 }
    244 
    245 
    246 /* does the necessary magic to figure out the fpe type */
    247 static int
    248 DetermineFPEType(const char *pathname)
    249 {
    250     int i;
    251 
    252     /* make sure init_font_handlers was called first */
    253     assert (num_fpe_types > 0);
    254 
    255     for (i = 0; i < num_fpe_types; i++) {
    256         if ((*fpe_functions[i]->name_check) (pathname))
    257             return i;
    258     }
    259     return -1;
    260 }
    261 
    262 
    263 static const char * const default_fpes[] = {
    264     "catalogue:/etc/X11/fontpath.d",
    265     "built-ins"
    266 };
    267 #define num_default_fpes  (sizeof(default_fpes) / sizeof(*default_fpes))
    268 
    269 FontPathElementPtr *
    270 init_font_paths(const char * const *font_paths, int *num_fpes)
    271 {
    272     FontPathElementPtr *fpe_list;
    273     int i;
    274 
    275     /* make sure init_font_handlers was called first */
    276     assert (num_fpe_types > 0);
    277 
    278     /* Use default if caller didn't supply any */
    279     if (*num_fpes == 0) {
    280 	font_paths = default_fpes;
    281 	*num_fpes = num_default_fpes;
    282     }
    283 
    284     fpe_list = calloc(*num_fpes, sizeof(FontPathElementPtr));
    285     assert(fpe_list != NULL);
    286 
    287     for (i = 0; i < *num_fpes; i++) {
    288 	int result;
    289 	FontPathElementPtr fpe = calloc(1, sizeof(FontPathElementRec));
    290 	assert(fpe != NULL);
    291 
    292 	fpe->name = strdup(font_paths[i]);
    293 	assert(fpe->name != NULL);
    294 	fpe->name_length = strlen(fpe->name);
    295 	assert(fpe->name_length > 0);
    296 	/* If path is to fonts.dir file, trim it off and use the full
    297 	   directory path instead.  Simplifies testing with afl. */
    298 	if (fpe->name_length > (int) sizeof("/fonts.dir")) {
    299 	    char *tail = fpe->name + fpe->name_length -
    300 		(sizeof("/fonts.dir") - 1);
    301 
    302 	    if (strcmp(tail, "/fonts.dir") == 0) {
    303 		char *fullpath;
    304 
    305 		*tail = '\0';
    306 		fullpath = realpath(fpe->name, NULL);
    307 		assert(fullpath != NULL);
    308 		free(fpe->name);
    309 		fpe->name = fullpath;
    310 		fpe->name_length = strlen(fpe->name);
    311 		assert(fpe->name_length > 0);
    312 	    }
    313 	}
    314 	fpe->type = DetermineFPEType(fpe->name);
    315 	if (fpe->type == -1)
    316 	    err(BadFontPath, "Unable to find handler for font path %s",
    317 		fpe->name);
    318 	result = (*fpe_functions[fpe->type]->init_fpe) (fpe);
    319 	if (result != Successful)
    320 	    err(result, "init_fpe failed for font path %s: error %d",
    321 		fpe->name, result);
    322 
    323 	printf("Initialized font path element #%d: %s\n", i, fpe->name);
    324 	fpe_list[i] = fpe;
    325     }
    326     printf("\n");
    327 
    328     return fpe_list;
    329 }
    330