* 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:
parent
892ea362f0
commit
146b4a86c6
|
@ -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>
|
2008-07-13 Vincent Torri <doursse at users dot sf dot net>
|
||||||
|
|
||||||
* src/lib/Evil.h:
|
* src/lib/Evil.h:
|
||||||
|
|
|
@ -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' also accepts some other, not widely useful, options. Run
|
||||||
`configure --help' for more details.
|
`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
|
|
||||||
|
|
|
@ -10,7 +10,6 @@ dnl otherwise, we set the correct flags
|
||||||
dnl for each platform.
|
dnl for each platform.
|
||||||
win32_libs=""
|
win32_libs=""
|
||||||
win32_cflags=""
|
win32_cflags=""
|
||||||
lt_enable_auto_import=""
|
|
||||||
case "$host_os" in
|
case "$host_os" in
|
||||||
mingw|mingw32)
|
mingw|mingw32)
|
||||||
win32_libs="-lole32 -luuid -lws2_32"
|
win32_libs="-lole32 -luuid -lws2_32"
|
||||||
|
@ -18,7 +17,6 @@ case "$host_os" in
|
||||||
cegcc)
|
cegcc)
|
||||||
win32_cflags="-mwin32"
|
win32_cflags="-mwin32"
|
||||||
win32_libs="-lws2"
|
win32_libs="-lws2"
|
||||||
lt_enable_auto_import="-Wl,--enable-auto-import"
|
|
||||||
;;
|
;;
|
||||||
mingw32ce)
|
mingw32ce)
|
||||||
win32_libs="-lws2"
|
win32_libs="-lws2"
|
||||||
|
@ -29,7 +27,6 @@ case "$host_os" in
|
||||||
esac
|
esac
|
||||||
AC_SUBST(win32_cflags)
|
AC_SUBST(win32_cflags)
|
||||||
AC_SUBST(win32_libs)
|
AC_SUBST(win32_libs)
|
||||||
AC_SUBST(lt_enable_auto_import)
|
|
||||||
|
|
||||||
dnl needed for correct definition of EAPI
|
dnl needed for correct definition of EAPI
|
||||||
AC_DEFINE(EFL_EVIL_BUILD, 1, [Define to mention that evil is built])
|
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"
|
version_info=`expr $VMAJ + $VMIN`":$VMIC:$VMIN"
|
||||||
AC_SUBST(version_info)
|
AC_SUBST(version_info)
|
||||||
|
|
||||||
|
AM_PROG_AS
|
||||||
AC_LANG(C)
|
AC_LANG(C)
|
||||||
AC_PROG_CPP
|
AC_PROG_CPP
|
||||||
AC_PROG_CC
|
AC_PROG_CC
|
||||||
|
@ -79,8 +77,6 @@ src/Makefile
|
||||||
src/bin/Makefile
|
src/bin/Makefile
|
||||||
src/lib/Makefile
|
src/lib/Makefile
|
||||||
src/lib/dlfcn/Makefile
|
src/lib/dlfcn/Makefile
|
||||||
src/lib/mman/Makefile
|
|
||||||
src/lib/pwd/Makefile
|
|
||||||
])
|
])
|
||||||
|
|
||||||
AC_OUTPUT
|
AC_OUTPUT
|
||||||
|
|
|
@ -9,19 +9,26 @@ AM_CPPFLAGS = \
|
||||||
|
|
||||||
AM_CFLAGS = @win32_cflags@
|
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_SOURCES = test_dlfcn.c
|
||||||
test_dlfcn_LDADD = $(top_builddir)/src/lib/libevil.la $(top_builddir)/src/lib/dlfcn/libdl.la
|
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_dlfcn_DEPENDENCIES = $(top_builddir)/src/lib/libevil.la $(top_builddir)/src/lib/dlfcn/libdl.la
|
||||||
|
|
||||||
test_pipe_SOURCES = test_pipe.c
|
test_pipe_SOURCES = test_pipe.c
|
||||||
test_pipe_LDADD = $(top_builddir)/src/lib/libevil.la
|
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_pipe_DEPENDENCIES = $(top_builddir)/src/lib/libevil.la
|
||||||
|
|
||||||
test_evil_SOURCES = test_evil.c
|
test_evil_SOURCES = test_evil.c
|
||||||
test_evil_LDADD = $(top_builddir)/src/lib/libevil.la
|
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
|
test_evil_DEPENDENCIES = $(top_builddir)/src/lib/libevil.la
|
||||||
|
|
||||||
|
EXTRA_DIST = suite.h test_memcpy.h
|
|
@ -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
|
|
@ -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;
|
||||||
|
}
|
|
@ -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__ */
|
|
@ -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 ());
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
#ifndef __EVIL_TEST_MEMCPY__
|
||||||
|
#define __EVIL_TEST_MEMCPY__
|
||||||
|
|
||||||
|
|
||||||
|
void test_memcpy(void);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __EVIL_TEST_MEMCPY__ */
|
|
@ -74,6 +74,10 @@ extern "C" {
|
||||||
|
|
||||||
#define PATH_MAX MAX_PATH
|
#define PATH_MAX MAX_PATH
|
||||||
|
|
||||||
|
#include "evil_stdlib.h"
|
||||||
|
#include "evil_unistd.h"
|
||||||
|
#include "evil_util.h"
|
||||||
|
|
||||||
|
|
||||||
#ifndef __CEGCC__
|
#ifndef __CEGCC__
|
||||||
|
|
||||||
|
@ -132,7 +136,6 @@ extern "C" {
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
|
|
||||||
typedef int pid_t;
|
|
||||||
typedef long ssize_t;
|
typedef long ssize_t;
|
||||||
typedef unsigned short mode_t;
|
typedef unsigned short mode_t;
|
||||||
|
|
||||||
|
@ -180,360 +183,9 @@ struct flock
|
||||||
*/
|
*/
|
||||||
EAPI int fcntl(int fd, int cmd, ...);
|
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__ */
|
#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;
|
typedef int nl_item;
|
||||||
|
|
||||||
#define __NL_ITEM( CATEGORY, INDEX ) ((CATEGORY << 16) | INDEX)
|
#define __NL_ITEM( CATEGORY, INDEX ) ((CATEGORY << 16) | INDEX)
|
||||||
|
|
|
@ -1,14 +1,22 @@
|
||||||
|
|
||||||
MAINTAINERCLEANFILES = Makefile.in
|
MAINTAINERCLEANFILES = Makefile.in
|
||||||
|
|
||||||
SUBDIRS = . dlfcn mman pwd
|
SUBDIRS = . dlfcn
|
||||||
|
|
||||||
lib_LTLIBRARIES = libevil.la
|
lib_LTLIBRARIES = libevil.la
|
||||||
|
|
||||||
include_HEADERS = Evil.h
|
include_HEADERS = Evil.h evil_stdlib.h evil_unistd.h evil_util.h
|
||||||
libevil_la_SOURCES = evil.c
|
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_CFLAGS = @win32_cflags@
|
||||||
libevil_la_LIBADD = @win32_libs@
|
libevil_la_LIBADD = @win32_libs@
|
||||||
libevil_la_DEPENDENCIES = $(top_builddir)/config.h
|
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@
|
||||||
|
|
|
@ -9,4 +9,4 @@ libdl_la_SOURCES = dlfcn.c
|
||||||
libdl_la_CFLAGS = @win32_cflags@
|
libdl_la_CFLAGS = @win32_cflags@
|
||||||
libdl_la_LIBADD = $(top_builddir)/src/lib/libevil.la
|
libdl_la_LIBADD = $(top_builddir)/src/lib/libevil.la
|
||||||
libdl_la_DEPENDENCIES = $(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@
|
||||||
|
|
|
@ -36,7 +36,6 @@
|
||||||
#endif /* HAVE___ATTRIBUTE__ */
|
#endif /* HAVE___ATTRIBUTE__ */
|
||||||
|
|
||||||
#include "Evil.h"
|
#include "Evil.h"
|
||||||
#include "pwd/pwd.h"
|
|
||||||
|
|
||||||
|
|
||||||
static struct passwd pw;
|
static struct passwd pw;
|
||||||
|
@ -104,529 +103,8 @@ int fcntl(int fd, int cmd, ...)
|
||||||
return res;
|
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__ */
|
#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;
|
|
||||||
|
|
||||||
closesocket (temp);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
out2:
|
|
||||||
closesocket (socket2);
|
|
||||||
out1:
|
|
||||||
closesocket (socket1);
|
|
||||||
out0:
|
|
||||||
closesocket (temp);
|
|
||||||
|
|
||||||
fds[0] = INVALID_SOCKET;
|
|
||||||
fds[1] = INVALID_SOCKET;
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *
|
|
||||||
evil_tmpdir_get(void)
|
|
||||||
{
|
|
||||||
#ifdef _WIN32_WCE
|
|
||||||
return "\\temp";
|
|
||||||
#else
|
|
||||||
char *tmpdir;
|
|
||||||
|
|
||||||
tmpdir = getenv("TMP");
|
|
||||||
if (!tmpdir) tmpdir = getenv("TEMP");
|
|
||||||
if (!tmpdir) tmpdir = getenv("USERPROFILE");
|
|
||||||
if (!tmpdir) tmpdir = getenv("WINDIR");
|
|
||||||
if (!tmpdir) tmpdir="C:\\";
|
|
||||||
|
|
||||||
return tmpdir;
|
|
||||||
#endif /* ! _WIN32_WCE */
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *
|
|
||||||
evil_homedir_get(void)
|
|
||||||
{
|
|
||||||
#ifdef _WIN32_WCE
|
|
||||||
return "\\my documents";
|
|
||||||
#else
|
|
||||||
char *homedir;
|
|
||||||
|
|
||||||
homedir = getenv("HOME");
|
|
||||||
if (!homedir) homedir = getenv("USERPROFILE");
|
|
||||||
if (!homedir) homedir = getenv("WINDIR");
|
|
||||||
if (!homedir) homedir="C:\\";
|
|
||||||
|
|
||||||
return homedir;
|
|
||||||
#endif /* ! _WIN32_WCE */
|
|
||||||
}
|
|
||||||
|
|
||||||
char *
|
|
||||||
evil_getcwd(char *buffer, size_t size)
|
|
||||||
{
|
|
||||||
#if defined(__CEGCC__) || defined(__MINGW32CE__)
|
|
||||||
wchar_t wpath[PATH_MAX];
|
|
||||||
char *cpath;
|
|
||||||
char *delim;
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
if (size <= 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
ret = GetModuleFileName(GetModuleHandle(NULL), (LPWSTR)&wpath, PATH_MAX);
|
|
||||||
|
|
||||||
if (!ret)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
cpath = evil_wchar_to_char(wpath);
|
|
||||||
if (!cpath)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (strlen(cpath) >= (size - 1))
|
|
||||||
{
|
|
||||||
free(cpath);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
delim = strrchr(cpath, '\\');
|
|
||||||
if (delim)
|
|
||||||
*delim = '\0';
|
|
||||||
|
|
||||||
if (!buffer)
|
|
||||||
{
|
|
||||||
buffer = (char *)malloc(sizeof(char) * size);
|
|
||||||
if (!buffer)
|
|
||||||
{
|
|
||||||
free(cpath);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
strcpy(buffer, cpath);
|
|
||||||
free(cpath);
|
|
||||||
|
|
||||||
return buffer;
|
|
||||||
#else
|
|
||||||
return _getcwd(buffer, size);
|
|
||||||
#endif /* ! __CEGCC__ && ! __MINGW32CE__ */
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef UNICODE
|
|
||||||
|
|
||||||
wchar_t *
|
|
||||||
evil_char_to_wchar(const char *text)
|
|
||||||
{
|
|
||||||
wchar_t *wtext;
|
|
||||||
int wsize;
|
|
||||||
|
|
||||||
wsize = MultiByteToWideChar(CP_ACP, 0, text, strlen(text) + 1, NULL, 0);
|
|
||||||
if ((wsize == 0) ||
|
|
||||||
(wsize > (int)(ULONG_MAX/sizeof(wchar_t))))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
wtext = malloc(wsize * sizeof(wchar_t));
|
|
||||||
if (wtext)
|
|
||||||
if (!MultiByteToWideChar(CP_ACP, 0, text, strlen(text) + 1, wtext, wsize))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
return wtext;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *
|
|
||||||
evil_wchar_to_char(const wchar_t *text)
|
|
||||||
{
|
|
||||||
char * atext;
|
|
||||||
int size;
|
|
||||||
int asize;
|
|
||||||
|
|
||||||
size = wcslen(text) + 1;
|
|
||||||
|
|
||||||
asize = WideCharToMultiByte(CP_ACP, 0, text, size, NULL, 0, NULL, NULL);
|
|
||||||
if (asize == 0)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
atext = (char*)malloc((asize + 1) * sizeof(char));
|
|
||||||
|
|
||||||
if (atext)
|
|
||||||
if (!WideCharToMultiByte(CP_ACP, 0, text, size, atext, asize, NULL, NULL))
|
|
||||||
return NULL;
|
|
||||||
atext[asize] = '\0';
|
|
||||||
|
|
||||||
return atext;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* UNICODE */
|
|
||||||
|
|
||||||
char *
|
|
||||||
evil_last_error_get(void)
|
|
||||||
{
|
|
||||||
char str[PATH_MAX];
|
|
||||||
LPTSTR str1;
|
|
||||||
char *str2;
|
|
||||||
DWORD err;
|
|
||||||
|
|
||||||
err = GetLastError();
|
|
||||||
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
||||||
NULL,
|
|
||||||
err,
|
|
||||||
0, // Default language
|
|
||||||
(LPTSTR)&str1,
|
|
||||||
0,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
#ifdef UNICODE
|
|
||||||
str2 = evil_wchar_to_char(str1);
|
|
||||||
LocalFree(str1);
|
|
||||||
#else
|
|
||||||
str2 = str1;
|
|
||||||
#endif /* ! UNICODE */
|
|
||||||
|
|
||||||
snprintf(str, PATH_MAX, "(%ld) %s", err, str2);
|
|
||||||
LocalFree(str2);
|
|
||||||
|
|
||||||
return strdup(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
replace(char *prev, char *value)
|
replace(char *prev, char *value)
|
||||||
{
|
{
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
# include <io.h>
|
# include <io.h>
|
||||||
#endif /* ! __CEGCC__ */
|
#endif /* ! __CEGCC__ */
|
||||||
|
|
||||||
#include "../Evil.h"
|
#include "Evil.h"
|
||||||
|
|
||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
# include "config.h"
|
# include "config.h"
|
|
@ -0,0 +1,42 @@
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include "config.h"
|
||||||
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
|
#include "pwd.h"
|
||||||
|
|
||||||
|
|
||||||
|
static struct passwd pw;
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __CEGCC__
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* ! __CEGCC__ */
|
|
@ -0,0 +1,268 @@
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#ifndef __MINGW32CE__
|
||||||
|
#include <errno.h>
|
||||||
|
#endif /* ! __MINGW32CE__ */
|
||||||
|
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <windows.h>
|
||||||
|
#undef WIN32_LEAN_AND_MEAN
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include "config.h"
|
||||||
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
|
#include "Evil.h"
|
||||||
|
|
||||||
|
/*** Local ***/
|
||||||
|
|
||||||
|
static void
|
||||||
|
_evil_stdlib_error_display(const char *fct,
|
||||||
|
LONG res)
|
||||||
|
{
|
||||||
|
char *error;
|
||||||
|
|
||||||
|
error = evil_format_message(res);
|
||||||
|
fprintf(stderr, "[Evil] [%s] ERROR: %ld\n", fct, error);
|
||||||
|
free(error);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Environment variable related functions
|
||||||
|
*
|
||||||
|
* char *getenv (const char *name);
|
||||||
|
* int putenv (const char *string);
|
||||||
|
* int setenv (const char *name, const char *value, int overwrite);
|
||||||
|
* void unsetenv (const char *name);
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(__CEGCC__) || defined(__MINGW32CE__)
|
||||||
|
|
||||||
|
static char _evil_stdlib_getenv_buffer[PATH_MAX];
|
||||||
|
|
||||||
|
char *
|
||||||
|
getenv(const char *name)
|
||||||
|
{
|
||||||
|
HKEY key;
|
||||||
|
wchar_t *wname;
|
||||||
|
char *buffer;
|
||||||
|
LONG res;
|
||||||
|
DWORD type;
|
||||||
|
DWORD size = PATH_MAX;
|
||||||
|
|
||||||
|
if (!name || !*name)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if ((res = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
||||||
|
TEXT("Software\\Efl\\Environment"),
|
||||||
|
0, 0,
|
||||||
|
&key)) != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
_evil_stdlib_error_display("getenv", res);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
wname = evil_char_to_wchar(name);
|
||||||
|
if (!wname)
|
||||||
|
{
|
||||||
|
if ((res = RegCloseKey (key)) != ERROR_SUCCESS)
|
||||||
|
_evil_stdlib_error_display("getenv", res);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((res = RegQueryValueEx(key, wname,
|
||||||
|
NULL, &type,
|
||||||
|
(LPBYTE)&buffer,
|
||||||
|
&size)) != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
_evil_stdlib_error_display("getenv", res);
|
||||||
|
if ((res = RegCloseKey (key)) != ERROR_SUCCESS)
|
||||||
|
_evil_stdlib_error_display("getenv", res);
|
||||||
|
free(wname);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(wname);
|
||||||
|
|
||||||
|
if ((res = RegCloseKey (key)) != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
_evil_stdlib_error_display("getenv", res);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer[0] == '\0')
|
||||||
|
return NULL;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return _evil_stdlib_getenv_buffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __CEGCC__ || __MINGW32CE__ */
|
||||||
|
|
||||||
|
#if ! defined(__CEGCC__)
|
||||||
|
|
||||||
|
int
|
||||||
|
putenv(const char *string)
|
||||||
|
{
|
||||||
|
#if ! ( defined(__CEGCC__) || defined(__MINGW32CE__) )
|
||||||
|
return _putenv(string);
|
||||||
|
#else
|
||||||
|
#endif /* __CEGCC__ || __MINGW32CE__ */
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* ! __CEGCC__ */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
setenv(const char *name,
|
||||||
|
const char *value,
|
||||||
|
int overwrite)
|
||||||
|
{
|
||||||
|
#if ! ( defined(__CEGCC__) || defined(__MINGW32CE__) )
|
||||||
|
|
||||||
|
char *old_name;
|
||||||
|
char *str;
|
||||||
|
int length;
|
||||||
|
|
||||||
|
if (!name || !*name)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* if '=' is found, return EINVAL */
|
||||||
|
if (strchr (name, '='))
|
||||||
|
{
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if name is already set and overwrite is 0, we exit with success */
|
||||||
|
old_name = getenv(name);
|
||||||
|
if (!overwrite && oldname)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
length = strlen(name) + strlen(value) + 2;
|
||||||
|
str = (char *)malloc(length);
|
||||||
|
if (!str)
|
||||||
|
{
|
||||||
|
errno = ENOMEM;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!value)
|
||||||
|
sprintf(str, "%s=", name);
|
||||||
|
else
|
||||||
|
sprintf(str, "%s=%s", name, value);
|
||||||
|
res = _putenv(str);
|
||||||
|
free(str);
|
||||||
|
|
||||||
|
#else /* __CEGCC__ || __MINGW32CE__ */
|
||||||
|
|
||||||
|
HKEY key;
|
||||||
|
LONG res;
|
||||||
|
DWORD disposition;
|
||||||
|
|
||||||
|
if (!name || !*name)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* if '=' is found, return an error */
|
||||||
|
if (strchr (name, '='))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if ((res = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
|
||||||
|
TEXT("Software\\Efl\\Environment"),
|
||||||
|
0, NULL,
|
||||||
|
REG_OPTION_VOLATILE,
|
||||||
|
0, NULL,
|
||||||
|
&key,
|
||||||
|
&disposition)) != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
_evil_stdlib_error_display("setenv", res);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* if name is already set and overwrite is 0, we exit with success */
|
||||||
|
if (!overwrite && (disposition == REG_OPENED_EXISTING_KEY))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if ((res = RegSetValueEx (key,
|
||||||
|
(LPCWSTR)name,
|
||||||
|
0, REG_SZ,
|
||||||
|
value,
|
||||||
|
strlen(value) + 1)) != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
_evil_stdlib_error_display("setenv", res);
|
||||||
|
if ((res = RegCloseKey (key)) != ERROR_SUCCESS)
|
||||||
|
_evil_stdlib_error_display("getenv", res);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((res = RegCloseKey (key)) != ERROR_SUCCESS)
|
||||||
|
{
|
||||||
|
_evil_stdlib_error_display("getenv", res);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __CEGCC__ || __MINGW32CE__ */
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if ! defined(__CEGCC__)
|
||||||
|
|
||||||
|
int
|
||||||
|
unsetenv(const char *name)
|
||||||
|
{
|
||||||
|
setenv(name, NULL, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* ! __CEGCC__ */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Files related functions
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if ! ( defined(__CEGCC__) || defined(__MINGW32CE__) )
|
||||||
|
|
||||||
|
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, PATH_MAX) != 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
_sopen_s(&fd, template, _O_RDWR | _O_BINARY | _O_CREAT, _SH_DENYNO, _S_IREAD | _S_IWRITE);
|
||||||
|
#endif /* ! __MINGW32__ */
|
||||||
|
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* ! ( __CEGCC__ || __MINGW32CE__ ) */
|
||||||
|
|
||||||
|
|
||||||
|
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__ */
|
||||||
|
}
|
|
@ -0,0 +1,145 @@
|
||||||
|
#ifndef __EVIL_STDLIB_H__
|
||||||
|
#define __EVIL_STDLIB_H__
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Environment variable related functions
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined(__CEGCC__) || defined(__MINGW32CE__)
|
||||||
|
|
||||||
|
EAPI char *getenv(const char *name);
|
||||||
|
|
||||||
|
#endif /* __CEGCC__ || __MINGW32CE__ */
|
||||||
|
|
||||||
|
|
||||||
|
#if ! defined(__CEGCC__)
|
||||||
|
|
||||||
|
EAPI int putenv(const char *string);
|
||||||
|
|
||||||
|
#endif /* ! __CEGCC__ */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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,
|
||||||
|
int overwrite);
|
||||||
|
|
||||||
|
|
||||||
|
#if ! defined(__CEGCC__)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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 and the third to 1. 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__ */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Files related functions
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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 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);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __EVIL_STDLIB_H__ */
|
||||||
|
|
|
@ -0,0 +1,396 @@
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <winsock2.h>
|
||||||
|
#undef WIN32_LEAN_AND_MEAN
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include "config.h"
|
||||||
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
|
#include "Evil.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Process identifer related functions
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
pid_t
|
||||||
|
getpid(void)
|
||||||
|
{
|
||||||
|
return (pid_t)GetCurrentProcessId();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Symbolic links and directory related functions
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* REMARK: Windows has no symbolic link. */
|
||||||
|
/* Nevertheless, it can create and read .lnk files */
|
||||||
|
int
|
||||||
|
symlink(const char *oldpath, const char *newpath)
|
||||||
|
{
|
||||||
|
#if defined(__CEGCC__) || defined(__MINGW32CE__)
|
||||||
|
wchar_t *w_oldpath;
|
||||||
|
wchar_t *w_newpath;
|
||||||
|
BOOL res;
|
||||||
|
|
||||||
|
w_oldpath = evil_char_to_wchar(oldpath);
|
||||||
|
if (!w_oldpath)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
w_newpath = evil_char_to_wchar(newpath);
|
||||||
|
if (!w_newpath)
|
||||||
|
{
|
||||||
|
free(w_oldpath);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = SHCreateShortcutEx(w_newpath, w_oldpath, NULL, NULL);
|
||||||
|
|
||||||
|
free(w_oldpath);
|
||||||
|
free(w_newpath);
|
||||||
|
|
||||||
|
return res ? 0 : -1;
|
||||||
|
#else
|
||||||
|
#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;
|
||||||
|
#endif /* ! __CEGCC__ && ! __MINGW32CE__ */
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t
|
||||||
|
readlink(const char *path, char *buf, size_t bufsiz)
|
||||||
|
{
|
||||||
|
#if defined(__CEGCC__) || defined(__MINGW32CE__)
|
||||||
|
wchar_t *w_path;
|
||||||
|
wchar_t w_newpath[MB_CUR_MAX];
|
||||||
|
char *newpath;
|
||||||
|
size_t length;
|
||||||
|
BOOL res;
|
||||||
|
|
||||||
|
w_path = evil_char_to_wchar(path);
|
||||||
|
if (!w_path)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
res = SHGetShortcutTarget(w_path, w_newpath, MB_CUR_MAX);
|
||||||
|
|
||||||
|
free(w_path);
|
||||||
|
|
||||||
|
if (!res)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
newpath = evil_wchar_to_char(w_newpath);
|
||||||
|
if (!newpath)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
length = strlen(newpath);
|
||||||
|
if (length > bufsiz)
|
||||||
|
length = bufsiz;
|
||||||
|
|
||||||
|
memcpy(buf, newpath, length);
|
||||||
|
|
||||||
|
free(newpath);
|
||||||
|
|
||||||
|
return length;
|
||||||
|
#else
|
||||||
|
#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;
|
||||||
|
#endif /* ! __CEGCC__ && ! __MINGW32CE__ */
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
evil_getcwd(char *buffer, size_t size)
|
||||||
|
{
|
||||||
|
#if defined(__CEGCC__) || defined(__MINGW32CE__)
|
||||||
|
wchar_t wpath[PATH_MAX];
|
||||||
|
char *cpath;
|
||||||
|
char *delim;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (size <= 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
ret = GetModuleFileName(GetModuleHandle(NULL), (LPWSTR)&wpath, PATH_MAX);
|
||||||
|
|
||||||
|
if (!ret)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
cpath = evil_wchar_to_char(wpath);
|
||||||
|
if (!cpath)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (strlen(cpath) >= (size - 1))
|
||||||
|
{
|
||||||
|
free(cpath);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
delim = strrchr(cpath, '\\');
|
||||||
|
if (delim)
|
||||||
|
*delim = '\0';
|
||||||
|
|
||||||
|
if (!buffer)
|
||||||
|
{
|
||||||
|
buffer = (char *)malloc(sizeof(char) * size);
|
||||||
|
if (!buffer)
|
||||||
|
{
|
||||||
|
free(cpath);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(buffer, cpath);
|
||||||
|
free(cpath);
|
||||||
|
|
||||||
|
return buffer;
|
||||||
|
#else
|
||||||
|
return _getcwd(buffer, size);
|
||||||
|
#endif /* ! __CEGCC__ && ! __MINGW32CE__ */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sockets and pipe related functions
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
closesocket (temp);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
out2:
|
||||||
|
closesocket (socket2);
|
||||||
|
out1:
|
||||||
|
closesocket (socket1);
|
||||||
|
out0:
|
||||||
|
closesocket (temp);
|
||||||
|
|
||||||
|
fds[0] = INVALID_SOCKET;
|
||||||
|
fds[1] = INVALID_SOCKET;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
|
@ -0,0 +1,187 @@
|
||||||
|
#ifndef __EVIL_UNISTD_H__
|
||||||
|
#define __EVIL_UNISTD_H__
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
|
||||||
|
typedef int pid_t;
|
||||||
|
|
||||||
|
#endif /* _MSC_VER */
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Process identifer related functions
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Symbolic links and directory related functions
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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 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);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sockets and pipe related functions
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __EVIL_UNISTD_H__ */
|
|
@ -0,0 +1,137 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <windows.h>
|
||||||
|
#undef WIN32_LEAN_AND_MEAN
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include "config.h"
|
||||||
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
|
#include "Evil.h"
|
||||||
|
|
||||||
|
|
||||||
|
wchar_t *
|
||||||
|
evil_char_to_wchar(const char *text)
|
||||||
|
{
|
||||||
|
wchar_t *wtext;
|
||||||
|
int wsize;
|
||||||
|
|
||||||
|
wsize = MultiByteToWideChar(CP_ACP, 0, text, strlen(text) + 1, NULL, 0);
|
||||||
|
if ((wsize == 0) ||
|
||||||
|
(wsize > (int)(ULONG_MAX / sizeof(wchar_t))))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
wtext = malloc(wsize * sizeof(wchar_t));
|
||||||
|
if (wtext)
|
||||||
|
if (!MultiByteToWideChar(CP_ACP, 0, text, strlen(text) + 1, wtext, wsize))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return wtext;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
evil_wchar_to_char(const wchar_t *text)
|
||||||
|
{
|
||||||
|
char * atext;
|
||||||
|
int size;
|
||||||
|
int asize;
|
||||||
|
|
||||||
|
size = wcslen(text) + 1;
|
||||||
|
|
||||||
|
asize = WideCharToMultiByte(CP_ACP, 0, text, size, NULL, 0, NULL, NULL);
|
||||||
|
if (asize == 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
atext = (char*)malloc((asize + 1) * sizeof(char));
|
||||||
|
|
||||||
|
if (atext)
|
||||||
|
if (!WideCharToMultiByte(CP_ACP, 0, text, size, atext, asize, NULL, NULL))
|
||||||
|
return NULL;
|
||||||
|
atext[asize] = '\0';
|
||||||
|
|
||||||
|
return atext;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
evil_format_message(long err)
|
||||||
|
{
|
||||||
|
LPTSTR msg;
|
||||||
|
char *str;
|
||||||
|
char *disp;
|
||||||
|
|
||||||
|
if (!FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
||||||
|
NULL,
|
||||||
|
err,
|
||||||
|
0, // Default language
|
||||||
|
(LPTSTR)&msg,
|
||||||
|
0,
|
||||||
|
NULL))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
#ifdef UNICODE
|
||||||
|
str = evil_wchar_to_char(msg);
|
||||||
|
#else
|
||||||
|
str = strdup(msg);
|
||||||
|
#endif /* UNICODE */
|
||||||
|
|
||||||
|
LocalFree(msg);
|
||||||
|
|
||||||
|
disp = (char *)malloc((strlen(str) + strlen("(00000) ") + 1) * sizeof(char));
|
||||||
|
if (!disp)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
snprintf(disp, strlen(str) + strlen("(00000) ") + 1,
|
||||||
|
"(%5d) %s", err, str);
|
||||||
|
|
||||||
|
free(str);
|
||||||
|
|
||||||
|
return disp;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *
|
||||||
|
evil_last_error_get(void)
|
||||||
|
{
|
||||||
|
DWORD err;
|
||||||
|
|
||||||
|
err = GetLastError();
|
||||||
|
return evil_format_message(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const char *
|
||||||
|
evil_tmpdir_get(void)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32_WCE
|
||||||
|
return "\\temp";
|
||||||
|
#else
|
||||||
|
char *tmpdir;
|
||||||
|
|
||||||
|
tmpdir = getenv("TMP");
|
||||||
|
if (!tmpdir) tmpdir = getenv("TEMP");
|
||||||
|
if (!tmpdir) tmpdir = getenv("USERPROFILE");
|
||||||
|
if (!tmpdir) tmpdir = getenv("WINDIR");
|
||||||
|
if (!tmpdir) tmpdir="C:\\";
|
||||||
|
|
||||||
|
return tmpdir;
|
||||||
|
#endif /* ! _WIN32_WCE */
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *
|
||||||
|
evil_homedir_get(void)
|
||||||
|
{
|
||||||
|
#ifdef _WIN32_WCE
|
||||||
|
return "\\my documents";
|
||||||
|
#else
|
||||||
|
char *homedir;
|
||||||
|
|
||||||
|
homedir = getenv("HOME");
|
||||||
|
if (!homedir) homedir = getenv("USERPROFILE");
|
||||||
|
if (!homedir) homedir = getenv("WINDIR");
|
||||||
|
if (!homedir) homedir="C:\\";
|
||||||
|
|
||||||
|
return homedir;
|
||||||
|
#endif /* ! _WIN32_WCE */
|
||||||
|
}
|
|
@ -0,0 +1,93 @@
|
||||||
|
#ifndef __EVIL_UTIL_H__
|
||||||
|
#define __EVIL_UTIL_H__
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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);
|
||||||
|
|
||||||
|
EAPI char *evil_format_message(long err);
|
||||||
|
|
||||||
|
EAPI char *evil_last_error_get(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __EVIL_UTIL_H__ */
|
|
@ -1,6 +0,0 @@
|
||||||
.deps
|
|
||||||
.libs
|
|
||||||
Makefile
|
|
||||||
Makefile.in
|
|
||||||
*.la
|
|
||||||
*.lo
|
|
|
@ -1,12 +0,0 @@
|
||||||
|
|
||||||
MAINTAINERCLEANFILES = Makefile.in
|
|
||||||
|
|
||||||
lib_LTLIBRARIES = libmman.la
|
|
||||||
|
|
||||||
nobase_include_HEADERS = sys/mman.h
|
|
||||||
libmman_la_SOURCES = mman.c
|
|
||||||
|
|
||||||
libmman_la_CFLAGS = @win32_cflags@
|
|
||||||
libmman_la_LIBADD = $(top_builddir)/src/lib/libevil.la
|
|
||||||
libmman_la_DEPENDENCIES = $(top_builddir)/config.h $(top_builddir)/src/lib/libevil.la
|
|
||||||
libmman_la_LDFLAGS = -no-undefined @lt_enable_auto_import@ -version-info @version_info@
|
|
|
@ -1,4 +0,0 @@
|
||||||
|
|
||||||
MAINTAINERCLEANFILES = Makefile.in
|
|
||||||
|
|
||||||
include_HEADERS = pwd.h
|
|
|
@ -192,6 +192,26 @@
|
||||||
RelativePath="..\..\src\lib\evil.c"
|
RelativePath="..\..\src\lib\evil.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\lib\evil_mman.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\lib\evil_pwd.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\lib\evil_stdlib.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\lib\evil_unistd.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath="..\..\src\lib\evil_util.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter
|
<Filter
|
||||||
Name="Header Files"
|
Name="Header Files"
|
||||||
|
|
Loading…
Reference in New Issue