On Sun, Oct 21, 2012 at 16:01:23 +0200, Dominik George wrote: > When opening local URLs and the file is a symbolic link, iceweasel resolves > them to their target before opening. This breaks relative links in the > document > and also deviates from the behaviour when using symbolic links on a webserver
This bug makes it effectively impossible to browse any documentation in a git-annex repository. I'm using an LD_PRELOAD hack (attached) to work around it: ./gen-with-links-as-files \ | gcc -shared -fPIC -x c -pipe -ldl -o with-links-as-files.so - LD_PRELOAD=`pwd`/with-links-as-files.so /usr/bin/iceweasel (Only the __lxstat* parts are really needed in this case.) -- Michael
#!/bin/sh cat_lxstat () { cat <<__EOF__ int __lxstat$1(int ver, const char *path, struct stat$1 *buf) { static int (*real_lxstat$1)(int, const char*, struct stat$1*); static int (*real_xstat$1)(int, const char*, struct stat$1*); int ret = -1; if (!real_lxstat$1) { real_lxstat$1 = dlsym(RTLD_NEXT, "__lxstat$1"); real_xstat$1 = dlsym(RTLD_NEXT, "__xstat$1"); if (!real_xstat$1 || !real_lxstat$1) { errno = ELIBACC; goto out; } } ret = real_lxstat$1(ver, path, buf); if (ret != 0) goto out; if (S_ISLNK(buf->st_mode)) { struct stat$1 tmp; ret = real_xstat$1(ver, path, &tmp); if (ret != 0) { // We can still use the lstat$1 result. ret = 0; goto out; } if (S_ISDIR(tmp.st_mode)) { *buf = tmp; } else if (S_ISREG(tmp.st_mode) && ((tmp.st_mode & 0111) == 0)) { *buf = tmp; } } out: return ret; } __EOF__ } cat_readdir () { cat <<__EOF__ static void fix_dirent$1(DIR *dir, struct dirent$1 *ent) { if (ent->d_type == DT_LNK || ent->d_type == DT_UNKNOWN) { int fd = openat(dirfd(dir), &ent->d_name[0], O_RDONLY); if (fd >= 0) { struct stat64 stbuf; if (fstat64(fd, &stbuf) == 0) { if (S_ISREG(stbuf.st_mode)) { ent->d_type = DT_REG; } else if (S_ISDIR(stbuf.st_mode)) { ent->d_type = DT_DIR; } else if (S_ISFIFO(stbuf.st_mode)) { ent->d_type = DT_FIFO; } else if (S_ISCHR(stbuf.st_mode)) { ent->d_type = DT_CHR; } else if (S_ISBLK(stbuf.st_mode)) { ent->d_type = DT_BLK; } else if (S_ISSOCK(stbuf.st_mode)) { ent->d_type = DT_SOCK; } } do {} while (close(fd) != 0 && errno == EINTR); } } } struct dirent$1* readdir$1(DIR *dir) { static struct dirent$1* (*real_readdir$1)(DIR*); struct dirent$1 *ret = NULL; if (!real_readdir$1) { real_readdir$1 = dlsym(RTLD_NEXT, "readdir$1"); if (!real_readdir$1) { errno = ELIBACC; goto out; } } ret = real_readdir$1(dir); if (ret) { fix_dirent$1(dir, ret); } out: return ret; } int readdir$1_r(DIR *dir, struct dirent$1 *entry, struct dirent$1 **result) { static int (*real_readdir${1}_r)(DIR*, struct dirent$1*, struct dirent$1*); int ret = -1; if (!real_readdir${1}_r) { real_readdir${1}_r = dlsym(RTLD_NEXT, "readdir${1}_r"); if (!real_readdir${1}_r) { errno = ELIBACC; goto out; } } ret = real_readdir${1}_r(dir, entry, *result); if (ret == 0 && *result) { fix_dirent$1(dir, *result); } out: return ret; } __EOF__ } cat_preload () { cat <<__EOF__ #define _GNU_SOURCE #include <dlfcn.h> #include <dirent.h> #include <errno.h> #include <fcntl.h> #include <stdio.h> #include <string.h> #include <sys/socket.h> #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> $(cat_lxstat '') $(cat_lxstat '64') $(cat_readdir '') $(cat_readdir '64') __EOF__ } cat_preload
signature.asc
Description: Digital signature