Jump to content

Pathrewrite: Difference between revisions

From EDM2
Line 49: Line 49:
so we need to create a DLL which export a function that sets the rewritten paths.
so we need to create a DLL which export a function that sets the rewritten paths.


=== Creating an example ===
== Creating an example ==


So we want to creat a DLL which we place in the CONFIG.SYS with a line like:
So we want to creat a DLL which we place in the CONFIG.SYS with a line like:
Line 57: Line 57:


This means 2 things.
This means 2 things.
* ecsprw.dll should be somewhere in the LIBPATH, lets put it in ecs\dll
# ecsprw.dll should be somewhere in the LIBPATH, lets put it in ecs\dll
* ecsprw.dll should export _ecsInitPath
# ecsprw.dll should export _ecsInitPath
 


=== The source files ===
=== The source files ===

Revision as of 18:14, 5 July 2006

Using the Innotek Libc pathrewrite function

When porting application from unix flavours you might run into the problem that some parts are hardcoded into the application, most famous is ofcourse /etc.

Libc provides a interface to work around these problems without completely rewriting the application, and thus easying the maintenance for the porter.

In this article I'll try to outline the posibilities from what I used myself and will give a example.

First lets see what is documented inside the libc hooks.c file:


/** @page pg_hooks  Hooks
 *
 * Presently this is a simple feature to load and call dlls as specified in
 * the LIBC_HOOK_DLLS environment variable.
 *
 *
 * @subsection  LIBC_HOOK_DLLS
 *
 * The format is <dllname>@<export>[!<type>]. LIBC will load <dllname>,
 * resolve <export>and call <export> according to the convention of <type>.
 * Single of double quotes can be applied to the <dllname>. If multiple hooks
 * is desired, they shall be separated by the semicolon, space or tab character.

 * Failure to parse this variable, load dlls and resolve functions as specified
 * bye this variable will not prevent libc processes from starting. So, do NOT
 * count on it as a security measure.
 *
 * @subsubsection   Types
 *
 * The default type is 'generic' and means that the libc module handle and
 * the address of __libc_Back_ldrSymbol will be passed.
 *
 * 'pathrewrite' is another type. The parameters here are the three
 * __libc_PathRewrite functions. The function should
 *
 *
 * @subsubsection   Examples
 *
 *  set LIBC_HOOK_DLLS=prwhome.dll@_instprws!pathrewrite
 *  set LIBC_HOOK_DLLS=/usr/lib/prwhome.dll@_instprws!pathrewrite
 *  set LIBC_HOOK_DLLS="c:\My Plugins\prwhome.dll"@_instprws!pathrewrite
 *  set LIBC_HOOK_DLLS=prwhome@_insthomeprws!pathrewrite prwhome@_instetcprws!pathrewrite
 */


so we need to create a DLL which export a function that sets the rewritten paths.

Creating an example

So we want to creat a DLL which we place in the CONFIG.SYS with a line like:

set LIBC_HOOK_DLLS=ecsprw.dll@_ecsInitPath!pathrewrite

This means 2 things.

  1. ecsprw.dll should be somewhere in the LIBPATH, lets put it in ecs\dll
  2. ecsprw.dll should export _ecsInitPath

The source files

ecsprw.def

LIBRARY ECSPRW
EXPORTS
	_ecsInitPath

note: the DESCRIPTION tag comes later

ecsprw.c

#include <InnoTekLIBC/pathrewrite.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

char                gszEtcTo[256];
char                gszVARLOGTo[256];
char                gszTMPTo[256];


__LIBC_PATHREWRITE  gEtcRule =
{
    __LIBC_PRWF_TYPE_DIR | __LIBC_PRWF_CASE_SENSITIVE,
    "/etc",  4,
    &gszEtcTo[0], 0
};

__LIBC_PATHREWRITE  gTMPRule =
{
    __LIBC_PRWF_TYPE_DIR | __LIBC_PRWF_CASE_SENSITIVE,
    "/tmp",  4,
    &gszTMPTo[0], 0
};

__LIBC_PATHREWRITE  gVARLOGRule =
{
    __LIBC_PRWF_TYPE_DIR | __LIBC_PRWF_CASE_SENSITIVE,
    "/var/log",  8,
    &gszVARLOGTo[0], 0
};




void ecsInitPath(int (*pfnAdd)(), int (*pfnRemove)(), int (*pfnRewrite)());


void ecsInitPath(int (*pfnAdd)(), int (*pfnRemove)(), int (*pfnRewrite)())
{
  int     rcRet = 0;
  strcpy(&gszEtcTo[0], getenv("ETC"));
  strcpy(&gszVARLOGTo[0], getenv("LOGFILES"));
  strcpy(&gszTMPTo[0], getenv("TMP"));

    gEtcRule.cchTo = strlen(gEtcRule.pszTo);
    gVARLOGRule.cchTo = strlen(gVARLOGRule.pszTo);
    gTMPRule.cchTo = strlen(gTMPRule.pszTo);

    if ((*pfnAdd)(&gEtcRule, 1))
    {
        rcRet++;
    }
    if ((*pfnAdd)(&gTMPRule, 1))
    {
        rcRet++;
    }
    if ((*pfnAdd)(&gVARLOGRule, 1))
    {
        rcRet++;
    }
   
}

What do we see in the source file ??

we declare some structures to hold the rewrite data:

__LIBC_PATHREWRITE  gVARLOGRule =
{
    __LIBC_PRWF_TYPE_DIR | __LIBC_PRWF_CASE_SENSITIVE,
    "/var/log",  8,
    &gszVARLOGTo[0], 0
};

we tell that gVARLOGRule holds information for a case sensitive directory rewrite of: '/var/log' to the contents of variable gszVARLOGTo.

This variable is initialized in:

  strcpy(&gszVARLOGTo[0], getenv("LOGFILES"));

where we fill it whith the contents of the environment variable 'LOGFILES' ( e.g. C:\VAR\LOG )

When called by LIBC the ecsInitPath functions gets 3 parameters, the first is only used here, which is a function pointer, this pointer is to a function which extends the path rewrite table and it takes a structure as described above as parameter.

this is how we call it:

if ((*pfnAdd)(&gVARLOGRule, 1))
    {
        rcRet++;
    }

Compiling

compiling is very easy, make sure you have GCC 3.3.5 CSD1

gcc -Zdll ecsprw.c ecsprw.def

Ofcourse this is a very easy example which we could easely extend with a administration program to maintain a database of which paths to rewrite.