2011-04-29

Building fusecompress on Centos 5.5

Setting up a backup solution using rdiff-backup, I realized that we would quickly run out of space without compression. Enter fusecompress: a fuse module to transparently compress the files in the filesystem. There's no RPM available for CentOS, but the current version of the code should behave properly on CentOS 6.

First, there are some build dependencies to install. Since lzma compression in fusecompress is so breaky, I decided to compile without it. Development Tools is roughly the equivalent of Debian's build-essential.

yum groupinstall 'Development Tools'
yum install boost boost-devel boost141-iostreams
yum install fuse fuse-devel zlib-devel bzip2-devel lzo-devel

Now get the source from github and compile it; should be easy, right...

su - build
git clone git://github.com/tex/fusecompress.git
cd fusecompress
./configure --with-z --with-bz2 --with-lzo2 --without-lzma
make

Of course, there are complaints. CentOS 5.5 ships with a 2.6.18 kernel, and Boost v1.33.1. Fusecompress uses syscalls from the 2.6.22+ kernel, and Boost v1.44+.

The first step is to backport the Boost v1.44 issues:

git revert 9d5137d7d067151a9822b40e3687b0f645b33937

Then, I coded up implementations of futimens(3) and utimensat(2). These allow nanosecond control of file mtime and ctime attributes. The old versions are now deprecated, and "only" have microsecond precision. These implementations just use the fact that 1ns = 1/1000µs.

#include <fcntl.h>
#include <sys/time.h>

int futimens(int fd, const struct timespec times[2]) {
   struct timeval tv[2];
   tv[0].tv_sec  = times[0].tv_sec;
   tv[0].tv_usec = times[0].tv_nsec / 1000;
   tv[1].tv_sec  = times[1].tv_sec;
   tv[1].tv_usec = times[1].tv_nsec / 1000;

   return futimes(fd, tv);
}

int utimensat(int dirfd, const char *pathname, const struct timespec times[2], int flags) {
   struct timeval tv[2];
   tv[0].tv_sec  = times[0].tv_sec;
   tv[0].tv_usec = times[0].tv_nsec / 1000;
   tv[1].tv_sec  = times[1].tv_sec;
   tv[1].tv_usec = times[1].tv_nsec / 1000;

   return futimesat(dirfd, pathname, tv);
}

Then some hacking of the makefiles to include my new .hpp and .o files in the outputs, and I have a working fusecompress for CentOS 5.5.

:wq