Simple uname(2) wrapper to work around a CrashPlan bug and enable real-time watching
/* | |
* Simple uname(2) wrapper library that appends ".0" to any release version | |
* of the form X.Y -- for example, "3.16-2-amd64" becomes "3.16.0-2-amd64". | |
* | |
* This crude hack is meant to work around a CrashPlan bug[*]: real-time | |
* watching is only enabled after checking the kernel version for inotify | |
* support (which was added in 2.6.13), but the version is expected to be of | |
* the form X.Y.Z. If this is not the case, CrashPlan assumes that inotify | |
* is not supported, and real-time watching is disabled. | |
* | |
* [*] https://bugs.debian.org/745984 | |
* | |
* | |
* INSTRUCTIONS: | |
* | |
* 1. Compile (feel free to rename the .so): | |
* | |
* gcc -Wall -O2 -shared -fPIC -ldl crashplan_uname.c -o libcrashplan_uname.so | |
* | |
* 2. (Optional) Install the .so where it can be found by ld.so: | |
* | |
* mv libcrashplan_uname.so /usr/local/lib/ && ldconfig | |
* | |
* 3. Add the following line to CrashPlan's bin/run.conf: | |
* (You will need to provide a full pathname if you skipped step 2.) | |
* | |
* export LD_PRELOAD=libcrashplan_uname.so | |
* | |
* You can now (re-)start the CrashPlan engine. Enjoy! | |
*/ | |
#define _GNU_SOURCE /* RTLD_NEXT is a GNU feature */ | |
#include <dlfcn.h> /* dynamic linking */ | |
#include <sys/utsname.h> /* uname() itself */ | |
#include <ctype.h> /* isdigit() */ | |
#include <string.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
int uname (struct utsname *buf) { | |
/* real uname() function */ | |
static int (*real_uname) (struct utsname *buf); | |
int ret; | |
/* dlsym() error, if any */ | |
char *error; | |
/* We'll need to scan the release string, and maybe copy part of it */ | |
char *p, *tmp; | |
int n_dots = 0; | |
/* Find the real uname() if we haven't already written it down */ | |
if (!real_uname) { | |
real_uname = dlsym(RTLD_NEXT, "uname"); | |
if ((error = dlerror()) != NULL) { | |
fprintf(stderr, "%s\n", error); | |
exit(1); | |
} | |
} | |
ret = real_uname(buf); | |
/* No need to continue if there's not enough room for ".0" anyway */ | |
if (strlen(buf->release) + 2 >= sizeof(buf->release)) | |
return ret; | |
/* Counting the dots... (the field is guaranteed null-terminated) */ | |
for (p = buf->release; *p; p++) { | |
if (*p == '.') | |
n_dots++; | |
else if (! isdigit(*p)) | |
break; | |
} | |
if (n_dots < 2) { | |
/* (No need for strndup/strncpy -- we know everything fits) */ | |
tmp = strdup(p); | |
*p = '.'; p++; | |
*p = '0'; p++; | |
strcpy(p, tmp); | |
free(tmp); | |
} | |
return ret; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment