File tzcode-symlink.patch of Package timezone

This patch is used on openSUSE 12.2 or newer. Nowadays,
/etc/localtime is by default a symbolic link to a zone
file in /usr/share/zoneinfo.

By default, zic tries the following approaches to create
/etc/localtime:

  1. Hard link
  2. Symbolic link
  3. File copy

This patch changes the logic slightly: keep using symbolic
links if /etc/localtime is already one. If it isn't, use
the default order as listed above.

Index: timezone-2014g/zic.c
===================================================================
--- timezone-2014g.orig/zic.c
+++ timezone-2014g/zic.c
@@ -106,7 +106,7 @@ static int	addtype(zic_t, char const *,
 static void	leapadd(zic_t, bool, int, int);
 static void	adjleap(void);
 static void	associate(void);
-static void	dolink(const char * fromfield, const char * tofield);
+static void	dolink(const char * fromfield, const char * tofield, int defaultsymlink);
 static char **	getfields(char * buf);
 static zic_t	gethms(const char * string, const char * errstring,
 		       bool);
@@ -608,7 +608,7 @@ _("%s: More than one -L option specified
 	*/
 	for (i = 0; i < nlinks; ++i) {
 		eat(links[i].l_filename, links[i].l_linenum);
-		dolink(links[i].l_from, links[i].l_to);
+		dolink(links[i].l_from, links[i].l_to, false);
 		if (noise)
 			for (j = 0; j < nlinks; ++j)
 				if (strcmp(links[i].l_to,
@@ -617,11 +617,11 @@ _("%s: More than one -L option specified
 	}
 	if (lcltime != NULL) {
 		eat(_("command line"), 1);
-		dolink(lcltime, TZDEFAULT);
+		dolink(lcltime, TZDEFAULT, true);
 	}
 	if (psxrules != NULL) {
 		eat(_("command line"), 1);
-		dolink(psxrules, TZDEFRULES);
+		dolink(psxrules, TZDEFRULES, false);
 	}
 	if (warnings && (ferror(stderr) || fclose(stderr) != 0))
 	  return EXIT_FAILURE;
@@ -687,8 +687,9 @@ namecheck(const char *name)
 }
 
 static void
-dolink(const char *const fromfield, const char *const tofield)
+dolink(const char *const fromfield, const char *const tofield, int defaultsymlink)
 {
+	struct stat st;
 	register char *	fromname;
 	register char *	toname;
 	register int fromisdir;
@@ -701,6 +702,10 @@ dolink(const char *const fromfield, cons
 		fromname = ecatalloc(fromname, "/");
 		fromname = ecatalloc(fromname, fromfield);
 	}
+
+	if (lstat(fromname, &st) == 0 && S_ISLNK(st.st_mode))
+		defaultsymlink = true;
+
 	if (tofield[0] == '/')
 		toname = ecpyalloc(tofield);
 	else {
@@ -721,14 +726,15 @@ dolink(const char *const fromfield, cons
 	}
 	if (itsdir(toname) <= 0)
 		remove(toname);
-	if (link(fromname, toname) != 0) {
+	if (defaultsymlink || link(fromname, toname) != 0) {
 		int	result;
 
 		if (! mkdirs(toname))
 			exit(EXIT_FAILURE);
 
-		result = link(fromname, toname);
-		if (result != 0) {
+		if (!defaultsymlink)
+			result = link(fromname, toname);
+		if ((defaultsymlink || (!defaultsymlink && result != 0))) {
 				const char *s = fromname;
 				const char *t;
 				register char * symlinkcontents = NULL;