coredump added.
This commit is contained in:
parent
52e5191dac
commit
60e1aec248
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,3 +1,5 @@
|
||||||
|
/coredump
|
||||||
|
|
||||||
# ---> Vim
|
# ---> Vim
|
||||||
# Swap
|
# Swap
|
||||||
[._]*.s[a-v][a-z]
|
[._]*.s[a-v][a-z]
|
||||||
|
|
12
Makefile
Normal file
12
Makefile
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
all: coredump
|
||||||
|
|
||||||
|
coredump: coredump.o
|
||||||
|
gcc -o $@ $^
|
||||||
|
|
||||||
|
%.o: %.c
|
||||||
|
gcc -fPIC -g -c -o $@ $<
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f coredump coredump.o
|
||||||
|
|
||||||
|
.PHONY: clean all
|
285
coredump.c
Normal file
285
coredump.c
Normal file
|
@ -0,0 +1,285 @@
|
||||||
|
#define _GNU_SOURCE
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/sendfile.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
typedef struct argv_t {
|
||||||
|
char *_self;
|
||||||
|
char *coredir;
|
||||||
|
char *pid; // %p
|
||||||
|
char *global_pid; // %P
|
||||||
|
char *tid; // %i
|
||||||
|
char *global_tid; // %I
|
||||||
|
char *uid; // %u
|
||||||
|
char *gid; // %g
|
||||||
|
char *dump_mode; // %d
|
||||||
|
char *signal; // %s
|
||||||
|
char *ts; // %t
|
||||||
|
char *hostname; // %h
|
||||||
|
char *exefn_; // %e
|
||||||
|
char *exefn; // %f
|
||||||
|
char *exepath; // %E
|
||||||
|
char *max_size; // %c
|
||||||
|
char *cpu; // %C
|
||||||
|
} argv_t;
|
||||||
|
|
||||||
|
const char const expected_pattern[] = "|%s <DESTINATION-PATH> %%p %%P %%i %%I %%u %%g %%d %%s %%t %%h %%e %%f %%E %%c %%C";
|
||||||
|
|
||||||
|
typedef char *path_t;
|
||||||
|
|
||||||
|
typedef struct args_t {
|
||||||
|
path_t _self;
|
||||||
|
path_t coredir;
|
||||||
|
pid_t pid;
|
||||||
|
pid_t global_pid;
|
||||||
|
uint tid;
|
||||||
|
uint global_tid;
|
||||||
|
uid_t uid;
|
||||||
|
gid_t gid;
|
||||||
|
uint dump_mode;
|
||||||
|
uint signal;
|
||||||
|
uint ts;
|
||||||
|
char* hostname;
|
||||||
|
path_t exefn_;
|
||||||
|
path_t exefn;
|
||||||
|
path_t exepath;
|
||||||
|
size_t max_size;
|
||||||
|
uint cpu;
|
||||||
|
} args_t;
|
||||||
|
// if max_size is 0 or bigger than MAX_SIZE, then MAX_SIZE (1GiB):
|
||||||
|
#define MAX_SIZE 1073741824
|
||||||
|
|
||||||
|
int prsint( long unsigned int *dst, char *src) {
|
||||||
|
*dst = 0;
|
||||||
|
for( uint i = 0; src[i]; i++) {
|
||||||
|
if( '0' <= src[i] && src[i] <= '9')
|
||||||
|
*dst = 10*(*dst) + src[i]-'0';
|
||||||
|
else
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#define CHK_EXST( key) \
|
||||||
|
if( NULL == v->key) { \
|
||||||
|
fprintf( stderr, "ERROR: Missing value for: %s\n", #key); \
|
||||||
|
return -1; \
|
||||||
|
}
|
||||||
|
#define TOSTR( key) CHK_EXST( key) \
|
||||||
|
s->key = v->key;
|
||||||
|
#define TOINT( key) CHK_EXST( key) \
|
||||||
|
if( -1 == prsint( &b, v->key)) { \
|
||||||
|
fprintf( stderr, "ERROR: Invalid value in: %s=%s\n", #key, v->key); \
|
||||||
|
return -1; \
|
||||||
|
} \
|
||||||
|
s->key = b;
|
||||||
|
|
||||||
|
int argv2args( argv_t *v, args_t *s) {
|
||||||
|
long unsigned int b;
|
||||||
|
TOSTR( coredir);
|
||||||
|
TOINT( pid);
|
||||||
|
TOINT( global_pid);
|
||||||
|
TOINT( tid);
|
||||||
|
TOINT( global_tid);
|
||||||
|
TOINT( uid);
|
||||||
|
TOINT( gid);
|
||||||
|
TOINT( dump_mode);
|
||||||
|
TOINT( signal);
|
||||||
|
TOINT( ts);
|
||||||
|
TOSTR( hostname);
|
||||||
|
TOSTR( exefn_);
|
||||||
|
TOSTR( exefn);
|
||||||
|
TOSTR( exepath);
|
||||||
|
TOINT( max_size);
|
||||||
|
TOINT( cpu);
|
||||||
|
}
|
||||||
|
|
||||||
|
int proc_filename( char *dest, size_t len, argv_t *argv, char* fn) {
|
||||||
|
size_t destl = snprintf( dest, len, "/proc/%s/%s", argv->pid, fn);
|
||||||
|
if( destl < 0) {
|
||||||
|
fprintf( stderr, "ERROR: gen path for %s: %s (%i)\n", fn, strerror( errno), errno);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if( len <= destl) {
|
||||||
|
fprintf( stderr, "ERROR: gen path for %s: /proc/-path to long: destl=%lu\n", fn, destl);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int core_filename( char *dest, size_t len, argv_t *argv, char* ext) {
|
||||||
|
size_t destl = snprintf( dest, len, "%s/core%s.%s", argv->coredir, ext, argv->pid);
|
||||||
|
if( destl < 0) {
|
||||||
|
fprintf( stderr, "ERROR: gen path for core%s: %s (%i)\n", ext, strerror( errno), errno);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if( len <= destl) {
|
||||||
|
fprintf( stderr, "ERROR: gen path for core%s: /proc/-path to long: destl=%lu\n", ext, destl);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void show_opened_files() {
|
||||||
|
pid_t selfpid = getpid();
|
||||||
|
pid_t child = fork();
|
||||||
|
switch( child) {
|
||||||
|
case -1:
|
||||||
|
fprintf( stderr, "ERROR: error while forking: %s (%i)\n", strerror( errno), errno);
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
char dir[1024];
|
||||||
|
snprintf( dir, sizeof dir, "/proc/%i/fd/", selfpid);
|
||||||
|
execl( "/usr/bin/env", "env", "ls", "-la", dir, NULL);
|
||||||
|
fprintf( stderr, "ERROR: Executing ls failed: %s (%i)\n", strerror( errno), errno);
|
||||||
|
exit( 2);
|
||||||
|
default:
|
||||||
|
int ws;
|
||||||
|
waitpid( child, &ws, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int dump_core( argv_t *argv, args_t *args) {
|
||||||
|
// Concept: Once used, not necessary anymore, we cen reuse the space again.
|
||||||
|
char path[1024]; // For any paths.
|
||||||
|
int rfd; // read file handler.
|
||||||
|
int wfd; // write file handler.
|
||||||
|
struct stat stat; // Needed for determine size of file.
|
||||||
|
|
||||||
|
// copy stdin -> core.pid
|
||||||
|
if( core_filename( path, sizeof path, argv, ""))
|
||||||
|
return 1;
|
||||||
|
if( -1 == (wfd = open( path, O_WRONLY | O_CREAT | O_TRUNC, 0600))) {
|
||||||
|
fprintf( stderr, "ERROR: Cannot open file %s: %s (%i)\n", path, strerror( errno), errno);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if( -1 == splice(
|
||||||
|
STDIN_FILENO, 0,
|
||||||
|
wfd, 0,
|
||||||
|
(args->max_size || MAX_SIZE < args->max_size) ? args->max_size : MAX_SIZE, 0)) {
|
||||||
|
fprintf( stderr, "ERROR: Cannot write core to file %s: %s (%i)\n", path, strerror( errno), errno);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
close( wfd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int copy_fd_to_fd( int infd, int outfd) {
|
||||||
|
char buf[1024];
|
||||||
|
size_t left;
|
||||||
|
while( 0 < (left = read( infd, buf, sizeof buf))) {
|
||||||
|
char *wb = buf;
|
||||||
|
ssize_t wr;
|
||||||
|
while( left > (wr = write( outfd, wb, left))) {
|
||||||
|
if( -1 == wr) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
left -= wr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int dump_cmdline( argv_t *argv, args_t *args) {
|
||||||
|
// Concept: Once used, not necessary anymore, we cen reuse the space again.
|
||||||
|
char path[1024]; // For any paths.
|
||||||
|
int rfd; // read file handler.
|
||||||
|
int wfd; // write file handler.
|
||||||
|
struct stat stat; // Needed for determine size of file.
|
||||||
|
|
||||||
|
// copy /proc/pid/cmdline -> core-cmdline.pid
|
||||||
|
if( proc_filename( path, sizeof path, argv, "cmdline")) return 1;
|
||||||
|
if( -1 == (rfd = open( path, O_RDONLY, 0644))) {
|
||||||
|
fprintf( stderr, "ERROR: Cannot open file %s: %s (%i)\n", path, strerror( errno), errno);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if( -1 == fstat( rfd, &stat)) {
|
||||||
|
fprintf( stderr, "ERROR: Cannot stat of file %s: %s (%i)\n", path, strerror( errno), errno);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if( core_filename( path, sizeof path, argv, "-cmdline")) return 1;
|
||||||
|
if( -1 == (wfd = open( path, O_WRONLY | O_CREAT | O_TRUNC, 0644))) {
|
||||||
|
fprintf( stderr, "ERROR: Cannot open file %s: %s (%i)\n", path, strerror( errno), errno);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
//show_opened_files();
|
||||||
|
//if( -1 == sendfile( wfd, rfd, NULL, 1024*1024)) {
|
||||||
|
if( -1 == copy_fd_to_fd( rfd, wfd)) {
|
||||||
|
fprintf( stderr, "ERROR: Cannot write to file %s: %s (%i)\n", path, strerror( errno), errno);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
close( rfd);
|
||||||
|
close( wfd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define P( s, m) if( -1 == fprintf( wfh, "%s=%s\n", #s, argv->m)) { \
|
||||||
|
fprintf( stderr, "ERROR: Cannot write to file %s: %s (%i)\n", path, strerror( errno), errno); \
|
||||||
|
return 1; \
|
||||||
|
}
|
||||||
|
int dump_md( argv_t *argv) {
|
||||||
|
// Concept: Once used, not necessary anymore, we cen reuse the space again.
|
||||||
|
char path[1024]; // For any paths.
|
||||||
|
FILE *wfh;
|
||||||
|
|
||||||
|
// write argv -> core-md.pid
|
||||||
|
if( core_filename( path, sizeof path, argv, "-md")) return 1;
|
||||||
|
umask( 0133);
|
||||||
|
if( NULL == (wfh = fopen( path, "w"))) {
|
||||||
|
fprintf( stderr, "ERROR: Cannot open file %s: %s (%i)\n", path, strerror( errno), errno);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
P(p, pid)
|
||||||
|
P(P, global_pid)
|
||||||
|
P(i, tid)
|
||||||
|
P(I, global_tid)
|
||||||
|
P(u, uid)
|
||||||
|
P(g, gid)
|
||||||
|
P(d, dump_mode)
|
||||||
|
P(s, signal)
|
||||||
|
P(t, ts)
|
||||||
|
P(h, hostname)
|
||||||
|
P(e, exefn_)
|
||||||
|
P(f, exefn)
|
||||||
|
P(E, exepath)
|
||||||
|
P(c, max_size)
|
||||||
|
P(C, cpu)
|
||||||
|
fclose( wfh);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main( size_t argc, argv_t *argv) {
|
||||||
|
args_t *args = malloc( sizeof (args_t));
|
||||||
|
args->_self = realpath( argv->_self, NULL);
|
||||||
|
|
||||||
|
if( (sizeof (argv_t))/(sizeof (char*)) > argc) {
|
||||||
|
fprintf( stderr, "ERROR: %li arguments expected. Exect value of kernel.core_pattern must be: `", (sizeof (argv_t))/(sizeof (char*)));
|
||||||
|
fprintf( stderr, expected_pattern, args->_self);
|
||||||
|
fprintf( stderr, "`. Given: %li\n", argc-1);
|
||||||
|
if( '/' != args->_self[0])
|
||||||
|
fprintf( stderr, "\tAttention: Absolut path instead of %s should be used!\n", args->_self);
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
argv2args( argv, args);
|
||||||
|
|
||||||
|
//fprintf( stderr, "dump core...\n");
|
||||||
|
dump_core( argv, args);
|
||||||
|
// That's all, core dump written. :)
|
||||||
|
// But, hold on, now the funny things will follow, which are the differences to a simple core-dump.
|
||||||
|
|
||||||
|
//fprintf( stderr, "dump cmdline...\n");
|
||||||
|
dump_cmdline( argv, args);
|
||||||
|
//fprintf( stderr, "dump metadata...\n");
|
||||||
|
dump_md( argv);
|
||||||
|
//fprintf( stderr, "exit...\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in a new issue