forked from pool/timezone
Andreas Stieger
0603a50597
absolute path. Prevent broken symlinks (bsc#1003324), add timezone-2016g-absolute-TZDEFAULT.patch tzcode-fromname.patch OBS-URL: https://build.opensuse.org/package/show/Base:System/timezone?expand=0&rev=197
108 lines
3.4 KiB
Diff
108 lines
3.4 KiB
Diff
From df9991a2186d4236ba1e97e6638fa53b578bc6d7 Mon Sep 17 00:00:00 2001
|
|
From: Paul Eggert <eggert@cs.ucla.edu>
|
|
Date: Thu, 6 Oct 2016 11:47:17 -0700
|
|
Subject: [PATCH] Do not assume TZDEFAULT is relative.
|
|
|
|
Problem reported by Andreas Stieger in:
|
|
http://mm.icann.org/pipermail/tz/2016-October/024280.html
|
|
* NEWS: Document this.
|
|
* zic.c (relname): New function.
|
|
(dolink): Use it.
|
|
---
|
|
zic.c | 65 ++++++++++++++++++++++++++++++++++++++++++++---------------------
|
|
1 file changed, 44 insertions(+), 21 deletions(-)
|
|
|
|
---
|
|
|
|
Fixes: https://bugzilla.suse.com/show_bug.cgi?id=1003324
|
|
|
|
diff --git a/zic.c b/zic.c
|
|
index 2505c11..eba223c 100644
|
|
--- a/zic.c
|
|
+++ b/zic.c
|
|
@@ -764,6 +764,44 @@ namecheck(const char *name)
|
|
return componentcheck(name, component, cp);
|
|
}
|
|
|
|
+/* Create symlink contents suitable for symlinking FROM to TO, as a
|
|
+ freshly allocated string. FROM should be a relative file name, and
|
|
+ is relative to the global variable DIRECTORY. TO can be either
|
|
+ relative or absolute. */
|
|
+static char *
|
|
+relname(char const *from, char const *to)
|
|
+{
|
|
+ size_t i, taillen, dotdotetcsize;
|
|
+ size_t dir_len = 0, dotdots = 0, linksize = SIZE_MAX;
|
|
+ char const *f = from;
|
|
+ char *result = NULL;
|
|
+ if (*to == '/') {
|
|
+ /* Make F absolute too. */
|
|
+ size_t len = strlen(directory);
|
|
+ bool needslash = len && directory[len - 1] != '/';
|
|
+ linksize = len + needslash + strlen(from) + 1;
|
|
+ f = result = emalloc(linksize);
|
|
+ strcpy(result, directory);
|
|
+ result[len] = '/';
|
|
+ strcpy(result + len + needslash, from);
|
|
+ }
|
|
+ for (i = 0; f[i] && f[i] == to[i]; i++)
|
|
+ if (f[i] == '/')
|
|
+ dir_len = i + 1;
|
|
+ for (; f[i]; i++)
|
|
+ dotdots += f[i] == '/' && f[i - 1] != '/';
|
|
+ taillen = i - dir_len;
|
|
+ dotdotetcsize = 3 * dotdots + taillen + 1;
|
|
+ if (dotdotetcsize <= linksize) {
|
|
+ if (!result)
|
|
+ result = emalloc(dotdotetcsize);
|
|
+ for (i = 0; i < dotdots; i++)
|
|
+ memcpy(result + 3 * i, "../", 3);
|
|
+ memmove(result + 3 * dotdots, f + dir_len, taillen + 1);
|
|
+ }
|
|
+ return result;
|
|
+}
|
|
+
|
|
static void
|
|
dolink(char const *fromfield, char const *tofield, bool staysymlink)
|
|
{
|
|
@@ -800,30 +838,15 @@ dolink(char const *fromfield, char const *tofield, bool staysymlink)
|
|
link_errno = link(fromfield, tofield) == 0 ? 0 : errno;
|
|
}
|
|
if (link_errno != 0) {
|
|
- const char *s = fromfield;
|
|
- const char *t;
|
|
- char *p;
|
|
- size_t dotdots = 0;
|
|
- char *symlinkcontents;
|
|
- int symlink_errno;
|
|
-
|
|
- do
|
|
- t = s;
|
|
- while ((s = strchr(s, '/'))
|
|
- && strncmp(fromfield, tofield, ++s - fromfield) == 0);
|
|
-
|
|
- for (s = tofield + (t - fromfield); *s; s++)
|
|
- dotdots += *s == '/';
|
|
- symlinkcontents = emalloc(3 * dotdots + strlen(t) + 1);
|
|
- for (p = symlinkcontents; dotdots-- != 0; p += 3)
|
|
- memcpy(p, "../", 3);
|
|
- strcpy(p, t);
|
|
- symlink_errno = symlink(symlinkcontents, tofield) == 0 ? 0 : errno;
|
|
+ bool absolute = *fromfield == '/';
|
|
+ char *linkalloc = absolute ? NULL : relname(fromfield, tofield);
|
|
+ char const *contents = absolute ? fromfield : linkalloc;
|
|
+ int symlink_errno = symlink(contents, tofield) == 0 ? 0 : errno;
|
|
if (symlink_errno == ENOENT && !todirs_made) {
|
|
mkdirs(tofield, true);
|
|
- symlink_errno = symlink(symlinkcontents, tofield) == 0 ? 0 : errno;
|
|
+ symlink_errno = symlink(contents, tofield) == 0 ? 0 : errno;
|
|
}
|
|
- free(symlinkcontents);
|
|
+ free(linkalloc);
|
|
if (symlink_errno == 0) {
|
|
if (link_errno != ENOTSUP)
|
|
warning(_("symbolic link used because hard link failed: %s"),
|
|
--
|
|
2.10.1
|
|
|