Create a gist now

Instantly share code, notes, and snippets.

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