* big rework of evil: put most of functions in evil.c in their own files

* add unit test for memcpy. more will come later


SVN revision: 35979
This commit is contained in:
Vincent Torri 2008-09-13 21:19:22 +00:00
parent 892ea362f0
commit 146b4a86c6
27 changed files with 1884 additions and 934 deletions

View File

@ -1,3 +1,8 @@
2008-09-13 Vincent Torri <doursse at users dot sf dot net>
* big rework of evil
* addition of a unit test for memcpy
2008-07-13 Vincent Torri <doursse at users dot sf dot net>
* src/lib/Evil.h:

View File

@ -235,26 +235,3 @@ an Autoconf bug. Until the bug is fixed you can use this workaround:
`configure' also accepts some other, not widely useful, options. Run
`configure --help' for more details.
================================================================================
NOTE: For compilation with mingw32ce, run configure with the option
--host=arm-wince-mingw32ce
NOTE: For compilation with cegcc, you have to do the following steps:
1) After having run autogen.sh, add in config.sub file:
cegcc)
basic_machine=arm-unknown
os=-cegcc
;;
after the mingw32ce case
2) in config.sub, add -cegcc* after -pe*. You should have a line like:
| -cygwin* | -pe* | -cegcc* | -psos* | -moss* | -proelf* | -rtems* \
3) run configure with the option
--host=arm-wince-cegcc

View File

@ -10,7 +10,6 @@ dnl otherwise, we set the correct flags
dnl for each platform.
win32_libs=""
win32_cflags=""
lt_enable_auto_import=""
case "$host_os" in
mingw|mingw32)
win32_libs="-lole32 -luuid -lws2_32"
@ -18,7 +17,6 @@ case "$host_os" in
cegcc)
win32_cflags="-mwin32"
win32_libs="-lws2"
lt_enable_auto_import="-Wl,--enable-auto-import"
;;
mingw32ce)
win32_libs="-lws2"
@ -29,7 +27,6 @@ case "$host_os" in
esac
AC_SUBST(win32_cflags)
AC_SUBST(win32_libs)
AC_SUBST(lt_enable_auto_import)
dnl needed for correct definition of EAPI
AC_DEFINE(EFL_EVIL_BUILD, 1, [Define to mention that evil is built])
@ -51,6 +48,7 @@ SNAP=`echo $PACKAGE_VERSION | awk -F. '{printf("%s", $4);}'`
version_info=`expr $VMAJ + $VMIN`":$VMIC:$VMIN"
AC_SUBST(version_info)
AM_PROG_AS
AC_LANG(C)
AC_PROG_CPP
AC_PROG_CC
@ -79,8 +77,6 @@ src/Makefile
src/bin/Makefile
src/lib/Makefile
src/lib/dlfcn/Makefile
src/lib/mman/Makefile
src/lib/pwd/Makefile
])
AC_OUTPUT

View File

@ -9,19 +9,26 @@ AM_CPPFLAGS = \
AM_CFLAGS = @win32_cflags@
bin_PROGRAMS = test_dlfcn test_pipe test_evil
bin_PROGRAMS = suite test_dlfcn test_pipe test_evil
suite_SOURCES = suite.c test_memcpy.c memcpy_glibc.S
suite_LDADD = $(top_builddir)/src/lib/libevil.la
suite_LDFLAGS = -Wl,--enable-auto-import
suite_DEPENDENCIES = $(top_builddir)/src/lib/libevil.la
test_dlfcn_SOURCES = test_dlfcn.c
test_dlfcn_LDADD = $(top_builddir)/src/lib/libevil.la $(top_builddir)/src/lib/dlfcn/libdl.la
test_dlfcn_LDFLAGS = @lt_enable_auto_import@
test_dlfcn_LDFLAGS = -Wl,--enable-auto-import
test_dlfcn_DEPENDENCIES = $(top_builddir)/src/lib/libevil.la $(top_builddir)/src/lib/dlfcn/libdl.la
test_pipe_SOURCES = test_pipe.c
test_pipe_LDADD = $(top_builddir)/src/lib/libevil.la
test_pipe_LDFLAGS = @lt_enable_auto_import@
test_pipe_LDFLAGS = -Wl,--enable-auto-import
test_pipe_DEPENDENCIES = $(top_builddir)/src/lib/libevil.la
test_evil_SOURCES = test_evil.c
test_evil_LDADD = $(top_builddir)/src/lib/libevil.la
test_evil_LDFLAGS = @lt_enable_auto_import@
test_evil_LDFLAGS = -Wl,--enable-auto-import
test_evil_DEPENDENCIES = $(top_builddir)/src/lib/libevil.la
EXTRA_DIST = suite.h test_memcpy.h

View File

@ -0,0 +1,231 @@
/* Copyright (C) 2006 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by MontaVista Software, Inc. (written by Nicolas Pitre)
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, write to the Free
Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
02111-1307 USA. */
/* Copyright (C) 2008 Vincent Torri
modification of the name and of the entry / end declaration
*/
/*
* Data preload for architectures that support it (ARM V5TE and above)
*/
#if (!defined (__ARM_ARCH_2__) && !defined (__ARM_ARCH_3__) \
&& !defined (__ARM_ARCH_3M__) && !defined (__ARM_ARCH_4__) \
&& !defined (__ARM_ARCH_4T__) && !defined (__ARM_ARCH_5__) \
&& !defined (__ARM_ARCH_5T__))
#define PLD(code...) code
#else
#define PLD(code...)
#endif
/*
* This can be used to enable code to cacheline align the source pointer.
* Experiments on tested architectures (StrongARM and XScale) didn't show
* this a worthwhile thing to do. That might be different in the future.
*/
//#define CALGN(code...) code
#define CALGN(code...)
/*
* Endian independent macros for shifting bytes within registers.
*/
#ifndef __ARMEB__
#define pull lsr
#define push lsl
#else
#define pull lsl
#define push lsr
#endif
.text
/* Prototype: void *memcpy_glibc(void *dest, const void *src, size_t n); */
.align
.global memcpy_glibc
.func memcpy_glibc
memcpy_glibc:
stmfd sp!, {r0, r4, lr}
subs r2, r2, #4
blt 8f
ands ip, r0, #3
PLD( pld [r1, #0] )
bne 9f
ands ip, r1, #3
bne 10f
1: subs r2, r2, #(28)
stmfd sp!, {r5 - r8}
blt 5f
CALGN( ands ip, r1, #31 )
CALGN( rsb r3, ip, #32 )
CALGN( sbcnes r4, r3, r2 ) @ C is always set here
CALGN( bcs 2f )
CALGN( adr r4, 6f )
CALGN( subs r2, r2, r3 ) @ C gets set
CALGN( add pc, r4, ip )
PLD( pld [r1, #0] )
2: PLD( subs r2, r2, #96 )
PLD( pld [r1, #28] )
PLD( blt 4f )
PLD( pld [r1, #60] )
PLD( pld [r1, #92] )
3: PLD( pld [r1, #124] )
4: ldmia r1!, {r3, r4, r5, r6, r7, r8, ip, lr}
subs r2, r2, #32
stmia r0!, {r3, r4, r5, r6, r7, r8, ip, lr}
bge 3b
PLD( cmn r2, #96 )
PLD( bge 4b )
5: ands ip, r2, #28
rsb ip, ip, #32
addne pc, pc, ip @ C is always clear here
b 7f
6: nop
ldr r3, [r1], #4
ldr r4, [r1], #4
ldr r5, [r1], #4
ldr r6, [r1], #4
ldr r7, [r1], #4
ldr r8, [r1], #4
ldr lr, [r1], #4
add pc, pc, ip
nop
nop
str r3, [r0], #4
str r4, [r0], #4
str r5, [r0], #4
str r6, [r0], #4
str r7, [r0], #4
str r8, [r0], #4
str lr, [r0], #4
CALGN( bcs 2b )
7: ldmfd sp!, {r5 - r8}
8: movs r2, r2, lsl #31
ldrneb r3, [r1], #1
ldrcsb r4, [r1], #1
ldrcsb ip, [r1]
strneb r3, [r0], #1
strcsb r4, [r0], #1
strcsb ip, [r0]
ldmfd sp!, {r0, r4, pc}
9: rsb ip, ip, #4
cmp ip, #2
ldrgtb r3, [r1], #1
ldrgeb r4, [r1], #1
ldrb lr, [r1], #1
strgtb r3, [r0], #1
strgeb r4, [r0], #1
subs r2, r2, ip
strb lr, [r0], #1
blt 8b
ands ip, r1, #3
beq 1b
10: bic r1, r1, #3
cmp ip, #2
ldr lr, [r1], #4
beq 17f
bgt 18f
.macro forward_copy_shift pull push
subs r2, r2, #28
blt 14f
CALGN( ands ip, r1, #31 )
CALGN( rsb ip, ip, #32 )
CALGN( sbcnes r4, ip, r2 ) @ C is always set here
CALGN( subcc r2, r2, ip )
CALGN( bcc 15f )
11: stmfd sp!, {r5 - r9}
PLD( pld [r1, #0] )
PLD( subs r2, r2, #96 )
PLD( pld [r1, #28] )
PLD( blt 13f )
PLD( pld [r1, #60] )
PLD( pld [r1, #92] )
12: PLD( pld [r1, #124] )
13: ldmia r1!, {r4, r5, r6, r7}
mov r3, lr, pull #\pull
subs r2, r2, #32
ldmia r1!, {r8, r9, ip, lr}
orr r3, r3, r4, push #\push
mov r4, r4, pull #\pull
orr r4, r4, r5, push #\push
mov r5, r5, pull #\pull
orr r5, r5, r6, push #\push
mov r6, r6, pull #\pull
orr r6, r6, r7, push #\push
mov r7, r7, pull #\pull
orr r7, r7, r8, push #\push
mov r8, r8, pull #\pull
orr r8, r8, r9, push #\push
mov r9, r9, pull #\pull
orr r9, r9, ip, push #\push
mov ip, ip, pull #\pull
orr ip, ip, lr, push #\push
stmia r0!, {r3, r4, r5, r6, r7, r8, r9, ip}
bge 12b
PLD( cmn r2, #96 )
PLD( bge 13b )
ldmfd sp!, {r5 - r9}
14: ands ip, r2, #28
beq 16f
15: mov r3, lr, pull #\pull
ldr lr, [r1], #4
subs ip, ip, #4
orr r3, r3, lr, push #\push
str r3, [r0], #4
bgt 15b
CALGN( cmp r2, #0 )
CALGN( bge 11b )
16: sub r1, r1, #(\push / 8)
b 8b
.endm
forward_copy_shift pull=8 push=24
17: forward_copy_shift pull=16 push=16
18: forward_copy_shift pull=24 push=8
.endfunc

191
legacy/evil/src/bin/suite.c Normal file
View File

@ -0,0 +1,191 @@
#include <stdlib.h>
#include <stdio.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN
#include "suite.h"
#include "test_memcpy.h"
typedef void(*function)(void);
struct test
{
const char *name;
function fct;
};
struct list
{
void *data;
list *next;
};
struct suite
{
list *first;
list *l;
};
unsigned char *buf1 = NULL;
unsigned char *buf2 = NULL;
size_t page_size = 0;
suite *
suite_new(void)
{
suite *s;
if (!QueryPerformanceFrequency(&freq))
return NULL;
s = (suite *)malloc(sizeof(suite));
if (!s) return NULL;
s->first = NULL;
s->l = NULL;
return s;
}
void
suite_del(suite *s)
{
list *l;
list *tmp;
if (!s) return;
l = s->first;
while (l)
{
tmp = l->next;
free(l->data);
free(l);
l = tmp;
}
free(s);
}
void
suite_time_start()
{
QueryPerformanceCounter(&start);
}
void
suite_time_stop()
{
QueryPerformanceCounter(&end);
}
double
suite_time_get()
{
return (double)(end.QuadPart - start.QuadPart) / (double)freq.QuadPart;
}
void
suite_test_add(suite *s, const char *name, function fct)
{
test *t;
list *l;
t = (test *)malloc(sizeof(test));
if (!t) return;
l = (list *)malloc(sizeof(list));
if (!l)
{
free(t);
return;
}
t->name = name;
t->fct = fct;
l->data = t;
l->next = NULL;
if (!s->first) s->first = l;
if (!s->l)
s->l = l;
else
{
s->l->next = l;
s->l =l;
}
}
void
suite_run(suite *s)
{
list *l;
l = s->first;
while (l)
{
test *t;
t = (test *)l->data;
printf("%s test\n", t->name);
t->fct();
l = l->next;
}
}
int
main()
{
test tests[] = {
{ "memcpy", test_memcpy },
{ NULL, NULL },
};
suite *s;
int i;
page_size = 2 * getpagesize();
buf1 = (unsigned char *)malloc(4 * getpagesize());
if (!buf1) return EXIT_FAILURE;
buf2 = (unsigned char *)malloc(4 * getpagesize());
if (!buf2)
{
free(buf1);
return EXIT_FAILURE;
}
memset (buf1, 0xa5, page_size);
memset (buf2, 0x5a, page_size);
s = suite_new();
if (!s)
{
free(buf2);
free(buf1);
return EXIT_FAILURE;
}
for (i = 0; ; ++i)
{
if (!tests[i].name)
break;
suite_test_add(s, tests[i].name, tests[i].fct);
}
suite_run(s);
suite_del(s);
free(buf2);
free(buf1);
return EXIT_SUCCESS;
}

View File

@ -0,0 +1,18 @@
#ifndef __EVIL_SUITE_H__
#define __EVIL_SUITE_H__
typedef struct test test;
typedef struct list list;
typedef struct suite suite;
LARGE_INTEGER freq;
LARGE_INTEGER start;
LARGE_INTEGER end;
void suite_time_start();
void suite_time_stop();
double suite_time_get();
#endif /* __EVIL_SUITE_H__ */

View File

@ -0,0 +1,113 @@
#include <stdlib.h>
#include <stdio.h>
#include <sys/time.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#undef WIN32_LEAN_AND_MEAN
#include "suite.h"
#include "test_memcpy.h"
typedef void *(*memcpy_decl)(void *dest, const void *src, size_t n);
void *memcpy_glibc(void *dest, const void *src, size_t n);
extern unsigned char *buf1;
extern unsigned char *buf2;
extern size_t page_size;
static void
test_memcpy_test_run(memcpy_decl fct, char *dst, const char *src, size_t len)
{
double start;
double end;
double best;
int i;
best = 1000000000.0;
for (i = 0; i < 32; ++i)
{
double time;
suite_time_start();
fct(dst, src, len);
suite_time_stop();
time = suite_time_get();
if (time < best) best = time;
}
printf (" %e", best);
}
static void
test_memcpy_tests_run(size_t align1, size_t align2, size_t len)
{
size_t i, j;
char *s1, *s2;
printf ("running test..\n");
/* align1 &= 63; */
/* if (align1 + len >= page_size) */
/* return; */
/* align2 &= 63; */
/* if (align2 + len >= page_size) */
/* return; */
s1 = (char *) (buf1 + align1);
s2 = (char *) (buf2 + align2);
for (i = 0, j = 1; i < len; i++, j += 23)
s1[i] = j;
printf ("length: %6d, align %2d/%2d:", (int)len, align1, align2);
test_memcpy_test_run(memcpy, s2, s1, len);
test_memcpy_test_run(memcpy_glibc, s2, s1, len);
printf ("\n");
}
void
test_memcpy(void)
{
size_t i;
/* for (i = 0; i < 18; ++i) */
/* { */
/* test_memcpy_tests_run(0, 0, 1 << i); */
/* test_memcpy_tests_run(i, 0, 1 << i); */
/* test_memcpy_tests_run(0, i, 1 << i); */
/* test_memcpy_tests_run(i, i, 1 << i); */
/* } */
/* for (i = 0; i < 32; ++i) */
/* { */
/* test_memcpy_tests_run(0, 0, i); */
/* test_memcpy_tests_run(i, 0, i); */
/* test_memcpy_tests_run(0, i, i); */
/* test_memcpy_tests_run(i, i, i); */
/* } */
/* for (i = 3; i < 32; ++i) */
/* { */
/* if ((i & (i - 1)) == 0) */
/* continue; */
/* test_memcpy_tests_run(0, 0, 16 * i); */
/* test_memcpy_tests_run(i, 0, 16 * i); */
/* test_memcpy_tests_run(0, i, 16 * i); */
/* test_memcpy_tests_run(i, i, 16 * i); */
/* } */
test_memcpy_tests_run(0, 0, getpagesize ());
test_memcpy_tests_run(0, 0, 2 * getpagesize ());
test_memcpy_tests_run(0, 0, 4 * getpagesize ());
test_memcpy_tests_run(0, 0, 8 * getpagesize ());
}

View File

@ -0,0 +1,8 @@
#ifndef __EVIL_TEST_MEMCPY__
#define __EVIL_TEST_MEMCPY__
void test_memcpy(void);
#endif /* __EVIL_TEST_MEMCPY__ */

View File

@ -74,6 +74,10 @@ extern "C" {
#define PATH_MAX MAX_PATH
#include "evil_stdlib.h"
#include "evil_unistd.h"
#include "evil_util.h"
#ifndef __CEGCC__
@ -132,7 +136,6 @@ extern "C" {
#ifdef _MSC_VER
typedef int pid_t;
typedef long ssize_t;
typedef unsigned short mode_t;
@ -180,360 +183,9 @@ struct flock
*/
EAPI int fcntl(int fd, int cmd, ...);
/**
* @brief Make temporay unique file name.
*
* @param template Template of the file to create.
* @return A file descriptor on success, -1 otherwise.
*
* Take the given file name @p template and overwrite a portion of it
* to create a file name. This file is guaranted not to exist at the
* time invocation and is suitable for use by the function.
*
* The @p template parameter can be any file name with some number of
* 'Xs' appended to it, for example @em baseXXXXXX, where @em base is
* the part of the new file that you supply and eacg 'X' is a placeholder
* for a character supplied by mkstemp(). The trailing 'Xs' are replaced
* with a five-digit value; this value is a unique number. Each successful
* call to mkstemp() modifes @p template.
*
* When mkstemp() succeeds, it creates and opens the template file for
* reading and writing.
*
* On success, the function returns the file descriptor of the
* temporary file. Otherwise, it returns -1 and errno is set to the
* following values:
* - EINVAL: @p template has an invalid format.
* - EACCESS: Given path is a directory, or file is read-only, but an
* open-for-writing operation was attempted.
* - EEXISTS: File name already exists.
* - EMFILE: No more file descriptors available.
* - ENOENT: File or path not found.
*
* Conformity: Should follow BSD conformity.
*
* Supported OS: Windows 98, Windows Me, Windows NT, Windows 2000,
* Windows XP.
*
* @ingroup Evil
*/
EAPI int mkstemp(char *template);
/**
* @brief Return the process identifier of the calling process.
*
* @return The process ID.
*
* Return the process identifier of the calling process. Until
* the process terminates, the process identifier uniquely
* identifies the process throughout the system.
*
* Conformity: Not appliclable.
*
* Supported OS: Windows 98, Windows Me, Windows NT, Windows 2000,
* Windows XP.
*
* @ingroup Evil
*/
EAPI pid_t getpid(void);
/**
* @brief Create a shell link.
*
* @param oldpath The file name to be linked.
* @param newpath The file name to create.
* @return 0 on success, -1 otherwise.
*
* Create a shell link @p newpath to @p oldpath (@p newpath is the
* name of the file created, @p oldpath is the string used in
* creating the shell link).
*
* On success, this function returns 0. Otherwise, it returns -1 and
* errno may be set to the following value:
* - ENOMEM: Not enough memory.
*
* On Windows, the symbolic links do not exist. Nevertheless
* shell links can be created. This function is named like the Unix
* function for portability reasons.
*
* Conformity: None.
*
* Supported OS: Windows 95, Windows 98, Windows Me, Windows NT, Windows 2000,
* Windows XP.
*
* @ingroup Evil
*/
EAPI int symlink(const char *oldpath, const char *newpath);
/**
* @brief Read value of a shell link.
*
* @param path The file name to be linked.
* @param buf The file name to create.
* @param bufsiz The size of the buffer.
* @return 0 on success, -1 otherwise.
*
* Place the content of the shell link @p path in the buffer
* @p buf, which has size @p bufzsiz.
*
* On success, this function returns the count of characters
* placed in the buffer. Otherwise, it returns -1 and errno may
* be set to the following value:
* - ENOMEM: Not enough memory.
*
* On Windows, the symbolic links do not exist. Nevertheless
* shell links can be managed. This function is named like the Unix
* function for portability reasons.
*
* Conformity: None.
*
* Supported OS: Windows 95, Windows 98, Windows Me, Windows NT, Windows 2000,
* Windows XP.
*
* @ingroup Evil
*/
EAPI ssize_t readlink(const char *path, char *buf, size_t bufsiz);
/**
* @brief Create, modify, or remove environment variables.
*
* @param name The name of the environment variable.
* @param value The value of the environment variable to set.
* @return 0 on success, -1 otherwise.
*
* Add the new environment variable @p name or modify its value if it
* exists, and set it to @p value. Environment variables define the
* environment in which a process executes. If @p value is @c NULL, the
* variable is removed (unset) and that call is equivalent to unsetenv().
* If the function succeeds, it returns 0, otherwise it returns -1.
*
* Conformity: Non applicable.
*
* Supported OS: Windows 95, Windows 98, Windows Me, Windows NT, Windows 2000,
* Windows XP.
*
* @ingroup Evil
*/
EAPI int setenv(const char *name, const char *value);
/**
* @brief Remove environment variables.
*
* @param name The name of the environment variable.
* @return 0 on success, -1 otherwise.
*
* Remove the new environment variable @p name if it exists. That
* function is equivalent to setenv() with its second parameter to
* @c NULL. If the function succeeds, it returns 0, otherwise it
* returns -1.
*
* Conformity: Non applicable.
*
* Supported OS: Windows 95, Windows 98, Windows Me, Windows NT, Windows 2000,
* Windows XP.
*
* @ingroup Evil
*/
EAPI int unsetenv(const char *name);
#endif /* ! __CEGCC__ */
/**
* @brief Return an absolute or full path name for a specified relative path name.
*
* @param file_name The absolute path name.
* @param resolved_name The relative path name.
* @return @c NULL on failure, a pointer to the absolute path name otherwise.
*
* The function expands the relative path name @p file_name to its
* fully qualified or absolute path and store it in the buffer pointed
* by @p resolved_name. The buffer is at most @c PATH_MAX bytes long.
* If @p resolved_name is @c NULL, malloc() is used to allocate a
* buffer of sufficient length to hold the path name. In that case, it
* is the responsability of the caller to free this buffer with free().
*
* That function can be used to obtain the absolute path name for
* relative paths (relPath) that include "./" or "../" in their names.
*
* Conformity: None.
*
* Supported OS: Windows 95, Windows 98, Windows Me, Windows NT, Windows 2000,
* Windows XP.
*
* @ingroup Evil
*/
EAPI char *realpath(const char *file_name, char *resolved_name);
/**
* @brief Initiates the use of Windows sockets.
*
* @return 1 on success, 0 otherwise.
*
* Initiates the use of Windows sockets. If the function succeeds,
* it returns 1, otherwise it returns 0.
*
* Conformity: Non applicable.
*
* Supported OS: Windows 95, Windows 98, Windows Me, Windows NT, Windows 2000,
* Windows XP.
*
* @ingroup Evil
*/
EAPI int evil_sockets_init(void);
/**
* @brief Shutdown the Windows socket system.
*
* Shutdown the Windows socket system.
*
* Conformity: Non applicable.
*
* Supported OS: Windows 95, Windows 98, Windows Me, Windows NT, Windows 2000,
* Windows XP.
*
* @ingroup Evil
*/
EAPI void evil_sockets_shutdown(void);
/**
* @brief Create a pair of sockets.
*
* @param fds A pointer that contains two sockets.
*
* Create a pair of sockets that can be use with select().
* Hence, evil_sockets_init() must have been caled at least
* once before. Contrary to Unix, that functions does not
* create a pair of file descriptors.
*
* Conformity: Not applicable.
*
* Supported OS: Windows 95, Windows 98, Windows Me, Windows NT, Windows 2000,
* Windows XP.
*
* @ingroup Evil
*/
EAPI int evil_pipe(int *fds);
/**
* @brief Return a dir to store temporary files.
*
* @return The directory to store temporary files.
*
* Return a directory to store temporary files. The function gets
* the value of the following environment variables, and in that order:
* - TMP
* - TEMP
* - USERPROFILE
* - WINDIR
* and returns its value if it exists. If none exists, the function
* returns "C:\".
*
* Conformity: Non applicable.
*
* Supported OS: Windows 95, Windows 98, Windows Me, Windows NT, Windows 2000,
* Windows XP.
*
* @ingroup Evil
*/
EAPI const char *evil_tmpdir_get(void);
/**
* @brief Return a dir to store personal files.
*
* @return The directory to store personal files.
*
* Return a directory to store personal files. The function gets
* the value of the following environment variables, and in that order:
* - HOME
* - USERPROFILE
* - WINDIR
* and returns its value if it exists. If none exists, the function
* returns "C:\".
*
* Conformity: Non applicable.
*
* Supported OS: Windows 95, Windows 98, Windows Me, Windows NT, Windows 2000,
* Windows XP.
*
* @ingroup Evil
*/
EAPI const char *evil_homedir_get(void);
/**
* @brief Get the current directory.
*
* @param buffer Buffer to store the current directory.
* @param size Size of the buffer.
* @return The current directory.
*
* On Windows desktop, use the _getcwd function in MSVCRT.
*
* On Windows CE, get the current directory by extracting the path
* from the executable that is running and put the result in @p buffer
* of length @p size. If @p size is less or equal than 0, return NULL.
* If the current absolute path would require a buffer longer than
* @p size elements, NULL is returned. If @p buffer is NULL, a buffer
* of length @p size is allocated and is returned. If the allocation
* fails, NULL is returned. On success, @p buffer is returned and
* contains the current directory. The last '\' is not included.
* If @p buffer is NULL, the returned value must be freed if not NULL.
*
* Specially usefull on WinCE where the current directory functionality
* is not supported.
*
* Conformity: Almost POSIX.1 (no errno set)
*
* Supported OS: Windows 95, Windows 98, Windows Me, Windows NT, Windows 2000,
* Windows XP, WinCE.
*
* @ingroup Evil
*/
EAPI char *evil_getcwd(char *buffer, size_t size);
#ifdef UNICODE
/**
* @brief Convert a string from char * to wchar_t *.
*
* @param text The string to convert.
* @return The converted string.
*
* Convert a string from char * to wchar_t * and return it. If the
* allocation or conversion fails, NULL is returned. On success, the
* returned value must be freed.
*
* Conformity: Non applicable.
*
* Supported OS: Windows 95, Windows 98, Windows Me, Windows NT, Windows 2000,
* Windows XP.
*
* @ingroup Evil
*/
EAPI wchar_t *evil_char_to_wchar(const char *text);
/**
* @brief Convert a string from wchar_t * to char *.
*
* @param text The string to convert.
* @return The converted string.
*
* Convert a string from wchar_t * to char * and return it. If the
* allocation or conversion fails, NULL is returned. On success, the
* returned value must be freed.
*
* Conformity: Non applicable.
*
* Supported OS: Windows 95, Windows 98, Windows Me, Windows NT, Windows 2000,
* Windows XP.
*
* @ingroup Evil
*/
EAPI char *evil_wchar_to_char(const wchar_t *text);
#endif /* UNICODE */
EAPI char *evil_last_error_get(void);
typedef int nl_item;
#define __NL_ITEM( CATEGORY, INDEX ) ((CATEGORY << 16) | INDEX)

View File

@ -1,14 +1,22 @@
MAINTAINERCLEANFILES = Makefile.in
SUBDIRS = . dlfcn mman pwd
SUBDIRS = . dlfcn
lib_LTLIBRARIES = libevil.la
include_HEADERS = Evil.h
libevil_la_SOURCES = evil.c
include_HEADERS = Evil.h evil_stdlib.h evil_unistd.h evil_util.h
nobase_include_HEADERS = sys/mman.h
libevil_la_SOURCES = \
evil.c \
evil_mman.c \
evil_pwd.c \
evil_stdlib.c \
evil_unistd.c \
evil_util.c
libevil_la_CFLAGS = @win32_cflags@
libevil_la_LIBADD = @win32_libs@
libevil_la_DEPENDENCIES = $(top_builddir)/config.h
libevil_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -version-info @version_info@
libevil_la_LDFLAGS = -no-undefined -Wl,--enable-auto-import -version-info @version_info@

View File

@ -9,4 +9,4 @@ libdl_la_SOURCES = dlfcn.c
libdl_la_CFLAGS = @win32_cflags@
libdl_la_LIBADD = $(top_builddir)/src/lib/libevil.la
libdl_la_DEPENDENCIES = $(top_builddir)/src/lib/libevil.la
libdl_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -version-info @version_info@
libdl_la_LDFLAGS = -no-undefined -Wl,--enable-auto-import -version-info @version_info@

View File

@ -36,7 +36,6 @@
#endif /* HAVE___ATTRIBUTE__ */
#include "Evil.h"
#include "pwd/pwd.h"
static struct passwd pw;
@ -104,529 +103,8 @@ int fcntl(int fd, int cmd, ...)
return res;
}
int
mkstemp(char *template)
{
int fd;
#ifdef __MINGW32__
if (!_mktemp(template))
return -1;
fd = _sopen(template, _O_RDWR | _O_BINARY | _O_CREAT | _O_EXCL, _SH_DENYNO, _S_IREAD | _S_IWRITE);
#else
if (_mktemp_s(template, _MAX_PATH) != 0)
return -1;
_sopen_s(&fd, template, _O_RDWR | _O_BINARY | _O_CREAT, _SH_DENYNO, _S_IREAD | _S_IWRITE);
#endif /* ! __MINGW32__ */
return fd;
}
pid_t
getpid(void)
{
return (pid_t)GetCurrentProcessId();
}
struct passwd *
getpwuid (uid_t uid)
{
static char user_name[PATH_MAX];
DWORD length;
BOOL res;
length = PATH_MAX;
/* get from USERPROFILE for win 98 ? */
res = GetUserName(user_name, &length);
pw.pw_name = (res ? user_name : NULL);
pw.pw_passwd = NULL;
pw.pw_uid = uid;
pw.pw_gid = 0;
pw.pw_change = 0;
pw.pw_class = NULL;
pw.pw_gecos = (res ? user_name : NULL);
pw.pw_dir = (char *)evil_homedir_get();
pw.pw_shell = getenv("SHELL");
if (pw.pw_shell == NULL)
pw.pw_shell = "sh";
pw.pw_expire = 0;
pw.pw_fields = 0;
return &pw;
}
/* REMARK: Windows has no symbolic link. */
/* Nevertheless, it can create and read .lnk files */
int
symlink(const char *oldpath, const char *newpath)
{
#ifdef UNICODE
wchar_t new_path[MB_CUR_MAX];
#endif /* UNICODE */
IShellLink *pISL;
IShellLink **shell_link;
IPersistFile *pIPF;
IPersistFile **persit_file;
HRESULT res;
res = CoInitialize(NULL);
if (FAILED(res))
{
if (res == E_OUTOFMEMORY)
errno = ENOMEM;
return -1;
}
/* Hack to cleanly remove a warning */
shell_link = &pISL;
if (FAILED(CoCreateInstance(&CLSID_ShellLink,
NULL,
CLSCTX_INPROC_SERVER,
&IID_IShellLink,
(void **)shell_link)))
goto no_instance;
if (FAILED(pISL->lpVtbl->SetPath(pISL, oldpath)))
goto no_setpath;
/* Hack to cleanly remove a warning */
persit_file = &pIPF;
if (FAILED(pISL->lpVtbl->QueryInterface(pISL, &IID_IPersistFile, (void **)persit_file)))
goto no_queryinterface;
#ifdef UNICODE
mbstowcs(new_path, newpath, MB_CUR_MAX);
if (FAILED(pIPF->lpVtbl->Save(pIPF, new_path, FALSE)))
goto no_save;
#else
if (FAILED(pIPF->lpVtbl->Save(pIPF, newpath, FALSE)))
goto no_save;
#endif /* ! UNICODE */
pIPF->lpVtbl->Release(pIPF);
pISL->lpVtbl->Release(pISL);
CoUninitialize();
return 0;
no_save:
pIPF->lpVtbl->Release(pIPF);
no_queryinterface:
no_setpath:
pISL->lpVtbl->Release(pISL);
no_instance:
CoUninitialize();
return -1;
}
ssize_t
readlink(const char *path, char *buf, size_t bufsiz)
{
#ifdef UNICODE
wchar_t old_path[MB_CUR_MAX];
#endif /* UNICODE */
char new_path[PATH_MAX];
IShellLink *pISL;
IShellLink **shell_link;
IPersistFile *pIPF;
IPersistFile **persit_file;
unsigned int length;
HRESULT res;
res = CoInitialize(NULL);
if (FAILED(res))
{
if (res == E_OUTOFMEMORY)
errno = ENOMEM;
return -1;
}
/* Hack to cleanly remove a warning */
persit_file = &pIPF;
if (FAILED(CoCreateInstance(&CLSID_ShellLink,
NULL,
CLSCTX_INPROC_SERVER,
&IID_IPersistFile,
(void **)persit_file)))
goto no_instance;
#ifdef UNICODE
mbstowcs(old_path, path, MB_CUR_MAX);
if (FAILED(pIPF->lpVtbl->Load(pIPF, old_path, STGM_READWRITE)))
goto no_load;
#else
if (FAILED(pIPF->lpVtbl->Load(pIPF, path, STGM_READWRITE)))
goto no_load;
#endif /* ! UNICODE */
shell_link = &pISL;
if (FAILED(pIPF->lpVtbl->QueryInterface(pIPF, &IID_IShellLink, (void **)shell_link)))
goto no_queryinterface;
if (FAILED(pISL->lpVtbl->GetPath(pISL, new_path, PATH_MAX, NULL, 0)))
goto no_getpath;
length = strlen(new_path);
if (length > bufsiz)
length = bufsiz;
memcpy(buf, new_path, length);
pISL->lpVtbl->Release(pISL);
pIPF->lpVtbl->Release(pIPF);
CoUninitialize();
return length;
no_getpath:
pISL->lpVtbl->Release(pISL);
no_queryinterface:
no_load:
pIPF->lpVtbl->Release(pIPF);
no_instance:
CoUninitialize();
return -1;
}
int
setenv(const char *name, const char *value)
{
char *str;
int length;
int res;
length = strlen(name) + strlen(value) + 2;
str = (char *)malloc(length);
sprintf(str, "%s=%s", name, value);
res = _putenv(str);
free(str);
return res;
}
int
unsetenv(const char *name)
{
char *str;
int length;
int res;
length = strlen(name) + 2;
str = (char *)malloc(length);
sprintf(str, "%s=", name);
res = _putenv(str);
free(str);
return res;
}
#endif /* ! __CEGCC__ */
char *
realpath(const char *file_name, char *resolved_name)
{
#if ! ( defined(__CEGCC__) || defined(__MINGW32CE__) )
return _fullpath(resolved_name, file_name, PATH_MAX);
#else
int length;
length = strlen(file_name);
if ((length + 1) > PATH_MAX)
length = PATH_MAX - 1;
memcpy(resolved_name, file_name, length);
resolved_name[length] = '\0';
return resolved_name;
#endif /* __CEGCC__ || __MINGW32CE__ */
}
int
evil_sockets_init(void)
{
WSADATA wsa_data;
return (WSAStartup(MAKEWORD( 2, 2 ), &wsa_data) == 0) ? 1 : 0;
}
void
evil_sockets_shutdown(void)
{
WSACleanup();
}
/*
* The code of the following functions has been kindly offered
* by Tor Lillqvist.
*/
int
evil_pipe(int *fds)
{
struct sockaddr_in saddr;
struct timeval tv;
SOCKET temp;
SOCKET socket1 = INVALID_SOCKET;
SOCKET socket2 = INVALID_SOCKET;
u_long arg;
fd_set read_set;
fd_set write_set;
int len;
temp = socket (AF_INET, SOCK_STREAM, 0);
if (temp == INVALID_SOCKET)
goto out0;
arg = 1;
if (ioctlsocket (temp, FIONBIO, &arg) == SOCKET_ERROR)
goto out0;
memset (&saddr, 0, sizeof (saddr));
saddr.sin_family = AF_INET;
saddr.sin_port = 0;
saddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
if (bind (temp, (struct sockaddr *)&saddr, sizeof (saddr)))
goto out0;
if (listen (temp, 1) == SOCKET_ERROR)
goto out0;
len = sizeof (saddr);
if (getsockname (temp, (struct sockaddr *)&saddr, &len))
goto out0;
socket1 = socket (AF_INET, SOCK_STREAM, 0);
if (socket1 == INVALID_SOCKET)
goto out0;
arg = 1;
if (ioctlsocket (socket1, FIONBIO, &arg) == SOCKET_ERROR)
goto out1;
if ((connect (socket1, (struct sockaddr *)&saddr, len) == SOCKET_ERROR) &&
(WSAGetLastError () != WSAEWOULDBLOCK))
goto out1;
FD_ZERO (&read_set);
FD_SET (temp, &read_set);
tv.tv_sec = 0;
tv.tv_usec = 0;
if (select (0, &read_set, NULL, NULL, NULL) == SOCKET_ERROR)
goto out1;
if (!FD_ISSET (temp, &read_set))
goto out1;
socket2 = accept (temp, (struct sockaddr *) &saddr, &len);
if (socket2 == INVALID_SOCKET)
goto out1;
FD_ZERO (&write_set);
FD_SET (socket1, &write_set);
tv.tv_sec = 0;
tv.tv_usec = 0;
if (select (0, NULL, &write_set, NULL, NULL) == SOCKET_ERROR)
goto out2;
if (!FD_ISSET (socket1, &write_set))
goto out2;
arg = 0;
if (ioctlsocket (socket1, FIONBIO, &arg) == SOCKET_ERROR)
goto out2;
arg = 0;
if (ioctlsocket (socket2, FIONBIO, &arg) == SOCKET_ERROR)
goto out2;
fds[0] = socket1;
fds[1] = socket2;