The random rantings of a concerned programmer.

Invoking mount(2) in FreeBSD 8.x

July 17th, 2011 | Category: Random

So I’m still writing Go bindings for a lot of common FreeBSD functionality. Yesterday I implemented a means to list all mounted filesystems, so today I’m writing the bindings to mount(2) to mount/umount them.

If you look at the man page for mount, you’ll see that the function signature looks like this:

    int mount(const char *type, const char *dir, int flags, void *data);

The void* should scare you.

I haven’t been able to dig up any information about what the fuck should be passed to it (granted, I haven’t looked very hard because, judging from the contents of src/sbin/mount_*/*.c in the FreeBSD sources, it’s been entirely superseded by nmount.

    int nmount(struct iovec *iov, u_int niov, int flags);

Poking around, struct iovec (eventually included from sys/uio.h) is defined as this:

struct iovec {
    void *iov_base;
    size_t iov_len;
}

Effectively, nmount takes an array of these structs which effectively form a flattened vector of (key, value) tuples. As far as I can tell, iov_base is always a NULL-terminated char*, and iov_len should be strlen(iov_base) + 1 (for the NULL terminator).

Unfortunately, the only hints that man 2 nmount gives us is

The following options are required by all file
     systems:
	   fstype     file system type name (e.g., ``procfs'')
	   fspath     mount point pathname (e.g., ``/proc'')

     Depending on the file system type, other options may be recognized or
     required; for example, most disk-based file systems require a ``from''
     option containing the pathname of a special device in addition to the
     options listed above.

So far, the only way I’ve been able to find the actual options is to dig through mount_* sources and see what they use, but it’s pretty gross. Take, for example, the following two filesystems:

  • nullfs simply layers one vnode on top of another, effectively grafting one directory over another.
  • unionfs (roughly) does the same thing, but still lets you access the grafted-over directory in read-only mode (and can be configured to do cool shit like copy-on-write).

They’re pretty close, but let’s look at the arguments that each of them take:

nullfs
  • fstype: “nullfs”
  • fspath: Path to the directory to graft over.
  • target: Path of the directory that’s being grafted onto another.

IMHO, "target" should be "from", bikesheds, et. al.

unionfs
  • fstype: “unionfs”
  • fspath: Path to the directory where the unionfs will be mounted.
  • from: Same as “target”, above.
  • below: Makes “fspath” writable, “from” read-only (swaps default behavior)
  • errmsg: …I have no fucking idea, a char[255] which presumably is used as a buffer instead of errno?
  • …anything else passed as -oyour=mom passed to mount_unionfs?!

Maybe this is more a gripe that unionfs seems to be very shitty. And maybe I just haven’t found a nice magical table of options that every filesystem takes. But FFFFFF SERIOUSLY >:(

3 comments

Calling a templated member function of a typedef’d template class

July 11th, 2011 | Category: Random

C++ is insane.

Assume you have a templated Object:

template  
struct Object {
	template  void func(){};
};

And you want to wrap up the instance in a Proxy object:

template 
struct Proxy {
	typedef Object WrappedType;
	WrappedType obj;

	static void Func() {
		Proxy *self = new Proxy;
		self->obj.func();
	}
};

Pretty straightforward, but when you actually try to invoke Proxy::Func on an arbitrary T using g++

struct Foo {};

int main() {
	Proxy::Func();
	return 0;
}

g++ shits itself completely:

$ g++ test1.cpp 
test1.cpp: In static member function ‘static void Proxy::Func()’:
test1.cpp:13: error: ‘Foo’ was not declared in this scope
test1.cpp:13: error: expected primary-expression before ‘)’ token
$ g++ --version
i686-apple-darwin10-g++-4.2.1 (GCC) 4.2.1 (Apple Inc. build 5666) (dot 3)

Fucking fantastic.

Some tinkering reveals that the compiler is getting confused as to what the fuck obj.func is somewhere. The following implementation of Func works fine (but defeats the point of using templates) --

	static void Func() {
		Proxy *self = new Proxy;
		Object bar = self->obj;
		bar.func();
	}

I searched for awhile and turned up jack diddly squat, then a co-worker informed me the fix is to use the following:

	static void Func() {
		Proxy *self = new Proxy;
		self->obj.template func();
	}

I don't know what the fuck this instance.template function<..>() bullshit is, but apparently MSVC implicitly puts it in there for you. I've certainly never seen it before and it's completely orthogonal to any fix I would have assumed.

tl;dr C++ is a clusterfuck.


EDIT: A stack overflow post which contains a reference to the C++03 standard (14.2/4) in the answers. fml.

4 comments

(Untitled)

February 26th, 2009 | Category: Random

lol fixed the scrapers scraping 4scrape problem (or, as much as I’m willing to).

The problem, as I see it, is that scrapers have a very abnormal usage pattern compared to normal visitors — they’re just pulling the big heavy images which cost a lot of bandwidth and CPU (in the form of I/O interrupts) to serve. My solution to the problem was to write a lighttpd module which basically throttles the number of “expensive” requests you can make. I don’t really give a shit that they’re scraping — what pisses me off is that they’re bringing the server to it’s knees by doing so.

Each IP address is associated with an integer representing the amount of resources it’s used. This value is reduced by a configurable amount each second, and increases whenever they access a marked resource. Once it gets over a maximum amount, the module starts throwing back 403 responses.

The way I’ve got it configured right now is to add 20 points for each full-size image fetched, then decay that value by 1 point/second. The maximum is 200 points before the server starts 403′ing, with a 600-point upper bound. Basically, this gives you a wallpaper every 20 seconds, allowing for bursts of activity.

I’ve also got code in place that stat‘s the requested files and bases the cost on the file size, but haven’t gotten around to testing it yet. Deploying a fucking lighttpd plugin was a goddamn nightmare (at least, compared to an Apache module) because the lighttpd developers are retards or something.

Anyway, we’ll see how this pans out. [source]

Comments are off for this post