How can i hook file saving in Linux systems (to show my programm dialog, opearting with them then)?
Just use the inotify interface to get notification of file system changes. See: http://linux.die.net/man/7/inotify
You can try FILE_PRELOAD utility which generate C++ code with hooks, compile and LD_PRELOAD it. After short look at it you can feel how easy to hook linux. Start point is this tutorial.
For example, if you want to change 'open call' of file /tmp/some with /tmp/replace_with:
#: FILE_PRELOAD -C "A+f:/tmp/some:/tmp/replace_with" -- bash
#: echo "HaHa" >> /tmp/some
#: ll /tmp/some
ls: cannot access /tmp/some: No such file or directory
#: cat /tmp/replace_with
HaHa
If you want to see the source of generated code just add "-p" to options.
#: FILE_PRELOAD -p -C "A+f:/tmp/some:/tmp/replace_with" -- bash
In additional all generated.cpp files you can find in /tmp/$USER/FILE_PRELOAD/cpp.
Have a nice play with linux hooks)
Generated code looks like this:
#include <sys/types.h>
#include <dlfcn.h>
#include <stdio.h>
#include <map>
#include <string>
#define I int
#define C char
#define S string
#define P printf
#define R return
using std::map;
using std::string;
typedef map<S,S> MAP;
static I (*old_open)(const C *p, I flags, mode_t mode);
extern "C"
I open (const C *p, I flags, mode_t mode){
old_open = dlsym(RTLD_NEXT, "open");
P("open hook\n");
MAP files;
files[p]=p;
files["/tmp/some"]="/tmp/replace_with";
S newpath = files[S(p)];
R old_open(newpath.c_str(), flags, mode);
}
# &compile
gcc -w -fpermissive -fPIC -c -Wall file.cpp
gcc -shared file.o -ldl -lstdc++ -o wrap_loadfile.so
LD_PRELOAD=./wrap_loadfile.so bash
nm -D /lib/libc.so.6 | grep open # we hook this syscall
If you can compile them you can link first against a custom library that provides open().
There's a stock way of doing it.
If you can't compile it, this works most of the time:
Write function _open_posthook that does syscall(NR_OPEN, ...)
Provide shared library libopenhook that provides your new open. Rembember you renamed open to _open_posthook() here unless you want recursion. Don't forget to also provide creat().
Load this library with LD_PRELOAD.
EDIT: if you're trying for security this won't work. You might be able to get away with using strace() but unless you are very careful a determined programmer can overcome that too.
Related
I have several projects in which I use many custom macros. For example,
//prog.c
#include <stdio.h>
#ifdef DBG_LEVEL_1
#define P(d) printf("%s:%d\n", #d, d);
#else
#define P(...)
#endif
#ifdef INLINE
#define INL static inline
#else
#define INL
#endif
INL void func_Sqr(int a)
{
printf("sqr(a):%d\n", a*a);
}
int main()
{
int a = 3;
P(a);
func_Sqr(a);
return 0;
}
I compile this in several ways,
gcc prog.c
gcc -DINLINE prog.c
gcc -DDBG_LEVEL_1 prog.c
gcc -DDBG_LEVEL_1 -DINLINE-DINLINE prog.c
Is there way to set these macros as enabled as default via environment variable?
We can solve this by creating a makefile where these macros are set. But I want to know if there any Linux environment related solution
Is there way to set these macros as enabled as default via environment variable?
Generally, no there is not. Gcc arguments are not affected by environment variables (except maybe DEPENDENCIES_OUTPUT..).
I advise to write a small wrapper function around the command, for example a bash function:
wgcc() {
gcc "${GCCARGS[#]}" "$#"
}
and then doing:
GCCARGS+=(-DA=1 -DB=2)
wgcc something.c
is trivial to do, easy to understand and maintain and communicate with other team members, easy to implement and share. Suprising haisenbugs will be easy to track - wgcc is unique name different then gcc. Still you could overwrite the original command with gcc() { command gcc "${GCCARGS[#]}" "$#"; } or by creating a /usr/local/bin/gcc file, making it a bit more confusing.
But! You can and I woult strongly advise not to do that, because it will be confusing to others and hard to maintain. You can use COMPILER_PATH environment variable to overwrite compiler tools and provide custom options. In steps:
Create a temporary directory
In that directory link all the subprograms of gcc to it's normal prefix, except the tools the behavior you want to modify, like cc1.
Then create cc1 as a script with that will call the original cc1 but will use some environment variable to pass extra arguments.
Then export the path as COMPILER_PATH so gcc will pick it up.
On my archlinux with gcc10.0.1 I did:
mkdir /tmp/temp
cd /tmp/temp
for i in /usr/lib/gcc/x86_64-pc-linux-gnu/10.1.0/{cc1plus,collect2,lto-wrapper,lto1}; do ln -vs "$i"; done
printf "%s\n" '#!/bin/sh' '/usr/lib/gcc/x86_64-pc-linux-gnu/10.1.0/cc1 $GCCARGS "$#"' > cc1
chmod +x cc1
export COMPILER_PATH=/tmp/temp
After that you can:
export GCCARGS=-DA=1
gcc -xc - <<<'int main() { printf("A=%d\n", A); }'
./a.out
> A=1
The GCC manual describes -fabi-compat-version=n, which is used to handle variations in C++ name mangling in the slightly variant C++ ABIs of GCC 3.4 to 9.2, and probably later. It has an important caveat:
On targets that support strong aliases, G++ works around mangling changes by
creating an alias with the correct mangled name when defining a symbol with
an incorrect mangled name. This switch specifies which ABI version to use for
the alias.
However, it's not immediately obvious how you find out if your platform does support strong aliases.
The easy way to find out is to write a small program that uses __attribute__ to create an alias, and then use nm to see if the alias exists. Here's sample code, which is a variant on the classic "Hello, World" program:
/* strong_alias.c
compile with 'gcc strong_alias.c'
run ./a.out to check it works, and then run 'nm ./a.out'
to check that strong_alias() has the same address as main() */
#include <stdio.h>
int main( int argc, char *argv[])
{
printf( "Hello, World\n");
return 0;
}
int strong_alias( int argc, char *argv[]) __attribute__ (( alias ("main")));
Compile it and check that it runs, then use nm strong_alias to look at its symbol table. Here's a version that was compiled on CentOS 7 for x86-64:
nm ./a.out | egrep ' (main|strong_alias)'
000000000040052d T main
000000000040052d T strong_alias
We can see that main and strong_alias have the same address, and are thus aliases.
I read the following manual:
http://linux.die.net/man/3/clock_gettime
and I wrote the following code:
#include <time.h>
int main() {
struct timespec clk;
clock_gettime(CLOCK_REALTIME, &clk);
return 0;
}
Surprisingly, I get the following errors:
Symbol CLOCK_REALTIME could not be resolved
undefined reference to clock_gettime
I still don't understand what is the problem. I included the header, and these names show in this header.
maybe you should use#define _POSIX_TIMERS,#define _REENTRANT
besides, when you compile the code, make sure to link the real-time library which is cc filename.c -o filename -lrt
Update 1.0:
sometimes in windows or mac os, C ide may not include real-time library automatically, or we may not used the posix directly without _POSIX_TIMES, therefore you have to link the real-time library manually. In Linux, you can just type in cc filename.c -o filename -lrt to compile the c file.
I'm trying to compile an object code with a reference to one lib. This is the code of libexample.c:
#include "libexample.h"
#include <signal.h>
#include <time.h>
timer_t sched;
struct itimerspec timer = {{0, 0}, {0, 0}};
void init() {
struct sigaction sa;
sigemptyset(&sa.sa_mask);
sigaction(SIGALRM, &sa, NULL);
timer_create(CLOCK_PROCESS_CPUTIME_ID, NULL, &sched);
timer_settime(sched, TIMER_ABSTIME, &timer, NULL);
}
And the simple code of a example program:
#include "libexample.h"
int main() {
init();
return 0;
}
I use this to compile:
gcc libexample.c -c -lrt -o libexample.o
gcc example.c -lrt ibexample.o -o example
And I get this when I'm trying to compile with the second line:
./libexample.so: undefined reference to `timer_create'
./libexample.so: undefined reference to `timer_settime'
Anyone knows what I'm doing wrong?
Add -lrt to your link command. timer_create and timer_settime are not part of the C Standard library.
gcc -fPIC -shared libexample.c -lrt -o libexample.so
gcc -L. example.c -lexample -o example
The man timer_create command explains you:
NAME
timer_create - create a POSIX per-process timer
SYNOPSIS
#include <signal.h>
#include <time.h>
int timer_create(clockid_t clockid, struct sigevent *sevp,
timer_t *timerid);
Link with -lrt.
So you should, as documentation says, link with -lrt.
So use
gcc libexample.c -fPIC -shared -o libexample.so -lrt
to produce your libexample.so.
As undur_gongor commented, you need to put the libraries in good order after all the rest (the usual order for gcc arguments is source files, object files, libraries in dependency order) in gcc or ld commands (and that is documented in ld documentation, and in gcc ones). So -lrt should go last.
And learn to read man pages.
Looks like you forgot to link in the library that defines timer_create and timer_settime -- you need to add -lrt to your gcc command.
(source: http://www.kernel.org/doc/man-pages/online/pages/man2/timer_create.2.html)
If you are using cmake, make sure you include the libraries using target_link_libraries(). For e.g., timer functions like timer_create() you need "rt" and for pthread you need "pthread" added using target_link_libraries().
I have read several tutorials but I still do not have any clue :-) I have a c File "liboratidy.c" this file includes some oder libraries:
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <tidy.h>
#include <buffio.h>
#include <oci.h>
#include <ociextp.h>
The needed files are located in /user/lib/libtidy.so and header files in /usr/include/tidy/ and /usr/lib/oracle/xe/app/oracle/product/10.2.0/server/rdbms/public/
I try to compile my code as shared library but every way I invoke my gcc compiler I will get a "xy.h file not found" error. But the files are existing. I have never done something with c,c++ ... how do I make a Makefile for compiling this source?
Thanks
Christian
The -I options should point to the directories (e.g. -I /usr/include/tidy) that contain the header files you need to compile against. The -L options should point to the directories (e.g. -L /usr/lib/opracle/.....) that contain the libraries you need to build against. The -l options should contain the shortened name (e.g. libfoo.so -> -lfoo) of the libraries you want to build against.