Added sys_fileread() for PostgreSQL --read-file binary

This commit is contained in:
Bernardo Damele 2010-01-19 13:37:04 +00:00
parent 574880ba73
commit 49146e573a
3 changed files with 547 additions and 414 deletions

View File

@ -1,207 +1,273 @@
/* /*
lib_postgresqludf_sys - a library with miscellaneous (operating) system level functions lib_postgresqludf_sys - a library with miscellaneous (operating) system level functions
Copyright (C) 2009 Bernardo Damele A. G. Copyright (C) 2009 Bernardo Damele A. G.
web: http://bernardodamele.blogspot.com/ web: http://bernardodamele.blogspot.com/
email: bernardo.damele@gmail.com email: bernardo.damele@gmail.com
This library is free software; you can redistribute it and/or This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version. version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful, This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details. Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32) #if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32)
#define _USE_32BIT_TIME_T #define _USE_32BIT_TIME_T
#define DLLEXP __declspec(dllexport) #define DLLEXP __declspec(dllexport)
#define BUILDING_DLL 1 #define BUILDING_DLL 1
#else #else
#define DLLEXP #define DLLEXP
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <unistd.h> #include <unistd.h>
#endif #endif
#include <postgres.h> #include <postgres.h>
#include <fmgr.h> #include <fmgr.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32) #if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32)
DWORD WINAPI exec_payload(LPVOID lpParameter); DWORD WINAPI exec_payload(LPVOID lpParameter);
#endif #endif
#ifdef PG_MODULE_MAGIC #ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC; PG_MODULE_MAGIC;
#endif #endif
PG_FUNCTION_INFO_V1(sys_exec); PG_FUNCTION_INFO_V1(sys_exec);
#ifdef PGDLLIMPORT #ifdef PGDLLIMPORT
extern PGDLLIMPORT Datum sys_exec(PG_FUNCTION_ARGS) { extern PGDLLIMPORT Datum sys_exec(PG_FUNCTION_ARGS) {
#else #else
extern DLLIMPORT Datum sys_exec(PG_FUNCTION_ARGS) { extern DLLIMPORT Datum sys_exec(PG_FUNCTION_ARGS) {
#endif #endif
text *argv0 = PG_GETARG_TEXT_P(0); text *argv0 = PG_GETARG_TEXT_P(0);
int32 argv0_size; int32 argv0_size;
int32 result = 0; int32 result = 0;
char *command; char *command;
argv0_size = VARSIZE(argv0) - VARHDRSZ; argv0_size = VARSIZE(argv0) - VARHDRSZ;
command = (char *)malloc(argv0_size + 1); command = (char *)malloc(argv0_size + 1);
memcpy(command, VARDATA(argv0), argv0_size); memcpy(command, VARDATA(argv0), argv0_size);
command[argv0_size] = '\0'; command[argv0_size] = '\0';
/* /*
Only if you want to log Only if you want to log
elog(NOTICE, "Command execution: %s", command); elog(NOTICE, "Command execution: %s", command);
*/ */
result = system(command); result = system(command);
free(command); free(command);
PG_FREE_IF_COPY(argv0, 0); PG_FREE_IF_COPY(argv0, 0);
PG_RETURN_INT32(result); PG_RETURN_INT32(result);
} }
PG_FUNCTION_INFO_V1(sys_eval); PG_FUNCTION_INFO_V1(sys_eval);
#ifdef PGDLLIMPORT #ifdef PGDLLIMPORT
extern PGDLLIMPORT Datum sys_eval(PG_FUNCTION_ARGS) { extern PGDLLIMPORT Datum sys_eval(PG_FUNCTION_ARGS) {
#else #else
extern DLLIMPORT Datum sys_eval(PG_FUNCTION_ARGS) { extern DLLIMPORT Datum sys_eval(PG_FUNCTION_ARGS) {
#endif #endif
text *argv0 = PG_GETARG_TEXT_P(0); text *argv0 = PG_GETARG_TEXT_P(0);
text *result_text; text *result_text;
int32 argv0_size; int32 argv0_size;
char *command; char *command;
char *result; char *result;
FILE *pipe; FILE *pipe;
char line[1024]; char line[1024];
int32 outlen, linelen; int32 outlen, linelen;
argv0_size = VARSIZE(argv0) - VARHDRSZ; argv0_size = VARSIZE(argv0) - VARHDRSZ;
command = (char *)malloc(argv0_size + 1); command = (char *)malloc(argv0_size + 1);
memcpy(command, VARDATA(argv0), argv0_size); memcpy(command, VARDATA(argv0), argv0_size);
command[argv0_size] = '\0'; command[argv0_size] = '\0';
/* /*
Only if you want to log Only if you want to log
elog(NOTICE, "Command evaluated: %s", command); elog(NOTICE, "Command evaluated: %s", command);
*/ */
result = (char *)malloc(1); result = (char *)malloc(1);
outlen = 0; outlen = 0;
pipe = popen(command, "r"); pipe = popen(command, "r");
while (fgets(line, sizeof(line), pipe) != NULL) { while (fgets(line, sizeof(line), pipe) != NULL) {
linelen = strlen(line); linelen = strlen(line);
result = (char *)realloc(result, outlen + linelen); result = (char *)realloc(result, outlen + linelen);
strncpy(result + outlen, line, linelen); strncpy(result + outlen, line, linelen);
outlen = outlen + linelen; outlen = outlen + linelen;
} }
pclose(pipe); pclose(pipe);
if (*result) { if (*result) {
result[outlen-1] = 0x00; result[outlen-1] = 0x00;
} }
result_text = (text *)malloc(VARHDRSZ + strlen(result)); result_text = (text *)malloc(VARHDRSZ + strlen(result));
#ifdef SET_VARSIZE #ifdef SET_VARSIZE
SET_VARSIZE(result_text, VARHDRSZ + strlen(result)); SET_VARSIZE(result_text, VARHDRSZ + strlen(result));
#else #else
VARATT_SIZEP(result_text) = strlen(result) + VARHDRSZ; VARATT_SIZEP(result_text) = strlen(result) + VARHDRSZ;
#endif #endif
memcpy(VARDATA(result_text), result, strlen(result)); memcpy(VARDATA(result_text), result, strlen(result));
PG_RETURN_POINTER(result_text); PG_RETURN_POINTER(result_text);
} }
PG_FUNCTION_INFO_V1(sys_bineval); PG_FUNCTION_INFO_V1(sys_bineval);
#ifdef PGDLLIMPORT #ifdef PGDLLIMPORT
extern PGDLLIMPORT Datum sys_bineval(PG_FUNCTION_ARGS) { extern PGDLLIMPORT Datum sys_bineval(PG_FUNCTION_ARGS) {
#else #else
extern DLLIMPORT Datum sys_bineval(PG_FUNCTION_ARGS) { extern DLLIMPORT Datum sys_bineval(PG_FUNCTION_ARGS) {
#endif #endif
text *argv0 = PG_GETARG_TEXT_P(0); text *argv0 = PG_GETARG_TEXT_P(0);
int32 argv0_size; int32 argv0_size;
size_t len; size_t len;
#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32) #if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32)
int pID; int pID;
char *code; char *code;
#else #else
int *addr; int *addr;
size_t page_size; size_t page_size;
pid_t pID; pid_t pID;
#endif #endif
argv0_size = VARSIZE(argv0) - VARHDRSZ; argv0_size = VARSIZE(argv0) - VARHDRSZ;
len = (size_t)argv0_size; len = (size_t)argv0_size;
#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32) #if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32)
// allocate a +rwx memory page // allocate a +rwx memory page
code = (char *) VirtualAlloc(NULL, len+1, MEM_COMMIT, PAGE_EXECUTE_READWRITE); code = (char *) VirtualAlloc(NULL, len+1, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
strncpy(code, VARDATA(argv0), len); strncpy(code, VARDATA(argv0), len);
WaitForSingleObject(CreateThread(NULL, 0, exec_payload, code, 0, &pID), INFINITE); WaitForSingleObject(CreateThread(NULL, 0, exec_payload, code, 0, &pID), INFINITE);
#else #else
pID = fork(); pID = fork();
if(pID<0) if(pID<0)
PG_RETURN_INT32(1); PG_RETURN_INT32(1);
if(pID==0) if(pID==0)
{ {
page_size = (size_t)sysconf(_SC_PAGESIZE)-1; // get page size page_size = (size_t)sysconf(_SC_PAGESIZE)-1; // get page size
page_size = (len+page_size) & ~(page_size); // align to page boundary page_size = (len+page_size) & ~(page_size); // align to page boundary
// mmap an rwx memory page // mmap an rwx memory page
addr = mmap(0, page_size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED|MAP_ANONYMOUS, 0, 0); addr = mmap(0, page_size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED|MAP_ANONYMOUS, 0, 0);
if (addr == MAP_FAILED) if (addr == MAP_FAILED)
PG_RETURN_INT32(1); PG_RETURN_INT32(1);
strncpy((char *)addr, VARDATA(argv0), len); strncpy((char *)addr, VARDATA(argv0), len);
((void (*)(void))addr)(); ((void (*)(void))addr)();
} }
if(pID>0) if(pID>0)
waitpid(pID, 0, WNOHANG); waitpid(pID, 0, WNOHANG);
#endif #endif
PG_RETURN_INT32(0); PG_RETURN_INT32(0);
} }
#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32) #if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32)
DWORD WINAPI exec_payload(LPVOID lpParameter) DWORD WINAPI exec_payload(LPVOID lpParameter)
{ {
__try __try
{ {
__asm __asm
{ {
mov eax, [lpParameter] mov eax, [lpParameter]
call eax call eax
} }
} }
__except(EXCEPTION_EXECUTE_HANDLER) __except(EXCEPTION_EXECUTE_HANDLER)
{ {
} }
return 0; return 0;
} }
#endif #endif
PG_FUNCTION_INFO_V1(sys_fileread);
#ifdef PGDLLIMPORT
extern PGDLLIMPORT Datum sys_fileread(PG_FUNCTION_ARGS) {
#else
extern DLLIMPORT Datum sys_fileread(PG_FUNCTION_ARGS) {
#endif
text *argv0 = PG_GETARG_TEXT_P(0);
text *result_text;
int32 argv0_size;
int32 len;
int32 i, j;
char *filename;
char *result;
char *buffer;
char table[] = "0123456789ABCDEF";
FILE *file;
argv0_size = VARSIZE(argv0) - VARHDRSZ;
filename = (char *)malloc(argv0_size + 1);
memcpy(filename, VARDATA(argv0), argv0_size);
filename[argv0_size] = '\0';
file = fopen(filename, "rb");
if (!file)
{
PG_RETURN_POINTER(NULL);
}
fseek(file, 0, SEEK_END);
len = ftell(file);
fseek(file, 0, SEEK_SET);
buffer=(char *)malloc(len + 1);
if (!buffer)
{
fclose(file);
PG_RETURN_POINTER(NULL);
}
fread(buffer, len, 1, file);
fclose(file);
result = (char *)malloc(2*len + 1);
for (i=0, j=0; i<len; i++)
{
result[j++] = table[(buffer[i] >> 4) & 0x0f];
result[j++] = table[ buffer[i] & 0x0f];
}
result[j] = '\0';
result_text = (text *)malloc(VARHDRSZ + strlen(result));
#ifdef SET_VARSIZE
SET_VARSIZE(result_text, VARHDRSZ + strlen(result));
#else
VARATT_SIZEP(result_text) = strlen(result) + VARHDRSZ;
#endif
memcpy(VARDATA(result_text), result, strlen(result));
free(result);
free(buffer);
free(filename);
PG_RETURN_POINTER(result_text);
}

View File

@ -22,3 +22,4 @@
CREATE OR REPLACE FUNCTION sys_exec(text) RETURNS int4 AS '/tmp/lib_postgresqludf_sys.so', 'sys_exec' LANGUAGE C RETURNS NULL ON NULL INPUT IMMUTABLE; CREATE OR REPLACE FUNCTION sys_exec(text) RETURNS int4 AS '/tmp/lib_postgresqludf_sys.so', 'sys_exec' LANGUAGE C RETURNS NULL ON NULL INPUT IMMUTABLE;
CREATE OR REPLACE FUNCTION sys_eval(text) RETURNS text AS '/tmp/lib_postgresqludf_sys.so', 'sys_eval' LANGUAGE C RETURNS NULL ON NULL INPUT IMMUTABLE; CREATE OR REPLACE FUNCTION sys_eval(text) RETURNS text AS '/tmp/lib_postgresqludf_sys.so', 'sys_eval' LANGUAGE C RETURNS NULL ON NULL INPUT IMMUTABLE;
CREATE OR REPLACE FUNCTION sys_bineval(text) RETURNS int4 AS '/tmp/lib_postgresqludf_sys.so', 'sys_bineval' LANGUAGE C RETURNS NULL ON NULL INPUT IMMUTABLE; CREATE OR REPLACE FUNCTION sys_bineval(text) RETURNS int4 AS '/tmp/lib_postgresqludf_sys.so', 'sys_bineval' LANGUAGE C RETURNS NULL ON NULL INPUT IMMUTABLE;
CREATE OR REPLACE FUNCTION sys_fileread(text) RETURNS text AS '/tmp/lib_postgresqludf_sys.so', 'sys_fileread' LANGUAGE C RETURNS NULL ON NULL INPUT IMMUTABLE;

View File

@ -1,207 +1,273 @@
/* /*
lib_postgresqludf_sys - a library with miscellaneous (operating) system level functions lib_postgresqludf_sys - a library with miscellaneous (operating) system level functions
Copyright (C) 2009 Bernardo Damele A. G. Copyright (C) 2009 Bernardo Damele A. G.
web: http://bernardodamele.blogspot.com/ web: http://bernardodamele.blogspot.com/
email: bernardo.damele@gmail.com email: bernardo.damele@gmail.com
This library is free software; you can redistribute it and/or This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version. version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful, This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details. Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/ */
#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32) #if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32)
#define _USE_32BIT_TIME_T #define _USE_32BIT_TIME_T
#define DLLEXP __declspec(dllexport) #define DLLEXP __declspec(dllexport)
#define BUILDING_DLL 1 #define BUILDING_DLL 1
#else #else
#define DLLEXP #define DLLEXP
#include <sys/mman.h> #include <sys/mman.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <unistd.h> #include <unistd.h>
#endif #endif
#include <postgres.h> #include <postgres.h>
#include <fmgr.h> #include <fmgr.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32) #if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32)
DWORD WINAPI exec_payload(LPVOID lpParameter); DWORD WINAPI exec_payload(LPVOID lpParameter);
#endif #endif
#ifdef PG_MODULE_MAGIC #ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC; PG_MODULE_MAGIC;
#endif #endif
PG_FUNCTION_INFO_V1(sys_exec); PG_FUNCTION_INFO_V1(sys_exec);
#ifdef PGDLLIMPORT #ifdef PGDLLIMPORT
extern PGDLLIMPORT Datum sys_exec(PG_FUNCTION_ARGS) { extern PGDLLIMPORT Datum sys_exec(PG_FUNCTION_ARGS) {
#else #else
extern DLLIMPORT Datum sys_exec(PG_FUNCTION_ARGS) { extern DLLIMPORT Datum sys_exec(PG_FUNCTION_ARGS) {
#endif #endif
text *argv0 = PG_GETARG_TEXT_P(0); text *argv0 = PG_GETARG_TEXT_P(0);
int32 argv0_size; int32 argv0_size;
int32 result = 0; int32 result = 0;
char *command; char *command;
argv0_size = VARSIZE(argv0) - VARHDRSZ; argv0_size = VARSIZE(argv0) - VARHDRSZ;
command = (char *)malloc(argv0_size + 1); command = (char *)malloc(argv0_size + 1);
memcpy(command, VARDATA(argv0), argv0_size); memcpy(command, VARDATA(argv0), argv0_size);
command[argv0_size] = '\0'; command[argv0_size] = '\0';
/* /*
Only if you want to log Only if you want to log
elog(NOTICE, "Command execution: %s", command); elog(NOTICE, "Command execution: %s", command);
*/ */
result = system(command); result = system(command);
free(command); free(command);
PG_FREE_IF_COPY(argv0, 0); PG_FREE_IF_COPY(argv0, 0);
PG_RETURN_INT32(result); PG_RETURN_INT32(result);
} }
PG_FUNCTION_INFO_V1(sys_eval); PG_FUNCTION_INFO_V1(sys_eval);
#ifdef PGDLLIMPORT #ifdef PGDLLIMPORT
extern PGDLLIMPORT Datum sys_eval(PG_FUNCTION_ARGS) { extern PGDLLIMPORT Datum sys_eval(PG_FUNCTION_ARGS) {
#else #else
extern DLLIMPORT Datum sys_eval(PG_FUNCTION_ARGS) { extern DLLIMPORT Datum sys_eval(PG_FUNCTION_ARGS) {
#endif #endif
text *argv0 = PG_GETARG_TEXT_P(0); text *argv0 = PG_GETARG_TEXT_P(0);
text *result_text; text *result_text;
int32 argv0_size; int32 argv0_size;
char *command; char *command;
char *result; char *result;
FILE *pipe; FILE *pipe;
char line[1024]; char line[1024];
int32 outlen, linelen; int32 outlen, linelen;
argv0_size = VARSIZE(argv0) - VARHDRSZ; argv0_size = VARSIZE(argv0) - VARHDRSZ;
command = (char *)malloc(argv0_size + 1); command = (char *)malloc(argv0_size + 1);
memcpy(command, VARDATA(argv0), argv0_size); memcpy(command, VARDATA(argv0), argv0_size);
command[argv0_size] = '\0'; command[argv0_size] = '\0';
/* /*
Only if you want to log Only if you want to log
elog(NOTICE, "Command evaluated: %s", command); elog(NOTICE, "Command evaluated: %s", command);
*/ */
result = (char *)malloc(1); result = (char *)malloc(1);
outlen = 0; outlen = 0;
pipe = popen(command, "r"); pipe = popen(command, "r");
while (fgets(line, sizeof(line), pipe) != NULL) { while (fgets(line, sizeof(line), pipe) != NULL) {
linelen = strlen(line); linelen = strlen(line);
result = (char *)realloc(result, outlen + linelen); result = (char *)realloc(result, outlen + linelen);
strncpy(result + outlen, line, linelen); strncpy(result + outlen, line, linelen);
outlen = outlen + linelen; outlen = outlen + linelen;
} }
pclose(pipe); pclose(pipe);
if (*result) { if (*result) {
result[outlen-1] = 0x00; result[outlen-1] = 0x00;
} }
result_text = (text *)malloc(VARHDRSZ + strlen(result)); result_text = (text *)malloc(VARHDRSZ + strlen(result));
#ifdef SET_VARSIZE #ifdef SET_VARSIZE
SET_VARSIZE(result_text, VARHDRSZ + strlen(result)); SET_VARSIZE(result_text, VARHDRSZ + strlen(result));
#else #else
VARATT_SIZEP(result_text) = strlen(result) + VARHDRSZ; VARATT_SIZEP(result_text) = strlen(result) + VARHDRSZ;
#endif #endif
memcpy(VARDATA(result_text), result, strlen(result)); memcpy(VARDATA(result_text), result, strlen(result));
PG_RETURN_POINTER(result_text); PG_RETURN_POINTER(result_text);
} }
PG_FUNCTION_INFO_V1(sys_bineval); PG_FUNCTION_INFO_V1(sys_bineval);
#ifdef PGDLLIMPORT #ifdef PGDLLIMPORT
extern PGDLLIMPORT Datum sys_bineval(PG_FUNCTION_ARGS) { extern PGDLLIMPORT Datum sys_bineval(PG_FUNCTION_ARGS) {
#else #else
extern DLLIMPORT Datum sys_bineval(PG_FUNCTION_ARGS) { extern DLLIMPORT Datum sys_bineval(PG_FUNCTION_ARGS) {
#endif #endif
text *argv0 = PG_GETARG_TEXT_P(0); text *argv0 = PG_GETARG_TEXT_P(0);
int32 argv0_size; int32 argv0_size;
size_t len; size_t len;
#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32) #if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32)
int pID; int pID;
char *code; char *code;
#else #else
int *addr; int *addr;
size_t page_size; size_t page_size;
pid_t pID; pid_t pID;
#endif #endif
argv0_size = VARSIZE(argv0) - VARHDRSZ; argv0_size = VARSIZE(argv0) - VARHDRSZ;
len = (size_t)argv0_size; len = (size_t)argv0_size;
#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32) #if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32)
// allocate a +rwx memory page // allocate a +rwx memory page
code = (char *) VirtualAlloc(NULL, len+1, MEM_COMMIT, PAGE_EXECUTE_READWRITE); code = (char *) VirtualAlloc(NULL, len+1, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
strncpy(code, VARDATA(argv0), len); strncpy(code, VARDATA(argv0), len);
WaitForSingleObject(CreateThread(NULL, 0, exec_payload, code, 0, &pID), INFINITE); WaitForSingleObject(CreateThread(NULL, 0, exec_payload, code, 0, &pID), INFINITE);
#else #else
pID = fork(); pID = fork();
if(pID<0) if(pID<0)
PG_RETURN_INT32(1); PG_RETURN_INT32(1);
if(pID==0) if(pID==0)
{ {
page_size = (size_t)sysconf(_SC_PAGESIZE)-1; // get page size page_size = (size_t)sysconf(_SC_PAGESIZE)-1; // get page size
page_size = (len+page_size) & ~(page_size); // align to page boundary page_size = (len+page_size) & ~(page_size); // align to page boundary
// mmap an rwx memory page // mmap an rwx memory page
addr = mmap(0, page_size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED|MAP_ANONYMOUS, 0, 0); addr = mmap(0, page_size, PROT_READ|PROT_WRITE|PROT_EXEC, MAP_SHARED|MAP_ANONYMOUS, 0, 0);
if (addr == MAP_FAILED) if (addr == MAP_FAILED)
PG_RETURN_INT32(1); PG_RETURN_INT32(1);
strncpy((char *)addr, VARDATA(argv0), len); strncpy((char *)addr, VARDATA(argv0), len);
((void (*)(void))addr)(); ((void (*)(void))addr)();
} }
if(pID>0) if(pID>0)
waitpid(pID, 0, WNOHANG); waitpid(pID, 0, WNOHANG);
#endif #endif
PG_RETURN_INT32(0); PG_RETURN_INT32(0);
} }
#if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32) #if defined(_WIN32) || defined(_WIN64) || defined(__WIN32__) || defined(WIN32)
DWORD WINAPI exec_payload(LPVOID lpParameter) DWORD WINAPI exec_payload(LPVOID lpParameter)
{ {
__try __try
{ {
__asm __asm
{ {
mov eax, [lpParameter] mov eax, [lpParameter]
call eax call eax
} }
} }
__except(EXCEPTION_EXECUTE_HANDLER) __except(EXCEPTION_EXECUTE_HANDLER)
{ {
} }
return 0; return 0;
} }
#endif #endif
PG_FUNCTION_INFO_V1(sys_fileread);
#ifdef PGDLLIMPORT
extern PGDLLIMPORT Datum sys_fileread(PG_FUNCTION_ARGS) {
#else
extern DLLIMPORT Datum sys_fileread(PG_FUNCTION_ARGS) {
#endif
text *argv0 = PG_GETARG_TEXT_P(0);
text *result_text;
int32 argv0_size;
int32 len;
int32 i, j;
char *filename;
char *result;
char *buffer;
char table[] = "0123456789ABCDEF";
FILE *file;
argv0_size = VARSIZE(argv0) - VARHDRSZ;
filename = (char *)malloc(argv0_size + 1);
memcpy(filename, VARDATA(argv0), argv0_size);
filename[argv0_size] = '\0';
file = fopen(filename, "rb");
if (!file)
{
PG_RETURN_POINTER(NULL);
}
fseek(file, 0, SEEK_END);
len = ftell(file);
fseek(file, 0, SEEK_SET);
buffer=(char *)malloc(len + 1);
if (!buffer)
{
fclose(file);
PG_RETURN_POINTER(NULL);
}
fread(buffer, len, 1, file);
fclose(file);
result = (char *)malloc(2*len + 1);
for (i=0, j=0; i<len; i++)
{
result[j++] = table[(buffer[i] >> 4) & 0x0f];
result[j++] = table[ buffer[i] & 0x0f];
}
result[j] = '\0';
result_text = (text *)malloc(VARHDRSZ + strlen(result));
#ifdef SET_VARSIZE
SET_VARSIZE(result_text, VARHDRSZ + strlen(result));
#else
VARATT_SIZEP(result_text) = strlen(result) + VARHDRSZ;
#endif
memcpy(VARDATA(result_text), result, strlen(result));
free(result);
free(buffer);
free(filename);
PG_RETURN_POINTER(result_text);
}