diff options
author | Paolo Bonzini <bonzini@gnu.org> | 2006-12-15 12:30:25 +0000 |
---|---|---|
committer | Paolo Bonzini <bonzini@gnu.org> | 2008-01-09 16:12:20 +0100 |
commit | ba68fb42b8db505a89da4987df5936997a3c226a (patch) | |
tree | 28c41aecc082a91b95312909851db53cb1bda464 /sed/utils.c | |
parent | 2128ec657b3d6bb3378424d0ddda923cdf8e2713 (diff) | |
download | sed-ba68fb42b8db505a89da4987df5936997a3c226a.tar.gz |
--posix disables all extensions to regular expressions
2006-12-15 Paolo Bonzini <bonzini@gnu.org>
* sed/regexp.c: Disable all extensions on --posix.
git-archimport-id: bonzini@gnu.org--2004b/sed--stable--4.1--patch-84
Diffstat (limited to 'sed/utils.c')
-rw-r--r-- | sed/utils.c | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/sed/utils.c b/sed/utils.c index b4f0164..78bb2ff 100644 --- a/sed/utils.c +++ b/sed/utils.c @@ -35,6 +35,10 @@ # include <stdlib.h> #endif /* HAVE_STDLIB_H */ +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> + #include "utils.h" const char *myname; @@ -342,6 +346,85 @@ do_ck_fclose(fp) } +/* Follow symlink and panic if something fails. Return the ultimate + symlink target, stored in a temporary buffer that the caller should + not free. */ +const char * +follow_symlink(const char *fname) +{ +#ifdef ENABLE_FOLLOW_SYMLINKS + static char *buf1, *buf2; + static int buf_size; + + struct stat statbuf; + const char *buf = fname, *c; + int rc; + + if (buf_size == 0) + { + buf1 = ck_malloc (PATH_MAX + 1); + buf2 = ck_malloc (PATH_MAX + 1); + buf_size = PATH_MAX + 1; + } + + while ((rc = lstat (buf, &statbuf)) == 0 + && (statbuf.st_mode & S_IFLNK) == S_IFLNK) + { + if (buf == buf2) + { + strcpy (buf1, buf2); + buf = buf1; + } + + while ((rc = readlink (buf, buf2, buf_size)) == buf_size) + { + buf_size *= 2; + buf1 = ck_realloc (buf1, buf_size); + buf2 = ck_realloc (buf2, buf_size); + } + if (rc < 0) + panic (_("couldn't follow symlink %s: %s"), buf, strerror(errno)); + else + buf2 [rc] = '\0'; + + if (buf2[0] != '/' && (c = strrchr (buf, '/')) != NULL) + { + /* Need to handle relative paths with care. Reallocate buf1 and + buf2 to be big enough. */ + int len = c - buf + 1; + if (len + rc + 1 > buf_size) + { + buf_size = len + rc + 1; + buf1 = ck_realloc (buf1, buf_size); + buf2 = ck_realloc (buf2, buf_size); + } + + /* Always store the new path in buf1. */ + if (buf != buf1) + memcpy (buf1, buf, len); + + /* Tack the relative symlink at the end of buf1. */ + memcpy (buf1 + len, buf2, rc + 1); + buf = buf1; + } + else + { + /* Use buf2 as the buffer, it saves a strcpy if it is not pointing to + another link. It works for absolute symlinks, and as long as + symlinks do not leave the current directory. */ + buf = buf2; + } + } + + if (rc < 0) + panic (_("cannot stat %s: %s"), buf, strerror(errno)); + + return buf; +#else + return fname; +#endif /* ENABLE_FOLLOW_SYMLINKS */ +} + /* Panic on failing rename */ void ck_rename (from, to, unlink_if_fail) |