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/lib/evil | |
parent | 59a9dfd11860888a35e96dfe51af63cea5cecfe1 (diff) |
merge: add evil files
SVN revision: 76464
Diffstat (limited to 'src/lib/evil')
77 files changed, 17758 insertions, 0 deletions
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 char)(val & 0xff); | ||
354 | saw_xdigit = 0; | ||
355 | digits = 0; | ||
356 | val = 0; | ||
357 | continue; | ||
358 | } | ||
359 | if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) && | ||
360 | getv4(curtok, tp, &bits) > 0) { | ||
361 | tp += NS_INADDRSZ; | ||
362 | saw_xdigit = 0; | ||
363 | ipv4 = 1; | ||
364 | break; /* '\0' was seen by inet_pton4(). */ | ||
365 | } | ||
366 | if (ch == '/' && getbits(src, &bits) > 0) | ||
367 | break; | ||
368 | goto enoent; | ||
369 | } | ||
370 | if (saw_xdigit) { | ||
371 | if (tp + NS_INT16SZ > endp) | ||
372 | goto enoent; | ||
373 | *tp++ = (unsigned char)((val >> 8) & 0xff); | ||
374 | *tp++ = (unsigned char)(val & 0xff); | ||
375 | } | ||
376 | if (bits == -1) | ||
377 | bits = 128; | ||
378 | |||
379 | words = (bits + 15) / 16; | ||
380 | if (words < 2) | ||
381 | words = 2; | ||
382 | if (ipv4) | ||
383 | words = 8; | ||
384 | endp = tmp + 2 * words; | ||
385 | |||
386 | if (colonp != NULL) { | ||
387 | /* | ||
388 | * Since some memmove()'s erroneously fail to handle | ||
389 | * overlapping regions, we'll do the shift by hand. | ||
390 | */ | ||
391 | const ssize_t n = tp - colonp; | ||
392 | ssize_t i; | ||
393 | |||
394 | if (tp == endp) | ||
395 | goto enoent; | ||
396 | for (i = 1; i <= n; i++) { | ||
397 | *(endp - i) = *(colonp + n - i); | ||
398 | *(colonp + n - i) = 0; | ||
399 | } | ||
400 | tp = endp; | ||
401 | } | ||
402 | if (tp != endp) | ||
403 | goto enoent; | ||
404 | |||
405 | bytes = (bits + 7) / 8; | ||
406 | if (bytes > size) | ||
407 | goto emsgsize; | ||
408 | memcpy(dst, tmp, bytes); | ||
409 | return (bits); | ||
410 | |||
411 | enoent: | ||
412 | SET_ERRNO(ENOENT); | ||
413 | return (-1); | ||
414 | |||
415 | emsgsize: | ||
416 | SET_ERRNO(EMSGSIZE); | ||
417 | return (-1); | ||
418 | } | ||
419 | |||
420 | /* | ||
421 | * int | ||
422 | * inet_net_pton(af, src, dst, size) | ||
423 | * convert network number from presentation to network format. | ||
424 | * accepts hex octets, hex strings, decimal octets, and /CIDR. | ||
425 | * "size" is in bytes and describes "dst". | ||
426 | * return: | ||
427 | * number of bits, either imputed classfully or specified with /CIDR, | ||
428 | * or -1 if some failure occurred (check errno). ENOENT means it was | ||
429 | * not a valid network specification. | ||
430 | * note: | ||
431 | * On Windows we store the error in the thread errno, not | ||
432 | * in the winsock error code. This is to avoid loosing the | ||
433 | * actual last winsock error. So use macro ERRNO to fetch the | ||
434 | * errno this funtion sets when returning (-1), not SOCKERRNO. | ||
435 | * author: | ||
436 | * Paul Vixie (ISC), June 1996 | ||
437 | */ | ||
438 | static int | ||
439 | ares_inet_net_pton(int af, const char *src, void *dst, size_t size) | ||
440 | { | ||
441 | switch (af) { | ||
442 | case AF_INET: | ||
443 | return (inet_net_pton_ipv4(src, dst, size)); | ||
444 | case AF_INET6: | ||
445 | return (inet_net_pton_ipv6(src, dst, size)); | ||
446 | default: | ||
447 | SET_ERRNO(EAFNOSUPPORT); | ||
448 | return (-1); | ||
449 | } | ||
450 | } | ||
451 | |||
452 | int | ||
453 | evil_inet_pton(int af, const char *src, void *dst) | ||
454 | { | ||
455 | int result; | ||
456 | size_t size; | ||
457 | |||
458 | if (af == AF_INET) | ||
459 | size = sizeof(struct in_addr); | ||
460 | else if (af == AF_INET6) | ||
461 | size = sizeof(struct ares_in6_addr); | ||
462 | else | ||
463 | { | ||
464 | SET_ERRNO(EAFNOSUPPORT); | ||
465 | return -1; | ||
466 | } | ||
467 | result = ares_inet_net_pton(af, src, dst, size); | ||
468 | if ((result == -1) && (ERRNO == ENOENT)) | ||
469 | return 0; | ||
470 | return (result > -1 ? 1 : -1); | ||
471 | } | ||
472 | |||
473 | |||
474 | /* const char * | ||
475 | * inet_ntop4(src, dst, size) | ||
476 | * format an IPv4 address, more or less like inet_ntoa() | ||
477 | * return: | ||
478 | * `dst' (as a const) | ||
479 | * notes: | ||
480 | * (1) uses no statics | ||
481 | * (2) takes a unsigned char* not an in_addr as input | ||
482 | * author: | ||
483 | * Paul Vixie, 1996. | ||
484 | */ | ||
485 | static const char * | ||
486 | inet_ntop4(const unsigned char *src, char *dst, size_t size) | ||
487 | { | ||
488 | static const char fmt[] = "%u.%u.%u.%u"; | ||
489 | char tmp[sizeof "255.255.255.255"]; | ||
490 | |||
491 | if (SPRINTF((tmp, fmt, src[0], src[1], src[2], src[3])) > size) | ||
492 | { | ||
493 | SET_ERRNO(ENOSPC); | ||
494 | return (NULL); | ||
495 | } | ||
496 | strcpy(dst, tmp); | ||
497 | return (dst); | ||
498 | } | ||
499 | |||
500 | /* const char * | ||
501 | * inet_ntop6(src, dst, size) | ||
502 | * convert IPv6 binary address into presentation (printable) format | ||
503 | * author: | ||
504 | * Paul Vixie, 1996. | ||
505 | */ | ||
506 | static const char * | ||
507 | inet_ntop6(const unsigned char *src, char *dst, size_t size) | ||
508 | { | ||
509 | /* | ||
510 | * Note that int32_t and int16_t need only be "at least" large enough | ||
511 | * to contain a value of the specified size. On some systems, like | ||
512 | * Crays, there is no such thing as an integer variable with 16 bits. | ||
513 | * Keep this in mind if you think this function should have been coded | ||
514 | * to use pointer overlays. All the world's not a VAX. | ||
515 | */ | ||
516 | char tmp[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")]; | ||
517 | char *tp; | ||
518 | struct { | ||
519 | long base; | ||
520 | long len; | ||
521 | } best, cur; | ||
522 | unsigned long words[NS_IN6ADDRSZ / NS_INT16SZ]; | ||
523 | int i; | ||
524 | |||
525 | /* | ||
526 | * Preprocess: | ||
527 | * Copy the input (bytewise) array into a wordwise array. | ||
528 | * Find the longest run of 0x00's in src[] for :: shorthanding. | ||
529 | */ | ||
530 | memset(words, '\0', sizeof(words)); | ||
531 | for (i = 0; i < NS_IN6ADDRSZ; i++) | ||
532 | words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3)); | ||
533 | |||
534 | best.base = -1; | ||
535 | cur.base = -1; | ||
536 | best.len = 0; | ||
537 | cur.len = 0; | ||
538 | |||
539 | for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) | ||
540 | { | ||
541 | if (words[i] == 0) | ||
542 | { | ||
543 | if (cur.base == -1) | ||
544 | cur.base = i, cur.len = 1; | ||
545 | else | ||
546 | cur.len++; | ||
547 | } | ||
548 | else | ||
549 | { | ||
550 | if (cur.base != -1) | ||
551 | { | ||
552 | if (best.base == -1 || cur.len > best.len) | ||
553 | best = cur; | ||
554 | cur.base = -1; | ||
555 | } | ||
556 | } | ||
557 | } | ||
558 | if (cur.base != -1) | ||
559 | { | ||
560 | if (best.base == -1 || cur.len > best.len) | ||
561 | best = cur; | ||
562 | } | ||
563 | if (best.base != -1 && best.len < 2) | ||
564 | best.base = -1; | ||
565 | |||
566 | /* | ||
567 | * Format the result. | ||
568 | */ | ||
569 | tp = tmp; | ||
570 | for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) | ||
571 | { | ||
572 | /* Are we inside the best run of 0x00's? */ | ||
573 | if (best.base != -1 && i >= best.base && | ||
574 | i < (best.base + best.len)) | ||
575 | { | ||
576 | if (i == best.base) | ||
577 | *tp++ = ':'; | ||
578 | continue; | ||
579 | } | ||
580 | /* Are we following an initial run of 0x00s or any real hex? */ | ||
581 | if (i != 0) | ||
582 | *tp++ = ':'; | ||
583 | /* Is this address an encapsulated IPv4? */ | ||
584 | if (i == 6 && best.base == 0 && | ||
585 | (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) | ||
586 | { | ||
587 | if (!inet_ntop4(src+12, tp, sizeof(tmp) - (tp - tmp))) | ||
588 | return (NULL); | ||
589 | tp += strlen(tp); | ||
590 | break; | ||
591 | } | ||
592 | tp += SPRINTF((tp, "%lx", words[i])); | ||
593 | } | ||
594 | |||
595 | /* Was it a trailing run of 0x00's? */ | ||
596 | if (best.base != -1 && (best.base + best.len) == (NS_IN6ADDRSZ / NS_INT16SZ)) | ||
597 | *tp++ = ':'; | ||
598 | *tp++ = '\0'; | ||
599 | |||
600 | /* | ||
601 | * Check for overflow, copy, and we're done. | ||
602 | */ | ||
603 | if ((size_t)(tp - tmp) > size) | ||
604 | { | ||
605 | SET_ERRNO(ENOSPC); | ||
606 | return (NULL); | ||
607 | } | ||
608 | strcpy(dst, tmp); | ||
609 | return (dst); | ||
610 | } | ||
611 | |||
612 | /* char * | ||
613 | * inet_ntop(af, src, dst, size) | ||
614 | * convert a network format address to presentation format. | ||
615 | * return: | ||
616 | * pointer to presentation format address (`dst'), or NULL (see errno). | ||
617 | * note: | ||
618 | * On Windows we store the error in the thread errno, not | ||
619 | * in the winsock error code. This is to avoid loosing the | ||
620 | * actual last winsock error. So use macro ERRNO to fetch the | ||
621 | * errno this funtion sets when returning NULL, not SOCKERRNO. | ||
622 | * author: | ||
623 | * Paul Vixie, 1996. | ||
624 | */ | ||
625 | static const char * | ||
626 | ares_inet_ntop(int af, const void *src, char *dst, size_t size) | ||
627 | { | ||
628 | switch (af) | ||
629 | { | ||
630 | case AF_INET: | ||
631 | return (inet_ntop4(src, dst, size)); | ||
632 | case AF_INET6: | ||
633 | return (inet_ntop6(src, dst, size)); | ||
634 | default: | ||
635 | SET_ERRNO(EAFNOSUPPORT); | ||
636 | return (NULL); | ||
637 | } | ||
638 | /* NOTREACHED */ | ||
639 | } | ||
640 | |||
641 | const char *evil_inet_ntop(int af, const char *src, void *dst, size_t size) | ||
642 | { | ||
643 | const char *result; | ||
644 | result = ares_inet_ntop(af, src, dst, size); | ||
645 | if ((result == NULL) && (ERRNO == ENOSPC)) | ||
646 | return NULL; | ||
647 | return result; | ||
648 | } | ||
diff --git a/src/lib/evil/evil_inet.h b/src/lib/evil/evil_inet.h new file mode 100644 index 0000000000..b81b8ff715 --- /dev/null +++ b/src/lib/evil/evil_inet.h | |||
@@ -0,0 +1,149 @@ | |||
1 | |||
2 | /* Copyright (C) 2005 by Daniel Stenberg | ||
3 | * | ||
4 | * Permission to use, copy, modify, and distribute this | ||
5 | * software and its documentation for any purpose and without | ||
6 | * fee is hereby granted, provided that the above copyright | ||
7 | * notice appear in all copies and that both that copyright | ||
8 | * notice and this permission notice appear in supporting | ||
9 | * documentation, and that the name of M.I.T. not be used in | ||
10 | * advertising or publicity pertaining to distribution of the | ||
11 | * software without specific, written prior permission. | ||
12 | * M.I.T. makes no representations about the suitability of | ||
13 | * this software for any purpose. It is provided "as is" | ||
14 | * without express or implied warranty. | ||
15 | */ | ||
16 | |||
17 | #ifndef __EVIL_INET_H__ | ||
18 | #define __EVIL_INET_H__ | ||
19 | |||
20 | |||
21 | /** | ||
22 | * @file evil_inet.h | ||
23 | * @brief The file that provides functions ported from Unix in arpa/inet.h. | ||
24 | * @defgroup Evil_Inet_Group Inet.h functions | ||
25 | * | ||
26 | * This header provides functions ported from Unix in arpa/inet.h. | ||
27 | * | ||
28 | * @{ | ||
29 | */ | ||
30 | |||
31 | /** | ||
32 | * @brief Convert IPv4 and IPv6 addresses from text to binary form. | ||
33 | * | ||
34 | * @param af The address family. | ||
35 | * @param src The address to convert. | ||
36 | * @param dst The converted address structure. | ||
37 | * @return 1 on success, 0 or -1 otherwise. | ||
38 | * | ||
39 | * This function converts IPv4 and IPv6 addresses from @p src to the | ||
40 | * binary form @p dst. The following address families to pass to @p af | ||
41 | * are currently supported: | ||
42 | * | ||
43 | * <ul> | ||
44 | * <li>i AF_INET: @p src points to a character string containing an IPv4 | ||
45 | * network address in dotted-decimal format, "ddd.ddd.ddd.ddd", where | ||
46 | * ddd is a decimal number of up to three digits in the range 0 to | ||
47 | * 255. The address is converted to a struct in_addr and copied to | ||
48 | * dst, which must be sizeof(struct in_addr) (4) bytes (32 bits) long. | ||
49 | * <li> AF_INET6: @p src points to a character string containing an | ||
50 | * IPv6 network address. The address is converted to a struct in6_addr | ||
51 | * and copied to dst, which must be sizeof(struct in6_addr) (16) bytes | ||
52 | * (128 bits) long. The allowed formats for IPv6 addresses follow | ||
53 | * these rules: | ||
54 | * <ol> | ||
55 | * <li>The preferred format is x:x:x:x:x:x:x:x. This form consists of | ||
56 | * eight hexadecimal numbers, each of which expresses a 16-bit value | ||
57 | * (i.e., each x can be up to 4 hex digits). | ||
58 | * <li>A series of contiguous zero values in the preferred format can | ||
59 | * be abbreviated to ::. Only one instance of :: can occur in an | ||
60 | * address. For example, the loopback address 0:0:0:0:0:0:0:1 can be | ||
61 | * abbreviated as ::1. The wildcard address, consisting of all zeros, | ||
62 | * can be written as ::. | ||
63 | * <li>An alternate format is useful for expressing IPv4-mapped IPv6 | ||
64 | * addresses. This form is written as x:x:x:x:x:x:d.d.d.d, where the | ||
65 | * six leading xs are hexadecimal values that define the six | ||
66 | * most-significant 16-bit pieces of the address (i.e., 96 bits), and | ||
67 | * the ds express a value in dotted-decimal notation that defines the | ||
68 | * least significant 32 bits of the address. An example of such an | ||
69 | * address is :: FFFF:204.152.189.116. | ||
70 | * </ul> | ||
71 | * </ul> | ||
72 | * On success this function returns 1 (network address was successfully | ||
73 | * converted). 0 is returned if @p src does not contain a character | ||
74 | * string representing a valid network address in the specified | ||
75 | * address family. If af does not contain a valid address family, -1 | ||
76 | * is returned and errno is set to EAFNOSUPPORT. | ||
77 | * | ||
78 | * @see evil_inet_ntop() | ||
79 | * @see inet_ntop() | ||
80 | * | ||
81 | * Conformity: POSIX.1-2001. | ||
82 | * | ||
83 | * Supported OS: Windows XP, CE. | ||
84 | * | ||
85 | */ | ||
86 | EAPI int evil_inet_pton(int af, const char *src, void *dst); | ||
87 | |||
88 | /** | ||
89 | * @def inet_pton(x,y,z) | ||
90 | * | ||
91 | * Wrapper around evil_inet_pton(). | ||
92 | */ | ||
93 | #define inet_pton(x,y,z) evil_inet_pton(x,y,z) | ||
94 | |||
95 | /** | ||
96 | * @brief Convert IPv4 and IPv6 addresses from binary to text form. | ||
97 | * | ||
98 | * @param af The address family. | ||
99 | * @param src The address structure to convert. | ||
100 | * @param dst A buffer containing the converted string. | ||
101 | * @param size The size of the buffer. | ||
102 | * @return 1 on success, 0 otherwise. | ||
103 | * | ||
104 | * This function converts the network address structure @p src in the | ||
105 | * @p af address family into a character string. The resulting string | ||
106 | * is copied to the buffer pointed to by @p dst, which must be a | ||
107 | * non-NULL pointer. The caller specifies the number of bytes | ||
108 | * available in this buffer in the argument @p size. The following | ||
109 | * address families to pass to @p af are currently supported: | ||
110 | * | ||
111 | * @li AF_INET: @p src points to a struct in_addr (in network byte | ||
112 | * order) which is converted to an IPv4 network address in the | ||
113 | * dotted-decimal format, "ddd.ddd.ddd.ddd". The buffer @p dst must be | ||
114 | * at least INET_ADDRSTRLEN bytes long. | ||
115 | * @li AF_INET6: @p src points to a struct in6_addr (in network byte | ||
116 | * order) which is converted to a representation of this address in | ||
117 | * the most appropriate IPv6 network address format for this | ||
118 | * address. The buffer @p dst must be at least INET6_ADDRSTRLEN bytes | ||
119 | * long. | ||
120 | * | ||
121 | * On success, this function returns a non-NULL pointer to @p dst. NULL is | ||
122 | * returned if there was an error, with errno set to indicate the | ||
123 | * error. | ||
124 | * | ||
125 | * @see evil_inet_pton() | ||
126 | * @see inet_pton() | ||
127 | * | ||
128 | * Conformity: POSIX.1-2001. | ||
129 | * | ||
130 | * Supported OS: Windows XP, CE. | ||
131 | * | ||
132 | */ | ||
133 | EAPI const char *evil_inet_ntop(int af, const char *src, void *dst, size_t size); | ||
134 | |||
135 | /** | ||
136 | * @def inet_ntop(x,y,z,s) | ||
137 | * | ||
138 | * Wrapper around evil_inet_ntop(). | ||
139 | */ | ||
140 | #define inet_ntop(x,y,z,s) evil_inet_ntop(x,y,z,s) | ||
141 | |||
142 | |||
143 | |||
144 | /** | ||
145 | * @} | ||
146 | */ | ||
147 | |||
148 | |||
149 | #endif /* __EVIL_INET_H__ */ | ||
diff --git a/src/lib/evil/evil_langinfo.c b/src/lib/evil/evil_langinfo.c new file mode 100644 index 0000000000..32b1f41386 --- /dev/null +++ b/src/lib/evil/evil_langinfo.c | |||
@@ -0,0 +1,53 @@ | |||
1 | #ifdef HAVE_CONFIG_H | ||
2 | # include "config.h" | ||
3 | #endif /* HAVE_CONFIG_H */ | ||
4 | |||
5 | #include "Evil.h" | ||
6 | |||
7 | |||
8 | #ifndef __MINGW32CE__ | ||
9 | |||
10 | static char * | ||
11 | replace(char *prev, char *value) | ||
12 | { | ||
13 | if (!value) | ||
14 | return prev; | ||
15 | |||
16 | if (prev) | ||
17 | free (prev); | ||
18 | return strdup (value); | ||
19 | } | ||
20 | |||
21 | char * | ||
22 | nl_langinfo(nl_item index) | ||
23 | { | ||
24 | static char *result = NULL; | ||
25 | static char *nothing = ""; | ||
26 | |||
27 | switch (index) | ||
28 | { | ||
29 | case CODESET: | ||
30 | { | ||
31 | char *p; | ||
32 | result = replace(result, setlocale(LC_CTYPE, NULL)); | ||
33 | if (!(p = strrchr(result, '.'))) | ||
34 | return nothing; | ||
35 | |||
36 | if ((++p - result) > 2) | ||
37 | strcpy(result, "cp"); | ||
38 | else | ||
39 | *result = '\0'; | ||
40 | strcat(result, p); | ||
41 | |||
42 | return result; | ||
43 | } | ||
44 | case RADIXCHAR: | ||
45 | { | ||
46 | return localeconv()->decimal_point; | ||
47 | } | ||
48 | } | ||
49 | |||
50 | return nothing; | ||
51 | } | ||
52 | |||
53 | #endif /* ! __MINGW32CE__ */ | ||
diff --git a/src/lib/evil/evil_langinfo.h b/src/lib/evil/evil_langinfo.h new file mode 100644 index 0000000000..0e9485a5c1 --- /dev/null +++ b/src/lib/evil/evil_langinfo.h | |||
@@ -0,0 +1,41 @@ | |||
1 | #ifndef __EVIL_LANGINFO_H__ | ||
2 | #define __EVIL_LANGINFO_H__ | ||
3 | |||
4 | |||
5 | #ifndef __MINGW32CE__ | ||
6 | |||
7 | #include <locale.h> | ||
8 | |||
9 | |||
10 | typedef int nl_item; | ||
11 | |||
12 | #define __NL_ITEM( CATEGORY, INDEX ) ((CATEGORY << 16) | INDEX) | ||
13 | #define __NL_ITEM_CATEGORY( ITEM ) (ITEM >> 16) | ||
14 | #define __NL_ITEM_INDEX( ITEM ) (ITEM & 0xffff) | ||
15 | |||
16 | enum { | ||
17 | /* | ||
18 | * LC_CTYPE category... | ||
19 | * Character set classification items. | ||
20 | */ | ||
21 | _NL_CTYPE_CODESET = __NL_ITEM( LC_CTYPE, 0 ), | ||
22 | _NL_NUMERIC_RADIXCHAR = __NL_ITEM( LC_NUMERIC, 0 ), | ||
23 | |||
24 | /* | ||
25 | * Dummy entry, to terminate the list. | ||
26 | */ | ||
27 | _NL_ITEM_CLASSIFICATION_END | ||
28 | }; | ||
29 | |||
30 | /* | ||
31 | * Define the public aliases for the enumerated classification indices... | ||
32 | */ | ||
33 | # define CODESET _NL_CTYPE_CODESET | ||
34 | # define RADIXCHAR _NL_NUMERIC_RADIXCHAR | ||
35 | |||
36 | EAPI char *nl_langinfo(nl_item index); | ||
37 | |||
38 | #endif /* __MINGW32CE__ */ | ||
39 | |||
40 | |||
41 | #endif /*__EVIL_LANGINFO_H__ */ | ||
diff --git a/src/lib/evil/evil_libgen.c b/src/lib/evil/evil_libgen.c new file mode 100644 index 0000000000..7e98f74386 --- /dev/null +++ b/src/lib/evil/evil_libgen.c | |||
@@ -0,0 +1,103 @@ | |||
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 | char _evil_basename_buf[PATH_MAX]; | ||
10 | char _evil_dirname_buf[PATH_MAX]; | ||
11 | |||
12 | char * | ||
13 | evil_basename(char *path) | ||
14 | { | ||
15 | char *p1; | ||
16 | char *p2; | ||
17 | size_t length; | ||
18 | |||
19 | /* path must begin by "?:\" or "?:/" */ | ||
20 | if ((!path) || !evil_path_is_absolute(path)) | ||
21 | { | ||
22 | memcpy(_evil_basename_buf, "C:\\", 4); | ||
23 | return _evil_basename_buf; | ||
24 | } | ||
25 | |||
26 | /* '/' --> '\\' */ | ||
27 | length = strlen(path); | ||
28 | p1 = strdup(path); | ||
29 | if (!p1) | ||
30 | { | ||
31 | memcpy(_evil_basename_buf, "C:\\", 4); | ||
32 | return _evil_basename_buf; | ||
33 | } | ||
34 | p2 = p1; | ||
35 | while (*p2) | ||
36 | { | ||
37 | if (*p2 == '/') *p2 = '\\'; | ||
38 | p2++; | ||
39 | } | ||
40 | |||
41 | /* remove trailing backslashes */ | ||
42 | p2 = p1 + (length - 1); | ||
43 | if (*p2 == '\\') | ||
44 | { | ||
45 | while (*p2 == '\\') | ||
46 | p2--; | ||
47 | } | ||
48 | *(p2 + 1) = '\0'; | ||
49 | |||
50 | p2 = strrchr(p1, '\\'); | ||
51 | memcpy(_evil_basename_buf, p2 + 1, (p1 + length + 1) - p2); | ||
52 | |||
53 | free(p1); | ||
54 | |||
55 | return _evil_basename_buf; | ||
56 | } | ||
57 | |||
58 | char * | ||
59 | evil_dirname(char *path) | ||
60 | { | ||
61 | char *p1; | ||
62 | char *p2; | ||
63 | size_t length; | ||
64 | |||
65 | /* path must begin by "?:\" or "?:/" */ | ||
66 | if ((!path) || !evil_path_is_absolute(path)) | ||
67 | { | ||
68 | memcpy(_evil_dirname_buf, "C:\\", 4); | ||
69 | return _evil_dirname_buf; | ||
70 | } | ||
71 | |||
72 | /* '/' --> '\\' */ | ||
73 | length = strlen(path); | ||
74 | p1 = strdup(path); | ||
75 | if (!p1) | ||
76 | { | ||
77 | memcpy(_evil_dirname_buf, "C:\\", 4); | ||
78 | return _evil_dirname_buf; | ||
79 | } | ||
80 | p2 = p1; | ||
81 | while (*p2) | ||
82 | { | ||
83 | if (*p2 == '/') *p2 = '\\'; | ||
84 | p2++; | ||
85 | } | ||
86 | |||
87 | /* remove trailing backslashes */ | ||
88 | p2 = p1 + (length - 1); | ||
89 | if (*p2 == '\\') | ||
90 | { | ||
91 | while (*p2 == '\\') | ||
92 | p2--; | ||
93 | } | ||
94 | *(p2 + 1) = '\0'; | ||
95 | |||
96 | p2 = strrchr(p1, '\\'); | ||
97 | *p2 = '\0'; | ||
98 | memcpy(_evil_dirname_buf, p1, strlen(p1) + 1); | ||
99 | |||
100 | free(p1); | ||
101 | |||
102 | return _evil_dirname_buf; | ||
103 | } | ||
diff --git a/src/lib/evil/evil_libgen.h b/src/lib/evil/evil_libgen.h new file mode 100644 index 0000000000..4ca977ce86 --- /dev/null +++ b/src/lib/evil/evil_libgen.h | |||
@@ -0,0 +1,88 @@ | |||
1 | #ifndef __EVIL_LIBGEN_H__ | ||
2 | #define __EVIL_LIBGEN_H__ | ||
3 | |||
4 | |||
5 | /** | ||
6 | * @file evil_libgen.h | ||
7 | * @brief The file that provides functions ported from Unix in libgen.h. | ||
8 | * @defgroup Evil_Libgen_Group Libgen.h functions. | ||
9 | * | ||
10 | * This header provides functions ported from Unix in libgen.h. | ||
11 | * | ||
12 | * @{ | ||
13 | */ | ||
14 | |||
15 | /** | ||
16 | * @brief Parse the base name component of a path. | ||
17 | * | ||
18 | * @param path The path to parse. | ||
19 | * @return The component following the final '/'. | ||
20 | * | ||
21 | * This function parses @p path and returns its component following | ||
22 | * the final '\'. Trailing '\' are not taken into account. On Windows | ||
23 | * XP, @p path must beginning by a drive letter followed by ':/' or | ||
24 | * ':\', otherwise "C:\" is returned. All characters '/' are replaced by '\'. On | ||
25 | * error (memory allocation failure), "C:\" is returned, otherwise the | ||
26 | * component following the final '\' is returned as a statically | ||
27 | * allocated memory. Hence the returns value must not be freed. | ||
28 | * | ||
29 | * Concatenating the string returned by dirname(), a "\", and the | ||
30 | * string returned by basename() yields a complete pathname. | ||
31 | * | ||
32 | * @see evil_dirname() | ||
33 | * @see dirname() | ||
34 | * | ||
35 | * Conformity: Non applicable. | ||
36 | * | ||
37 | * Supported OS: Windows XP. | ||
38 | */ | ||
39 | EAPI char *evil_basename(char *path); | ||
40 | |||
41 | /** | ||
42 | * @def basename(p) | ||
43 | * | ||
44 | * Wrapper around evil_basename(). | ||
45 | */ | ||
46 | #define basename(p) evil_basename(p) | ||
47 | |||
48 | /** | ||
49 | * @brief Parse the dir name component of a path. | ||
50 | * | ||
51 | * @param path The path to parse. | ||
52 | * @return The component up to, but not including, the final '/'. | ||
53 | * | ||
54 | * This function parses @p path and returns its component up to, but | ||
55 | * not including, the final '/'. Trailing '\' are not taken into | ||
56 | * account. On Windows XP, @p path must beginning by a drive letter | ||
57 | * followed by ':/' or ':\', otherwise "C:\" is returned. All | ||
58 | * characters '/' are replaced by '\'. On error (memory allocation | ||
59 | * failure), "C:\" is returned, otherwise, the component up to, but | ||
60 | * not including, the final '/' is returned as a statically allocated | ||
61 | * memory. Hence the returns value must not be freed. | ||
62 | * | ||
63 | * Concatenating the string returned by dirname(), a "\", and the | ||
64 | * string returned by basename() yields a complete pathname. | ||
65 | * | ||
66 | * @see evil_basename() | ||
67 | * @see basename() | ||
68 | * | ||
69 | * Conformity: Non applicable. | ||
70 | * | ||
71 | * Supported OS: Windows XP. | ||
72 | */ | ||
73 | EAPI char *evil_dirname(char *path); | ||
74 | |||
75 | /** | ||
76 | * @def dirname(p) | ||
77 | * | ||
78 | * Wrapper around evil_dirname(). | ||
79 | */ | ||
80 | #define dirname(p) evil_dirname(p) | ||
81 | |||
82 | |||
83 | /** | ||
84 | * @} | ||
85 | */ | ||
86 | |||
87 | |||
88 | #endif /* __EVIL_LIBGEN_H__ */ | ||
diff --git a/src/lib/evil/evil_link_ce.c b/src/lib/evil/evil_link_ce.c new file mode 100644 index 0000000000..17532cc4d6 --- /dev/null +++ b/src/lib/evil/evil_link_ce.c | |||
@@ -0,0 +1,90 @@ | |||
1 | #ifdef HAVE_CONFIG_H | ||
2 | # include "config.h" | ||
3 | #endif /* HAVE_CONFIG_H */ | ||
4 | |||
5 | #ifndef WIN32_LEAN_AND_MEAN | ||
6 | # define WIN32_LEAN_AND_MEAN | ||
7 | #endif | ||
8 | #include <windows.h> | ||
9 | #undef WIN32_LEAN_AND_MEAN | ||
10 | |||
11 | #include <shellapi.h> | ||
12 | |||
13 | #include "Evil.h" | ||
14 | #include "evil_private.h" | ||
15 | |||
16 | |||
17 | /* | ||
18 | * Symbolic links and directory related functions | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | |||
23 | /* REMARK: Windows has no symbolic link. */ | ||
24 | /* Nevertheless, it can create and read .lnk files */ | ||
25 | |||
26 | int | ||
27 | symlink(const char *oldpath, const char *newpath) | ||
28 | { | ||
29 | wchar_t *w_oldpath; | ||
30 | wchar_t *w_newpath; | ||
31 | BOOL res; | ||
32 | |||
33 | w_oldpath = evil_char_to_wchar(oldpath); | ||
34 | if (!w_oldpath) | ||
35 | return -1; | ||
36 | |||
37 | w_newpath = evil_char_to_wchar(newpath); | ||
38 | if (!w_newpath) | ||
39 | { | ||
40 | free(w_oldpath); | ||
41 | return -1; | ||
42 | } | ||
43 | |||
44 | res = SHCreateShortcut(w_newpath, w_oldpath); | ||
45 | if (!res) | ||
46 | _evil_last_error_display(__FUNCTION__); | ||
47 | |||
48 | free(w_oldpath); | ||
49 | free(w_newpath); | ||
50 | |||
51 | return res ? 0 : -1; | ||
52 | } | ||
53 | |||
54 | ssize_t | ||
55 | readlink(const char *path, char *buf, size_t bufsiz) | ||
56 | { | ||
57 | wchar_t *w_path; | ||
58 | wchar_t w_newpath[1024]; | ||
59 | char *newpath; | ||
60 | size_t length; | ||
61 | BOOL res; | ||
62 | |||
63 | w_path = evil_char_to_wchar(path); | ||
64 | if (!w_path) | ||
65 | return -1; | ||
66 | |||
67 | res = SHGetShortcutTarget(w_path, w_newpath, 1024); | ||
68 | if (!res) | ||
69 | _evil_last_error_display(__FUNCTION__); | ||
70 | |||
71 | free(w_path); | ||
72 | |||
73 | if (!res) | ||
74 | return -1; | ||
75 | |||
76 | newpath = evil_wchar_to_char(w_newpath); | ||
77 | if (!newpath) | ||
78 | return -1; | ||
79 | |||
80 | /* That stupid SHGetShortcutTarget add " around the file name... */ | ||
81 | length = strlen(newpath) - 2; | ||
82 | if (length > bufsiz) | ||
83 | length = bufsiz; | ||
84 | |||
85 | memcpy(buf, newpath + 1, length); | ||
86 | |||
87 | free(newpath); | ||
88 | |||
89 | return length; | ||
90 | } | ||
diff --git a/src/lib/evil/evil_link_xp.cpp b/src/lib/evil/evil_link_xp.cpp new file mode 100644 index 0000000000..675908f75b --- /dev/null +++ b/src/lib/evil/evil_link_xp.cpp | |||
@@ -0,0 +1,151 @@ | |||
1 | #ifdef HAVE_CONFIG_H | ||
2 | # include "config.h" | ||
3 | #endif /* HAVE_CONFIG_H */ | ||
4 | |||
5 | #ifdef HAVE_ERRNO_H | ||
6 | #include <errno.h> | ||
7 | #endif /* HAVE_ERRNO_H */ | ||
8 | |||
9 | #include <shlobj.h> | ||
10 | #include <objidl.h> | ||
11 | #include <cstdio> | ||
12 | |||
13 | #include "Evil.h" | ||
14 | |||
15 | |||
16 | /* | ||
17 | * Symbolic links and directory related functions | ||
18 | * | ||
19 | */ | ||
20 | |||
21 | |||
22 | /* REMARK: Windows has no symbolic link. */ | ||
23 | /* Nevertheless, it can create and read .lnk files */ | ||
24 | int | ||
25 | symlink(const char *oldpath, const char *newpath) | ||
26 | { | ||
27 | char fullname[PATH_MAX]; | ||
28 | wchar_t *wnewpath; | ||
29 | IShellLink *pISL; | ||
30 | IPersistFile *pIPF; | ||
31 | HRESULT res; | ||
32 | size_t size; | ||
33 | |||
34 | realpath(oldpath, fullname); | ||
35 | |||
36 | res = CoInitialize(NULL); | ||
37 | if (FAILED(res)) | ||
38 | { | ||
39 | if (res == E_OUTOFMEMORY) | ||
40 | errno = ENOMEM; | ||
41 | return -1; | ||
42 | } | ||
43 | |||
44 | if (FAILED(CoCreateInstance(CLSID_ShellLink, | ||
45 | NULL, | ||
46 | CLSCTX_INPROC_SERVER, | ||
47 | IID_IShellLink, | ||
48 | (void **)&pISL))) | ||
49 | goto no_instance; | ||
50 | |||
51 | if (FAILED(pISL->SetPath(fullname))) | ||
52 | goto no_setpath; | ||
53 | |||
54 | if (FAILED(pISL->QueryInterface(IID_IPersistFile, (void **)&pIPF))) | ||
55 | goto no_queryinterface; | ||
56 | |||
57 | size = mbstowcs(NULL, newpath, 0); | ||
58 | wnewpath = (wchar_t *)malloc((size + 1) * sizeof(wchar_t)); | ||
59 | if (!wnewpath) | ||
60 | goto malloc_failure; | ||
61 | if (mbstowcs(wnewpath, newpath, size + 1) == (size_t)(-1)) | ||
62 | goto translation_failure; | ||
63 | if (FAILED(pIPF->Save(wnewpath, FALSE))) | ||
64 | goto no_save; | ||
65 | |||
66 | free(wnewpath); | ||
67 | pIPF->Release(); | ||
68 | pISL->Release(); | ||
69 | CoUninitialize(); | ||
70 | |||
71 | return 0; | ||
72 | |||
73 | no_save: | ||
74 | translation_failure: | ||
75 | malloc_failure: | ||
76 | pIPF->Release(); | ||
77 | no_queryinterface: | ||
78 | no_setpath: | ||
79 | pISL->Release(); | ||
80 | no_instance: | ||
81 | CoUninitialize(); | ||
82 | return -1; | ||
83 | } | ||
84 | |||
85 | ssize_t | ||
86 | readlink(const char *path, char *buf, size_t bufsiz) | ||
87 | { | ||
88 | wchar_t *wpath; | ||
89 | char new_path[PATH_MAX]; | ||
90 | IShellLink *pISL; | ||
91 | IPersistFile *pIPF; | ||
92 | size_t length; | ||
93 | HRESULT res; | ||
94 | size_t size; | ||
95 | |||
96 | res = CoInitialize(NULL); | ||
97 | if (FAILED(res)) | ||
98 | { | ||
99 | if (res == E_OUTOFMEMORY) | ||
100 | errno = ENOMEM; | ||
101 | return -1; | ||
102 | } | ||
103 | |||
104 | if (FAILED(CoCreateInstance(CLSID_ShellLink, | ||
105 | NULL, | ||
106 | CLSCTX_INPROC_SERVER, | ||
107 | IID_IShellLink, | ||
108 | (void **)&pISL))) | ||
109 | goto couninitialize; | ||
110 | |||
111 | if (FAILED(pISL->QueryInterface(IID_IPersistFile, (void **)&pIPF))) | ||
112 | goto release_shell_link; | ||
113 | |||
114 | size = mbstowcs(NULL, path, 0); | ||
115 | wpath = (wchar_t *)malloc((size + 1) * sizeof(wchar_t)); | ||
116 | if (!wpath) | ||
117 | goto release_persist_file; | ||
118 | |||
119 | mbstowcs(wpath, path, size + 1); | ||
120 | if (FAILED(pIPF->Load(wpath, STGM_READ))) | ||
121 | goto free_wpath; | ||
122 | |||
123 | if (FAILED(pISL->Resolve(NULL, SLR_UPDATE | SLR_NO_UI))) | ||
124 | goto free_wpath; | ||
125 | |||
126 | if (FAILED(pISL->GetPath(new_path, PATH_MAX, NULL, 0))) | ||
127 | goto free_wpath; | ||
128 | |||
129 | length = strlen(new_path); | ||
130 | if (length > bufsiz) | ||
131 | length = bufsiz; | ||
132 | |||
133 | memcpy(buf, new_path, length); | ||
134 | |||
135 | free(wpath); | ||
136 | pISL->Release(); | ||
137 | pIPF->Release(); | ||
138 | CoUninitialize(); | ||
139 | |||
140 | return length; | ||
141 | |||
142 | free_wpath: | ||
143 | free(wpath); | ||
144 | release_persist_file: | ||
145 | pIPF->Release(); | ||
146 | release_shell_link: | ||
147 | pISL->Release(); | ||
148 | couninitialize: | ||
149 | CoUninitialize(); | ||
150 | return -1; | ||
151 | } | ||
diff --git a/src/lib/evil/evil_macro.h b/src/lib/evil/evil_macro.h new file mode 100644 index 0000000000..b2500d33c7 --- /dev/null +++ b/src/lib/evil/evil_macro.h | |||
@@ -0,0 +1,193 @@ | |||
1 | #ifndef __EVIL_MACRO_H__ | ||
2 | #define __EVIL_MACRO_H__ | ||
3 | |||
4 | |||
5 | #ifndef __cdecl | ||
6 | # define EVIL_CDECL_IS_DEFINED | ||
7 | # ifdef __GNUC__ | ||
8 | # define __cdecl __attribute__((__cdecl__)) | ||
9 | # else | ||
10 | # define __cdecl | ||
11 | # endif | ||
12 | #endif /* __cdecl */ | ||
13 | |||
14 | |||
15 | #ifdef EAPI | ||
16 | # undef EAPI | ||
17 | #endif /* EAPI */ | ||
18 | |||
19 | #ifdef _WIN32 | ||
20 | # ifdef EFL_EVIL_BUILD | ||
21 | # ifdef DLL_EXPORT | ||
22 | # define EAPI __declspec(dllexport) | ||
23 | # else | ||
24 | # define EAPI | ||
25 | # endif /* ! DLL_EXPORT */ | ||
26 | # else | ||
27 | # define EAPI __declspec(dllimport) | ||
28 | # endif /* ! EFL_EVIL_BUILD */ | ||
29 | #endif /* _WIN32 */ | ||
30 | |||
31 | |||
32 | #ifndef __EVIL_GNUC_PREREQ | ||
33 | # if defined __GNUC__ && defined __GNUC_MINOR__ | ||
34 | # define __EVIL_GNUC_PREREQ( major, minor )\ | ||
35 | (__GNUC__ > (major) || (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor))) | ||
36 | # else | ||
37 | # define __EVIL_GNUC_PREREQ( major, minor ) | ||
38 | # endif | ||
39 | #endif /* __EVIL_GNUC_PREREQ */ | ||
40 | |||
41 | |||
42 | #ifndef __EVIL_NOTHROW | ||
43 | # if __EVIL_GNUC_PREREQ( 3, 3 ) | ||
44 | # define __EVIL_NOTHROW __attribute__((__nothrow__)) | ||
45 | # else | ||
46 | # define __EVIL_NOTHROW | ||
47 | # endif | ||
48 | #endif /* __EVIL_NOTHROW */ | ||
49 | |||
50 | |||
51 | #ifndef __EVIL_PRINTF | ||
52 | # if __EVIL_GNUC_PREREQ( 2, 4 ) | ||
53 | # define __EVIL_PRINTF(fmt, arg) __attribute__((__format__ (__gnu_printf__, fmt, arg))) | ||
54 | # else | ||
55 | # define __EVIL_PRINTF(fmt, arg) | ||
56 | # endif | ||
57 | #endif /* __EVIL_PRINTF */ | ||
58 | |||
59 | |||
60 | #ifndef PATH_MAX | ||
61 | # define PATH_MAX MAX_PATH | ||
62 | #endif /* PATH_MAX */ | ||
63 | #ifdef fprintf | ||
64 | # undef fprintf | ||
65 | #endif | ||
66 | |||
67 | #ifdef printf | ||
68 | # undef printf | ||
69 | #endif | ||
70 | |||
71 | #ifdef sprintf | ||
72 | # undef sprintf | ||
73 | #endif | ||
74 | |||
75 | #ifdef snprintf | ||
76 | # undef snprintf | ||
77 | #endif | ||
78 | |||
79 | #ifdef vfprintf | ||
80 | # undef vfprintf | ||
81 | #endif | ||
82 | |||
83 | #ifdef vprintf | ||
84 | # undef vprintf | ||
85 | #endif | ||
86 | |||
87 | #ifdef vsprintf | ||
88 | # undef vsprintf | ||
89 | #endif | ||
90 | |||
91 | #ifdef vsnprintf | ||
92 | # undef vsnprintf | ||
93 | #endif | ||
94 | |||
95 | #ifdef fscanf | ||
96 | # undef fscanf | ||
97 | #endif | ||
98 | |||
99 | #ifdef scanf | ||
100 | # undef scanf | ||
101 | #endif | ||
102 | |||
103 | #ifdef sscanf | ||
104 | # undef sscanf | ||
105 | #endif | ||
106 | |||
107 | #ifdef vfscanf | ||
108 | # undef vfscanf | ||
109 | #endif | ||
110 | |||
111 | #ifdef vscanf | ||
112 | # undef vscanf | ||
113 | #endif | ||
114 | |||
115 | #ifdef vsscanf | ||
116 | # undef vsscanf | ||
117 | #endif | ||
118 | |||
119 | #ifdef asprintf | ||
120 | # undef asprintf | ||
121 | #endif | ||
122 | |||
123 | #ifdef vasprintf | ||
124 | # undef vasprintf | ||
125 | #endif | ||
126 | |||
127 | |||
128 | #if defined(_INTTYPES_H_) && defined(PRId64) | ||
129 | |||
130 | #undef PRId64 | ||
131 | #undef PRIdLEAST64 | ||
132 | #undef PRIdFAST64 | ||
133 | #undef PRIdMAX | ||
134 | #undef PRIi64 | ||
135 | #undef PRIiLEAST64 | ||
136 | #undef PRIiFAST64 | ||
137 | #undef PRIiMAX | ||
138 | #undef PRIo64 | ||
139 | #undef PRIoLEAST64 | ||
140 | #undef PRIoFAST64 | ||
141 | #undef PRIoMAX | ||
142 | #undef PRIu64 | ||
143 | #undef PRIuLEAST64 | ||
144 | #undef PRIuFAST64 | ||
145 | #undef PRIuMAX | ||
146 | #undef PRIx64 | ||
147 | #undef PRIxLEAST64 | ||
148 | #undef PRIxFAST64 | ||
149 | #undef PRIxMAX | ||
150 | #undef PRIX64 | ||
151 | #undef PRIXLEAST64 | ||
152 | #undef PRIXFAST64 | ||
153 | #undef PRIXMAX | ||
154 | |||
155 | #undef SCNd64 | ||
156 | #undef SCNdLEAST64 | ||
157 | #undef SCNdFAST64 | ||
158 | #undef SCNdMAX | ||
159 | #undef SCNi64 | ||
160 | #undef SCNiLEAST64 | ||
161 | #undef SCNiFAST64 | ||
162 | #undef SCNiMAX | ||
163 | #undef SCNo64 | ||
164 | #undef SCNoLEAST64 | ||
165 | #undef SCNoFAST64 | ||
166 | #undef SCNoMAX | ||
167 | #undef SCNx64 | ||
168 | #undef SCNxLEAST64 | ||
169 | #undef SCNxFAST64 | ||
170 | #undef SCNxMAX | ||
171 | #undef SCNu64 | ||
172 | #undef SCNuLEAST64 | ||
173 | #undef SCNuFAST64 | ||
174 | #undef SCNuMAX | ||
175 | |||
176 | #ifdef _WIN64 | ||
177 | #undef PRIdPTR | ||
178 | #undef PRIiPTR | ||
179 | #undef PRIoPTR | ||
180 | #undef PRIuPTR | ||
181 | #undef PRIxPTR | ||
182 | #undef PRIXPTR | ||
183 | |||
184 | #undef SCNdPTR | ||
185 | #undef SCNiPTR | ||
186 | #undef SCNoPTR | ||
187 | #undef SCNxPTR | ||
188 | #undef SCNuPTR | ||
189 | #endif /* _WIN64 */ | ||
190 | |||
191 | #endif /* defined(_INTTYPES_H_) && defined(PRId64) */ | ||
192 | |||
193 | #endif /* __EVIL_MACRO_H__ */ | ||
diff --git a/src/lib/evil/evil_macro_pop.h b/src/lib/evil/evil_macro_pop.h new file mode 100644 index 0000000000..a82818da9b --- /dev/null +++ b/src/lib/evil/evil_macro_pop.h | |||
@@ -0,0 +1,93 @@ | |||
1 | #ifndef __EVIL_MACRO_POP_H__ | ||
2 | #define __EVIL_MACRO_POP_H__ | ||
3 | |||
4 | |||
5 | #ifdef EVIL_CDECL_IS_DEFINED | ||
6 | # undef __cdecl | ||
7 | # undef EVIL_CDECL_IS_DEFINED | ||
8 | #endif | ||
9 | |||
10 | #define fprintf _evil_fprintfa | ||
11 | #define printf _evil_printfa | ||
12 | #define snprintf _evil_snprintfa | ||
13 | #define sprintf _evil_sprintfa | ||
14 | #define vfprintf _evil_vfprintfa | ||
15 | #define vprintf _evil_vprintfa | ||
16 | #define vsnprintf _evil_vsnprintfa | ||
17 | #define vsprintf _evil_vsprintfa | ||
18 | |||
19 | #define fscanf _evil_fscanf | ||
20 | #define scanf _evil_scanf | ||
21 | #define sscanf _evil_sscanf | ||
22 | #define vfscanf _evil_vfscanf | ||
23 | #define vscanf _evil_vscanf | ||
24 | #define vsscanf _evil_vsscanf | ||
25 | |||
26 | #define asprintf _evil_asprintf | ||
27 | #define vasprintf _evil_vasprintf | ||
28 | |||
29 | /* Redefine to GNU specific PRI... and SCN... macros. */ | ||
30 | |||
31 | #define PRId64 "lld" | ||
32 | #define PRIdLEAST64 "lld" | ||
33 | #define PRIdFAST64 "lld" | ||
34 | #define PRIdMAX "lld" | ||
35 | #define PRIi64 "lli" | ||
36 | #define PRIiLEAST64 "lli" | ||
37 | #define PRIiFAST64 "lli" | ||
38 | #define PRIiMAX "lli" | ||
39 | #define PRIo64 "llo" | ||
40 | #define PRIoLEAST64 "llo" | ||
41 | #define PRIoFAST64 "llo" | ||
42 | #define PRIoMAX "llo" | ||
43 | #define PRIu64 "llu" | ||
44 | #define PRIuLEAST64 "llu" | ||
45 | #define PRIuFAST64 "llu" | ||
46 | #define PRIuMAX "llu" | ||
47 | #define PRIx64 "llx" | ||
48 | #define PRIxLEAST64 "llx" | ||
49 | #define PRIxFAST64 "llx" | ||
50 | #define PRIxMAX "llx" | ||
51 | #define PRIX64 "llX" | ||
52 | #define PRIXLEAST64 "llX" | ||
53 | #define PRIXFAST64 "llX" | ||
54 | #define PRIXMAX "llX" | ||
55 | |||
56 | #define SCNd64 "lld" | ||
57 | #define SCNdLEAST64 "lld" | ||
58 | #define SCNdFAST64 "lld" | ||
59 | #define SCNdMAX "lld" | ||
60 | #define SCNi64 "lli" | ||
61 | #define SCNiLEAST64 "lli" | ||
62 | #define SCNiFAST64 "lli" | ||
63 | #define SCNiMAX "lli" | ||
64 | #define SCNo64 "llo" | ||
65 | #define SCNoLEAST64 "llo" | ||
66 | #define SCNoFAST64 "llo" | ||
67 | #define SCNoMAX "llo" | ||
68 | #define SCNx64 "llx" | ||
69 | #define SCNxLEAST64 "llx" | ||
70 | #define SCNxFAST64 "llx" | ||
71 | #define SCNxMAX "llx" | ||
72 | #define SCNu64 "llu" | ||
73 | #define SCNuLEAST64 "llu" | ||
74 | #define SCNuFAST64 "llu" | ||
75 | #define SCNuMAX "llu" | ||
76 | |||
77 | #ifdef _WIN64 | ||
78 | #define PRIdPTR "lld" | ||
79 | #define PRIiPTR "lli" | ||
80 | #define PRIoPTR "llo" | ||
81 | #define PRIuPTR "llu" | ||
82 | #define PRIxPTR "llx" | ||
83 | #define PRIXPTR "llX" | ||
84 | |||
85 | #define SCNdPTR "lld" | ||
86 | #define SCNiPTR "lli" | ||
87 | #define SCNoPTR "llo" | ||
88 | #define SCNxPTR "llx" | ||
89 | #define SCNuPTR "llu" | ||
90 | #endif /* _WIN64 */ | ||
91 | |||
92 | |||
93 | #endif /* __EVIL_MACRO_POP_H__ */ | ||
diff --git a/src/lib/evil/evil_main.c b/src/lib/evil/evil_main.c new file mode 100644 index 0000000000..ee1eb1d113 --- /dev/null +++ b/src/lib/evil/evil_main.c | |||
@@ -0,0 +1,74 @@ | |||
1 | #ifdef HAVE_CONFIG_H | ||
2 | # include <config.h> | ||
3 | #endif | ||
4 | |||
5 | #ifndef WIN32_LEAN_AND_MEAN | ||
6 | # define WIN32_LEAN_AND_MEAN | ||
7 | #endif | ||
8 | #include <winsock2.h> | ||
9 | #undef WIN32_LEAN_AND_MEAN | ||
10 | |||
11 | #include "Evil.h" | ||
12 | #include "evil_private.h" | ||
13 | |||
14 | |||
15 | static int _evil_init_count = 0; | ||
16 | |||
17 | extern LONGLONG _evil_time_freq; | ||
18 | extern LONGLONG _evil_time_count; | ||
19 | extern long _evil_time_second; | ||
20 | |||
21 | int | ||
22 | evil_init(void) | ||
23 | { | ||
24 | SYSTEMTIME st; | ||
25 | LARGE_INTEGER freq; | ||
26 | LARGE_INTEGER count; | ||
27 | WORD second = 59; | ||
28 | |||
29 | if (++_evil_init_count != 1) | ||
30 | return _evil_init_count; | ||
31 | |||
32 | if (!QueryPerformanceFrequency(&freq)) | ||
33 | return 0; | ||
34 | |||
35 | _evil_time_freq = freq.QuadPart; | ||
36 | |||
37 | /* be sure that second + 1 != 0 */ | ||
38 | while (second == 59) | ||
39 | { | ||
40 | GetSystemTime(&st); | ||
41 | second = st.wSecond; | ||
42 | } | ||
43 | |||
44 | /* retrieve the tick corresponding to the time we retrieve above */ | ||
45 | while (1) | ||
46 | { | ||
47 | GetSystemTime(&st); | ||
48 | QueryPerformanceCounter(&count); | ||
49 | if (st.wSecond == second + 1) | ||
50 | break; | ||
51 | } | ||
52 | |||
53 | _evil_time_second = _evil_systemtime_to_time(st); | ||
54 | if (_evil_time_second < 0) | ||
55 | return --_evil_init_count; | ||
56 | |||
57 | _evil_time_count = count.QuadPart; | ||
58 | |||
59 | if (!evil_sockets_init()) | ||
60 | return --_evil_init_count; | ||
61 | |||
62 | return _evil_init_count; | ||
63 | } | ||
64 | |||
65 | int | ||
66 | evil_shutdown(void) | ||
67 | { | ||
68 | if (--_evil_init_count != 0) | ||
69 | return _evil_init_count; | ||
70 | |||
71 | evil_sockets_shutdown(); | ||
72 | |||
73 | return _evil_init_count; | ||
74 | } | ||
diff --git a/src/lib/evil/evil_main.h b/src/lib/evil/evil_main.h new file mode 100644 index 0000000000..157e6028b7 --- /dev/null +++ b/src/lib/evil/evil_main.h | |||
@@ -0,0 +1,52 @@ | |||
1 | #ifndef __EVIL_MAIN_H__ | ||
2 | #define __EVIL_MAIN_H__ | ||
3 | |||
4 | |||
5 | /** | ||
6 | * @file evil_main.h | ||
7 | * @brief The file that provides functions to initialize and shut down Evil. | ||
8 | * @defgroup Evil_Main_Group Main | ||
9 | * | ||
10 | * This header provides functions to initialize and shut down the Evil | ||
11 | * library. | ||
12 | * | ||
13 | * @{ | ||
14 | */ | ||
15 | |||
16 | |||
17 | /** | ||
18 | * @brief Initialize the Evil library. | ||
19 | * | ||
20 | * This function initializes the Evil library. It must be called before | ||
21 | * using evil_time_get(), gettimeofday() or pipe(). It returns 0 on | ||
22 | * failure, otherwise it returns the number of times it has already been | ||
23 | * called. | ||
24 | * | ||
25 | * When Evil is not used anymore, call evil_shutdown() to shut down | ||
26 | * the Evil library. | ||
27 | */ | ||
28 | EAPI int evil_init(void); | ||
29 | |||
30 | /** | ||
31 | * @brief Shut down the Evil library. | ||
32 | * | ||
33 | * @return 0 when the Evil library is completely shut down, 1 or | ||
34 | * greater otherwise. | ||
35 | * | ||
36 | * This function shuts down the Evil library. It returns 0 when it has | ||
37 | * been called the same number of times than evil_init(). | ||
38 | * | ||
39 | * Once this function succeeds (that is, @c 0 is returned), you must | ||
40 | * not call any of the Evil function listed in evil_init() | ||
41 | * documentation anymore . You must call evil_init() again to use these | ||
42 | * functions again. | ||
43 | */ | ||
44 | EAPI int evil_shutdown(void); | ||
45 | |||
46 | |||
47 | /** | ||
48 | * @} | ||
49 | */ | ||
50 | |||
51 | |||
52 | #endif /* __EVIL_MAIN_H__ */ | ||
diff --git a/src/lib/evil/evil_mman.c b/src/lib/evil/evil_mman.c new file mode 100644 index 0000000000..8898357cfc --- /dev/null +++ b/src/lib/evil/evil_mman.c | |||
@@ -0,0 +1,234 @@ | |||
1 | #ifdef HAVE_CONFIG_H | ||
2 | # include "config.h" | ||
3 | #endif /* HAVE_CONFIG_H */ | ||
4 | |||
5 | #include <stdlib.h> | ||
6 | #include <stdio.h> | ||
7 | #include <sys/types.h> | ||
8 | |||
9 | #ifndef _MSC_VER | ||
10 | # include <unistd.h> | ||
11 | #endif | ||
12 | |||
13 | #ifndef WIN32_LEAN_AND_MEAN | ||
14 | # define WIN32_LEAN_AND_MEAN | ||
15 | #endif | ||
16 | #include <windows.h> | ||
17 | #undef WIN32_LEAN_AND_MEAN | ||
18 | |||
19 | # include <io.h> | ||
20 | |||
21 | #include "evil_macro.h" | ||
22 | #include "sys/mman.h" | ||
23 | #include "evil_util.h" | ||
24 | #include "evil_private.h" | ||
25 | #define APICHAR char | ||
26 | #include "evil_print.h" | ||
27 | |||
28 | #ifdef __MINGW32CE__ | ||
29 | # define _get_osfhandle(FILEDES) ((long)FILEDES) | ||
30 | #endif /* __MINGW32CE__ */ | ||
31 | |||
32 | |||
33 | /***** API *****/ | ||
34 | |||
35 | |||
36 | void * | ||
37 | mmap(void *addr __UNUSED__, | ||
38 | size_t len, | ||
39 | int prot, | ||
40 | int flags, | ||
41 | int fd, | ||
42 | off_t offset) | ||
43 | { | ||
44 | OSVERSIONINFO os_version; | ||
45 | |||
46 | os_version.dwOSVersionInfoSize = sizeof(os_version); | ||
47 | if (!GetVersionEx(&os_version)) | ||
48 | { | ||
49 | char *str; | ||
50 | |||
51 | str = evil_last_error_get(); | ||
52 | fprintf(stderr, "[Evil] [mmap] GetVersionEx failed: %s\n", str); | ||
53 | free(str); | ||
54 | |||
55 | return MAP_FAILED; | ||
56 | } | ||
57 | |||
58 | #ifdef _WIN32_WCE | ||
59 | if ((os_version.dwPlatformId == VER_PLATFORM_WIN32_CE) && | ||
60 | (os_version.dwMajorVersion < 5)) | ||
61 | { | ||
62 | void *data; | ||
63 | size_t size; | ||
64 | |||
65 | data = malloc(len); | ||
66 | if (!data) | ||
67 | { | ||
68 | fprintf (stderr, "[Evil] [mmap] malloc failed\n"); | ||
69 | return MAP_FAILED; | ||
70 | } | ||
71 | |||
72 | size = read(fd, data, len); | ||
73 | if (size != len) | ||
74 | { | ||
75 | fprintf (stderr, "[Evil] [mmap] read failed\n"); | ||
76 | free(data); | ||
77 | return MAP_FAILED; | ||
78 | } | ||
79 | |||
80 | if (lseek(fd, 0, SEEK_SET) == -1) | ||
81 | { | ||
82 | fprintf (stderr, "[Evil] [mmap] lseek failed\n"); | ||
83 | free(data); | ||
84 | return MAP_FAILED; | ||
85 | } | ||
86 | |||
87 | return data; | ||
88 | } | ||
89 | else | ||
90 | #endif /* ! _WIN32_WCE */ | ||
91 | { | ||
92 | HANDLE fm; | ||
93 | DWORD protect = PAGE_NOACCESS; | ||
94 | DWORD acs = 0; | ||
95 | HANDLE handle; | ||
96 | void *data; | ||
97 | |||
98 | /* support only MAP_SHARED */ | ||
99 | if (!(flags & MAP_SHARED)) | ||
100 | return MAP_FAILED; | ||
101 | |||
102 | if (prot & PROT_EXEC) | ||
103 | { | ||
104 | if (prot & PROT_READ) | ||
105 | { | ||
106 | if (prot & PROT_WRITE) | ||
107 | protect = PAGE_EXECUTE_READWRITE; | ||
108 | else | ||
109 | protect = PAGE_EXECUTE_READ; | ||
110 | } | ||
111 | else | ||
112 | { | ||
113 | if (prot & PROT_WRITE) | ||
114 | protect = PAGE_EXECUTE_WRITECOPY; | ||
115 | else | ||
116 | protect = PAGE_EXECUTE; | ||
117 | } | ||
118 | } | ||
119 | else | ||
120 | { | ||
121 | if (prot & PROT_READ) | ||
122 | { | ||
123 | if (prot & PROT_WRITE) | ||
124 | protect = PAGE_READWRITE; | ||
125 | else | ||
126 | protect = PAGE_READONLY; | ||
127 | } | ||
128 | else if (prot & PROT_WRITE) | ||
129 | protect = PAGE_WRITECOPY; | ||
130 | } | ||
131 | |||
132 | handle = (HANDLE)_get_osfhandle(fd); | ||
133 | if (handle == INVALID_HANDLE_VALUE) | ||
134 | { | ||
135 | fprintf(stderr, "[Evil] [mmap] _get_osfhandle failed\n"); | ||
136 | |||
137 | return MAP_FAILED; | ||
138 | } | ||
139 | |||
140 | fm = CreateFileMapping(handle, NULL, protect, 0, 0, NULL); | ||
141 | if (!fm) | ||
142 | { | ||
143 | char *str; | ||
144 | |||
145 | str = evil_last_error_get(); | ||
146 | fprintf(stderr, "[Evil] [mmap] CreateFileMapping failed: %s\n", str); | ||
147 | free(str); | ||
148 | |||
149 | return MAP_FAILED; | ||
150 | } | ||
151 | |||
152 | if (protect & PAGE_READWRITE) | ||
153 | acs = FILE_MAP_ALL_ACCESS; | ||
154 | if (protect & PAGE_WRITECOPY) | ||
155 | acs = FILE_MAP_COPY; | ||
156 | #if 0 | ||
157 | if (protect & (PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_READ)) | ||
158 | acs = FILE_MAP_EXECUTE; | ||
159 | #endif | ||
160 | if (protect & (PAGE_READWRITE | PAGE_READONLY)) | ||
161 | acs = FILE_MAP_READ; | ||
162 | else | ||
163 | { | ||
164 | if (protect & PAGE_READWRITE) | ||
165 | acs = FILE_MAP_WRITE; | ||
166 | } | ||
167 | |||
168 | data = MapViewOfFile(fm, | ||
169 | acs, | ||
170 | offset & 0xffff0000, | ||
171 | offset & 0x0000ffff, | ||
172 | len); | ||
173 | CloseHandle(fm); | ||
174 | |||
175 | if (!data) | ||
176 | { | ||
177 | char *str; | ||
178 | |||
179 | str = evil_last_error_get(); | ||
180 | fprintf(stderr, "[Evil] [mmap] MapViewOfFile failed: %s\n", str); | ||
181 | free(str); | ||
182 | |||
183 | return MAP_FAILED; | ||
184 | } | ||
185 | |||
186 | return data; | ||
187 | } | ||
188 | } | ||
189 | |||
190 | int | ||
191 | munmap(void *addr, | ||
192 | size_t len __UNUSED__) | ||
193 | { | ||
194 | #ifdef _WIN32_WCE | ||
195 | OSVERSIONINFO os_version; | ||
196 | |||
197 | os_version.dwOSVersionInfoSize = sizeof(os_version); | ||
198 | if (!GetVersionEx(&os_version)) | ||
199 | { | ||
200 | char *str; | ||
201 | |||
202 | str = evil_last_error_get(); | ||
203 | fprintf(stderr, "[Evil] [munmap] GetVersionEx failed: %s\n", str); | ||
204 | free(str); | ||
205 | |||
206 | return -1; | ||
207 | } | ||
208 | |||
209 | if ((os_version.dwPlatformId == VER_PLATFORM_WIN32_CE) && | ||
210 | (os_version.dwMajorVersion < 5)) | ||
211 | { | ||
212 | if (addr && (addr != MAP_FAILED)) | ||
213 | free(addr); | ||
214 | |||
215 | return 0; | ||
216 | } | ||
217 | else | ||
218 | #endif /* ! _WIN32_WCE */ | ||
219 | { | ||
220 | BOOL res; | ||
221 | |||
222 | res = UnmapViewOfFile(addr); | ||
223 | if (!res) | ||
224 | { | ||
225 | char *str; | ||
226 | |||
227 | str = evil_last_error_get(); | ||
228 | fprintf(stderr, "[Evil] [munmap] UnmapViewOfFile failed: %s\n", str); | ||
229 | free(str); | ||
230 | } | ||
231 | |||
232 | return (res == 0) ? -1 : 0; | ||
233 | } | ||
234 | } | ||
diff --git a/src/lib/evil/evil_pformat.h b/src/lib/evil/evil_pformat.h new file mode 100644 index 0000000000..ad9b61e024 --- /dev/null +++ b/src/lib/evil/evil_pformat.h | |||
@@ -0,0 +1,61 @@ | |||
1 | #ifndef __EVIL_PRIVATE_H__ | ||
2 | #define __EVIL_PRIVATE_H__ | ||
3 | |||
4 | |||
5 | #include "evil_macro.h" | ||
6 | |||
7 | |||
8 | #ifdef __BUILD_WIDEAPI | ||
9 | #define APICHAR wchar_t | ||
10 | #else | ||
11 | #define APICHAR char | ||
12 | #endif | ||
13 | |||
14 | /* The following are the declarations specific to the `pformat' API... | ||
15 | */ | ||
16 | #define PFORMAT_TO_FILE 0x1000 | ||
17 | #define PFORMAT_NOLIMIT 0x2000 | ||
18 | |||
19 | |||
20 | #ifdef __cplusplus | ||
21 | extern "C" { | ||
22 | #endif | ||
23 | |||
24 | |||
25 | #ifdef __BUILD_WIDEAPI | ||
26 | # define __fputc(X,STR) fputwc((wchar_t) (X), (STR)) | ||
27 | # define _evil_pformat _evil_pformatw | ||
28 | |||
29 | # define _evil_fprintf _evil_fprintfw | ||
30 | # define _evil_printf _evil_printfw | ||
31 | # define _evil_snprintf _evil_snprintfw | ||
32 | # define _evil_sprintf _evil_sprintfw | ||
33 | |||
34 | # define _evil_vfprintf _evil_vfprintfw | ||
35 | # define _evil_vprintf _evil_vprintfw | ||
36 | # define _evil_vsnprintf _evil_vsnprintfw | ||
37 | # define _evil_vsprintf _evil_vsprintfw | ||
38 | #else | ||
39 | # define __fputc(X,STR) fputc((X), (STR)) | ||
40 | # define _evil_pformat _evil_pformata | ||
41 | |||
42 | # define _evil_fprintf _evil_fprintfa | ||
43 | # define _evil_printf _evil_printfa | ||
44 | # define _evil_snprintf _evil_snprintfa | ||
45 | # define _evil_sprintf _evil_sprintfa | ||
46 | |||
47 | # define _evil_vfprintf _evil_vfprintfa | ||
48 | # define _evil_vprintf _evil_vprintfa | ||
49 | # define _evil_vsnprintf _evil_vsnprintfa | ||
50 | # define _evil_vsprintf _evil_vsprintfa | ||
51 | #endif | ||
52 | |||
53 | int __cdecl _evil_pformat(int, void *, int, const APICHAR *, va_list) __EVIL_NOTHROW; | ||
54 | |||
55 | |||
56 | #ifdef __cplusplus | ||
57 | } | ||
58 | #endif | ||
59 | |||
60 | |||
61 | #endif /* __EVIL_PRIVATE_H__ */ | ||
diff --git a/src/lib/evil/evil_pformata.c b/src/lib/evil/evil_pformata.c new file mode 100644 index 0000000000..ee1d68e772 --- /dev/null +++ b/src/lib/evil/evil_pformata.c | |||
@@ -0,0 +1,2493 @@ | |||
1 | /* pformat.c | ||
2 | * | ||
3 | * $Id: pformat.c,v 1.9 2011/01/07 22:57:00 keithmarshall Exp $ | ||
4 | * | ||
5 | * Provides a core implementation of the formatting capabilities | ||
6 | * common to the entire `printf()' family of functions; it conforms | ||
7 | * generally to C99 and SUSv3/POSIX specifications, with extensions | ||
8 | * to support Microsoft's non-standard format specifications. | ||
9 | * | ||
10 | * Written by Keith Marshall <keithmarshall@users.sourceforge.net> | ||
11 | * | ||
12 | * This is free software. You may redistribute and/or modify it as you | ||
13 | * see fit, without restriction of copyright. | ||
14 | * | ||
15 | * This software is provided "as is", in the hope that it may be useful, | ||
16 | * but WITHOUT WARRANTY OF ANY KIND, not even any implied warranty of | ||
17 | * MERCHANTABILITY, nor of FITNESS FOR ANY PARTICULAR PURPOSE. At no | ||
18 | * time will the author accept any form of liability for any damages, | ||
19 | * however caused, resulting from the use of this software. | ||
20 | * | ||
21 | * The elements of this implementation which deal with the formatting | ||
22 | * of floating point numbers, (i.e. the `%e', `%E', `%f', `%F', `%g' | ||
23 | * and `%G' format specifiers, but excluding the hexadecimal floating | ||
24 | * point `%a' and `%A' specifiers), make use of the `__gdtoa' function | ||
25 | * written by David M. Gay, and are modelled on his sample code, which | ||
26 | * has been deployed under its accompanying terms of use:-- | ||
27 | * | ||
28 | ****************************************************************** | ||
29 | * Copyright (C) 1997, 1999, 2001 Lucent Technologies | ||
30 | * All Rights Reserved | ||
31 | * | ||
32 | * Permission to use, copy, modify, and distribute this software and | ||
33 | * its documentation for any purpose and without fee is hereby | ||
34 | * granted, provided that the above copyright notice appear in all | ||
35 | * copies and that both that the copyright notice and this | ||
36 | * permission notice and warranty disclaimer appear in supporting | ||
37 | * documentation, and that the name of Lucent or any of its entities | ||
38 | * not be used in advertising or publicity pertaining to | ||
39 | * distribution of the software without specific, written prior | ||
40 | * permission. | ||
41 | * | ||
42 | * LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, | ||
43 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. | ||
44 | * IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY | ||
45 | * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
46 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER | ||
47 | * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, | ||
48 | * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF | ||
49 | * THIS SOFTWARE. | ||
50 | ****************************************************************** | ||
51 | * | ||
52 | */ | ||
53 | #include <stdio.h> | ||
54 | #include <stdarg.h> | ||
55 | #include <stddef.h> | ||
56 | #include <stdint.h> | ||
57 | #include <stdlib.h> | ||
58 | #include <string.h> | ||
59 | #include <limits.h> | ||
60 | #include <locale.h> | ||
61 | #include <wchar.h> | ||
62 | #include <math.h> | ||
63 | |||
64 | /* FIXME: The following belongs in values.h, but current MinGW | ||
65 | * has nothing useful there! OTOH, values.h is not a standard | ||
66 | * header, and it's use may be considered obsolete; perhaps it | ||
67 | * is better to just keep these definitions here. | ||
68 | */ | ||
69 | #ifndef _VALUES_H | ||
70 | /* | ||
71 | * values.h | ||
72 | * | ||
73 | */ | ||
74 | #define _VALUES_H | ||
75 | |||
76 | #include <limits.h> | ||
77 | |||
78 | #define _TYPEBITS(type) (sizeof(type) * CHAR_BIT) | ||
79 | |||
80 | #define LLONGBITS _TYPEBITS(long long) | ||
81 | |||
82 | #endif /* !defined _VALUES_H -- end of file */ | ||
83 | |||
84 | #include "evil_pformat.h" | ||
85 | #include "gdtoa/gdtoa.h" | ||
86 | |||
87 | /* Bit-map constants, defining the internal format control | ||
88 | * states, which propagate through the flags. | ||
89 | */ | ||
90 | #define PFORMAT_GROUPED 0x1000 | ||
91 | #define PFORMAT_HASHED 0x0800 | ||