195 lines
4.8 KiB
C
195 lines
4.8 KiB
C
/*
|
|
syscall.c -- override open(2)
|
|
|
|
(c) Han-Wen Nienhuys <hanwen@cs.uu.nl> 1998
|
|
(c) Jork Loeser <jork.loeser@inf.tu-dresden.de> 2002
|
|
(c) Michael Roitzsch <mroi@os.inf.tu-dresden.de> 2007
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <fcntl.h>
|
|
#include <stdarg.h>
|
|
#include <errno.h>
|
|
#include <stddef.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
#include <fcntl.h>
|
|
#include <unistd.h>
|
|
#include <sys/syscall.h>
|
|
#include <unistd.h>
|
|
/* Assume GNU as target platform. We need this in dlfcn.h */
|
|
#define __USE_GNU
|
|
#include <dlfcn.h>
|
|
#include "gendep.h"
|
|
|
|
#ifdef __ELF__
|
|
# define OPEN __open
|
|
# define OPEN64 __open64
|
|
# define FOPEN __fopen
|
|
# define FOPEN64 __fopen64
|
|
# define UNLINK __unlink
|
|
#else
|
|
# define OPEN open
|
|
# define OPEN64 open64
|
|
# define FOPEN fopen
|
|
# define FOPEN64 fopen64
|
|
# define UNLINK unlink
|
|
#endif
|
|
|
|
#define VERBOSE 0 /* set to 1 to log open/unlink calls */
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
/*
|
|
This breaks if we hook gendep onto another library that overrides open(2).
|
|
(zlibc comes to mind)
|
|
*/
|
|
static int real_open (const char *fn, int flags, int mode)
|
|
{
|
|
if(VERBOSE) printf("real_open(%s)\n", fn);
|
|
return (syscall(SYS_open, (fn), (flags), (mode)));
|
|
}
|
|
|
|
int OPEN(const char *fn, int flags, ...)
|
|
{
|
|
int rv ;
|
|
va_list p;
|
|
va_start (p,flags);
|
|
|
|
if(VERBOSE) printf("open(%s) called\n", fn);
|
|
rv = real_open (fn, flags, va_arg (p, int));
|
|
if (rv >=0)
|
|
gendep__register_open (fn, flags);
|
|
|
|
return rv;
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
typedef int(*open64_type)(const char*, int flag, int mode);
|
|
|
|
static int real_open64(const char*path, int flag, int mode){
|
|
static open64_type f_open64;
|
|
|
|
if(VERBOSE) printf("real_open64(%s)\n", path);
|
|
if(f_open64==0){
|
|
*(void**)(&f_open64) = dlsym(RTLD_NEXT, "open64");
|
|
if(!f_open64){
|
|
fprintf(stderr, "gendep: Cannot resolve open64()\n");
|
|
errno=ENOENT;
|
|
return 0;
|
|
}
|
|
}
|
|
return f_open64(path, flag, mode);
|
|
}
|
|
|
|
int OPEN64(const char*path, int flag, int mode){
|
|
int f;
|
|
|
|
if(VERBOSE) printf("open64(%s)\n", path);
|
|
f = real_open64(path, flag, mode);
|
|
if(f>=0){
|
|
gendep__register_open(path, flag);
|
|
}
|
|
return f;
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
typedef FILE* (*fopen_type)(const char*, const char*);
|
|
|
|
static FILE* real_fopen(const char*path, const char*mode){
|
|
static fopen_type f_fopen;
|
|
|
|
if(VERBOSE) printf("real_fopen(%s)\n", path);
|
|
if(f_fopen==0){
|
|
*(void**)(&f_fopen) = dlsym(RTLD_NEXT, "fopen");
|
|
if(!f_fopen){
|
|
fprintf(stderr, "gendep: Cannot resolve fopen()\n");
|
|
errno=ENOENT;
|
|
return 0;
|
|
}
|
|
}
|
|
return f_fopen(path, mode);
|
|
}
|
|
|
|
FILE* FOPEN(const char*path, const char*mode){
|
|
FILE *f;
|
|
int binmode;
|
|
|
|
if(VERBOSE) printf("fopen(%s)\n", path);
|
|
f = real_fopen(path, mode);
|
|
if(f){
|
|
if(strchr(mode, 'w') || strchr(mode, 'a')){
|
|
binmode=O_WRONLY;
|
|
} else {
|
|
binmode=O_RDONLY;
|
|
}
|
|
gendep__register_open(path, binmode);
|
|
}
|
|
return f;
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
typedef FILE* (*fopen64_type)(const char*, const char*);
|
|
|
|
static FILE* real_fopen64(const char*path, const char*mode){
|
|
static fopen64_type f_fopen64;
|
|
|
|
if(VERBOSE) printf("real_fopen64(%s)\n", path);
|
|
if(f_fopen64==0){
|
|
*(void**)(&f_fopen64) = dlsym(RTLD_NEXT, "fopen64");
|
|
if(!f_fopen64){
|
|
fprintf(stderr, "gendep: Cannot resolve fopen64()\n");
|
|
errno=ENOENT;
|
|
return 0;
|
|
}
|
|
}
|
|
return f_fopen64(path, mode);
|
|
}
|
|
|
|
FILE* FOPEN64(const char*path, const char*mode){
|
|
FILE *f;
|
|
int binmode;
|
|
|
|
if(VERBOSE) printf("fopen64(%s)\n", path);
|
|
f = real_fopen64(path, mode);
|
|
if(f){
|
|
if(strchr(mode, 'w') || strchr(mode, 'a')){
|
|
binmode=O_WRONLY;
|
|
} else {
|
|
binmode=O_RDONLY;
|
|
}
|
|
gendep__register_open(path, binmode);
|
|
}
|
|
return f;
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
static int real_unlink (const char *fn)
|
|
{
|
|
if(VERBOSE) printf("real_unlink(%s)\n", fn);
|
|
return syscall(SYS_unlink, (fn));
|
|
}
|
|
|
|
int UNLINK(const char *fn)
|
|
{
|
|
int rv ;
|
|
|
|
if(VERBOSE) printf("unlink(%s)\n", fn);
|
|
rv = real_unlink (fn);
|
|
if (rv >=0)
|
|
gendep__register_unlink (fn);
|
|
|
|
return rv;
|
|
}
|
|
|
|
/* ----------------------------------------------------------------------- */
|
|
#ifdef __ELF__
|
|
int open (const char *fn, int flags, ...) __attribute__ ((alias ("__open")));
|
|
int open64 (const char *fn, int flags, ...) __attribute__ ((alias ("__open64")));
|
|
int unlink(const char *fn) __attribute__ ((alias ("__unlink")));
|
|
FILE *fopen (const char *path, const char *mode) __attribute__ ((alias ("__fopen")));
|
|
FILE *fopen64 (const char *path, const char *mode) __attribute__ ((alias ("__fopen64")));
|
|
#endif
|