- As mentioned in the last report, I skipped one week in favour of the GUADEC.
- I had a funny C problem. Consider the following two functions:
static int safe_read (void *data, size_t length, FILE* file) { int status = fread(data, length, 1, file); if (status == -1) error_report("%s: read packet (%lu) data on stream %p " "failed (%d): %s", __FUNCTION__, length, file, status, strerror(errno)); status = fflush(file); return status; } static int safe_write (void *data, size_t length, FILE* file) { int status = fwrite(data, length, 1, file); if (status == -1) error_report("%s: writing packet (%lu) data on stream %p " "failed (%d): %s", __FUNCTION__, length, file, status, strerror(errno)); status = fflush(file); return status; }
Now you might want to deduplicate the code and make it one big and two small functions:
static int safe_operation (size_t (func) (void *, size_t, size_t, FILE*), void *data, size_t length, FILE* file) { int status = func(data, length, 1, file); const char *funcstr = "undeclared"; // switch (*func) { // case fread: // funcstr = "read"; // break; // case fwrite: // funcstr = "write"; // break; // default: // funcstr = "?"; // break; // } if (status == -1) error_report("%s: %s (%p) packet (%lu) data on stream %p " "failed (%d): %s", __FUNCTION__, funcstr, *func, length, file, status, strerror(errno)); status = fflush(file); return status; }
but it wouldn’t compile because fread and fwrite have slightly different signatures.
The solution is to:typedef size_t (*fwrite_fn)(const void * __restrict, size_t, size_t, FILE * __restrict); static int safe_operation (fwrite_fn func, void *data, size_t length, FILE* file) { int status = func(data, length, 1, file); const char *funcstr = "undeclared"; if (status == -1) error_report("%s: %s (%p) packet (%lu) data on stream %p " "failed (%d): %s", __FUNCTION__, funcstr, *func, length, file, status, strerror(errno)); status = fflush(file); return status; } int main(void) { int x; safe_operation((fwrite_fn)fread, &x, sizeof x, stderr); safe_operation(fwrite, &x, sizeof x, stderr); return 0; }
Thanks to Roland for pointing that out.
- On smth unrelated: Fought with OpenSSL and it’s API and documentation. But more on that in a different post.
- Fortunately, only Gajim crashed once. Well rhythmbox locks up, too, as it always does
- Annoyed by the fact, that it takes ages to “make” a freshly made kernel!
muelli@bigbox ~/git/linux-2.6 $ time make CHK include/linux/version.h CHK include/generated/utsrelease.h CALL scripts/checksyscalls.sh CHK include/generated/compile.h CHK include/linux/version.h make[2]: `scripts/unifdef' is up to date. TEST posttest Succeed: decoded and checked 1382728 instructions Kernel: arch/x86/boot/bzImage is ready (#14) Building modules, stage 2. MODPOST 2107 modules WARNING: modpost: Found 4 section mismatch(es). To see full details build your kernel with: 'make CONFIG_DEBUG_SECTION_MISMATCH=y' real 14m7.842s user 1m33.747s sys 0m25.388s muelli@bigbox ~/git/linux-2.6 $
- Trying to automatically create a FAT image and fill populate it with the built modules is more cumbersome than expected. guestmount is way too much overhead: It requires qemu and channels the data out over the network (sic!). I just want a FUSE implementation that is capable of writing a FAT image! There seems to be UMFUSE but it’s packaged for Debian/Ubuntu and not for Fedora.Find the sources is quite a challenge (it’s here: https://view-os.svn.sourceforge.net/svnroot/view-os/trunk/fuse-modules/fat) but I can’t build it, because they haven’t really prepared their code for anybody else to build it. After being harassed to generate the ./configure file (autoconf,; aclocal; autoconf), it also wants shtool to be installed AND in a local directory (/.-). I gave up as it kept bugging me about a missing config.sub. But I still wanted to get that FUSE module so I dug up my Ubuntu chroot and apt-get sourced the files, ./configure && make && make install. Beautiful. Turns out, that the official FUSE wiki lists two ways to mount a FATfs: the one I’ve just described and a dead project (FatFuse).
I then threw together this shellscript:
##!/bin/bash MOD_DIR=/tmp/linux-modules/ FAT_IMAGE=/tmp/modules.$$.fat FAT_MOUNT=/tmp/share/ FAT_TARGET_IMAGE=/tmp/modules.fat make modules_install INSTALL_MOD_PATH="$MOD_DIR" && bytes=$(( $(du -s $MOD_DIR | awk '{print $1}') + $(( 20 * 1024)) )) # # create FAT image dd if=/dev/zero of=$FAT_IMAGE bs=1024 count=$bytes && mkfs.vfat $FAT_IMAGE && fusefat -o nonempty -o rw+ $FAT_IMAGE $FAT_MOUNT && cp -dRx $MOD_DIR/* $FAT_MOUNT fusermount -u $FAT_MOUNT && echo $FAT_IMAGE && ln -sf $FAT_IMAGE $FAT_TARGET_IMAGE
and I start qemu like that:
/opt/muelli/qemu/bin/qemu-system-x86_64 -drive file=/tmp/ubuntu-snapshots.qcow2,if=virtio -kernel ~/git/linux-2.6/arch/x86_64/boot/bzImage -append 'selinux=0 root=/dev/vda init=/sbin/init' -m 1G -drive file=/tmp/modules.fat,if=virtio,readonly=on -monitor stdio -loadvm 1
which allows me to access the module on the FAT drive on /dev/vdb. I can also snapshot the booted machine which saves me an awful lot of time for booting. But it took me quite a while to make QEmu do that, because the snapshot parameter for the disk does not save snapshots! Also, the FAT drive has to marked as readonly for QEmu to only save snapshots on the only remaining writable drive. But QEmu fails to make a drive readonly if the selected interface is IDE. Thus, you need virtio… Thanks to the helpful folks on IRC… - So yeah, all in all, I didn’t make any substantial progress :-/ I hope to finish a Webcam in software soonish though.