diff options
author | Vincent Torri <vincent.torri@gmail.com> | 2012-09-11 16:13:11 +0000 |
---|---|---|
committer | Vincent Torri <vincent.torri@gmail.com> | 2012-09-11 16:13:11 +0000 |
commit | cd69ef4c8a66e7155967a8b661a014856979cf31 (patch) | |
tree | 4a351ae4a4ca91abf29c85254b85ea8da71f74b0 /src | |
parent | 59a9dfd11860888a35e96dfe51af63cea5cecfe1 (diff) |
merge: add evil files
SVN revision: 76464
Diffstat (limited to 'src')
103 files changed, 19456 insertions, 0 deletions
diff --git a/src/bin/evil/Makefile.am b/src/bin/evil/Makefile.am new file mode 100644 index 0000000000..538bbdcc69 --- /dev/null +++ b/src/bin/evil/Makefile.am | |||
@@ -0,0 +1,53 @@ | |||
1 | |||
2 | MAINTAINERCLEANFILES = Makefile.in | ||
3 | |||
4 | AM_CPPFLAGS = \ | ||
5 | -I$(top_srcdir) \ | ||
6 | -I$(top_srcdir)/bin \ | ||
7 | -I$(top_srcdir)/src/lib \ | ||
8 | @EVIL_CPPFLAGS@ | ||
9 | |||
10 | AM_CFLAGS = @EVIL_CFLAGS@ | ||
11 | |||
12 | bin_PROGRAMS = evil_suite test_evil | ||
13 | |||
14 | evil_suite_SOURCES = \ | ||
15 | evil_suite.c \ | ||
16 | evil_test_dlfcn.c \ | ||
17 | evil_test_environment.c \ | ||
18 | evil_test_gettimeofday.c \ | ||
19 | evil_test_link.c \ | ||
20 | evil_test_memcpy.c \ | ||
21 | evil_test_mkstemp.c \ | ||
22 | evil_test_pipe.c \ | ||
23 | evil_test_print.c \ | ||
24 | evil_test_realpath.c \ | ||
25 | evil_test_util.c \ | ||
26 | evil_suite.h \ | ||
27 | evil_test_dlfcn.h \ | ||
28 | evil_test_environment.h \ | ||
29 | evil_test_gettimeofday.h \ | ||
30 | evil_test_link.h \ | ||
31 | evil_test_memcpy.h \ | ||
32 | evil_test_mkstemp.h \ | ||
33 | evil_test_pipe.h \ | ||
34 | evil_test_print.h \ | ||
35 | evil_test_realpath.h \ | ||
36 | evil_test_util.h | ||
37 | |||
38 | if EVIL_HAVE_WINCE | ||
39 | |||
40 | evil_suite_SOURCES += memcpy_glibc_arm.S | ||
41 | |||
42 | #else | ||
43 | |||
44 | #suite_SOURCES += memcpy_glibc_i686.S | ||
45 | |||
46 | endif | ||
47 | |||
48 | evil_suite_LDADD = $(top_builddir)/src/lib/libdl.la $(top_builddir)/src/lib/libevil.la -lm | ||
49 | evil_suite_LDFLAGS = -Wl,--enable-auto-import | ||
50 | |||
51 | test_evil_SOURCES = test_evil.c | ||
52 | test_evil_LDADD = $(top_builddir)/src/lib/libevil.la | ||
53 | test_evil_LDFLAGS = -Wl,--enable-auto-import | ||
diff --git a/src/bin/evil/evil_suite.c b/src/bin/evil/evil_suite.c new file mode 100644 index 0000000000..ba928f0682 --- /dev/null +++ b/src/bin/evil/evil_suite.c | |||
@@ -0,0 +1,221 @@ | |||
1 | #ifdef HAVE_CONFIG_H | ||
2 | # include "config.h" | ||
3 | #endif /* HAVE_CONFIG_H */ | ||
4 | |||
5 | #include <stdlib.h> | ||
6 | #include <stdio.h> | ||
7 | |||
8 | #define WIN32_LEAN_AND_MEAN | ||
9 | #include <windows.h> | ||
10 | #undef WIN32_LEAN_AND_MEAN | ||
11 | |||
12 | #include "Evil.h" | ||
13 | #include "evil_suite.h" | ||
14 | #include "evil_test_dlfcn.h" | ||
15 | #include "evil_test_environment.h" | ||
16 | #include "evil_test_gettimeofday.h" | ||
17 | #include "evil_test_link.h" | ||
18 | #include "evil_test_memcpy.h" | ||
19 | #include "evil_test_mkstemp.h" | ||
20 | #include "evil_test_pipe.h" | ||
21 | #include "evil_test_print.h" | ||
22 | #include "evil_test_realpath.h" | ||
23 | #include "evil_test_util.h" | ||
24 | |||
25 | |||
26 | typedef int(*function)(suite *s); | ||
27 | |||
28 | struct test | ||
29 | { | ||
30 | const char *name; | ||
31 | function fct; | ||
32 | }; | ||
33 | |||
34 | struct list | ||
35 | { | ||
36 | void *data; | ||
37 | int succeed; | ||
38 | list *next; | ||
39 | }; | ||
40 | |||
41 | struct suite | ||
42 | { | ||
43 | LARGE_INTEGER freq; | ||
44 | LARGE_INTEGER start; | ||
45 | LARGE_INTEGER end; | ||
46 | |||
47 | list *first; | ||
48 | list *l; | ||
49 | |||
50 | int tests_count; | ||
51 | int tests_success; | ||
52 | }; | ||
53 | |||
54 | |||
55 | static suite * | ||
56 | suite_new(void) | ||
57 | { | ||
58 | suite *s; | ||
59 | |||
60 | s = (suite *)malloc(sizeof(suite)); | ||
61 | if (!s) return NULL; | ||
62 | |||
63 | if (!QueryPerformanceFrequency(&s->freq)) | ||
64 | { | ||
65 | free(s); | ||
66 | return NULL; | ||
67 | } | ||
68 | |||
69 | s->first = NULL; | ||
70 | s->l = NULL; | ||
71 | |||
72 | s->tests_count = 0; | ||
73 | s->tests_success = 0; | ||
74 | |||
75 | return s; | ||
76 | } | ||
77 | |||
78 | static void | ||
79 | suite_del(suite *s) | ||
80 | { | ||
81 | list *l; | ||
82 | list *tmp; | ||
83 | |||
84 | if (!s) return; | ||
85 | |||
86 | l = s->first; | ||
87 | while (l) | ||
88 | { | ||
89 | tmp = l->next; | ||
90 | free(l->data); | ||
91 | free(l); | ||
92 | l = tmp; | ||
93 | } | ||
94 | |||
95 | free(s); | ||
96 | } | ||
97 | |||
98 | void | ||
99 | suite_time_start(suite *s) | ||
100 | { | ||
101 | QueryPerformanceCounter(&s->start); | ||
102 | } | ||
103 | |||
104 | void | ||
105 | suite_time_stop(suite *s) | ||
106 | { | ||
107 | QueryPerformanceCounter(&s->end); | ||
108 | } | ||
109 | |||
110 | double | ||
111 | suite_time_get(suite *s) | ||
112 | { | ||
113 | return (double)(s->end.QuadPart - s->start.QuadPart) / (double)s->freq.QuadPart; | ||
114 | } | ||
115 | |||
116 | static void | ||
117 | suite_test_add(suite *s, const char *name, function fct) | ||
118 | { | ||
119 | test *t; | ||
120 | list *l; | ||
121 | |||
122 | t = (test *)malloc(sizeof(test)); | ||
123 | if (!t) return; | ||
124 | |||
125 | l = (list *)malloc(sizeof(list)); | ||
126 | if (!l) | ||
127 | { | ||
128 | free(t); | ||
129 | return; | ||
130 | } | ||
131 | |||
132 | t->name = name; | ||
133 | t->fct = fct; | ||
134 | |||
135 | l->data = t; | ||
136 | l->succeed = 0; | ||
137 | l->next = NULL; | ||
138 | |||
139 | if (!s->first) s->first = l; | ||
140 | |||
141 | if (!s->l) | ||
142 | s->l = l; | ||
143 | else | ||
144 | { | ||
145 | s->l->next = l; | ||
146 | s->l =l; | ||
147 | } | ||
148 | } | ||
149 | |||
150 | static void | ||
151 | suite_run(suite *s) | ||
152 | { | ||
153 | list *l; | ||
154 | |||
155 | l = s->first; | ||
156 | while (l) | ||
157 | { | ||
158 | test *t; | ||
159 | |||
160 | t = (test *)l->data; | ||
161 | l->succeed = t->fct(s); | ||
162 | printf("%s test: %s\n", t->name, l->succeed ? "success" : "failure"); | ||
163 | s->tests_count++; | ||
164 | if (l->succeed) | ||
165 | s->tests_success++; | ||
166 | l = l->next; | ||
167 | } | ||
168 | } | ||
169 | |||
170 | static void | ||
171 | suite_show(suite *s) | ||
172 | { | ||
173 | printf ("\n%d/%d tests passed (%d%%)\n", | ||
174 | s->tests_success, | ||
175 | s->tests_count, | ||
176 | (100 * s->tests_success) / s->tests_count); | ||
177 | } | ||
178 | |||
179 | int | ||
180 | main(void) | ||
181 | { | ||
182 | test tests[] = { | ||
183 | { "dlfcn ", test_dlfcn }, | ||
184 | { "environment ", test_environment }, | ||
185 | { "gettimeofday", test_gettimeofday }, | ||
186 | { "link ", test_link }, | ||
187 | { "mkstemp ", test_mkstemp }, | ||
188 | { "pipe ", test_pipe }, | ||
189 | { "print ", test_print }, | ||
190 | { "realpath ", test_realpath }, | ||
191 | { "util ", test_util }, | ||
192 | /* { "memcpy ", test_memcpy }, */ | ||
193 | { NULL, NULL }, | ||
194 | }; | ||
195 | suite *s; | ||
196 | int i; | ||
197 | |||
198 | if (!evil_init()) | ||
199 | return EXIT_FAILURE; | ||
200 | |||
201 | s = suite_new(); | ||
202 | if (!s) | ||
203 | { | ||
204 | evil_shutdown(); | ||
205 | return EXIT_FAILURE; | ||
206 | } | ||
207 | |||
208 | for (i = 0; tests[i].name; ++i) | ||
209 | { | ||
210 | suite_test_add(s, tests[i].name, tests[i].fct); | ||
211 | } | ||
212 | |||
213 | suite_run(s); | ||
214 | |||
215 | suite_show(s); | ||
216 | |||
217 | suite_del(s); | ||
218 | evil_shutdown(); | ||
219 | |||
220 | return EXIT_SUCCESS; | ||
221 | } | ||
diff --git a/src/bin/evil/evil_suite.h b/src/bin/evil/evil_suite.h new file mode 100644 index 0000000000..d3284b4fbb --- /dev/null +++ b/src/bin/evil/evil_suite.h | |||
@@ -0,0 +1,14 @@ | |||
1 | #ifndef __EVIL_SUITE_H__ | ||
2 | #define __EVIL_SUITE_H__ | ||
3 | |||
4 | |||
5 | typedef struct test test; | ||
6 | typedef struct list list; | ||
7 | typedef struct suite suite; | ||
8 | |||
9 | void suite_time_start(suite *s); | ||
10 | void suite_time_stop(suite *s); | ||
11 | double suite_time_get(suite *s); | ||
12 | |||
13 | |||
14 | #endif /* __EVIL_SUITE_H__ */ | ||
diff --git a/src/bin/evil/evil_test_dlfcn.c b/src/bin/evil/evil_test_dlfcn.c new file mode 100644 index 0000000000..fb32dd1540 --- /dev/null +++ b/src/bin/evil/evil_test_dlfcn.c | |||
@@ -0,0 +1,80 @@ | |||
1 | #ifdef HAVE_CONFIG_H | ||
2 | # include "config.h" | ||
3 | #endif /* HAVE_CONFIG_H */ | ||
4 | |||
5 | #include <string.h> | ||
6 | #include <dlfcn.h> | ||
7 | |||
8 | #include <Evil.h> | ||
9 | |||
10 | #include "evil_suite.h" | ||
11 | #include "evil_test_dlfcn.h" | ||
12 | |||
13 | |||
14 | typedef int (*_evil_init)(void); | ||
15 | typedef int (*_evil_shutdwon)(void); | ||
16 | |||
17 | |||
18 | static int | ||
19 | test_dlfcn_test_dlopen(void) | ||
20 | { | ||
21 | void *handle; | ||
22 | |||
23 | handle = dlopen("libevil-1.dll", 0); | ||
24 | if (!handle) | ||
25 | return 0; | ||
26 | |||
27 | if (dlclose(handle)) | ||
28 | return 0; | ||
29 | |||
30 | return 1; | ||
31 | } | ||
32 | |||
33 | static int | ||
34 | test_dlfcn_test_dlsym(void) | ||
35 | { | ||
36 | void *handle; | ||
37 | _evil_init sym_init; | ||
38 | _evil_shutdwon sym_shutdown; | ||
39 | |||
40 | handle = dlopen("libevil-1.dll", 0); | ||
41 | if (!handle) | ||
42 | return 0; | ||
43 | |||
44 | sym_init = dlsym(handle, "evil_init"); | ||
45 | if (!sym_init) | ||
46 | { | ||
47 | dlclose(handle); | ||
48 | return 0; | ||
49 | } | ||
50 | |||
51 | sym_shutdown = dlsym(handle, "evil_shutdown"); | ||
52 | if (!sym_shutdown) | ||
53 | { | ||
54 | dlclose(handle); | ||
55 | return 0; | ||
56 | } | ||
57 | |||
58 | if (dlclose(handle)) | ||
59 | return 0; | ||
60 | |||
61 | return 1; | ||
62 | } | ||
63 | |||
64 | static int | ||
65 | test_dlfcn_tests_run(suite *s __UNUSED__) | ||
66 | { | ||
67 | int res; | ||
68 | |||
69 | res = test_dlfcn_test_dlopen(); | ||
70 | res &= test_dlfcn_test_dlsym(); | ||
71 | |||
72 | return res; | ||
73 | } | ||
74 | |||
75 | int | ||
76 | test_dlfcn(suite *s) | ||
77 | { | ||
78 | |||
79 | return test_dlfcn_tests_run(s); | ||
80 | } | ||
diff --git a/src/bin/evil/evil_test_dlfcn.h b/src/bin/evil/evil_test_dlfcn.h new file mode 100644 index 0000000000..0c9bce689e --- /dev/null +++ b/src/bin/evil/evil_test_dlfcn.h | |||
@@ -0,0 +1,8 @@ | |||
1 | #ifndef __EVIL_TEST_DLFCN_H__ | ||
2 | #define __EVIL_TEST_DLFCN_H__ | ||
3 | |||
4 | |||
5 | int test_dlfcn(suite *s); | ||
6 | |||
7 | |||
8 | #endif /* __EVIL_TEST_DLFCN_H__ */ | ||
diff --git a/src/bin/evil/evil_test_environment.c b/src/bin/evil/evil_test_environment.c new file mode 100644 index 0000000000..3048a40124 --- /dev/null +++ b/src/bin/evil/evil_test_environment.c | |||
@@ -0,0 +1,178 @@ | |||
1 | #ifdef HAVE_CONFIG_H | ||
2 | # include "config.h" | ||
3 | #endif /* HAVE_CONFIG_H */ | ||
4 | |||
5 | #include <string.h> | ||
6 | |||
7 | #include <Evil.h> | ||
8 | |||
9 | #include "evil_suite.h" | ||
10 | #include "evil_test_environment.h" | ||
11 | |||
12 | |||
13 | static int | ||
14 | test_env_test_setenv_NULL(void) | ||
15 | { | ||
16 | char *val; | ||
17 | int res; | ||
18 | |||
19 | res = setenv("EVIL_TEST_ENV", NULL, 1); | ||
20 | if (res < 0) | ||
21 | return 0; | ||
22 | |||
23 | val = getenv("EVIL_TEST_ENV"); | ||
24 | |||
25 | return val ? 0 : 1; | ||
26 | } | ||
27 | |||
28 | static int | ||
29 | test_env_test_setenv_NULL_after_set(void) | ||
30 | { | ||
31 | char *val; | ||
32 | int res; | ||
33 | |||
34 | res = setenv("EVIL_TEST_ENV", "val", 1); | ||
35 | if (res < 0) | ||
36 | return 0; | ||
37 | |||
38 | val = getenv("EVIL_TEST_ENV"); | ||
39 | if (!val) | ||
40 | return 0; | ||
41 | |||
42 | if (strcmp(val, "val")) | ||
43 | return 0; | ||
44 | |||
45 | res = setenv("EVIL_TEST_ENV", NULL, 1); | ||
46 | if (res < 0) | ||
47 | return 0; | ||
48 | |||
49 | val = getenv("EVIL_TEST_ENV"); | ||
50 | |||
51 | return val ? 0 : 1; | ||
52 | } | ||
53 | |||
54 | static int | ||
55 | test_env_test_getenv_one(void) | ||
56 | { | ||
57 | char *val; | ||
58 | int res; | ||
59 | |||
60 | res = setenv("EVIL_TEST_ENV", "val", 1); | ||
61 | if (res < 0) | ||
62 | return 0; | ||
63 | |||
64 | val = getenv("EVIL_TEST_ENV"); | ||
65 | if (!val) | ||
66 | return 0; | ||
67 | |||
68 | if (strcmp(val, "val")) | ||
69 | return 0; | ||
70 | |||
71 | return 1; | ||
72 | } | ||
73 | |||
74 | static int | ||
75 | test_env_test_getenv_two(void) | ||
76 | { | ||
77 | char *val; | ||
78 | int res; | ||
79 | |||
80 | res = setenv("EVIL_TEST_ENV1", "val1", 1); | ||
81 | if (res < 0) | ||
82 | return 0; | ||
83 | |||
84 | res = setenv("EVIL_TEST_ENV2", "val2", 1); | ||
85 | if (res < 0) | ||
86 | return 0; | ||
87 | |||
88 | val = getenv("EVIL_TEST_ENV1"); | ||
89 | if (!val) | ||
90 | return 0; | ||
91 | if (strcmp(val, "val1")) | ||
92 | return 0; | ||
93 | |||
94 | val = getenv("EVIL_TEST_ENV2"); | ||
95 | if (!val) | ||
96 | return 0; | ||
97 | |||
98 | if (strcmp(val, "val2")) | ||
99 | return 0; | ||
100 | |||
101 | return 1; | ||
102 | } | ||
103 | |||
104 | static int | ||
105 | test_env_test_getenv_two_swapped(void) | ||
106 | { | ||
107 | char *val; | ||
108 | int res; | ||
109 | |||
110 | res = setenv("EVIL_TEST_ENV1", "val1", 1); | ||
111 | if (res < 0) | ||
112 | return 0; | ||
113 | |||
114 | res = setenv("EVIL_TEST_ENV2", "val2", 1); | ||
115 | if (res < 0) | ||
116 | return 0; | ||
117 | |||
118 | val = getenv("EVIL_TEST_ENV2"); | ||
119 | if (!val) | ||
120 | return 0; | ||
121 | if (strcmp(val, "val2")) | ||
122 | return 0; | ||
123 | |||
124 | val = getenv("EVIL_TEST_ENV1"); | ||
125 | if (!val) | ||
126 | return 0; | ||
127 | |||
128 | if (strcmp(val, "val1")) | ||
129 | return 0; | ||
130 | |||
131 | return 1; | ||
132 | } | ||
133 | |||
134 | static int | ||
135 | test_env_test_unsetenv(void) | ||
136 | { | ||
137 | char *val; | ||
138 | int res; | ||
139 | |||
140 | res = setenv("EVIL_TEST_ENV", "val", 1); | ||
141 | if (res < 0) | ||
142 | return 0; | ||
143 | |||
144 | val = getenv("EVIL_TEST_ENV"); | ||
145 | if (!val) | ||
146 | return 0; | ||
147 | |||
148 | if (unsetenv("EVIL_TEST_ENV") != 0) | ||
149 | return 0; | ||
150 | |||
151 | val = getenv("EVIL_TEST_ENV"); | ||
152 | if (val) | ||
153 | return 0; | ||
154 | |||
155 | return 1; | ||
156 | } | ||
157 | |||
158 | static int | ||
159 | test_env_tests_run(suite *s __UNUSED__) | ||
160 | { | ||
161 | int res; | ||
162 | |||
163 | res = test_env_test_setenv_NULL(); | ||
164 | res &= test_env_test_setenv_NULL_after_set(); | ||
165 | res &= test_env_test_getenv_one(); | ||
166 | res &= test_env_test_getenv_two(); | ||
167 | res &= test_env_test_getenv_two_swapped(); | ||
168 | res &= test_env_test_unsetenv(); | ||
169 | |||
170 | return res; | ||
171 | } | ||
172 | |||
173 | int | ||
174 | test_environment(suite *s) | ||
175 | { | ||
176 | |||
177 | return test_env_tests_run(s); | ||
178 | } | ||
diff --git a/src/bin/evil/evil_test_environment.h b/src/bin/evil/evil_test_environment.h new file mode 100644 index 0000000000..763ee401b1 --- /dev/null +++ b/src/bin/evil/evil_test_environment.h | |||
@@ -0,0 +1,8 @@ | |||
1 | #ifndef __EVIL_TEST_ENVIRONMENT_H__ | ||
2 | #define __EVIL_TEST_ENVIRONMENT_H__ | ||
3 | |||
4 | |||
5 | int test_environment(suite *s); | ||
6 | |||
7 | |||
8 | #endif /* __EVIL_TEST_ENVIRONMENT_H__ */ | ||
diff --git a/src/bin/evil/evil_test_gettimeofday.c b/src/bin/evil/evil_test_gettimeofday.c new file mode 100644 index 0000000000..49742eb5d3 --- /dev/null +++ b/src/bin/evil/evil_test_gettimeofday.c | |||
@@ -0,0 +1,51 @@ | |||
1 | #ifdef HAVE_CONFIG_H | ||
2 | # include "config.h" | ||
3 | #endif /* HAVE_CONFIG_H */ | ||
4 | |||
5 | #include <string.h> | ||
6 | #include <math.h> | ||
7 | #include <sys/time.h> | ||
8 | |||
9 | #include <Evil.h> | ||
10 | |||
11 | #include "evil_suite.h" | ||
12 | #include "evil_test_gettimeofday.h" | ||
13 | |||
14 | static int | ||
15 | test_time_test_gettimeofday(void) | ||
16 | { | ||
17 | struct timeval tp1; | ||
18 | struct timeval tp2; | ||
19 | double delta; | ||
20 | |||
21 | gettimeofday (&tp1, NULL); | ||
22 | |||
23 | Sleep(1000); | ||
24 | |||
25 | gettimeofday (&tp2, NULL); | ||
26 | |||
27 | delta = (double)(tp2.tv_sec - tp1.tv_sec) + (double)(tp2.tv_usec - tp1.tv_usec) / 1000000.0; | ||
28 | if (fabs(delta - 1) > 0.005) | ||
29 | { | ||
30 | return 0; | ||
31 | } | ||
32 | |||
33 | return 1; | ||
34 | } | ||
35 | |||
36 | static int | ||
37 | test_time_tests_run(suite *s __UNUSED__) | ||
38 | { | ||
39 | int res; | ||
40 | |||
41 | res = test_time_test_gettimeofday(); | ||
42 | |||
43 | return res; | ||
44 | } | ||
45 | |||
46 | int | ||
47 | test_gettimeofday(suite *s) | ||
48 | { | ||
49 | |||
50 | return test_time_tests_run(s); | ||
51 | } | ||
diff --git a/src/bin/evil/evil_test_gettimeofday.h b/src/bin/evil/evil_test_gettimeofday.h new file mode 100644 index 0000000000..ad3155b146 --- /dev/null +++ b/src/bin/evil/evil_test_gettimeofday.h | |||
@@ -0,0 +1,8 @@ | |||
1 | #ifndef __EVIL_TEST_GETTIMEOFDAY_H__ | ||
2 | #define __EVIL_TEST_GETTIMEOFDAY_H__ | ||
3 | |||
4 | |||
5 | int test_gettimeofday(suite *s); | ||
6 | |||
7 | |||
8 | #endif /* __EVIL_TEST_GETTIMEOFDAY_H__ */ | ||
diff --git a/src/bin/evil/evil_test_link.c b/src/bin/evil/evil_test_link.c new file mode 100644 index 0000000000..cf4cd931ae --- /dev/null +++ b/src/bin/evil/evil_test_link.c | |||
@@ -0,0 +1,158 @@ | |||
1 | #ifdef HAVE_CONFIG_H | ||
2 | # include "config.h" | ||
3 | #endif /* HAVE_CONFIG_H */ | ||
4 | |||
5 | #include <string.h> | ||
6 | |||
7 | #include <Evil.h> | ||
8 | |||
9 | #include "evil_suite.h" | ||
10 | #include "evil_test_link.h" | ||
11 | |||
12 | static int | ||
13 | test_link_test_file_create(const char *name, const char *data) | ||
14 | { | ||
15 | FILE *f; | ||
16 | size_t length; | ||
17 | size_t res; | ||
18 | |||
19 | f = fopen(name, "wb"); | ||
20 | if (!f) | ||
21 | return 0; | ||
22 | |||
23 | length = strlen(data) + 1; | ||
24 | res = fwrite(data, 1, length, f); | ||
25 | if (res < length) | ||
26 | { | ||
27 | fclose(f); | ||
28 | return 0; | ||
29 | } | ||
30 | |||
31 | fclose(f); | ||
32 | |||
33 | return 1; | ||
34 | } | ||
35 | |||
36 | static int | ||
37 | test_link_test_symlink(void) | ||
38 | { | ||
39 | #ifdef _WIN32_WCE | ||
40 | const char *old_name = "\\efl\\evil_test_link.dat"; | ||
41 | const char *new_name = "\\efl\\evil_test_link.lnk"; | ||
42 | #else | ||
43 | const char *old_name = "evil_test_link.dat"; | ||
44 | const char *new_name = "evil_test_link.lnk"; | ||
45 | #endif | ||
46 | |||
47 | if (!test_link_test_file_create(old_name, | ||
48 | "evil_test_link symlink data\n")) | ||
49 | return 0; | ||
50 | |||
51 | if (symlink(old_name, new_name) < 0) | ||
52 | { | ||
53 | unlink(old_name); | ||
54 | return 0; | ||
55 | } | ||
56 | |||
57 | if (unlink(new_name) < 0) | ||
58 | { | ||
59 | unlink(old_name); | ||
60 | return 0; | ||
61 | } | ||
62 | |||
63 | if (unlink(old_name) < 0) | ||
64 | return 0; | ||
65 | |||
66 | return 1; | ||
67 | } | ||
68 | |||
69 | static int | ||
70 | test_link_test_readlink(void) | ||
71 | { | ||
72 | char buf[1024]; | ||
73 | #ifdef _WIN32_WCE | ||
74 | const char *old_name = "\\efl\\evil_test_link.dat"; | ||
75 | const char *new_name = "\\efl\\evil_test_link.lnk"; | ||
76 | #else | ||
77 | const char *old_name = "evil_test_link.dat"; | ||
78 | const char *new_name = "evil_test_link.lnk"; | ||
79 | #endif | ||
80 | const char *data = "evil_test_link symlink data\n"; | ||
81 | FILE *f; | ||
82 | ssize_t s1; | ||
83 | size_t s2; | ||
84 | int l; | ||
85 | |||
86 | if (!test_link_test_file_create(old_name, data)) | ||
87 | return 0; | ||
88 | |||
89 | if (symlink(old_name, new_name) < 0) | ||
90 | return 0; | ||
91 | |||
92 | if ((s1 = readlink(new_name, buf, 1023)) < 0) | ||
93 | { | ||
94 | unlink(old_name); | ||
95 | unlink(new_name); | ||
96 | return 0; | ||
97 | } | ||
98 | |||
99 | buf[s1] = '\0'; | ||
100 | |||
101 | f = fopen(buf, "rb"); | ||
102 | if (!f) | ||
103 | { | ||
104 | unlink(old_name); | ||
105 | unlink(new_name); | ||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | l = strlen(data); | ||
110 | s2 = fread(buf, 1, l + 1, f); | ||
111 | |||
112 | if ((int)s2 != (l + 1)) | ||
113 | { | ||
114 | fclose(f); | ||
115 | unlink(old_name); | ||
116 | unlink(new_name); | ||
117 | return 0; | ||
118 | } | ||
119 | |||
120 | if (strcmp(buf, data)) | ||
121 | { | ||
122 | fclose(f); | ||
123 | unlink(old_name); | ||
124 | unlink(new_name); | ||
125 | return 0; | ||
126 | } | ||
127 | |||
128 | fclose(f); | ||
129 | |||
130 | if (unlink(new_name) < 0) | ||
131 | { | ||
132 | unlink(old_name); | ||
133 | return 0; | ||
134 | } | ||
135 | |||
136 | if (unlink(old_name) < 0) | ||
137 | return 0; | ||
138 | |||
139 | return 1; | ||
140 | } | ||
141 | |||
142 | static int | ||
143 | test_link_tests_run(suite *s __UNUSED__) | ||
144 | { | ||
145 | int res; | ||
146 | |||
147 | res = test_link_test_symlink(); | ||
148 | res &= test_link_test_readlink(); | ||
149 | |||
150 | return res; | ||
151 | } | ||
152 | |||
153 | int | ||
154 | test_link(suite *s) | ||
155 | { | ||
156 | |||
157 | return test_link_tests_run(s); | ||
158 | } | ||
diff --git a/src/bin/evil/evil_test_link.h b/src/bin/evil/evil_test_link.h new file mode 100644 index 0000000000..6f8bfa2328 --- /dev/null +++ b/src/bin/evil/evil_test_link.h | |||
@@ -0,0 +1,8 @@ | |||
1 | #ifndef __EVIL_TEST_LINK_H__ | ||
2 | #define __EVIL_TEST_LINK_H__ | ||
3 | |||
4 | |||
5 | int test_link(suite *s); | ||
6 | |||
7 | |||
8 | #endif /* __EVIL_TEST_LINK_H__ */ | ||
diff --git a/src/bin/evil/evil_test_memcpy.c b/src/bin/evil/evil_test_memcpy.c new file mode 100644 index 0000000000..0adfe373f0 --- /dev/null +++ b/src/bin/evil/evil_test_memcpy.c | |||
@@ -0,0 +1,145 @@ | |||
1 | #ifdef HAVE_CONFIG_H | ||
2 | # include "config.h" | ||
3 | #endif /* HAVE_CONFIG_H */ | ||
4 | |||
5 | #include <stdlib.h> | ||
6 | #include <stdio.h> | ||
7 | |||
8 | #define WIN32_LEAN_AND_MEAN | ||
9 | #include <windows.h> | ||
10 | #undef WIN32_LEAN_AND_MEAN | ||
11 | |||
12 | #include "evil_suite.h" | ||
13 | #include "evil_test_memcpy.h" | ||
14 | |||
15 | |||
16 | typedef void *(*memcpy_decl)(void *dest, const void *src, size_t n); | ||
17 | |||
18 | void *memcpy_glibc(void *dest, const void *src, size_t n); | ||
19 | |||
20 | |||
21 | static unsigned char *buf1 = NULL; | ||
22 | static unsigned char *buf2 = NULL; | ||
23 | static size_t page_size = 0; | ||
24 | |||
25 | |||
26 | #if defined (__MINGW32CE__) || defined (_MSC_VER) | ||
27 | static int | ||
28 | getpagesize() | ||
29 | { | ||
30 | return 1024; | ||
31 | } | ||
32 | #endif /* __MINGW32CE__ || _MSC_VER */ | ||
33 | |||
34 | |||
35 | static void | ||
36 | test_memcpy_test_run(suite *s, memcpy_decl fct, char *dst, const char *src, size_t len) | ||
37 | { | ||
38 | double best; | ||
39 | int i; | ||
40 | |||
41 | best = 1000000000.0; | ||
42 | |||
43 | for (i = 0; i < 128; ++i) | ||
44 | { | ||
45 | double time; | ||
46 | |||
47 | suite_time_start(s); | ||
48 | fct(dst, src, len); | ||
49 | suite_time_stop(s); | ||
50 | time = suite_time_get(s); | ||
51 | if (time < best) best = time; | ||
52 | } | ||
53 | |||
54 | printf (" %e", best); | ||
55 | } | ||
56 | |||
57 | static void | ||
58 | test_memcpy_tests_run(suite *s, size_t align1, size_t align2, size_t len) | ||
59 | { | ||
60 | size_t i, j; | ||
61 | char *s1, *s2; | ||
62 | |||
63 | printf ("running test..\n"); | ||
64 | |||
65 | /* align1 &= 63; */ | ||
66 | /* if (align1 + len >= page_size) */ | ||
67 | /* return; */ | ||
68 | |||
69 | /* align2 &= 63; */ | ||
70 | /* if (align2 + len >= page_size) */ | ||
71 | /* return; */ | ||
72 | |||
73 | s1 = (char *) (buf1 + align1); | ||
74 | s2 = (char *) (buf2 + align2); | ||
75 | |||
76 | for (i = 0, j = 1; i < len; i++, j += 23) | ||
77 | s1[i] = j; | ||
78 | |||
79 | printf ("length: %6d, align %2d/%2d:", (int)len, align1, align2); | ||
80 | |||
81 | test_memcpy_test_run(s, memcpy, s2, s1, len); | ||
82 | #ifdef _WIN32_WCE | ||
83 | test_memcpy_test_run(s, memcpy_glibc, s2, s1, len); | ||
84 | #endif /* _WIN32_WCE */ | ||
85 | |||
86 | printf ("\n"); | ||
87 | } | ||
88 | |||
89 | int | ||
90 | test_memcpy(suite *s) | ||
91 | { | ||
92 | size_t i; | ||
93 | |||
94 | page_size = 2 * 1024; | ||
95 | |||
96 | buf1 = (unsigned char *)malloc(16 * getpagesize()); | ||
97 | if (!buf1) return 0; | ||
98 | |||
99 | buf2 = (unsigned char *)malloc(16 * getpagesize()); | ||
100 | if (!buf2) | ||
101 | { | ||
102 | free(buf1); | ||
103 | return 0; | ||
104 | } | ||
105 | |||
106 | memset (buf1, 0xa5, page_size); | ||
107 | memset (buf2, 0x5a, page_size); | ||
108 | |||
109 | for (i = 0; i < 5; ++i) | ||
110 | { | ||
111 | test_memcpy_tests_run(s, 0, 0, 1 << i); | ||
112 | test_memcpy_tests_run(s, i, 0, 1 << i); | ||
113 | test_memcpy_tests_run(s, 0, i, 1 << i); | ||
114 | test_memcpy_tests_run(s, i, i, 1 << i); | ||
115 | } | ||
116 | |||
117 | for (i = 0; i < 32; ++i) | ||
118 | { | ||
119 | test_memcpy_tests_run(s, 0, 0, i); | ||
120 | test_memcpy_tests_run(s, i, 0, i); | ||
121 | test_memcpy_tests_run(s, 0, i, i); | ||
122 | test_memcpy_tests_run(s, i, i, i); | ||
123 | } | ||
124 | |||
125 | for (i = 3; i < 32; ++i) | ||
126 | { | ||
127 | if ((i & (i - 1)) == 0) | ||
128 | continue; | ||
129 | test_memcpy_tests_run(s, 0, 0, 16 * i); | ||
130 | test_memcpy_tests_run(s, i, 0, 16 * i); | ||
131 | test_memcpy_tests_run(s, 0, i, 16 * i); | ||
132 | test_memcpy_tests_run(s, i, i, 16 * i); | ||
133 | } | ||
134 | |||
135 | test_memcpy_tests_run(s, 0, 0, getpagesize ()); | ||
136 | test_memcpy_tests_run(s, 0, 0, 2 * getpagesize ()); | ||
137 | test_memcpy_tests_run(s, 0, 0, 4 * getpagesize ()); | ||
138 | test_memcpy_tests_run(s, 0, 0, 8 * getpagesize ()); | ||
139 | test_memcpy_tests_run(s, 0, 0, 16 * getpagesize ()); | ||
140 | |||
141 | free(buf2); | ||
142 | free(buf1); | ||
143 | |||
144 | return 1; | ||
145 | } | ||
diff --git a/src/bin/evil/evil_test_memcpy.h b/src/bin/evil/evil_test_memcpy.h new file mode 100644 index 0000000000..808dd09f37 --- /dev/null +++ b/src/bin/evil/evil_test_memcpy.h | |||
@@ -0,0 +1,8 @@ | |||
1 | #ifndef __EVIL_TEST_MEMCPY__ | ||
2 | #define __EVIL_TEST_MEMCPY__ | ||
3 | |||
4 | |||
5 | int test_memcpy(suite *s); | ||
6 | |||
7 | |||
8 | #endif /* __EVIL_TEST_MEMCPY__ */ | ||
diff --git a/src/bin/evil/evil_test_mkstemp.c b/src/bin/evil/evil_test_mkstemp.c new file mode 100644 index 0000000000..dc8c4e64f5 --- /dev/null +++ b/src/bin/evil/evil_test_mkstemp.c | |||
@@ -0,0 +1,53 @@ | |||
1 | #ifdef HAVE_CONFIG_H | ||
2 | # include "config.h" | ||
3 | #endif /* HAVE_CONFIG_H */ | ||
4 | |||
5 | #include <string.h> | ||
6 | |||
7 | #include <Evil.h> | ||
8 | |||
9 | #include "evil_suite.h" | ||
10 | #include "evil_test_mkstemp.h" | ||
11 | |||
12 | |||
13 | static int | ||
14 | test_mkstemp_test(void) | ||
15 | { | ||
16 | char _template[PATH_MAX]; | ||
17 | #ifdef _WIN32_WCE | ||
18 | char cwd[PATH_MAX]; | ||
19 | #endif | ||
20 | int fd; | ||
21 | |||
22 | #ifdef _WIN32_WCE | ||
23 | if (!getcwd(cwd, PATH_MAX)) | ||
24 | return 0; | ||
25 | _snprintf(_template, PATH_MAX, "%s\\%s", cwd, "file_XXXXXX"); | ||
26 | #else | ||
27 | _snprintf(_template, PATH_MAX, "%s", "file_XXXXXX"); | ||
28 | #endif | ||
29 | |||
30 | fd = mkstemp(_template); | ||
31 | |||
32 | if (fd < 0) | ||
33 | return 0; | ||
34 | |||
35 | return 1; | ||
36 | } | ||
37 | |||
38 | static int | ||
39 | test_mkstemp_run(suite *s __UNUSED__) | ||
40 | { | ||
41 | int res; | ||
42 | |||
43 | res = test_mkstemp_test(); | ||
44 | |||
45 | return res; | ||
46 | } | ||
47 | |||
48 | int | ||
49 | test_mkstemp(suite *s) | ||
50 | { | ||
51 | |||
52 | return test_mkstemp_run(s); | ||
53 | } | ||
diff --git a/src/bin/evil/evil_test_mkstemp.h b/src/bin/evil/evil_test_mkstemp.h new file mode 100644 index 0000000000..f5bb0c4270 --- /dev/null +++ b/src/bin/evil/evil_test_mkstemp.h | |||
@@ -0,0 +1,8 @@ | |||
1 | #ifndef __EVIL_TEST_MKSTEMP_H__ | ||
2 | #define __EVIL_TEST_MKSTEMP_H__ | ||
3 | |||
4 | |||
5 | int test_mkstemp(suite *s); | ||
6 | |||
7 | |||
8 | #endif /* __EVIL_TEST_MKSTEMP_H__ */ | ||
diff --git a/src/bin/evil/evil_test_pipe.c b/src/bin/evil/evil_test_pipe.c new file mode 100644 index 0000000000..2fc530d545 --- /dev/null +++ b/src/bin/evil/evil_test_pipe.c | |||
@@ -0,0 +1,126 @@ | |||
1 | #ifdef HAVE_CONFIG_H | ||
2 | # include "config.h" | ||
3 | #endif /* HAVE_CONFIG_H */ | ||
4 | |||
5 | #include <stdlib.h> | ||
6 | #include <stdio.h> | ||
7 | |||
8 | # define WIN32_LEAN_AND_MEAN | ||
9 | # include <winsock2.h> | ||
10 | # undef WIN32_LEAN_AND_MEAN | ||
11 | |||
12 | #include <Evil.h> | ||
13 | |||
14 | #include "evil_suite.h" | ||
15 | #include "evil_test_pipe.h" | ||
16 | |||
17 | |||
18 | #define FDREAD 0 | ||
19 | #define FDWRITE 1 | ||
20 | |||
21 | typedef struct | ||
22 | { | ||
23 | int val; | ||
24 | int fd_write; | ||
25 | } data; | ||
26 | |||
27 | |||
28 | static DWORD WINAPI | ||
29 | thread (void *param) | ||
30 | { | ||
31 | data *d; | ||
32 | void *buf[1]; | ||
33 | |||
34 | Sleep (2 * 1000); | ||
35 | d = (data *)param; | ||
36 | buf[0] = d; | ||
37 | send(d->fd_write, (char *)buf, sizeof(buf), 0); | ||
38 | |||
39 | return 0; | ||
40 | } | ||
41 | |||
42 | static int | ||
43 | test_pipe_test(void) | ||
44 | { | ||
45 | int sockets[2]; | ||
46 | struct timeval t; | ||
47 | fd_set rfds; | ||
48 | int ret; | ||
49 | data *d; | ||
50 | DWORD thread_id; | ||
51 | HANDLE h; | ||
52 | |||
53 | FD_ZERO(&rfds); | ||
54 | |||
55 | t.tv_sec = 5; | ||
56 | t.tv_usec = 0; | ||
57 | |||
58 | if (pipe(sockets) < 0) | ||
59 | return 0; | ||
60 | |||
61 | FD_SET(sockets[FDREAD], &rfds); | ||
62 | fcntl(sockets[FDREAD], F_SETFL, O_NONBLOCK); | ||
63 | |||
64 | d = (data *)malloc(sizeof (data)); | ||
65 | if (!d) | ||
66 | return 0; | ||
67 | |||
68 | d->val = 14; | ||
69 | d->fd_write = sockets[FDWRITE]; | ||
70 | |||
71 | h = CreateThread(NULL, 0, thread, d, 0, &thread_id); | ||
72 | if (!h) | ||
73 | |||
74 | ret = select(sockets[FDREAD] + 1, &rfds, NULL, NULL, &t); | ||
75 | |||
76 | if (ret < 0) | ||
77 | goto free_d; | ||
78 | else if (ret == 0) | ||
79 | goto close_h; | ||
80 | else /* ret > 0 */ | ||
81 | { | ||
82 | void *buf[1]; | ||
83 | data *d2 = NULL; | ||
84 | int len; | ||
85 | |||
86 | while ((len = recv(sockets[FDREAD], (char *)buf, sizeof(buf), 0)) > 0) | ||
87 | { | ||
88 | if (len == sizeof(buf)) | ||
89 | { | ||
90 | d2 = (data *)buf[0]; | ||
91 | break; | ||
92 | } | ||
93 | } | ||
94 | if (d2 && (d2->val == d->val)) | ||
95 | ret = 1; | ||
96 | else | ||
97 | ret = 0; | ||
98 | } | ||
99 | |||
100 | CloseHandle(h); | ||
101 | free(d); | ||
102 | |||
103 | return ret; | ||
104 | |||
105 | close_h: | ||
106 | CloseHandle(h); | ||
107 | free_d: | ||
108 | free(d); | ||
109 | return 0; | ||
110 | } | ||
111 | |||
112 | static int | ||
113 | test_pipe_run(suite *s __UNUSED__) | ||
114 | { | ||
115 | int res; | ||
116 | |||
117 | res = test_pipe_test(); | ||
118 | |||
119 | return res; | ||
120 | } | ||
121 | |||
122 | int | ||
123 | test_pipe(suite *s) | ||
124 | { | ||
125 | return test_pipe_run(s); | ||
126 | } | ||
diff --git a/src/bin/evil/evil_test_pipe.h b/src/bin/evil/evil_test_pipe.h new file mode 100644 index 0000000000..ff8041f716 --- /dev/null +++ b/src/bin/evil/evil_test_pipe.h | |||
@@ -0,0 +1,8 @@ | |||
1 | #ifndef __EVIL_TEST_PIPE_H__ | ||
2 | #define __EVIL_TEST_PIPE_H__ | ||
3 | |||
4 | |||
5 | int test_pipe(suite *s); | ||
6 | |||
7 | |||
8 | #endif /* __EVIL_TEST_PIPE_H__ */ | ||
diff --git a/src/bin/evil/evil_test_print.c b/src/bin/evil/evil_test_print.c new file mode 100644 index 0000000000..b930a538f4 --- /dev/null +++ b/src/bin/evil/evil_test_print.c | |||
@@ -0,0 +1,46 @@ | |||
1 | #ifdef HAVE_CONFIG_H | ||
2 | # include "config.h" | ||
3 | #endif /* HAVE_CONFIG_H */ | ||
4 | |||
5 | #include <stdlib.h> | ||
6 | #include <stdio.h> | ||
7 | |||
8 | #include <Evil.h> | ||
9 | |||
10 | #include "evil_suite.h" | ||
11 | #include "evil_test_print.h" | ||
12 | |||
13 | static int | ||
14 | test_print_test(void) | ||
15 | { | ||
16 | char buf[16]; | ||
17 | int i1 = 1; | ||
18 | size_t i2 = 123456; | ||
19 | int res; | ||
20 | |||
21 | res = printf("%02hhd\n", i1); | ||
22 | if (res != 3) | ||
23 | return 0; | ||
24 | |||
25 | res = snprintf(buf, sizeof(buf), "%zu", i2); | ||
26 | if (res != 6) | ||
27 | return 0; | ||
28 | |||
29 | return 1; | ||
30 | } | ||
31 | |||
32 | static int | ||
33 | test_print_run(suite *s __UNUSED__) | ||
34 | { | ||
35 | int res; | ||
36 | |||
37 | res = test_print_test(); | ||
38 | |||
39 | return res; | ||
40 | } | ||
41 | |||
42 | int | ||
43 | test_print(suite *s) | ||
44 | { | ||
45 | return test_print_run(s); | ||
46 | } | ||
diff --git a/src/bin/evil/evil_test_print.h b/src/bin/evil/evil_test_print.h new file mode 100644 index 0000000000..2bbf43904f --- /dev/null +++ b/src/bin/evil/evil_test_print.h | |||
@@ -0,0 +1,8 @@ | |||
1 | #ifndef __EVIL_TEST_PRINT_H__ | ||
2 | #define __EVIL_TEST_PRINT_H__ | ||
3 | |||
4 | |||
5 | int test_print(suite *s); | ||
6 | |||
7 | |||
8 | #endif /* __EVIL_TEST_PRINT_H__ */ | ||
diff --git a/src/bin/evil/evil_test_realpath.c b/src/bin/evil/evil_test_realpath.c new file mode 100644 index 0000000000..f9a48cb977 --- /dev/null +++ b/src/bin/evil/evil_test_realpath.c | |||
@@ -0,0 +1,44 @@ | |||
1 | #ifdef HAVE_CONFIG_H | ||
2 | # include "config.h" | ||
3 | #endif /* HAVE_CONFIG_H */ | ||
4 | |||
5 | #include <string.h> | ||
6 | |||
7 | #include <Evil.h> | ||
8 | |||
9 | #include "evil_suite.h" | ||
10 | #include "evil_test_realpath.h" | ||
11 | |||
12 | |||
13 | static int | ||
14 | test_realpath_test(void) | ||
15 | { | ||
16 | char buf[PATH_MAX]; | ||
17 | char *filename; | ||
18 | char *result; | ||
19 | |||
20 | filename = "evil_suite.exe"; | ||
21 | |||
22 | if (!(result = realpath(filename, buf))) | ||
23 | return 0; | ||
24 | |||
25 | printf ("res : %s\n", buf); | ||
26 | |||
27 | return 1; | ||
28 | } | ||
29 | |||
30 | static int | ||
31 | test_realpath_run(suite *s __UNUSED__) | ||
32 | { | ||
33 | int res; | ||
34 | |||
35 | res = test_realpath_test(); | ||
36 | |||
37 | return res; | ||
38 | } | ||
39 | |||
40 | int | ||
41 | test_realpath(suite *s) | ||
42 | { | ||
43 | return test_realpath_run(s); | ||
44 | } | ||
diff --git a/src/bin/evil/evil_test_realpath.h b/src/bin/evil/evil_test_realpath.h new file mode 100644 index 0000000000..0205aad149 --- /dev/null +++ b/src/bin/evil/evil_test_realpath.h | |||
@@ -0,0 +1,8 @@ | |||
1 | #ifndef __EVIL_TEST_REALPATH_H__ | ||
2 | #define __EVIL_TEST_REALPATH_H__ | ||
3 | |||
4 | |||
5 | int test_realpath(suite *s); | ||
6 | |||
7 | |||
8 | #endif /* __EVIL_TEST_REALPATH_H__ */ | ||
diff --git a/src/bin/evil/evil_test_util.c b/src/bin/evil/evil_test_util.c new file mode 100644 index 0000000000..6226ceb040 --- /dev/null +++ b/src/bin/evil/evil_test_util.c | |||
@@ -0,0 +1,110 @@ | |||
1 | #ifdef HAVE_CONFIG_H | ||
2 | # include "config.h" | ||
3 | #endif /* HAVE_CONFIG_H */ | ||
4 | |||
5 | #include <string.h> | ||
6 | |||
7 | #include <Evil.h> | ||
8 | |||
9 | #include "evil_suite.h" | ||
10 | #include "evil_test_util.h" | ||
11 | |||
12 | |||
13 | static int test_path_absolute_test_1(void) | ||
14 | { | ||
15 | char *path; | ||
16 | int result; | ||
17 | |||
18 | path = NULL; | ||
19 | result = evil_path_is_absolute(path); | ||
20 | if (result != 0) | ||
21 | return 0; | ||
22 | |||
23 | return 1; | ||
24 | } | ||
25 | |||
26 | static int test_path_absolute_test_2(void) | ||
27 | { | ||
28 | char *path; | ||
29 | int result; | ||
30 | |||
31 | path = "1"; | ||
32 | result = evil_path_is_absolute(path); | ||
33 | if (result != 0) | ||
34 | return 0; | ||
35 | |||
36 | return 1; | ||
37 | } | ||
38 | |||
39 | static int test_path_absolute_test_3(void) | ||
40 | { | ||
41 | char *path; | ||
42 | int result; | ||
43 | |||
44 | path = "1:\\"; | ||
45 | result = evil_path_is_absolute(path); | ||
46 | if (result != 0) | ||
47 | return 0; | ||
48 | |||
49 | return 1; | ||
50 | } | ||
51 | |||
52 | static int test_path_absolute_test_4(void) | ||
53 | { | ||
54 | char *path; | ||
55 | int result; | ||
56 | |||
57 | path = "1/\\"; | ||
58 | result = evil_path_is_absolute(path); | ||
59 | if (result != 0) | ||
60 | return 0; | ||
61 | |||
62 | return 1; | ||
63 | } | ||
64 | |||
65 | static int test_path_absolute_test_5(void) | ||
66 | { | ||
67 | char *path; | ||
68 | int result; | ||
69 | |||
70 | path = "F:/foo"; | ||
71 | result = evil_path_is_absolute(path); | ||
72 | if (result == 0) | ||
73 | return 0; | ||
74 | |||
75 | return 1; | ||
76 | } | ||
77 | |||
78 | static int test_path_absolute_test_6(void) | ||
79 | { | ||
80 | char *path; | ||
81 | int result; | ||
82 | |||
83 | path = "C:\\foo"; | ||
84 | result = evil_path_is_absolute(path); | ||
85 | if (result == 0) | ||
86 | return 0; | ||
87 | |||
88 | return 1; | ||
89 | } | ||
90 | |||
91 | static int | ||
92 | test_path_absolute_run(suite *s __UNUSED__) | ||
93 | { | ||
94 | int res; | ||
95 | |||
96 | res = test_path_absolute_test_1(); | ||
97 | res &= test_path_absolute_test_2(); | ||
98 | res &= test_path_absolute_test_3(); | ||
99 | res &= test_path_absolute_test_4(); | ||
100 | res &= test_path_absolute_test_5(); | ||
101 | res &= test_path_absolute_test_6(); | ||
102 | |||
103 | return res; | ||
104 | } | ||
105 | |||
106 | int | ||
107 | test_util(suite *s) | ||
108 | { | ||
109 | return test_path_absolute_run(s); | ||
110 | } | ||
diff --git a/src/bin/evil/evil_test_util.h b/src/bin/evil/evil_test_util.h new file mode 100644 index 0000000000..bee5c7a164 --- /dev/null +++ b/src/bin/evil/evil_test_util.h | |||
@@ -0,0 +1,8 @@ | |||
1 | #ifndef __EVIL_TEST_UTIL_H__ | ||
2 | #define __EVIL_TEST_UTIL_H__ | ||
3 | |||
4 | |||
5 | int test_util(suite *s); | ||
6 | |||
7 | |||
8 | #endif /* __EVIL_TEST_UTIL_H__ */ | ||
diff --git a/src/bin/evil/memcpy_glibc_arm.S b/src/bin/evil/memcpy_glibc_arm.S new file mode 100644 index 0000000000..7c42898647 --- /dev/null +++ b/src/bin/evil/memcpy_glibc_arm.S | |||
@@ -0,0 +1,231 @@ | |||
1 | /* Copyright (C) 2006 Free Software Foundation, Inc. | ||
2 | This file is part of the GNU C Library. | ||
3 | |||
4 | Contributed by MontaVista Software, Inc. (written by Nicolas Pitre) | ||
5 | |||
6 | The GNU C Library is free software; you can redistribute it and/or | ||
7 | modify it under the terms of the GNU Lesser General Public | ||
8 | License as published by the Free Software Foundation; either | ||
9 | version 2.1 of the License, or (at your option) any later version. | ||
10 | |||
11 | The GNU C Library is distributed in the hope that it will be useful, | ||
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
14 | Lesser General Public License for more details. | ||
15 | |||
16 | You should have received a copy of the GNU Lesser General Public | ||
17 | License along with the GNU C Library; if not, write to the Free | ||
18 | Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | ||
19 | 02111-1307 USA. */ | ||
20 | |||
21 | /* Copyright (C) 2008 Vincent Torri | ||
22 | modification of the name and of the entry / end declaration | ||
23 | */ | ||
24 | |||
25 | /* | ||
26 | * Data preload for architectures that support it (ARM V5TE and above) | ||
27 | */ | ||
28 | #if (!defined (__ARM_ARCH_2__) && !defined (__ARM_ARCH_3__) \ | ||
29 | && !defined (__ARM_ARCH_3M__) && !defined (__ARM_ARCH_4__) \ | ||
30 | && !defined (__ARM_ARCH_4T__) && !defined (__ARM_ARCH_5__) \ | ||
31 | && !defined (__ARM_ARCH_5T__)) | ||
32 | #define PLD(code...) code | ||
33 | #else | ||
34 | #define PLD(code...) | ||
35 | #endif | ||
36 | |||
37 | /* | ||
38 | * This can be used to enable code to cacheline align the source pointer. | ||
39 | * Experiments on tested architectures (StrongARM and XScale) didn't show | ||
40 | * this a worthwhile thing to do. That might be different in the future. | ||
41 | */ | ||
42 | //#define CALGN(code...) code | ||
43 | #define CALGN(code...) | ||
44 | |||
45 | /* | ||
46 | * Endian independent macros for shifting bytes within registers. | ||
47 | */ | ||
48 | #ifndef __ARMEB__ | ||
49 | #define pull lsr | ||
50 | #define push lsl | ||
51 | #else | ||
52 | #define pull lsl | ||
53 | #define push lsr | ||
54 | #endif | ||
55 | |||
56 | .text | ||
57 | |||
58 | /* Prototype: void *memcpy_glibc(void *dest, const void *src, size_t n); */ | ||
59 | |||
60 | .align | ||
61 | .global memcpy_glibc | ||
62 | .func memcpy_glibc | ||
63 | memcpy_glibc: | ||
64 | |||
65 | stmfd sp!, {r0, r4, lr} | ||
66 | |||
67 | subs r2, r2, #4 | ||
68 | blt 8f | ||
69 | ands ip, r0, #3 | ||
70 | PLD( pld [r1, #0] ) | ||
71 | bne 9f | ||
72 | ands ip, r1, #3 | ||
73 | bne 10f | ||
74 | |||
75 | 1: subs r2, r2, #(28) | ||
76 | stmfd sp!, {r5 - r8} | ||
77 | blt 5f | ||
78 | |||
79 | CALGN( ands ip, r1, #31 ) | ||
80 | CALGN( rsb r3, ip, #32 ) | ||
81 | CALGN( sbcnes r4, r3, r2 ) @ C is always set here | ||
82 | CALGN( bcs 2f ) | ||
83 | CALGN( adr r4, 6f ) | ||
84 | CALGN( subs r2, r2, r3 ) @ C gets set | ||
85 | CALGN( add pc, r4, ip ) | ||
86 | |||
87 | PLD( pld [r1, #0] ) | ||
88 | 2: PLD( subs r2, r2, #96 ) | ||
89 | PLD( pld [r1, #28] ) | ||
90 | PLD( blt 4f ) | ||
91 | PLD( pld [r1, #60] ) | ||
92 | PLD( pld [r1, #92] ) | ||
93 | |||
94 | 3: PLD( pld [r1, #124] ) | ||
95 | 4: ldmia r1!, {r3, r4, r5, r6, r7, r8, ip, lr} | ||
96 | subs r2, r2, #32 | ||
97 | stmia r0!, {r3, r4, r5, r6, r7, r8, ip, lr} | ||
98 | bge 3b | ||
99 | PLD( cmn r2, #96 ) | ||
100 | PLD( bge 4b ) | ||
101 | |||
102 | 5: ands ip, r2, #28 | ||
103 | rsb ip, ip, #32 | ||
104 | addne pc, pc, ip @ C is always clear here | ||
105 | b 7f | ||
106 | 6: nop | ||
107 | ldr r3, [r1], #4 | ||
108 | ldr r4, [r1], #4 | ||
109 | ldr r5, [r1], #4 | ||
110 | ldr r6, [r1], #4 | ||
111 | ldr r7, [r1], #4 | ||
112 | ldr r8, [r1], #4 | ||
113 | ldr lr, [r1], #4 | ||
114 | |||
115 | add pc, pc, ip | ||
116 | nop | ||
117 | nop | ||
118 | str r3, [r0], #4 | ||
119 | str r4, [r0], #4 | ||
120 | str r5, [r0], #4 | ||
121 | str r6, [r0], #4 | ||
122 | str r7, [r0], #4 | ||
123 | str r8, [r0], #4 | ||
124 | str lr, [r0], #4 | ||
125 | |||
126 | CALGN( bcs 2b ) | ||
127 | |||
128 | 7: ldmfd sp!, {r5 - r8} | ||
129 | |||
130 | 8: movs r2, r2, lsl #31 | ||
131 | ldrneb r3, [r1], #1 | ||
132 | ldrcsb r4, [r1], #1 | ||
133 | ldrcsb ip, [r1] | ||
134 | strneb r3, [r0], #1 | ||
135 | strcsb r4, [r0], #1 | ||
136 | strcsb ip, [r0] | ||
137 | |||
138 | ldmfd sp!, {r0, r4, pc} | ||
139 | |||
140 | 9: rsb ip, ip, #4 | ||
141 | cmp ip, #2 | ||
142 | ldrgtb r3, [r1], #1 | ||
143 | ldrgeb r4, [r1], #1 | ||
144 | ldrb lr, [r1], #1 | ||
145 | strgtb r3, [r0], #1 | ||
146 | strgeb r4, [r0], #1 | ||
147 | subs r2, r2, ip | ||
148 | strb lr, [r0], #1 | ||
149 | blt 8b | ||
150 | ands ip, r1, #3 | ||
151 | beq 1b | ||
152 | |||
153 | 10: bic r1, r1, #3 | ||
154 | cmp ip, #2 | ||
155 | ldr lr, [r1], #4 | ||
156 | beq 17f | ||
157 | bgt 18f | ||
158 | |||
159 | |||
160 | .macro forward_copy_shift pull push | ||
161 | |||
162 | subs r2, r2, #28 | ||
163 | blt 14f | ||
164 | |||
165 | CALGN( ands ip, r1, #31 ) | ||
166 | CALGN( rsb ip, ip, #32 ) | ||
167 | CALGN( sbcnes r4, ip, r2 ) @ C is always set here | ||
168 | CALGN( subcc r2, r2, ip ) | ||
169 | CALGN( bcc 15f ) | ||
170 | |||
171 | 11: stmfd sp!, {r5 - r9} | ||
172 | |||
173 | PLD( pld [r1, #0] ) | ||
174 | PLD( subs r2, r2, #96 ) | ||
175 | PLD( pld [r1, #28] ) | ||
176 | PLD( blt 13f ) | ||
177 | PLD( pld [r1, #60] ) | ||
178 | PLD( pld [r1, #92] ) | ||
179 | |||
180 | 12: PLD( pld [r1, #124] ) | ||
181 | 13: ldmia r1!, {r4, r5, r6, r7} | ||
182 | mov r3, lr, pull #\pull | ||
183 | subs r2, r2, #32 | ||
184 | ldmia r1!, {r8, r9, ip, lr} | ||
185 | orr r3, r3, r4, push #\push | ||
186 | mov r4, r4, pull #\pull | ||
187 | orr r4, r4, r5, push #\push | ||
188 | mov r5, r5, pull #\pull | ||
189 | orr r5, r5, r6, push #\push | ||
190 | mov r6, r6, pull #\pull | ||
191 | orr r6, r6, r7, push #\push | ||
192 | mov r7, r7, pull #\pull | ||
193 | orr r7, r7, r8, push #\push | ||
194 | mov r8, r8, pull #\pull | ||
195 | orr r8, r8, r9, push #\push | ||
196 | mov r9, r9, pull #\pull | ||
197 | orr r9, r9, ip, push #\push | ||
198 | mov ip, ip, pull #\pull | ||
199 | orr ip, ip, lr, push #\push | ||
200 | stmia r0!, {r3, r4, r5, r6, r7, r8, r9, ip} | ||
201 | bge 12b | ||
202 | PLD( cmn r2, #96 ) | ||
203 | PLD( bge 13b ) | ||
204 | |||
205 | ldmfd sp!, {r5 - r9} | ||
206 | |||
207 | 14: ands ip, r2, #28 | ||
208 | beq 16f | ||
209 | |||
210 | 15: mov r3, lr, pull #\pull | ||
211 | ldr lr, [r1], #4 | ||
212 | subs ip, ip, #4 | ||
213 | orr r3, r3, lr, push #\push | ||
214 | str r3, [r0], #4 | ||
215 | bgt 15b | ||
216 | CALGN( cmp r2, #0 ) | ||
217 | CALGN( bge 11b ) | ||
218 | |||
219 | 16: sub r1, r1, #(\push / 8) | ||
220 | b 8b | ||
221 | |||
222 | .endm | ||
223 | |||
224 | |||
225 | forward_copy_shift pull=8 push=24 | ||
226 | |||
227 | 17: forward_copy_shift pull=16 push=16 | ||
228 | |||
229 | 18: forward_copy_shift pull=24 push=8 | ||
230 | |||
231 | .endfunc | ||
diff --git a/src/bin/evil/memcpy_glibc_i686.S b/src/bin/evil/memcpy_glibc_i686.S new file mode 100755 index 0000000000..72da118cf0 --- /dev/null +++ b/src/bin/evil/memcpy_glibc_i686.S | |||
@@ -0,0 +1,81 @@ | |||
1 | /* Copy memory block and return pointer to beginning of destination block | ||
2 | For Intel 80x86, x>=6. | ||
3 | This file is part of the GNU C Library. | ||
4 | Copyright (C) 1999, 2000, 2003, 2004 Free Software Foundation, Inc. | ||
5 | Contributed by Ulrich Drepper <drepper@cygnus.com>, 1999. | ||
6 | |||
7 | The GNU C Library is free software; you can redistribute it and/or | ||
8 | modify it under the terms of the GNU Lesser General Public | ||
9 | License as published by the Free Software Foundation; either | ||
10 | version 2.1 of the License, or (at your option) any later version. | ||
11 | |||
12 | The GNU C Library is distributed in the hope that it will be useful, | ||
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | Lesser General Public License for more details. | ||
16 | |||
17 | You should have received a copy of the GNU Lesser General Public | ||
18 | License along with the GNU C Library; if not, write to the Free | ||
19 | Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA | ||
20 | 02111-1307 USA. */ | ||
21 | |||
22 | # define CHECK_BOUNDS_BOTH_WIDE(VAL_REG, BP_MEM, LENGTH) \ | ||
23 | CHECK_BOUNDS_LOW(VAL_REG, BP_MEM); \ | ||
24 | addl LENGTH, VAL_REG; \ | ||
25 | cmpl 8+BP_MEM, VAL_REG; \ | ||
26 | jbe 0f; /* continue if value <= high */ \ | ||
27 | BOUNDS_VIOLATED; \ | ||
28 | 0: subl LENGTH, VAL_REG /* restore value */ | ||
29 | |||
30 | # define RETURN_BOUNDED_POINTER(BP_MEM) \ | ||
31 | movl RTN(%esp), %edx; \ | ||
32 | movl %eax, 0(%edx); \ | ||
33 | movl 4+BP_MEM, %eax; \ | ||
34 | movl %eax, 4(%edx); \ | ||
35 | movl 8+BP_MEM, %eax; \ | ||
36 | movl %eax, 8(%edx) | ||
37 | |||
38 | #define PTR_SIZE 12 | ||
39 | #define RTN_SIZE 4 | ||
40 | #define LINKAGE 8 | ||
41 | |||
42 | #define PARMS LINKAGE /* no space for saved regs */ | ||
43 | #define RTN PARMS | ||
44 | #define DEST RTN+RTN_SIZE | ||
45 | #define SRC DEST+PTR_SIZE | ||
46 | #define LEN SRC+PTR_SIZE | ||
47 | |||
48 | .text | ||
49 | |||
50 | .align | ||
51 | .global memcpy_glibc | ||
52 | .func memcpy_glibc | ||
53 | memcpy_glibc: | ||
54 | |||
55 | pushl %ebp | ||
56 | movl %esp, %ebp | ||
57 | |||
58 | movl LEN(%esp), %ecx | ||
59 | movl %edi, %eax | ||
60 | movl DEST(%esp), %edi | ||
61 | movl %esi, %edx | ||
62 | movl SRC(%esp), %esi | ||
63 | |||
64 | cld | ||
65 | shrl $1, %ecx | ||
66 | jnc 1f | ||
67 | movsb | ||
68 | 1: shrl $1, %ecx | ||
69 | jnc 2f | ||
70 | movsw | ||
71 | 2: rep | ||
72 | movsl | ||
73 | movl %eax, %edi | ||
74 | movl %edx, %esi | ||
75 | movl DEST(%esp), %eax | ||
76 | RETURN_BOUNDED_POINTER (DEST(%esp)) | ||
77 | |||
78 | movl %ebp, %esp | ||
79 | popl %ebp | ||
80 | |||
81 | .endfunc | ||
diff --git a/src/bin/evil/test_evil.c b/src/bin/evil/test_evil.c new file mode 100644 index 0000000000..5b91172cb3 --- /dev/null +++ b/src/bin/evil/test_evil.c | |||
@@ -0,0 +1,27 @@ | |||
1 | #include <stdlib.h> | ||
2 | #include <stdio.h> | ||
3 | #include <sys/time.h> | ||
4 | |||
5 | #include <windows.h> | ||
6 | |||
7 | |||
8 | |||
9 | int | ||
10 | main() | ||
11 | { | ||
12 | struct timeval tv; | ||
13 | double t1 = 0.0; | ||
14 | double t2 = 0.0; | ||
15 | |||
16 | if (gettimeofday(&tv, NULL) == 0) | ||
17 | t1 = tv.tv_sec + tv.tv_usec / 1000000.0; | ||
18 | |||
19 | Sleep(3000); | ||
20 | |||
21 | if (gettimeofday(&tv, NULL) == 0) | ||
22 | t2 = tv.tv_sec + tv.tv_usec / 1000000.0; | ||
23 | |||
24 | printf ("3 seconds ? %f\n", t2 - t1); | ||
25 | |||
26 | return EXIT_SUCCESS; | ||
27 | } | ||
diff --git a/src/lib/evil/Evil.h b/src/lib/evil/Evil.h new file mode 100644 index 0000000000..e807dffb61 --- /dev/null +++ b/src/lib/evil/Evil.h | |||
@@ -0,0 +1,186 @@ | |||
1 | #ifndef __EVIL_H__ | ||
2 | #define __EVIL_H__ | ||
3 | |||
4 | /** | ||
5 | * @mainpage Evil | ||
6 | * @image html e_big.png | ||
7 | * @author Vincent Torri | ||
8 | * @version 1.7.0 | ||
9 | * @date 2008-2012 | ||
10 | * | ||
11 | * @section intro_sec Introduction | ||
12 | * | ||
13 | * The Evil library is an evil library that ports some evil Unix | ||
14 | * functions to the Windows (XP or above, or Mobile) platform. The | ||
15 | * evilness is so huge that the most of the functions are not POSIX or | ||
16 | * BSD compliant. | ||
17 | * | ||
18 | * These functions are intended to be used in the Enlightenment | ||
19 | * Foundation Libraries only and can be compiled only on Windows, | ||
20 | * using MSYS/MinGW on Windows, and cross-compilation on Unix. This | ||
21 | * library is minimal in the sense that only the functions needed to | ||
22 | * compile the EFL are available. The purpose of this library is NOT | ||
23 | * to have a full POSIX emulation et it is NOT a replacement of | ||
24 | * cygwin. To compare the size of the DLL themselves, Evil is around | ||
25 | * 33 KB and cygwin DLL is around 800 KB. | ||
26 | * | ||
27 | * @section acknowledgments_sec Acknowledgments | ||
28 | * | ||
29 | * This library has receive some from people interested in the EFL or | ||
30 | * not. Among them, evil thanks to Lars Munch, Raoul Hecky, Nicolas | ||
31 | * Aguirre, Tor Lillqvist, Lance Fetters, Vincent Richomme, Paul | ||
32 | * Vixie, Daniel Stenberg, who helped the author of the library in | ||
33 | * different fields (code and tests). | ||
34 | * | ||
35 | * @section license_sec license | ||
36 | * | ||
37 | * The Evil library is distributes under a modified BSD license. See | ||
38 | * the files COPYING and COPYING-PLAIN in the top level directory for | ||
39 | * the full license text. | ||
40 | * | ||
41 | * @section reference_sec Reference API | ||
42 | * | ||
43 | * Use the horizontal menu above to navigate into the reference API | ||
44 | */ | ||
45 | |||
46 | /** | ||
47 | * @file Evil.h | ||
48 | * @brief The file that provides miscellaneous functions ported from Unix. | ||
49 | * @defgroup Evil Miscellaneous functions ported from Unix. | ||
50 | * | ||
51 | * This header provides miscellaneous functions that exist on Unix | ||
52 | * but not on Windows platform. They try to follow the conformance of | ||
53 | * the Unix versions. | ||
54 | */ | ||
55 | |||
56 | /** | ||
57 | * @cond LOCAL | ||
58 | */ | ||
59 | |||
60 | #ifdef __cplusplus | ||
61 | extern "C" { | ||
62 | #endif | ||
63 | |||
64 | |||
65 | #ifndef WIN32_LEAN_AND_MEAN | ||
66 | # define WIN32_LEAN_AND_MEAN | ||
67 | #endif | ||
68 | #include <windows.h> | ||
69 | #undef WIN32_LEAN_AND_MEAN | ||
70 | |||
71 | #include <stdlib.h> | ||
72 | #include <stdio.h> | ||
73 | #include <time.h> | ||
74 | #include <limits.h> | ||
75 | #include <sys/stat.h> | ||
76 | #include <fcntl.h> | ||
77 | #include <math.h> | ||
78 | #include <direct.h> | ||
79 | |||
80 | |||
81 | #ifdef _MSC_VER | ||
82 | |||
83 | # include <io.h> | ||
84 | |||
85 | # define F_OK 0 /* Check for file existence */ | ||
86 | # define X_OK 1 /* MS access() doesn't check for execute permission. */ | ||
87 | # define W_OK 2 /* Check for write permission */ | ||
88 | # define R_OK 4 /* Check for read permission */ | ||
89 | |||
90 | typedef DWORD pid_t; | ||
91 | typedef unsigned short mode_t; | ||
92 | |||
93 | typedef unsigned short uint16_t; | ||
94 | typedef unsigned int uint32_t; | ||
95 | typedef signed int int32_t; | ||
96 | typedef __int64 int64_t; | ||
97 | typedef unsigned __int64 uint64_t; | ||
98 | typedef SSIZE_T ssize_t; | ||
99 | |||
100 | # define strdup(s) _strdup(s) | ||
101 | # define unlink(filename) _unlink(filename) | ||
102 | # define fileno(f) _fileno(f) | ||
103 | # define fdopen(fd,m) _fdopen((fd),(m)) | ||
104 | # define access(p,m) _access((p),(m)) | ||
105 | # define hypot(x,y) _hypot((x),(y)) | ||
106 | # define tzset _tzset | ||
107 | |||
108 | #endif /* _MSC_VER */ | ||
109 | |||
110 | #ifdef _WIN32_WCE | ||
111 | # ifndef offsetof | ||
112 | # define offsetof(type, ident) ((size_t)&(((type*)0)->ident)) | ||
113 | # endif | ||
114 | #endif | ||
115 | |||
116 | typedef unsigned long uid_t; | ||
117 | typedef unsigned long gid_t; | ||
118 | |||
119 | |||
120 | #include "evil_macro.h" | ||
121 | #include "evil_fcntl.h" | ||
122 | #include "evil_inet.h" | ||
123 | #include "evil_langinfo.h" | ||
124 | #include "evil_libgen.h" | ||
125 | #include "evil_main.h" | ||
126 | #include "evil_print.h" | ||
127 | #include "evil_stdlib.h" | ||
128 | #include "evil_stdio.h" | ||
129 | #include "evil_string.h" | ||
130 | #include "evil_time.h" | ||
131 | #include "evil_unistd.h" | ||
132 | #include "evil_util.h" | ||
133 | #include "evil_macro_pop.h" | ||
134 | |||
135 | |||
136 | #if (defined(_WIN32) && !defined(_UWIN) && !defined(__CYGWIN__)) | ||
137 | # if defined(_MSC_VER) || defined(__MINGW32__) | ||
138 | |||
139 | # ifdef S_ISDIR | ||
140 | # undef S_ISDIR | ||
141 | # endif | ||
142 | # ifdef S_ISREG | ||
143 | # undef S_ISREG | ||
144 | # endif | ||
145 | # define S_ISDIR(m) (((m) & _S_IFMT) == _S_IFDIR) | ||
146 | # define S_ISREG(m) (((m) & _S_IFMT) == _S_IFREG) | ||
147 | |||
148 | # define S_ISLNK(m) 0 | ||
149 | |||
150 | # define S_IRUSR _S_IRUSR | ||
151 | # define S_IWUSR _S_IWUSR | ||
152 | # define S_IXUSR _S_IXUSR | ||
153 | # define S_IRGRP S_IRUSR | ||
154 | # define S_IROTH S_IRUSR | ||
155 | # define S_IWGRP S_IWUSR | ||
156 | # define S_IWOTH S_IWUSR | ||
157 | # define S_IXGRP S_IXUSR | ||
158 | # define S_IXOTH S_IXUSR | ||
159 | |||
160 | # define _S_IRWXU (_S_IREAD | _S_IWRITE | _S_IEXEC) | ||
161 | # define _S_IXUSR _S_IEXEC | ||
162 | # define _S_IWUSR _S_IWRITE | ||
163 | # define _S_IRUSR _S_IREAD | ||
164 | |||
165 | # define mkdir(p,m) _mkdir(p) | ||
166 | /* | ||
167 | # define close(fd) _close(fd) | ||
168 | # define read(fd,buffer,count) _read((fd),(buffer),(count)) | ||
169 | # define write(fd,buffer,count) _write((fd),(buffer),(count)) | ||
170 | # define unlink(filename) _unlink((filename)) | ||
171 | # define lstat(f,s) _stat((f),(s)) | ||
172 | */ | ||
173 | |||
174 | # endif | ||
175 | #endif | ||
176 | |||
177 | |||
178 | #ifdef __cplusplus | ||
179 | } | ||
180 | #endif | ||
181 | |||
182 | /** | ||
183 | * @endcond | ||
184 | */ | ||
185 | |||
186 | #endif /* __EVIL_H__ */ | ||
diff --git a/src/lib/evil/Makefile.am b/src/lib/evil/Makefile.am new file mode 100644 index 0000000000..62d0d56bf3 --- /dev/null +++ b/src/lib/evil/Makefile.am | |||
@@ -0,0 +1,132 @@ | |||
1 | |||
2 | MAINTAINERCLEANFILES = Makefile.in | ||
3 | |||
4 | lib_LTLIBRARIES = libevil.la libdl.la | ||
5 | |||
6 | install_evilheadersdir = $(includedir)/evil-@VMAJ@ | ||
7 | dist_install_evilheaders_DATA = \ | ||
8 | Evil.h \ | ||
9 | evil_fcntl.h \ | ||
10 | evil_inet.h \ | ||
11 | evil_langinfo.h \ | ||
12 | evil_libgen.h \ | ||
13 | evil_macro.h \ | ||
14 | evil_macro_pop.h \ | ||
15 | evil_main.h \ | ||
16 | evil_print.h \ | ||
17 | evil_stdlib.h \ | ||
18 | evil_stdio.h \ | ||
19 | evil_string.h \ | ||
20 | evil_time.h \ | ||
21 | evil_unistd.h \ | ||
22 | evil_util.h | ||
23 | |||
24 | stdheadersdir = $(includedir)/evil-@VMAJ@ | ||
25 | nobase_dist_stdheaders_DATA = pwd.h sys/mman.h fnmatch.h dirent.h dlfcn.h | ||
26 | |||
27 | if EVIL_HAVE_WINCE | ||
28 | |||
29 | nobase_dist_stdheaders_DATA += mingw32ce/errno.h | ||
30 | |||
31 | endif | ||
32 | |||
33 | # gdtoa | ||
34 | libevil_la_SOURCES = \ | ||
35 | gdtoa/arithchk.c \ | ||
36 | gdtoa/dmisc.c \ | ||
37 | gdtoa/dtoa.c \ | ||
38 | gdtoa/gd_arith.h \ | ||
39 | gdtoa/g_dfmt.c \ | ||
40 | gdtoa/gd_qnan.h \ | ||
41 | gdtoa/gdtoa.c \ | ||
42 | gdtoa/gdtoa_fltrnds.h \ | ||
43 | gdtoa/gdtoa.h \ | ||
44 | gdtoa/gdtoaimp.h \ | ||
45 | gdtoa/gethex.c \ | ||
46 | gdtoa/g_ffmt.c \ | ||
47 | gdtoa/g__fmt.c \ | ||
48 | gdtoa/gmisc.c \ | ||
49 | gdtoa/g_xfmt.c \ | ||
50 | gdtoa/hd_init.c \ | ||
51 | gdtoa/hexnan.c \ | ||
52 | gdtoa/misc.c \ | ||
53 | gdtoa/qnan.c \ | ||
54 | gdtoa/smisc.c \ | ||
55 | gdtoa/strtodg.c \ | ||
56 | gdtoa/strtof.c \ | ||
57 | gdtoa/strtopx.c \ | ||
58 | gdtoa/sum.c \ | ||
59 | gdtoa/ulp.c | ||
60 | |||
61 | #evil | ||
62 | libevil_la_SOURCES += \ | ||
63 | evil_dirent.c \ | ||
64 | evil_fcntl.c \ | ||
65 | evil_fnmatch.c \ | ||
66 | evil_fnmatch_list_of_states.c \ | ||
67 | evil_inet.c \ | ||
68 | evil_langinfo.c \ | ||
69 | evil_libgen.c \ | ||
70 | evil_main.c \ | ||
71 | evil_mman.c \ | ||
72 | evil_pformata.c \ | ||
73 | evil_pformatw.c \ | ||
74 | evil_printa.c \ | ||
75 | evil_printw.c \ | ||
76 | evil_pwd.c \ | ||
77 | evil_stdlib.c \ | ||
78 | evil_stdio.c \ | ||
79 | evil_string.c \ | ||
80 | evil_time.c \ | ||
81 | evil_unistd.c \ | ||
82 | evil_util.c \ | ||
83 | evil_uuid.c \ | ||
84 | evil_pformat.h \ | ||
85 | evil_private.h \ | ||
86 | evil_fnmatch_private.h | ||
87 | |||
88 | if EVIL_HAVE_WINCE | ||
89 | |||
90 | libevil_la_SOURCES += evil_errno.c evil_link_ce.c | ||
91 | |||
92 | else | ||
93 | |||
94 | libevil_la_SOURCES += evil_link_xp.cpp | ||
95 | |||
96 | endif | ||
97 | |||
98 | libevil_la_CPPFLAGS = @EVIL_CPPFLAGS@ | ||
99 | libevil_la_CFLAGS = @EVIL_CFLAGS@ | ||
100 | libevil_la_CXXFLAGS = @EVIL_CXXFLAGS@ | ||
101 | libevil_la_LIBADD = @EVIL_LIBS@ | ||
102 | libevil_la_LDFLAGS = -no-undefined -Wl,--enable-auto-import -version-info @version_info@ | ||
103 | |||
104 | if EVIL_HAVE_WINCE | ||
105 | |||
106 | libevil_la_LINK = $(LINK) $(libevil_la_LDFLAGS) | ||
107 | |||
108 | else | ||
109 | |||
110 | libevil_la_LINK = $(CXXLINK) $(libevil_la_LDFLAGS) | ||
111 | |||
112 | endif | ||
113 | |||
114 | libdl_la_SOURCES = dlfcn.c | ||
115 | |||
116 | libdl_la_CPPFLAGS = @EVIL_DLFCN_CPPFLAGS@ | ||
117 | libdl_la_CFLAGS = @EVIL_CFLAGS@ | ||
118 | libdl_la_LIBADD = $(top_builddir)/src/lib/libevil.la @EVIL_DLFCN_LIBS@ | ||
119 | libdl_la_LDFLAGS = -no-undefined -Wl,--enable-auto-import -version-info @version_info@ | ||
120 | |||
121 | EXTRA_DIST = gdtoa/README gdtoa/README.mingw | ||
122 | |||
123 | install-data-hook: | ||
124 | rm -f $(libdir)/libevil.la $(libdir)/libdl.la | ||
125 | |||
126 | uninstall-local: | ||
127 | rm -f $(DESTDIR)$(bindir)/libevil-@VMAJ@.dll | ||
128 | rm -f $(DESTDIR)$(bindir)/libdl-@VMAJ@.dll | ||
129 | rm -f $(DESTDIR)$(libdir)/libevil.dll.a | ||
130 | rm -f $(DESTDIR)$(libdir)/libevil.a | ||
131 | rm -f $(DESTDIR)$(libdir)/libdl.dll.a | ||
132 | rm -f $(DESTDIR)$(libdir)/libdl.a | ||
diff --git a/src/lib/evil/dirent.h b/src/lib/evil/dirent.h new file mode 100644 index 0000000000..3fe9d12866 --- /dev/null +++ b/src/lib/evil/dirent.h | |||
@@ -0,0 +1,141 @@ | |||
1 | #ifndef __EVIL_DIRENT_H__ | ||
2 | #define __EVIL_DIRENT_H__ | ||
3 | |||
4 | #ifdef EAPI | ||
5 | # undef EAPI | ||
6 | #endif /* EAPI */ | ||
7 | |||
8 | #ifdef _WIN32 | ||
9 | # ifdef EFL_EVIL_BUILD | ||
10 | # ifdef DLL_EXPORT | ||
11 | # define EAPI __declspec(dllexport) | ||
12 | # else | ||
13 | # define EAPI | ||
14 | # endif /* ! DLL_EXPORT */ | ||
15 | # else | ||
16 | # define EAPI __declspec(dllimport) | ||
17 | # endif /* ! EFL_EVIL_BUILD */ | ||
18 | #endif /* _WIN32 */ | ||
19 | |||
20 | |||
21 | /** | ||
22 | * @file dirent.h | ||
23 | * @brief The file that provides functions ported from Unix in dirent.h. | ||
24 | * @defgroup Evil_Dirent_Group Dirent.h functions | ||
25 | * | ||
26 | * This header provides functions ported from Unix in dirent.h. | ||
27 | * | ||
28 | * @{ | ||
29 | */ | ||
30 | |||
31 | |||
32 | #ifdef UNICODE | ||
33 | # include <wchar.h> | ||
34 | #endif | ||
35 | |||
36 | /** | ||
37 | * @def DT_UNKNOWN | ||
38 | * Specifies that the file type is unknown. | ||
39 | */ | ||
40 | #define DT_UNKNOWN 0 | ||
41 | |||
42 | /** | ||
43 | * @def DT_DIR | ||
44 | * Specifies that the file type is a directory. | ||
45 | */ | ||
46 | #define DT_DIR 4 | ||
47 | |||
48 | /** | ||
49 | * @typedef DIR | ||
50 | * @brief A structure that describes a directory stream. | ||
51 | */ | ||
52 | typedef struct DIR DIR; | ||
53 | |||
54 | /** | ||
55 | * @struct dirent | ||
56 | * @brief A structure that describes a directory stream. | ||
57 | */ | ||
58 | struct dirent | ||
59 | { | ||
60 | char d_name[260 + 1]; /**< The filename. */ | ||
61 | int d_mode; /**< The mode */ | ||
62 | unsigned char d_type; /**< The type */ | ||
63 | }; | ||
64 | |||
65 | |||
66 | #ifdef __cplusplus | ||
67 | extern "C" { | ||
68 | #endif /* __cplusplus */ | ||
69 | |||
70 | |||
71 | /** | ||
72 | * @brief Open the given directory. | ||
73 | * | ||
74 | * @param name The directory to open. | ||
75 | * @return A pointer to the directory stream. | ||
76 | * | ||
77 | * This function opens the directory @p name and return the directory | ||
78 | * stream. On error or if @p dir is NULL, -1 is returned, and errno is | ||
79 | * set appropriately (on Windows XP only). On success, 0 is returned. | ||
80 | * | ||
81 | * @see closedir() | ||
82 | * @see readdir() | ||
83 | * | ||
84 | * Conformity: None. | ||
85 | * | ||
86 | * Supported OS: Windows XP, CE. | ||
87 | */ | ||
88 | EAPI DIR *opendir(char const *name); | ||
89 | |||
90 | /** | ||
91 | * @brief Close the given directory. | ||
92 | * | ||
93 | * @param dir The directory stream to close. | ||
94 | * @return A pointer to the directory stream. | ||
95 | * | ||
96 | * This function closes the stream directory @p dir. On error or is | ||
97 | * @p path is NULL or an empty string, NULL is returned, and errno is set | ||
98 | * appropriately (on Windows XP only). | ||
99 | * | ||
100 | * @see opendir() | ||
101 | * @see readdir() | ||
102 | * | ||
103 | * Conformity: None. | ||
104 | * | ||
105 | * Supported OS: Windows XP, CE. | ||
106 | */ | ||
107 | EAPI int closedir(DIR *dir); | ||
108 | |||
109 | /** | ||
110 | * @brief Read the given directory. | ||
111 | * | ||
112 | * @param dir The directory stream to read. | ||
113 | * @return A pointer to a dirent structure, @c NULL oterhwise. | ||
114 | * | ||
115 | * This function returns a pointer to a dirent structure representing | ||
116 | * the next directory entry in the directory stream pointed to by | ||
117 | * @p dir. It returns NULL on reaching the end of the directory stream | ||
118 | * or if an error occurred and errno is set appropriately (on Windows XP only). | ||
119 | * | ||
120 | * @see opendir() | ||
121 | * @see readdir() | ||
122 | * | ||
123 | * Conformity: None. | ||
124 | * | ||
125 | * Supported OS: Windows XP, CE. | ||
126 | */ | ||
127 | EAPI struct dirent *readdir(DIR *dir); | ||
128 | |||
129 | |||
130 | #ifdef __cplusplus | ||
131 | } | ||
132 | #endif /* __cplusplus */ | ||
133 | |||
134 | |||
135 | |||
136 | /** | ||
137 | * @} | ||
138 | */ | ||
139 | |||
140 | |||
141 | #endif /* __EVIL_DIRENT_H__ */ | ||
diff --git a/src/lib/evil/dlfcn.c b/src/lib/evil/dlfcn.c new file mode 100644 index 0000000000..818cabf014 --- /dev/null +++ b/src/lib/evil/dlfcn.c | |||
@@ -0,0 +1,272 @@ | |||
1 | #ifdef HAVE_CONFIG_H | ||
2 | # include "config.h" | ||
3 | #endif /* HAVE_CONFIG_H */ | ||
4 | |||
5 | #include <stdlib.h> | ||
6 | |||
7 | #if defined(__MINGW32CE__) || defined(_MSC_VER) | ||
8 | # include <limits.h> | ||
9 | #endif /* __MINGW32CE__ || _MSC_VER */ | ||
10 | |||
11 | #ifndef WIN32_LEAN_AND_MEAN | ||
12 | # define WIN32_LEAN_AND_MEAN | ||
13 | #endif | ||
14 | #include <windows.h> | ||
15 | #undef WIN32_LEAN_AND_MEAN | ||
16 | |||
17 | #ifdef _WIN32_WCE | ||
18 | # include <tlhelp32.h> /* CreateToolhelp32Snapshot */ | ||
19 | #else | ||
20 | # include <psapi.h> /* EnumProcessModules(Ex) */ | ||
21 | #endif | ||
22 | |||
23 | #include "Evil.h" | ||
24 | |||
25 | #include "dlfcn.h" | ||
26 | |||
27 | |||
28 | static char *dl_err = NULL; | ||
29 | static int dl_err_viewed = 0; | ||
30 | |||
31 | static void | ||
32 | get_last_error(char *desc) | ||
33 | { | ||
34 | char *str; | ||
35 | size_t l1; | ||
36 | size_t l2; | ||
37 | |||
38 | str = evil_last_error_get(); | ||
39 | |||
40 | l1 = strlen(desc); | ||
41 | l2 = strlen(str); | ||
42 | |||
43 | if (dl_err) | ||
44 | free(dl_err); | ||
45 | |||
46 | dl_err = (char *)malloc(sizeof(char) * (l1 + l2 + 1)); | ||
47 | if (!dl_err) | ||
48 | dl_err = strdup("not enough resource"); | ||
49 | else | ||
50 | { | ||
51 | memcpy(dl_err, desc, l1); | ||
52 | memcpy(dl_err + l1, str, l2); | ||
53 | dl_err[l1 + l2] = '\0'; | ||
54 | } | ||
55 | free(str); | ||
56 | dl_err_viewed = 0; | ||
57 | } | ||
58 | |||
59 | void * | ||
60 | dlopen(const char* path, int mode __UNUSED__) | ||
61 | { | ||
62 | HMODULE module = NULL; | ||
63 | |||
64 | if (!path) | ||
65 | { | ||
66 | module = GetModuleHandle(NULL); | ||
67 | if (!module) | ||
68 | get_last_error("GetModuleHandle returned: "); | ||
69 | } | ||
70 | else | ||
71 | { | ||
72 | char *new_path; | ||
73 | size_t l; | ||
74 | unsigned int i; | ||
75 | |||
76 | /* according to MSDN, we must change the slash to backslash */ | ||
77 | l = strlen(path); | ||
78 | new_path = (char *)malloc(sizeof(char) * (l + 1)); | ||
79 | if (!new_path) | ||
80 | { | ||
81 | if (dl_err) | ||
82 | free(dl_err); | ||
83 | dl_err = strdup("not enough resource"); | ||
84 | dl_err_viewed = 0; | ||
85 | return NULL; | ||
86 | } | ||
87 | for (i = 0; i <= l; i++) | ||
88 | { | ||
89 | if (path[i] == '/') | ||
90 | new_path[i] = '\\'; | ||
91 | else | ||
92 | new_path[i] = path[i]; | ||
93 | } | ||
94 | #ifdef UNICODE | ||
95 | { | ||
96 | wchar_t *wpath; | ||
97 | |||
98 | wpath = evil_char_to_wchar(new_path); | ||
99 | module = LoadLibrary(wpath); | ||
100 | free(wpath); | ||
101 | } | ||
102 | #else | ||
103 | module = LoadLibraryEx(new_path, NULL, | ||
104 | LOAD_WITH_ALTERED_SEARCH_PATH); | ||
105 | #endif /* ! UNICODE */ | ||
106 | if (!module) | ||
107 | get_last_error("LoadLibraryEx returned: "); | ||
108 | |||
109 | free(new_path); | ||
110 | } | ||
111 | |||
112 | return module; | ||
113 | } | ||
114 | |||
115 | int | ||
116 | dlclose(void* handle) | ||
117 | { | ||
118 | if (FreeLibrary(handle)) | ||
119 | return 0; | ||
120 | else | ||
121 | { | ||
122 | get_last_error("FreeLibrary returned: "); | ||
123 | return -1; | ||
124 | } | ||
125 | } | ||
126 | |||
127 | void * | ||
128 | dlsym(void *handle, const char *symbol) | ||
129 | { | ||
130 | FARPROC fp = NULL; | ||
131 | LPCTSTR new_symbol; | ||
132 | |||
133 | if (!symbol || !*symbol) return NULL; | ||
134 | |||
135 | #ifdef UNICODE | ||
136 | new_symbol = evil_char_to_wchar(symbol); | ||
137 | #else | ||
138 | new_symbol = symbol; | ||
139 | #endif /* UNICODE */ | ||
140 | |||
141 | if (handle == RTLD_DEFAULT) | ||
142 | { | ||
143 | #ifdef _WIN32_WCE | ||
144 | HANDLE snapshot; | ||
145 | MODULEENTRY32 module; | ||
146 | |||
147 | snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS | | ||
148 | TH32CS_SNAPMODULE | | ||
149 | TH32CS_GETALLMODS, | ||
150 | 0); | ||
151 | if (!snapshot) | ||
152 | return NULL; | ||
153 | |||
154 | module.dwSize = sizeof(module); | ||
155 | if (Module32First(snapshot, &module)) | ||
156 | do { | ||
157 | fp = GetProcAddress(module.hModule, new_symbol); | ||
158 | if (fp) break; | ||
159 | } while (Module32Next(snapshot, &module)); | ||
160 | |||
161 | CloseToolhelp32Snapshot(snapshot); | ||
162 | #else | ||
163 | HMODULE modules[1024]; | ||
164 | DWORD needed; | ||
165 | DWORD i; | ||
166 | |||
167 | /* TODO: use EnumProcessModulesEx() on Windows >= Vista */ | ||
168 | if (!EnumProcessModules(GetCurrentProcess(), | ||
169 | modules, sizeof(modules), &needed)) | ||
170 | return NULL; | ||
171 | |||
172 | for (i = 0; i < (needed / sizeof(HMODULE)); i++) | ||
173 | { | ||
174 | fp = GetProcAddress(modules[i], new_symbol); | ||
175 | if (fp) break; | ||
176 | } | ||
177 | #endif | ||
178 | } | ||
179 | else | ||
180 | fp = GetProcAddress(handle, new_symbol); | ||
181 | |||
182 | #ifdef UNICODE | ||
183 | free((void *)new_symbol); | ||
184 | #endif /* UNICODE */ | ||
185 | |||
186 | if (!fp) | ||
187 | get_last_error("GetProcAddress returned: "); | ||
188 | |||
189 | return fp; | ||
190 | } | ||
191 | |||
192 | int | ||
193 | dladdr (const void *addr __UNUSED__, Dl_info *info) | ||
194 | { | ||
195 | TCHAR tpath[PATH_MAX]; | ||
196 | MEMORY_BASIC_INFORMATION mbi; | ||
197 | char *path; | ||
198 | char *tmp; | ||
199 | size_t length; | ||
200 | int ret = 0; | ||
201 | |||
202 | if (!info) | ||
203 | return 0; | ||
204 | |||
205 | #ifdef _WIN32_WINNT | ||
206 | length = VirtualQuery(addr, &mbi, sizeof(mbi)); | ||
207 | if (!length) | ||
208 | return 0; | ||
209 | |||
210 | if (mbi.State != MEM_COMMIT) | ||
211 | return 0; | ||
212 | |||
213 | if (!mbi.AllocationBase) | ||
214 | return 0; | ||
215 | |||
216 | ret = GetModuleFileName((HMODULE)mbi.AllocationBase, (LPTSTR)&tpath, PATH_MAX); | ||
217 | if (!ret) | ||
218 | return 0; | ||
219 | #else | ||
220 | ret = GetModuleFileName(NULL, (LPTSTR)&tpath, PATH_MAX); | ||
221 | if (!ret) | ||
222 | return 0; | ||
223 | #endif | ||
224 | |||
225 | #ifdef UNICODE | ||
226 | path = evil_wchar_to_char(tpath); | ||
227 | #else | ||
228 | path = tpath; | ||
229 | #endif /* ! UNICODE */ | ||
230 | |||
231 | length = strlen (path); | ||
232 | if (length >= PATH_MAX) | ||
233 | { | ||
234 | length = PATH_MAX - 1; | ||
235 | path[PATH_MAX - 1] = '\0'; | ||
236 | } | ||
237 | |||
238 | /* replace '/' by '\' */ | ||
239 | tmp = path; | ||
240 | while (*tmp) | ||
241 | { | ||
242 | if (*tmp == '/') *tmp = '\\'; | ||
243 | tmp++; | ||
244 | } | ||
245 | |||
246 | memcpy (info->dli_fname, path, length + 1); | ||
247 | info->dli_fbase = NULL; | ||
248 | info->dli_sname = NULL; | ||
249 | info->dli_saddr = NULL; | ||
250 | |||
251 | #ifdef UNICODE | ||
252 | free (path); | ||
253 | #endif /* ! UNICODE */ | ||
254 | |||
255 | return 1; | ||
256 | } | ||
257 | |||
258 | char * | ||
259 | dlerror (void) | ||
260 | { | ||
261 | if (!dl_err_viewed) | ||
262 | { | ||
263 | dl_err_viewed = 1; | ||
264 | return dl_err; | ||
265 | } | ||
266 | else | ||
267 | { | ||
268 | if (dl_err) | ||
269 | free(dl_err); | ||
270 | return NULL; | ||
271 | } | ||
272 | } | ||
diff --git a/src/lib/evil/dlfcn.h b/src/lib/evil/dlfcn.h new file mode 100644 index 0000000000..610331b702 --- /dev/null +++ b/src/lib/evil/dlfcn.h | |||
@@ -0,0 +1,258 @@ | |||
1 | #ifndef __EVIL_DLFCN_H__ | ||
2 | #define __EVIL_DLFCN_H__ | ||
3 | |||
4 | |||
5 | #include <limits.h> | ||
6 | |||
7 | |||
8 | #ifdef EAPI | ||
9 | # undef EAPI | ||
10 | #endif /* EAPI */ | ||
11 | |||
12 | #ifdef _WIN32 | ||
13 | # ifdef EFL_EVIL_DLFCN_BUILD | ||
14 | # ifdef DLL_EXPORT | ||
15 | # define EAPI __declspec(dllexport) | ||
16 | # else | ||
17 | # define EAPI | ||
18 | # endif /* ! DLL_EXPORT */ | ||
19 | # else | ||
20 | # define EAPI __declspec(dllimport) | ||
21 | # endif /* ! EFL_EVIL_DLFCN_BUILD */ | ||
22 | #endif /* _WIN32 */ | ||
23 | |||
24 | |||
25 | #ifdef __cplusplus | ||
26 | extern "C" { | ||
27 | #endif | ||
28 | |||
29 | #ifdef _WIN32_WCE | ||
30 | # ifndef PATH_MAX | ||
31 | # define PATH_MAX 260 | ||
32 | # endif | ||
33 | #endif | ||
34 | |||
35 | |||
36 | /** | ||
37 | * @file dlfcn.h | ||
38 | * @brief The file that provides functions to manage dynamic-link libraries | ||
39 | * @defgroup Dlfcn Functions that manage dynamic-link libraries. | ||
40 | * | ||
41 | * This header provides functions to load and unload dynamic-link | ||
42 | * libaries, to get the address of a symbol, and to get diagnostic | ||
43 | * information. | ||
44 | */ | ||
45 | |||
46 | |||
47 | /** | ||
48 | * @def RTLD_LAZY | ||
49 | * Lazy function call binding. | ||
50 | */ | ||
51 | # define RTLD_LAZY 0x00001 /* lazy function call binding */ | ||
52 | |||
53 | /** | ||
54 | * @def RTLD_NOW | ||
55 | * Immediate function call binding. | ||
56 | */ | ||
57 | # define RTLD_NOW 0x00002 /* immediate function call binding */ | ||
58 | |||
59 | /** | ||
60 | * @def RTLD_GLOBAL | ||
61 | * Symbols in this dlopen'ed obj are visible to other dlopen'ed objs. | ||
62 | */ | ||
63 | # define RTLD_GLOBAL 0x00100 /* symbols in this dlopen'ed obj are visible | ||
64 | to other dlopen'ed objs */ | ||
65 | |||
66 | /** | ||
67 | * @def RTLD_NODELETE | ||
68 | * Symbols are not deleted when closed. | ||
69 | */ | ||
70 | #define RTLD_NODELETE 0x01000 /* do not delete object when closed. */ | ||
71 | |||
72 | /** | ||
73 | * @def RTLD_DEFAULT | ||
74 | * Symbols are searched in all the DLL opened by the current process. | ||
75 | */ | ||
76 | #define RTLD_DEFAULT ((void*)1) /* search the symbol on all the DLL of the current process */ | ||
77 | |||
78 | /** | ||
79 | * @typedef Dl_info | ||
80 | * @brief A structure that stores infomation of a calling process. | ||
81 | */ | ||
82 | typedef struct Dl_info Dl_info; | ||
83 | |||
84 | /** | ||
85 | * @struct Dl_info | ||
86 | * @brief A structure that stores infomation of a calling process. | ||
87 | */ | ||
88 | struct Dl_info | ||
89 | { | ||
90 | char dli_fname[PATH_MAX]; /**< Filename of defining object */ | ||
91 | void *dli_fbase; /**< Load address of that object */ | ||
92 | const char *dli_sname; /**< Name of nearest lower symbol */ | ||
93 | void *dli_saddr; /**< Exact value of nearest symbol */ | ||
94 | }; | ||
95 | |||
96 | /** | ||
97 | * @brief Map a specified executable module (either a .dll or .exe file) | ||
98 | * into the address space of the user process. | ||
99 | * | ||
100 | * @param path Name of the module. | ||
101 | * @param mode Unused. | ||
102 | * @return A pointer that represent the module, or @c NULL on failure. | ||
103 | * | ||
104 | * Map a specified executable module (either a .dll or .exe file) | ||
105 | * into the address space of the user process. If @p path is @c NULL, | ||
106 | * then the module corresponding to the current process is returned. | ||
107 | * Otherwise the module specified by @p path is loaded if it exists. | ||
108 | * If not, @c NULL is returned. The directory separators can be forward | ||
109 | * slash, or backward ones. Mapping a module can map other modules. | ||
110 | * @p mode is unused. | ||
111 | * | ||
112 | * If an error occurred, an error string can be retrived with dlerror(). | ||
113 | * | ||
114 | * According to the OS, the search order of the module can change, | ||
115 | * according to the value of SafeDllSearchMode. | ||
116 | * | ||
117 | * - For Windows Vista, Windows Server 2003, and Windows XP SP2: | ||
118 | * SafeDLLSearchMode is enabled by default. | ||
119 | * - For Windows XP and Windows 2000 SP4: SafeDLLSearchMode is disabled | ||
120 | * by default. | ||
121 | * | ||
122 | * If SafeDllSearchMode is enabled | ||
123 | * - The directory from which the application loaded. | ||
124 | * - The system directory. Use the GetSystemDirectory() function | ||
125 | * to get the path of this directory. | ||
126 | * - The 16-bit system directory. There is no function that obtains | ||
127 | * the path of this directory, but it is searched. | ||
128 | * - The Windows directory. Use the GetWindowsDirectory() function | ||
129 | * to get the path of this directory. | ||
130 | * - The current directory. | ||
131 | * - The directories that are listed in the PATH environment variable. | ||
132 | * Note that this does not include the per-application path specified | ||
133 | * by the App Paths registry key. | ||
134 | * | ||
135 | * If SafeDllSearchMode is disabled | ||
136 | * - The directory from which the application loaded. | ||
137 | * - The current directory. | ||
138 | * - The system directory. Use the GetSystemDirectory() function | ||
139 | * to get the path of this directory. | ||
140 | * - The 16-bit system directory. There is no function that obtains | ||
141 | * the path of this directory, but it is searched. | ||
142 | * - The Windows directory. Use the GetWindowsDirectory() function | ||
143 | * to get the path of this directory. | ||
144 | * - The directories that are listed in the PATH environment variable. | ||
145 | * Note that this does not include the per-application path specified | ||
146 | * by the App Paths registry key. | ||
147 | * | ||
148 | * Conformity: None. | ||
149 | * | ||
150 | * Supported OS: Windows Vista, Windows XP or Windows 2000 | ||
151 | * Professional. | ||
152 | * | ||
153 | * @ingroup Dlfcn | ||
154 | */ | ||
155 | EAPI void *dlopen(const char* path, int mode); | ||
156 | |||
157 | /** | ||
158 | * @brief Close a dynamic-link library. | ||
159 | * | ||
160 | * @param handle Handle that references a dynamic-link library. | ||
161 | * @return O on sucess, -1 otherwise. | ||
162 | * | ||
163 | * Release a reference to the dynamic-link library referenced | ||
164 | * by @p handle. If the reference count drops to 0, the handle is | ||
165 | * removed from the address space and is rendered invalid. @p handle | ||
166 | * is the value returned by a previous call to dlopen(). | ||
167 | * | ||
168 | * If no error occurred, the returned value is 0, otherwise the | ||
169 | * returned value is -1 and an error string can be retrived with | ||
170 | * dlerror(). | ||
171 | * | ||
172 | * Conformity: None. | ||
173 | * | ||
174 | * Supported OS: Windows Vista, Windows XP or Windows 2000 | ||
175 | * Professional. | ||
176 | * | ||
177 | * @ingroup Dlfcn | ||
178 | */ | ||
179 | EAPI int dlclose(void* handle); | ||
180 | |||
181 | /** | ||
182 | * @brief Get the address of a symbol. | ||
183 | * | ||
184 | * @param handle Handle that references a dynamic-link library. | ||
185 | * @param symbol @c NULL-terminated string. | ||
186 | * @return O on sucess, NULL otherwise. | ||
187 | * | ||
188 | * Return the address of the code or data location specified by the | ||
189 | * string @p symbol. @p handle references a library that contains | ||
190 | * the function or variable @p symbol. | ||
191 | * | ||
192 | * If no error occurred, the returned value is the code or data | ||
193 | * location, otherwise the returned value is NULL and an error | ||
194 | * string can be retrived with dlerror(). | ||
195 | * | ||
196 | * Conformity: None. | ||
197 | * | ||
198 | * Supported OS: Windows Vista, Windows XP or Windows 2000 | ||
199 | * Professional. | ||
200 | * | ||
201 | * @ingroup Dlfcn | ||
202 | */ | ||
203 | EAPI void *dlsym(void* handle, const char* symbol); | ||
204 | |||
205 | /** | ||
206 | * @brief Get the location of the current process (.exe) | ||
207 | * | ||
208 | * @param addr Unused. | ||
209 | * @param info Pointer to the Dl_info to fill. | ||
210 | * @return 1 on success, 0 otherwise. | ||
211 | * | ||
212 | * Fill the dli_fname member of @p info with the absolute name | ||
213 | * of the current calling process (.exe file that is executed). | ||
214 | * All other members are set to @c NULL. | ||
215 | * | ||
216 | * Contrary to the unix function, the full name of the shared | ||
217 | * library is not returned, but insted the full name of the current | ||
218 | * calling process (.exe file). | ||
219 | * | ||
220 | * Conformity: None. | ||
221 | * | ||
222 | * Supported OS: Windows Vista, Windows XP or Windows 2000 | ||
223 | * Professional. | ||
224 | * | ||
225 | * @ingroup Dlfcn | ||
226 | */ | ||
227 | EAPI int dladdr (const void *addr, Dl_info *info); | ||
228 | |||
229 | /** | ||
230 | * @brief Get diagnostic information | ||
231 | * | ||
232 | * @return A @c NULL-terminated string if an error occured, @c NULL | ||
233 | * otherwise. | ||
234 | * | ||
235 | * Return a @c NULL-terminated character string describing the last | ||
236 | * error that occurred on this thread during a call to dlopen(), | ||
237 | * dlsym(), or dlclose(). If no such error has occurred, dlerror() | ||
238 | * returns a null pointer. At each call to dlerror(), the error | ||
239 | * indication is reset. Thus in the case of two calls to dlerror(), | ||
240 | * where the second call follows the first immediately, the second | ||
241 | * call will always return a null pointer. | ||
242 | * | ||
243 | * Conformity: None. | ||
244 | * | ||
245 | * Supported OS: Windows Vista, Windows XP or Windows 2000 | ||
246 | * Professional. | ||
247 | * | ||
248 | * @ingroup Dlfcn | ||
249 | */ | ||
250 | EAPI char *dlerror (void); | ||
251 | |||
252 | |||
253 | #ifdef __cplusplus | ||
254 | } | ||
255 | #endif | ||
256 | |||
257 | |||
258 | #endif /* __EVIL_DLFCN_H__ */ | ||
diff --git a/src/lib/evil/evil_dirent.c b/src/lib/evil/evil_dirent.c new file mode 100644 index 0000000000..e02b95fe27 --- /dev/null +++ b/src/lib/evil/evil_dirent.c | |||
@@ -0,0 +1,197 @@ | |||
1 | #ifdef HAVE_CONFIG_H | ||
2 | # include "config.h" | ||
3 | #endif /* HAVE_CONFIG_H */ | ||
4 | |||
5 | #include <dirent.h> | ||
6 | |||
7 | #ifdef HAVE_ERRNO_H | ||
8 | # include <errno.h> | ||
9 | #endif | ||
10 | |||
11 | #include "Evil.h" | ||
12 | |||
13 | |||
14 | struct DIR | ||
15 | { | ||
16 | struct dirent dirent; | ||
17 | WIN32_FIND_DATA data; | ||
18 | HANDLE handle; | ||
19 | }; | ||
20 | |||
21 | |||
22 | DIR *opendir(char const *name) | ||
23 | { | ||
24 | DIR *dir; | ||
25 | char *tmp1; | ||
26 | char *tmp2; | ||
27 | DWORD attr; | ||
28 | size_t l; | ||
29 | #ifdef UNICODE | ||
30 | wchar_t *wname; | ||
31 | char *d_name; | ||
32 | #endif | ||
33 | |||
34 | /* valid name */ | ||
35 | if (!name || !*name) | ||
36 | { | ||
37 | #ifdef HAVE_ERRNO_H | ||
38 | errno = ENOENT; | ||
39 | #endif | ||
40 | return NULL; | ||
41 | } | ||
42 | |||
43 | #ifdef UNICODE | ||
44 | wname = evil_char_to_wchar(name); | ||
45 | if (!wname) | ||
46 | { | ||
47 | # ifdef HAVE_ERRNO_H | ||
48 | errno = ENOMEM; | ||
49 | # endif | ||
50 | return NULL; | ||
51 | } | ||
52 | |||
53 | if((attr = GetFileAttributes(wname)) == 0xFFFFFFFF) | ||
54 | #else | ||
55 | if((attr = GetFileAttributes(name)) == 0xFFFFFFFF) | ||
56 | #endif | ||
57 | { | ||
58 | #ifdef HAVE_ERRNO_H | ||
59 | errno = ENOENT; | ||
60 | #endif | ||
61 | return NULL; | ||
62 | } | ||
63 | |||
64 | #ifdef UNICODE | ||
65 | free(wname); | ||
66 | #endif | ||
67 | |||
68 | /* directory */ | ||
69 | if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) | ||
70 | { | ||
71 | #ifdef HAVE_ERRNO_H | ||
72 | errno = ENOTDIR; | ||
73 | #endif | ||
74 | return NULL; | ||
75 | } | ||
76 | |||
77 | dir = (DIR *)malloc(sizeof(DIR)); | ||
78 | if (!dir) | ||
79 | { | ||
80 | #ifdef HAVE_ERRNO_H | ||
81 | errno = ENOMEM; | ||
82 | #endif | ||
83 | return NULL; | ||
84 | } | ||
85 | |||
86 | l = strlen(name); | ||
87 | tmp1 = (char *)malloc(sizeof(char) * l + 5); | ||
88 | if (!tmp1) | ||
89 | { | ||
90 | #ifdef HAVE_ERRNO_H | ||
91 | errno = ENOMEM; | ||
92 | #endif | ||
93 | return NULL; | ||
94 | } | ||
95 | |||
96 | memcpy(tmp1, name, l); | ||
97 | memcpy(tmp1 + l, "\\*.*", 5); | ||
98 | |||
99 | tmp2 = tmp1; | ||
100 | while (*tmp2) | ||
101 | { | ||
102 | if (*tmp2 == '/') *tmp2 = '\\'; | ||
103 | tmp2++; | ||
104 | } | ||
105 | |||
106 | #ifdef UNICODE | ||
107 | wname = evil_char_to_wchar(tmp1); | ||
108 | if (!wname) | ||
109 | { | ||
110 | #ifdef HAVE_ERRNO_H | ||
111 | errno = ENOMEM; | ||
112 | #endif | ||
113 | free(tmp1); | ||
114 | |||
115 | return NULL; | ||
116 | } | ||
117 | dir->handle = FindFirstFile(wname, &dir->data); | ||
118 | free(wname); | ||
119 | #else | ||
120 | dir->handle = FindFirstFile(tmp1, &dir->data); | ||
121 | #endif | ||
122 | |||
123 | free(tmp1); | ||
124 | |||
125 | if (dir->handle == INVALID_HANDLE_VALUE) | ||
126 | { | ||
127 | free(dir); | ||
128 | return NULL; | ||
129 | } | ||
130 | |||
131 | #ifdef UNICODE | ||
132 | d_name = evil_wchar_to_char(dir->data.cFileName); | ||
133 | strcpy(dir->dirent.d_name, d_name); | ||
134 | free(d_name); | ||
135 | #else | ||
136 | strcpy(dir->dirent.d_name, dir->data.cFileName); | ||
137 | #endif | ||
138 | dir->dirent.d_mode = (int)dir->data.dwFileAttributes; | ||
139 | |||
140 | if (dir->data.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY) | ||
141 | dir->dirent.d_type = DT_DIR; | ||
142 | else | ||
143 | dir->dirent.d_type = DT_UNKNOWN; | ||
144 | |||
145 | return dir; | ||
146 | } | ||
147 | |||
148 | int closedir(DIR *dir) | ||
149 | { | ||
150 | if (!dir) | ||
151 | { | ||
152 | #ifdef HAVE_ERRNO_H | ||
153 | errno = EBADF; | ||
154 | #endif | ||
155 | return -1; | ||
156 | } | ||
157 | |||
158 | if (dir->handle != INVALID_HANDLE_VALUE) | ||
159 | FindClose(dir->handle); | ||
160 | free(dir); | ||
161 | |||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | struct dirent *readdir(DIR *dir) | ||
166 | { | ||
167 | #ifdef UNICODE | ||
168 | char *d_name; | ||
169 | #endif | ||
170 | |||
171 | if (!dir) | ||
172 | { | ||
173 | #ifdef HAVE_ERRNO_H | ||
174 | errno = EBADF; | ||
175 | #endif | ||
176 | return NULL; | ||
177 | } | ||
178 | |||
179 | if (dir->handle == INVALID_HANDLE_VALUE) | ||
180 | return NULL; | ||
181 | |||
182 | #ifdef UNICODE | ||
183 | d_name = evil_wchar_to_char(dir->data.cFileName); | ||
184 | strcpy(dir->dirent.d_name, d_name); | ||
185 | free(d_name); | ||
186 | #else | ||
187 | strcpy(dir->dirent.d_name, dir->data.cFileName); | ||
188 | #endif | ||
189 | |||
190 | if (!FindNextFile(dir->handle, &dir->data)) | ||
191 | { | ||
192 | FindClose(dir->handle); | ||
193 | dir->handle = INVALID_HANDLE_VALUE; | ||
194 | } | ||
195 | |||
196 | return &dir->dirent; | ||
197 | } | ||
diff --git a/src/lib/evil/evil_errno.c b/src/lib/evil/evil_errno.c new file mode 100644 index 0000000000..37cac611f0 --- /dev/null +++ b/src/lib/evil/evil_errno.c | |||
@@ -0,0 +1,9 @@ | |||
1 | #ifdef HAVE_CONFIG_H | ||
2 | # include <config.h> | ||
3 | #endif | ||
4 | |||
5 | #include "Evil.h" | ||
6 | #include "mingw32ce/errno.h" | ||
7 | |||
8 | |||
9 | int errno = 0; | ||
diff --git a/src/lib/evil/evil_fcntl.c b/src/lib/evil/evil_fcntl.c new file mode 100644 index 0000000000..7c62c2a310 --- /dev/null +++ b/src/lib/evil/evil_fcntl.c | |||
@@ -0,0 +1,124 @@ | |||
1 | #ifdef HAVE_CONFIG_H | ||
2 | # include "config.h" | ||
3 | #endif /* HAVE_CONFIG_H */ | ||
4 | |||
5 | #include <stdio.h> | ||
6 | |||
7 | #ifdef _MSC_VER | ||
8 | # include <io.h> /* for _get_osfhandle _lseek and _locking */ | ||
9 | #endif | ||
10 | |||
11 | #include <sys/locking.h> | ||
12 | |||
13 | #include <winsock2.h> /* for ioctlsocket */ | ||
14 | |||
15 | #include "Evil.h" | ||
16 | |||
17 | |||
18 | #ifdef __MINGW32CE__ | ||
19 | # define _get_osfhandle(FILEDES) ((HANDLE)FILEDES) | ||
20 | #endif /* __MINGW32CE__ */ | ||
21 | |||
22 | |||
23 | /* | ||
24 | * port of fcntl function | ||
25 | * | ||
26 | */ | ||
27 | |||
28 | int fcntl(int fd, int cmd, ...) | ||
29 | { | ||
30 | va_list va; | ||
31 | HANDLE h; | ||
32 | int res = -1; | ||
33 | |||
34 | va_start (va, cmd); | ||
35 | |||
36 | h = (HANDLE)_get_osfhandle(fd); | ||
37 | if (h == INVALID_HANDLE_VALUE) | ||
38 | return -1; | ||
39 | |||
40 | if (cmd == F_GETFD) | ||
41 | { | ||
42 | #ifndef __MINGW32CE__ | ||
43 | DWORD flag; | ||
44 | |||
45 | if (!GetHandleInformation(h, &flag)) | ||
46 | return -1; | ||
47 | |||
48 | res = 0; | ||
49 | #endif /* ! __MINGW32CE__ */ | ||
50 | } | ||
51 | |||
52 | if (cmd == F_SETFD) | ||
53 | { | ||
54 | long flag; | ||
55 | |||
56 | flag = va_arg(va, long); | ||
57 | if (flag == FD_CLOEXEC) | ||
58 | { | ||
59 | #ifndef __MINGW32CE__ | ||
60 | if (SetHandleInformation(h, HANDLE_FLAG_INHERIT, 0)) | ||
61 | res = 0; | ||
62 | #endif /* ! __MINGW32CE__ */ | ||
63 | } | ||
64 | } | ||
65 | else if (cmd == F_SETFL) | ||
66 | { | ||
67 | long flag; | ||
68 | |||
69 | flag = va_arg(va, long); | ||
70 | if (flag == O_NONBLOCK) | ||
71 | { | ||
72 | u_long arg = 1; | ||
73 | int type; | ||
74 | int len; | ||
75 | int ret; | ||
76 | |||
77 | len = (int)sizeof(int); | ||
78 | ret = getsockopt((SOCKET)fd, SOL_SOCKET, SO_TYPE, (char *)&type, &len); | ||
79 | if (!ret && (type == SOCK_STREAM)) | ||
80 | { | ||
81 | if (!ioctlsocket((SOCKET)fd, FIONBIO, &arg) == SOCKET_ERROR) | ||
82 | res = 0; | ||
83 | } | ||
84 | } | ||
85 | } | ||
86 | #ifndef __MINGW32CE__ | ||
87 | else if ((cmd == F_SETLK) || (cmd == F_SETLKW)) | ||
88 | { | ||
89 | struct flock *fl; | ||
90 | off_t length = 0; | ||
91 | long pos; | ||
92 | |||
93 | fl = va_arg(va, struct flock *); | ||
94 | |||
95 | if (fl->l_len == 0) | ||
96 | { | ||
97 | length = _lseek(fd, 0L, SEEK_END); | ||
98 | if (length != -1L) | ||
99 | res = 0; | ||
100 | } | ||
101 | fl->l_len = length - fl->l_start - 1; | ||
102 | |||
103 | pos = _lseek(fd, fl->l_start, fl->l_whence); | ||
104 | if (pos != -1L) | ||
105 | res = 0; | ||
106 | |||
107 | if ((fl->l_type == F_RDLCK) || (fl->l_type == F_WRLCK)) | ||
108 | { | ||
109 | if (cmd == F_SETLK) | ||
110 | res = _locking(fd, _LK_NBLCK, fl->l_len); /* if cannot be locked, we return immediatly */ | ||
111 | else /* F_SETLKW */ | ||
112 | res = _locking(fd, _LK_LOCK, fl->l_len); /* otherwise, we try several times */ | ||
113 | } | ||
114 | |||
115 | if (fl->l_type == F_UNLCK) | ||
116 | res = _locking(fd, _LK_UNLCK, fl->l_len); | ||
117 | } | ||
118 | |||
119 | #endif /* ! __MINGW32CE__ */ | ||
120 | |||
121 | va_end(va); | ||
122 | |||
123 | return res; | ||
124 | } | ||
diff --git a/src/lib/evil/evil_fcntl.h b/src/lib/evil/evil_fcntl.h new file mode 100644 index 0000000000..194341b369 --- /dev/null +++ b/src/lib/evil/evil_fcntl.h | |||
@@ -0,0 +1,110 @@ | |||
1 | #ifndef __EVIL_FCNTL_H__ | ||
2 | #define __EVIL_FCNTL_H__ | ||
3 | |||
4 | |||
5 | # include <sys/types.h> | ||
6 | |||
7 | |||
8 | /** | ||
9 | * @def FD_CLOEXEC | ||
10 | * Specifies that the file descriptor should be closed when an exec() | ||
11 | * function is invoked. | ||
12 | */ | ||
13 | # define FD_CLOEXEC 1 | ||
14 | |||
15 | /** | ||
16 | * @def O_NONBLOCK | ||
17 | * Specifies that the socket is in non-blocking mode. | ||
18 | */ | ||
19 | # define O_NONBLOCK 04000 | ||
20 | |||
21 | /** | ||
22 | * @def F_SETFD | ||
23 | * Specifies that fcntl() should set the file descriptor flags | ||
24 | * associated with the filedes argument. | ||
25 | */ | ||
26 | |||
27 | /** | ||
28 | * @def F_SETLK | ||
29 | * Specifies that fcntl() should set or clear a file segment lock | ||
30 | * according to the lock description pointed to by the third argument. | ||
31 | */ | ||
32 | |||
33 | /** | ||
34 | * @def F_SETLKW | ||
35 | * Equivalent to F_SETLK except that if a shared or exclusive lock | ||
36 | * is blocked by other locks, the thread shall wait until the request | ||
37 | * can be satisfied. | ||
38 | */ | ||
39 | |||
40 | # define F_GETFD 1 | ||
41 | # define F_SETFD 2 | ||
42 | # define F_SETFL 4 | ||
43 | # define F_SETLK 6 | ||
44 | # define F_SETLKW 7 | ||
45 | |||
46 | /** | ||
47 | * @def F_RDLCK | ||
48 | * Read (or shared) lock | ||
49 | */ | ||
50 | |||
51 | /** | ||
52 | * @def F_WRLCK | ||
53 | * Write (or exclusive) lock | ||
54 | */ | ||
55 | |||
56 | /** | ||
57 | * @def F_UNLCK | ||
58 | * Remove lock | ||
59 | */ | ||
60 | |||
61 | # ifndef F_RDLCK | ||
62 | # define F_RDLCK 0 | ||
63 | # define F_WRLCK 1 | ||
64 | # define F_UNLCK 2 | ||
65 | # endif /* ! F_RDLCK */ | ||
66 | |||
67 | /** | ||
68 | * @struct flock | ||
69 | * @brief A structure that controls the lock of a file descriptor. | ||
70 | */ | ||
71 | struct flock | ||
72 | { | ||
73 | short int l_type; /**< lock type: read, write, ... */ | ||
74 | short int l_whence; /**< type of l_start */ | ||
75 | off_t l_start; /**< starting offset */ | ||
76 | off_t l_len; /**< 0 means end of the file */ | ||
77 | pid_t l_pid; /**< lock owner */ | ||
78 | }; | ||
79 | |||
80 | |||
81 | /** | ||
82 | * @brief Provide control over file descriptors. | ||
83 | * | ||
84 | * @param fd The file descriptor. | ||
85 | * @param cmd The type of control. | ||
86 | * @return 0 on success, -1 otherwise. | ||
87 | * | ||
88 | * Performs one of various miscellaneous operations on @p fd. | ||
89 | * The operation in question is determined by @p cmd: | ||
90 | * | ||
91 | * - F_SETFD: Set the close-on-exec flag to the value specified | ||
92 | * by the argument after command (only the least significant | ||
93 | * bit is used). | ||
94 | * - F_SETLK and F_SETLKW: used to manage discretionary file locks. | ||
95 | * The third argument must be a pointer to a struct flock (that | ||
96 | * may be overwritten by this call). | ||
97 | * | ||
98 | * This function returns 0 on success, -1 otherwise. | ||
99 | * | ||
100 | * Conformity: None. | ||
101 | * | ||
102 | * Supported OS: Windows Vista, Windows XP or Windows 2000 | ||
103 | * Professional. | ||
104 | * | ||
105 | * @ingroup Evil | ||
106 | */ | ||
107 | EAPI int fcntl(int fd, int cmd, ...); | ||
108 | |||
109 | |||
110 | #endif /* __EVIL_FCNTL_H__ */ | ||
diff --git a/src/lib/evil/evil_fnmatch.c b/src/lib/evil/evil_fnmatch.c new file mode 100644 index 0000000000..0b4af7bfb0 --- /dev/null +++ b/src/lib/evil/evil_fnmatch.c | |||
@@ -0,0 +1,231 @@ | |||
1 | #ifdef HAVE_CONFIG_H | ||
2 | # include "config.h" | ||
3 | #endif /* HAVE_CONFIG_H */ | ||
4 | |||
5 | #include <assert.h> | ||
6 | #include <string.h> | ||
7 | |||
8 | #include "fnmatch.h" | ||
9 | #include "evil_fnmatch_private.h" | ||
10 | |||
11 | enum fnmatch_status | ||
12 | { | ||
13 | fnmatch_not_found = 0, | ||
14 | fnmatch_found = 1, | ||
15 | fnmatch_syntax_error = 2 | ||
16 | }; | ||
17 | |||
18 | static | ||
19 | size_t | ||
20 | fnmatch_match_class_token(enum fnmatch_status *status, | ||
21 | const char *class_token, | ||
22 | char c) | ||
23 | { | ||
24 | if (! *class_token) | ||
25 | { | ||
26 | *status = fnmatch_syntax_error; | ||
27 | return 0; | ||
28 | } | ||
29 | else if (class_token[1] == '-' && class_token[2] != ']') | ||
30 | { | ||
31 | if (class_token[0] <= c && c <= class_token[2]) | ||
32 | *status = fnmatch_found; | ||
33 | return 3; | ||
34 | } | ||
35 | else | ||
36 | { | ||
37 | if (c == *class_token) | ||
38 | *status = fnmatch_found; | ||
39 | return 1; | ||
40 | } | ||
41 | } | ||
42 | |||
43 | static | ||
44 | size_t | ||
45 | fnmatch_complement_class(const char *class_token) | ||
46 | { | ||
47 | switch (*class_token) | ||
48 | { | ||
49 | case 0: | ||
50 | return FNM_SYNTAXERR; | ||
51 | |||
52 | case '!': | ||
53 | return 1; | ||
54 | |||
55 | default: | ||
56 | return 0; | ||
57 | } | ||
58 | } | ||
59 | |||
60 | static | ||
61 | size_t | ||
62 | fnmatch_match_class(const char *class, | ||
63 | char c) | ||
64 | { | ||
65 | const size_t complement = fnmatch_complement_class(class + 1); | ||
66 | enum fnmatch_status status; | ||
67 | size_t pos; | ||
68 | |||
69 | if (complement == FNM_SYNTAXERR) | ||
70 | return FNM_SYNTAXERR; | ||
71 | |||
72 | status = fnmatch_not_found; | ||
73 | pos = 1 + complement; | ||
74 | |||
75 | do | ||
76 | pos += fnmatch_match_class_token(&status, class + pos, c); | ||
77 | while (class[pos] && class[pos] != ']'); | ||
78 | |||
79 | if (status == fnmatch_syntax_error || ! class[pos]) | ||
80 | return FNM_SYNTAXERR; | ||
81 | |||
82 | if (status == fnmatch_found) | ||
83 | return complement ? 0 : pos + 1; | ||
84 | else | ||
85 | return complement ? pos + 1 : 0; | ||
86 | } | ||
87 | |||
88 | static | ||
89 | size_t | ||
90 | fnmatch_chrcasecmp(char a, | ||
91 | char b) | ||
92 | { | ||
93 | if ('A' <= a && a <= 'Z') | ||
94 | a += 'a' - 'A'; | ||
95 | if ('A' <= b && b <= 'Z') | ||
96 | b += 'a' - 'A'; | ||
97 | return a == b; | ||
98 | } | ||
99 | |||
100 | static | ||
101 | size_t | ||
102 | fnmatch_match_token(const char *token, | ||
103 | char c, | ||
104 | e_bool leading, | ||
105 | int flags) | ||
106 | { | ||
107 | if (*token == '\\' && !(flags & FNM_NOESCAPE)) | ||
108 | return token[1] ? (token[1] == c ? 2 : 0) : FNM_SYNTAXERR; | ||
109 | |||
110 | if (c == '/' && (flags & FNM_PATHNAME)) | ||
111 | return *token == '/'; | ||
112 | |||
113 | if (c == '.' && leading && (flags & FNM_PERIOD)) | ||
114 | return *token == '.'; | ||
115 | |||
116 | switch (*token) | ||
117 | { | ||
118 | case '?': | ||
119 | return 1; | ||
120 | |||
121 | case '[': | ||
122 | return fnmatch_match_class(token, c); | ||
123 | |||
124 | default: | ||
125 | if (flags & FNM_CASEFOLD) | ||
126 | return fnmatch_chrcasecmp(*token, c); | ||
127 | return *token == c ? 1 : 0; | ||
128 | } | ||
129 | } | ||
130 | |||
131 | static | ||
132 | void | ||
133 | fnmatch_init_states(struct list_of_states *states) | ||
134 | { | ||
135 | states->size = 1; | ||
136 | states->states[0] = 0; | ||
137 | memset(states->has, 0, states->reserved * sizeof (*states->has)); | ||
138 | states->has[0] = 1; | ||
139 | } | ||
140 | |||
141 | static | ||
142 | size_t | ||
143 | fnmatch_check_finals(const char *pattern, | ||
144 | const struct list_of_states *states) | ||
145 | { | ||
146 | size_t i, j; | ||
147 | for (i = 0; i < states->size; ++i) | ||
148 | { | ||
149 | e_bool match = 1; | ||
150 | |||
151 | for (j = states->states[i]; pattern[j]; ++j) | ||
152 | if (pattern[j] != '*') | ||
153 | { | ||
154 | match = 0; | ||
155 | break; | ||
156 | } | ||
157 | |||
158 | if (match) | ||
159 | return 0; | ||
160 | } | ||
161 | return FNM_NOMATCH; | ||
162 | } | ||
163 | |||
164 | int | ||
165 | fnmatch(const char *pattern, | ||
166 | const char *string, | ||
167 | int flags) | ||
168 | { | ||
169 | struct list_of_states *states; | ||
170 | struct list_of_states *new_states; | ||
171 | e_bool leading = 1; | ||
172 | char *c; | ||
173 | size_t r; | ||
174 | |||
175 | assert(pattern); | ||
176 | assert(string); | ||
177 | |||
178 | states = fnmatch_list_of_states_alloc(2, strlen(pattern)); | ||
179 | new_states = states + 1; | ||
180 | |||
181 | if (! states) | ||
182 | return FNM_NOMEM; | ||
183 | fnmatch_init_states(states); | ||
184 | |||
185 | |||
186 | for (c = (char *)string; *c && states->size; ++c) | ||
187 | { | ||
188 | size_t i; | ||
189 | fnmatch_list_of_states_clear(new_states); | ||
190 | |||
191 | for (i = 0; i < states->size; ++i) | ||
192 | { | ||
193 | const size_t pos = states->states[i]; | ||
194 | |||
195 | if (! pattern[pos]) | ||
196 | { | ||
197 | if (*c == '/' && (flags & FNM_LEADING_DIR)) | ||
198 | return 0; | ||
199 | continue; | ||
200 | } | ||
201 | else if (pattern[pos] == '*') | ||
202 | { | ||
203 | fnmatch_list_of_states_insert(states, pos + 1); | ||
204 | if ((*c != '/' || !(flags & FNM_PATHNAME)) && | ||
205 | (*c != '.' || !leading || !(flags & FNM_PERIOD))) | ||
206 | fnmatch_list_of_states_insert(new_states, pos); | ||
207 | } | ||
208 | else | ||
209 | { | ||
210 | const size_t m = fnmatch_match_token(pattern + pos, *c, | ||
211 | leading, flags); | ||
212 | |||
213 | if (m == FNM_SYNTAXERR) | ||
214 | return FNM_SYNTAXERR; | ||
215 | else if (m) | ||
216 | fnmatch_list_of_states_insert(new_states, pos + m); | ||
217 | } | ||
218 | } | ||
219 | { | ||
220 | struct list_of_states *tmp = states; | ||
221 | |||
222 | states = new_states; | ||
223 | new_states = tmp; | ||
224 | } | ||
225 | leading = *c == '/' && (flags & FNM_PATHNAME); | ||
226 | } | ||
227 | |||
228 | r = fnmatch_check_finals(pattern, states); | ||
229 | fnmatch_list_of_states_free(states < new_states ? states : new_states, 2); | ||
230 | return (int)r; | ||
231 | } | ||
diff --git a/src/lib/evil/evil_fnmatch_list_of_states.c b/src/lib/evil/evil_fnmatch_list_of_states.c new file mode 100644 index 0000000000..c6cfb7fe81 --- /dev/null +++ b/src/lib/evil/evil_fnmatch_list_of_states.c | |||
@@ -0,0 +1,77 @@ | |||
1 | #ifdef HAVE_CONFIG_H | ||
2 | # include "config.h" | ||
3 | #endif /* HAVE_CONFIG_H */ | ||
4 | |||
5 | #include <assert.h> | ||
6 | #include <stdlib.h> | ||
7 | #include <string.h> | ||
8 | |||
9 | #include "evil_fnmatch_private.h" | ||
10 | |||
11 | struct list_of_states* | ||
12 | fnmatch_list_of_states_alloc(size_t n, | ||
13 | size_t pattern_len) | ||
14 | { | ||
15 | struct list_of_states *l; | ||
16 | |||
17 | const size_t reserved = pattern_len + 1; | ||
18 | const size_t states_size = sizeof (*l->states) * reserved; | ||
19 | const size_t has_size = sizeof (*l->has) * reserved; | ||
20 | const size_t states_has_size = states_size + has_size; | ||
21 | const size_t struct_size = sizeof (*l) + states_has_size; | ||
22 | |||
23 | unsigned char *states; | ||
24 | unsigned char *has; | ||
25 | size_t i; | ||
26 | |||
27 | l = malloc(n * struct_size); | ||
28 | if (!l) | ||
29 | return 0; | ||
30 | |||
31 | states = (unsigned char *) (l + n); | ||
32 | has = states + states_size; | ||
33 | |||
34 | for (i = 0; i < n; ++i) | ||
35 | { | ||
36 | l[i].reserved = reserved; | ||
37 | l[i].states = (size_t *) states; | ||
38 | l[i].has = (e_bool *) has; | ||
39 | states += states_has_size; | ||
40 | has += states_has_size; | ||
41 | } | ||
42 | |||
43 | return l; | ||
44 | } | ||
45 | |||
46 | void | ||
47 | fnmatch_list_of_states_free(struct list_of_states *lists, | ||
48 | size_t n) | ||
49 | { | ||
50 | assert(lists); | ||
51 | |||
52 | (void) n; | ||
53 | free(lists); | ||
54 | } | ||
55 | |||
56 | void | ||
57 | fnmatch_list_of_states_insert(struct list_of_states *list, | ||
58 | size_t state) | ||
59 | { | ||
60 | assert(list); | ||
61 | assert(state < list->reserved); | ||
62 | |||
63 | if (list->has[state]) | ||
64 | return; | ||
65 | |||
66 | list->states[list->size++] = state; | ||
67 | list->has[state] = 1; | ||
68 | } | ||
69 | |||
70 | void | ||
71 | fnmatch_list_of_states_clear(struct list_of_states *list) | ||
72 | { | ||
73 | assert(list); | ||
74 | |||
75 | list->size = 0; | ||
76 | memset(list->has, 0, list->reserved * sizeof (*list->has)); | ||
77 | } | ||
diff --git a/src/lib/evil/evil_fnmatch_private.h b/src/lib/evil/evil_fnmatch_private.h new file mode 100644 index 0000000000..f5ced5d68f --- /dev/null +++ b/src/lib/evil/evil_fnmatch_private.h | |||
@@ -0,0 +1,24 @@ | |||
1 | #ifndef __EVIL_FNMATCH_PRIVATE_H__ | ||
2 | #define __EVIL_FNMATCH_PRIVATE_H__ | ||
3 | |||
4 | |||
5 | typedef int e_bool; | ||
6 | |||
7 | struct list_of_states | ||
8 | { | ||
9 | size_t reserved; | ||
10 | size_t size; | ||
11 | size_t *states; | ||
12 | e_bool *has; | ||
13 | }; | ||
14 | |||
15 | struct list_of_states *fnmatch_list_of_states_alloc(size_t n, size_t pattern_len); | ||
16 | |||
17 | void fnmatch_list_of_states_free(struct list_of_states *lists, size_t n); | ||
18 | |||
19 | void fnmatch_list_of_states_insert(struct list_of_states *list, size_t state); | ||
20 | |||
21 | void fnmatch_list_of_states_clear(struct list_of_states *list); | ||
22 | |||
23 | |||
24 | #endif /* __EVIL_FNMATCH_PRIVATE_H__ */ | ||
diff --git a/src/lib/evil/evil_inet.c b/src/lib/evil/evil_inet.c new file mode 100644 index 0000000000..99ce14edc2 --- /dev/null +++ b/src/lib/evil/evil_inet.c | |||
@@ -0,0 +1,648 @@ | |||
1 | |||
2 | /* | ||
3 | * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") | ||
4 | * Copyright (c) 1996,1999 by Internet Software Consortium. | ||
5 | * | ||
6 | * Permission to use, copy, modify, and distribute this software for any | ||
7 | * purpose with or without fee is hereby granted, provided that the above | ||
8 | * copyright notice and this permission notice appear in all copies. | ||
9 | * | ||
10 | * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES | ||
11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR | ||
13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT | ||
16 | * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
17 | */ | ||
18 | |||
19 | /* | ||
20 | * Modifications: Vincent Torri, for the integration in Evil | ||
21 | * - modification of the name of some functions | ||
22 | * * modification of the management of the error | ||
23 | */ | ||
24 | |||
25 | #ifdef HAVE_CONFIG_H | ||
26 | # include "config.h" | ||
27 | #endif /* HAVE_CONFIG_H */ | ||
28 | |||
29 | #include <stdio.h> | ||
30 | #include <ctype.h> | ||
31 | |||
32 | #ifdef HAVE_ERRNO_H | ||
33 | # include <errno.h> | ||
34 | #endif /* HAVE_ERRNO_H */ | ||
35 | |||
36 | #ifndef WIN32_LEAN_AND_MEAN | ||
37 | # define WIN32_LEAN_AND_MEAN | ||
38 | #endif | ||
39 | #include <winsock2.h> | ||
40 | #undef WIN32_LEAN_AND_MEAN | ||
41 | |||
42 | #include "evil_macro.h" | ||
43 | #include "evil_inet.h" | ||
44 | #include "evil_private.h" | ||
45 | #define APICHAR char | ||
46 | #include "evil_print.h" | ||
47 | |||
48 | #ifndef EMSGSIZE | ||
49 | # define EMSGSIZE WSAEMSGSIZE | ||
50 | #endif | ||
51 | |||
52 | #ifndef EAFNOSUPPORT | ||
53 | # define EAFNOSUPPORT WSAEAFNOSUPPORT | ||
54 | #endif | ||
55 | |||
56 | #define SPRINTF(x) ((size_t)sprintf x) | ||
57 | |||
58 | #define ERRNO ((int)GetLastError()) | ||
59 | #define SET_ERRNO(x) (SetLastError((DWORD)(x))) | ||
60 | |||
61 | #define ISDIGIT(x) (isdigit((int) ((unsigned char)x))) | ||
62 | #define ISXDIGIT(x) (isxdigit((int) ((unsigned char)x))) | ||
63 | #define ISUPPER(x) (isupper((int) ((unsigned char)x))) | ||
64 | |||
65 | #define NS_IN6ADDRSZ 16 | ||
66 | #define NS_INT16SZ 2 | ||
67 | #define NS_INADDRSZ sizeof(IN_ADDR) | ||
68 | |||
69 | |||
70 | struct ares_in6_addr { | ||
71 | union { | ||
72 | unsigned char _S6_u8[16]; | ||
73 | } _S6_un; | ||
74 | }; | ||
75 | |||
76 | const struct ares_in6_addr ares_in6addr_any = { { { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 } } }; | ||
77 | |||
78 | |||
79 | /* | ||
80 | * static int | ||
81 | * inet_net_pton_ipv4(src, dst, size) | ||
82 | * convert IPv4 network number from presentation to network format. | ||
83 | * accepts hex octets, hex strings, decimal octets, and /CIDR. | ||
84 | * "size" is in bytes and describes "dst". | ||
85 | * return: | ||
86 | * number of bits, either imputed classfully or specified with /CIDR, | ||
87 | * or -1 if some failure occurred (check errno). ENOENT means it was | ||
88 | * not an IPv4 network specification. | ||
89 | * note: | ||
90 | * network byte order assumed. this means 192.5.5.240/28 has | ||
91 | * 0b11110000 in its fourth octet. | ||
92 | * note: | ||
93 | * On Windows we store the error in the thread errno, not | ||
94 | * in the winsock error code. This is to avoid loosing the | ||
95 | * actual last winsock error. So use macro ERRNO to fetch the | ||
96 | * errno this funtion sets when returning (-1), not SOCKERRNO. | ||
97 | * author: | ||
98 | * Paul Vixie (ISC), June 1996 | ||
99 | */ | ||
100 | static int | ||
101 | inet_net_pton_ipv4(const char *src, unsigned char *dst, size_t size) | ||
102 | { | ||
103 | static const char xdigits[] = "0123456789abcdef"; | ||
104 | static const char digits[] = "0123456789"; | ||
105 | int n, ch, tmp = 0, dirty, bits; | ||
106 | const unsigned char *odst = dst; | ||
107 | |||
108 | ch = *src++; | ||
109 | if (ch == '0' && (src[0] == 'x' || src[0] == 'X') | ||
110 | && ISXDIGIT(src[1])) { | ||
111 | /* Hexadecimal: Eat nybble string. */ | ||
112 | if (!size) | ||
113 | goto emsgsize; | ||
114 | dirty = 0; | ||
115 | src++; /* skip x or X. */ | ||
116 | while ((ch = *src++) != '\0' && ISXDIGIT(ch)) { | ||
117 | if (ISUPPER(ch)) | ||
118 | ch = tolower(ch); | ||
119 | n = (int)(strchr(xdigits, ch) - xdigits); | ||
120 | if (dirty == 0) | ||
121 | tmp = n; | ||
122 | else | ||
123 | tmp = (tmp << 4) | n; | ||
124 | if (++dirty == 2) { | ||
125 | if (!size--) | ||
126 | goto emsgsize; | ||
127 | *dst++ = (unsigned char) tmp; | ||
128 | dirty = 0; | ||
129 | } | ||
130 | } | ||
131 | if (dirty) { /* Odd trailing nybble? */ | ||
132 | if (!size--) | ||
133 | goto emsgsize; | ||
134 | *dst++ = (unsigned char) (tmp << 4); | ||
135 | } | ||
136 | } else if (ISDIGIT(ch)) { | ||
137 | /* Decimal: eat dotted digit string. */ | ||
138 | for (;;) { | ||
139 | tmp = 0; | ||
140 | do { | ||
141 | n = (int)(strchr(digits, ch) - digits); | ||
142 | tmp *= 10; | ||
143 | tmp += n; | ||
144 | if (tmp > 255) | ||
145 | goto enoent; | ||
146 | } while ((ch = *src++) != '\0' && | ||
147 | ISDIGIT(ch)); | ||
148 | if (!size--) | ||
149 | goto emsgsize; | ||
150 | *dst++ = (unsigned char) tmp; | ||
151 | if (ch == '\0' || ch == '/') | ||
152 | break; | ||
153 | if (ch != '.') | ||
154 | goto enoent; | ||
155 | ch = *src++; | ||
156 | if (!ISDIGIT(ch)) | ||
157 | goto enoent; | ||
158 | } | ||
159 | } else | ||
160 | goto enoent; | ||
161 | |||
162 | bits = -1; | ||
163 | if (ch == '/' && | ||
164 | ISDIGIT(src[0]) && dst > odst) { | ||
165 | /* CIDR width specifier. Nothing can follow it. */ | ||
166 | ch = *src++; /* Skip over the /. */ | ||
167 | bits = 0; | ||
168 | do { | ||
169 | n = (int)(strchr(digits, ch) - digits); | ||
170 | bits *= 10; | ||
171 | bits += n; | ||
172 | } while ((ch = *src++) != '\0' && ISDIGIT(ch)); | ||
173 | if (ch != '\0') | ||
174 | goto enoent; | ||
175 | if (bits > 32) | ||
176 | goto emsgsize; | ||
177 | } | ||
178 | |||
179 | /* Firey death and destruction unless we prefetched EOS. */ | ||
180 | if (ch != '\0') | ||
181 | goto enoent; | ||
182 | |||
183 | /* If nothing was written to the destination, we found no address. */ | ||
184 | if (dst == odst) | ||
185 | goto enoent; | ||
186 | /* If no CIDR spec was given, infer width from net class. */ | ||
187 | if (bits == -1) { | ||
188 | if (*odst >= 240) /* Class E */ | ||
189 | bits = 32; | ||
190 | else if (*odst >= 224) /* Class D */ | ||
191 | bits = 8; | ||
192 | else if (*odst >= 192) /* Class C */ | ||
193 | bits = 24; | ||
194 | else if (*odst >= 128) /* Class B */ | ||
195 | bits = 16; | ||
196 | else /* Class A */ | ||
197 | bits = 8; | ||
198 | /* If imputed mask is narrower than specified octets, widen. */ | ||
199 | if (bits < ((dst - odst) * 8)) | ||
200 | bits = (int)(dst - odst) * 8; | ||
201 | /* | ||
202 | * If there are no additional bits specified for a class D | ||
203 | * address adjust bits to 4. | ||
204 | */ | ||
205 | if (bits == 8 && *odst == 224) | ||
206 | bits = 4; | ||
207 | } | ||
208 | /* Extend network to cover the actual mask. */ | ||
209 | while (bits > ((dst - odst) * 8)) { | ||
210 | if (!size--) | ||
211 | goto emsgsize; | ||
212 | *dst++ = '\0'; | ||
213 | } | ||
214 | return (bits); | ||
215 | |||
216 | enoent: | ||
217 | SET_ERRNO(ENOENT); | ||
218 | return (-1); | ||
219 | |||
220 | emsgsize: | ||
221 | SET_ERRNO(EMSGSIZE); | ||
222 | return (-1); | ||
223 | } | ||
224 | |||
225 | static int | ||
226 | getbits(const char *src, int *bitsp) | ||
227 | { | ||
228 | static const char digits[] = "0123456789"; | ||
229 | int n; | ||
230 | int val; | ||
231 | char ch; | ||
232 | |||
233 | val = 0; | ||
234 | n = 0; | ||
235 | while ((ch = *src++) != '\0') { | ||
236 | const char *pch; | ||
237 | |||
238 | pch = strchr(digits, ch); | ||
239 | if (pch != NULL) { | ||
240 | if (n++ != 0 && val == 0) /* no leading zeros */ | ||
241 | return (0); | ||
242 | val *= 10; | ||
243 | val += (pch - digits); | ||
244 | if (val > 128) /* range */ | ||
245 | return (0); | ||
246 | continue; | ||
247 | } | ||
248 | return (0); | ||
249 | } | ||
250 | if (n == 0) | ||
251 | return (0); | ||
252 | *bitsp = val; | ||
253 | return (1); | ||
254 | } | ||
255 | |||
256 | static int | ||
257 | getv4(const char *src, unsigned char *dst, int *bitsp) | ||
258 | { | ||
259 | static const char digits[] = "0123456789"; | ||
260 | unsigned char *odst = dst; | ||
261 | int n; | ||
262 | unsigned int val; | ||
263 | char ch; | ||
264 | |||
265 | val = 0; | ||
266 | n = 0; | ||
267 | while ((ch = *src++) != '\0') { | ||
268 | const char *pch; | ||
269 | |||
270 | pch = strchr(digits, ch); | ||
271 | if (pch != NULL) { | ||
272 | if (n++ != 0 && val == 0) /* no leading zeros */ | ||
273 | return (0); | ||
274 | val *= 10; | ||
275 | val += (pch - digits); | ||
276 | if (val > 255) /* range */ | ||
277 | return (0); | ||
278 | continue; | ||
279 | } | ||
280 | if (ch == '.' || ch == '/') { | ||
281 | if (dst - odst > 3) /* too many octets? */ | ||
282 | return (0); | ||
283 | *dst++ = (unsigned char)val; | ||
284 | if (ch == '/') | ||
285 | return (getbits(src, bitsp)); | ||
286 | val = 0; | ||
287 | n = 0; | ||
288 | continue; | ||
289 | } | ||
290 | return (0); | ||
291 | } | ||
292 | if (n == 0) | ||
293 | return (0); | ||
294 | if (dst - odst > 3) /* too many octets? */ | ||
295 | return (0); | ||
296 | *dst++ = (unsigned char)val; | ||
297 | return (1); | ||
298 | } | ||
299 | |||
300 | static int | ||
301 | inet_net_pton_ipv6(const char *src, unsigned char *dst, size_t size) | ||
302 | { | ||
303 | static const char xdigits_l[] = "0123456789abcdef", | ||
304 | xdigits_u[] = "0123456789ABCDEF"; | ||
305 | unsigned char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp; | ||
306 | const char *xdigits, *curtok; | ||
307 | int ch, saw_xdigit; | ||
308 | unsigned int val; | ||
309 | int digits; | ||
310 | int bits; | ||
311 | size_t bytes; | ||
312 | int words; | ||
313 | int ipv4; | ||
314 | |||
315 | memset((tp = tmp), '\0', NS_IN6ADDRSZ); | ||
316 | endp = tp + NS_IN6ADDRSZ; | ||
317 | colonp = NULL; | ||
318 | /* Leading :: requires some special handling. */ | ||
319 | if (*src == ':') | ||
320 | if (*++src != ':') | ||
321 | goto enoent; | ||
322 | curtok = src; | ||
323 | saw_xdigit = 0; | ||
324 | val = 0; | ||
325 | digits = 0; | ||
326 | bits = -1; | ||
327 | ipv4 = 0; | ||
328 | while ((ch = *src++) != '\0') { | ||
329 | const char *pch; | ||
330 | |||
331 | if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) | ||
332 | pch = strchr((xdigits = xdigits_u), ch); | ||
333 | if (pch != NULL) { | ||
334 | val <<= 4; | ||
335 | val |= (pch - xdigits); | ||
336 | if (++digits > 4) | ||
337 | goto enoent; | ||
338 | saw_xdigit = 1; | ||
339 | continue; | ||
340 | } | ||
341 | if (ch == ':') { | ||
342 | curtok = src; | ||
343 | if (!saw_xdigit) { | ||
344 | if (colonp) | ||
345 | goto enoent; | ||
346 | colonp = tp; | ||
347 | continue; | ||
348 | } else if (*src == '\0') | ||
349 | goto enoent; | ||
350 | if (tp + NS_INT16SZ > endp) | ||
351 | return (0); | ||
352 | *tp++ = (unsigned char)((val >> 8) & 0xff); | ||
353 | *tp++ = (unsigned c |