doc: Add screenshot to spiv page.
[gfxprim/pasky.git] / tests / framework / tst_preload_FILE.c
blob1d546a26aa676c7804401a7170e07b062fad09c5
1 /*****************************************************************************
2 * This file is part of gfxprim library. *
3 * *
4 * Gfxprim is free software; you can redistribute it and/or *
5 * modify it under the terms of the GNU Lesser General Public *
6 * License as published by the Free Software Foundation; either *
7 * version 2.1 of the License, or (at your option) any later version. *
8 * *
9 * Gfxprim is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
12 * Lesser General Public License for more details. *
13 * *
14 * You should have received a copy of the GNU Lesser General Public *
15 * License along with gfxprim; if not, write to the Free Software *
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, *
17 * Boston, MA 02110-1301 USA *
18 * *
19 * Copyright (C) 2009-2012 Cyril Hrubis <metan@ucw.cz> *
20 * *
21 *****************************************************************************/
23 #define _GNU_SOURCE
24 #include <stdio.h>
25 #include <dlfcn.h>
26 #include <errno.h>
27 #include <string.h>
29 #include "tst_test.h"
30 #include "tst_preload_FILE.h"
32 struct tst_fail_FILE *failures = NULL;
34 void tst_fail_FILE_register(struct tst_fail_FILE *self)
36 failures = self;
39 static struct tst_fail_FILE *failure_by_path(const char *path,
40 enum tst_file_call call)
42 unsigned int i;
44 if (failures == NULL)
45 return NULL;
47 for (i = 0; failures[i].path != NULL; i++)
48 if (failures[i].call == call &&
49 !strcmp(path, failures[i].path))
50 return &failures[i];
52 return NULL;
55 void failures_init_FILE(const char *path, FILE *f)
57 unsigned int i;
59 if (failures == NULL)
60 return;
62 //TODO: warn on f not NULL
63 for (i = 0; failures[i].path != NULL; i++)
64 if (!strcmp(path, failures[i].path))
65 failures[i].f = f;
68 static struct tst_fail_FILE *failure_by_FILE(FILE *f, enum tst_file_call call)
70 unsigned int i;
72 if (failures == NULL)
73 return NULL;
75 for (i = 0; failures[i].path != NULL; i++)
76 if (failures[i].call == call && f == failures[i].f)
77 return &failures[i];
79 return NULL;
82 FILE *fopen(const char *path, const char *mode)
84 static FILE *(*real_fopen)(const char *, const char *);
86 if (!real_fopen)
87 real_fopen = dlsym(RTLD_NEXT, "fopen");
89 struct tst_fail_FILE *failure = failure_by_path(path, TST_FAIL_FOPEN);
91 if (failure) {
92 if (failure->err)
93 errno = failure->err;
95 return NULL;
99 FILE *f = real_fopen(path, mode);
101 failures_init_FILE(path, f);
103 return f;
106 int fclose(FILE *fp)
108 static int (*real_fclose)(FILE *);
110 if (!real_fclose)
111 real_fclose = dlsym(RTLD_NEXT, "fclose");
113 struct tst_fail_FILE *failure = failure_by_FILE(fp, TST_FAIL_FCLOSE);
116 * We close the file here correctly, we can because when fclose() has
117 * failed any further access results in undefined behavior.
119 if (failure) {
120 real_fclose(fp);
122 if (failure->err)
123 errno = failure->err;
125 return EOF;
128 return real_fclose(fp);