patch: filetype symlinks

Jeff King <[email protected]> Sun, 22 Feb 2004 22:01:31 -0500 (EST)
Newsgroups gmane.comp.djb.publicfile
Message-ID <[email protected]>
I have just written a patch to allow publicfile's content-type
determining mechanism to follow symbolic links before examining a
filename. The goal is to avoid ugly URLs like
http://host/foo.content=type; instead, I want http://host/foo with the
correct content-type. The patch is included at the end of this message.

I am interested in comments on:
  - is there a way to accomplish what I want short of this patch? I am
    also using Uwe Ohse's filetype environment variable patch, but it's
    often easier to just give a specific file a type.
  - the patch does not do recursive readlink()s, since there may be
    cycles. Do people think that would be a useful addition?
  - other general comments

-Peff

--- CUT HERE ---
publicfile 0.52 filetype symlinks patch 20040222
http://peff.net/patches/publicfile-0.52-filetype-links-diff
Public domain.

This patch causes publicfile to follow symbolic links when using the filename
to determine a file's type. For example:

echo 'some content' >foo.application=x-my-type
ln -s foo.application=x-my-type foo

The file "foo" can now be accessed as either:
http://.../foo.application=x-my-type
or
http://.../foo
and the content-type application/x-my-type will be reported in both cases.

Note: only one readlink is performed. Thus in the following example, 'foo'
will not have a named content-type:
echo 'data' >file.content=type
ln -s file.content=type bar
ln -s bar foo

--- filetype.c.orig	2004-02-22 08:29:24.000000000 -0500
+++ filetype.c	2004-02-22 21:59:07.000000000 -0500
@@ -1,6 +1,8 @@
 #include "filetype.h"
 #include "str.h"

+#include <unistd.h>
+
 void filetype(char *fn,stralloc *contenttype)
 {
   char *x;
@@ -8,6 +10,15 @@
   int i;
   char ch;

+  char linkbuf[1024];
+  int linklen;
+
+  linklen = readlink(fn, linkbuf, sizeof(linkbuf) - 1);
+  if(linklen != -1) {
+    linkbuf[linklen+1] = '\0';
+    fn = linkbuf;
+  }
+
   if (!stralloc_copys(contenttype,"Content-Type: ")) _exit(21);

   x = fn + str_rchr(fn,'.');