pruning your tree

This is from a mailing list post I’ve just replied to. Since I had to look it up, it’s worth blogging. :)

It seems like a simple task. Find all the files in the current directory, excluding .svn directories. I’ve mocked up a simple layout.

% find .

By default, find prints out everything. But we only want files.

% find . -type f

Now, we want to exclude everything under .svn. Easy.

% find . -name .svn -prune -type f

Ooops. That’s not good. What happened here? Well, the default for find is to and two expressions together. If we or it, we get what we want.

% find . -name .svn -prune -or -type f

Again, not so good. The problem is that default action to print everything. Because we’ve specified no action, it’ll print out each match, and that includes the .svn directories (even though it correctly stops going into them).

The answer is to provide an explicit action instead.

% find . -name .svn -prune -or -type f -print

This works, because now there is no default action, and the explicit action is only associated with the -type f predicate.


Like a lot of people, most of my Unix knowledge comes from an early reading of Advanced Programming in the UNIX Environment. This is an excellent tome on the interfaces provided by the kernel to programs on a Unix system.

Unfortunately, it’s over 15 years old now, and things have moved on. Naturally, I haven’t quite kept up. So I’ve just been pleasantly surprised to see that OS X has grown a sandbox system (via). There is scant documentation available:

Also, if you poke around, you’ll find /usr/include/sandbox.h and /usr/share/sandbox. The latter is interesting — it contains lisp-like definitions of access control lists for various processes.

What’s interesting to me is sandbox-exec though. This can be used with one of the builtin profiles to easily restrict access. For example:

$ sandbox-exec -n nowrite touch /tmp/foo
touch: /tmp/foo: Operation not permitted

After using strings(1) on apple’s libc (/usr/lib/libSystem.dylib), I managed to get these builtin profile names out:

TCP/IP networking is prohibited
All sockets-based networking is prohibited.
All operating system services are prohibited.
File system writes are prohibited.
File system writes are restricted to the temporary folder /var/tmp and the folder specified by the confstr(3) configuration variable _CS_DARWIN_USER_TEMP_DIR.

They’re only documented as internal constants for C programs, but it’s quite handy to have them available for sandbox-exec. It would be nice to know in more detail what they actually did, though.

Of course, this still isn’t really getting down to how the sandbox is implemented. Is it done inside the kernel or on the userland side? I don’t really know. And I don’t yet have enough dtrace-fu to figure it out.

See also:

Anyway, this seems like a fun toy. And of course, it’s reminded me that I need to try out chromium on the mac… Drat, no PPC support. :-(

Locales That Work

As I mentioned before, I don’t like locales. But of course, the solution is blindingly obvious and had passed me by. Unicode Support on FreeBSD points out the correct solution, which avoids breaking ls.


Marvellous. Now things can autodetect that I’d like UTF-8, please.