Practicum Status Update Week 10

  • 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.

Leave a Reply

Your email address will not be published. Required fields are marked *

Creative Commons Attribution-ShareAlike 3.0 Unported
This work by Muelli is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported.