Bug 1200555

Summary: glibc: support /etc/localtime as a symbolic link [rhel-6.8.0]
Product: Red Hat Enterprise Linux 6 Reporter: Paulo Andrade <pandrade>
Component: glibcAssignee: Florian Weimer <fweimer>
Status: CLOSED ERRATA QA Contact: Arjun Shankar <ashankar>
Severity: medium Docs Contact: Marc Muehlfeld <mmuehlfe>
Priority: medium    
Version: 6.7CC: apetrova, ashankar, codonell, fweimer, javier.ramirez, mcermak, mmuehlfe, mnewsome, pfrankli, salmy, tradej
Target Milestone: rcKeywords: Patch
Target Release: ---   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: glibc-2.12-1.187.el6 Doc Type: Release Note
Doc Text:
_glibc_ and _tzdata_ updates no longer replace `/etc/localtime` symbolic links Previously, on systems where the `/etc/localtime` file was a symbolic link, updates of the _glibc_ and _tzdata_ packages replaced the link with the time-zone file defined in the `/etc/sysconfig/clock` configuration file. A patch has been applied to address the problem and `/etc/localtime` as a symbolic link is no longer replaced. For optimum compatibility, it is recommended not to modify `/etc/localtime` directly. Instead, edit the `/etc/sysconfig/clock` configuration file and execute the `tzdata-update` command afterwards.
Story Points: ---
Clone Of: Environment:
Last Closed: 2016-05-10 21:26:23 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:
Bug Depends On: 1289696, 1292833    
Bug Blocks: 1172231, 1271375    

Description Paulo Andrade 2015-03-10 20:24:51 UTC
Due to a rpm feature, that silently removes
or overwrites %config(noreplace) files if
they are symlinks, it would be suggested to
make /etc/localtime not owned by any package,
and add a variant of the scriptlet from
systemd to glibc, just that it would only
create it if non existent. i.e. do not
touch whatever is from previous installs.

Untested, suggested scriptlet:

---8<---
%posttrans
if [ ! -e /etc/localtime -a -e /etc/sysconfig/clock ] ; then
       . /etc/sysconfig/clock >/dev/null 2>&1 || :
       if [ -n "$ZONE" -a -e "/usr/share/zoneinfo/$ZONE" ] ; then
              ln -sf "../usr/share/zoneinfo/$ZONE" /etc/localtime >/dev/null 2>&1 || :
       fi
fi
---8<---

Comment 2 Florian Weimer 2015-12-05 21:06:10 UTC
(In reply to Paulo Andrade from comment #0)
> Untested, suggested scriptlet:
> 
> ---8<---
> %posttrans
> if [ ! -e /etc/localtime -a -e /etc/sysconfig/clock ] ; then
>        . /etc/sysconfig/clock >/dev/null 2>&1 || :
>        if [ -n "$ZONE" -a -e "/usr/share/zoneinfo/$ZONE" ] ; then
>               ln -sf "../usr/share/zoneinfo/$ZONE" /etc/localtime >/dev/null
> 2>&1 || :
>        fi
> fi
> ---8<---

Thanks for the suggestion.  glibc-common has a dependency on /bin/bash, so the shell should be available from %posttrans.  However, technically, ln might not.  I don't see anything else pulling coreutils among the dependencies of glibc-common, and I would really like to avoid changing the dependencies.

Your proposed change would still change the time zone from UTC to whatever is configured in /etc/sysconfig/clock if the /etc/localtime file had simply been removed to switch the time zone to UTC.  I think that is still surprising.

Comment 3 Florian Weimer 2015-12-05 21:16:24 UTC
tzdata-update should do what we want.  It is written in a very peculiar way, presumably to reduce executable size despite static linking:

  INTERNAL_SYSCALL_DECL (err);
  long int fd = INTERNAL_SYSCALL (open, err, 2, "/etc/sysconfig/clock", O_RDONLY);
  if (INTERNAL_SYSCALL_ERROR_P (fd, err))
    return 0;
  ssize_t ret = readall (fd, buffer, sizeof (buffer) - 1);
  INTERNAL_SYSCALL (close, err, 1, fd);
  if (ret <= 0 || (size_t) ret == sizeof (buffer) - 1)
    return 0;
  char *p = buffer;
  while (p != NULL)
    {
      while (*p == ' ' || *p == '\t') p++;
      if (simple_memcmp (p, "ZONE", 4) == 0)

If this program does what I think it does, it would be sufficient to turn /etc/locatime into a %ghost file and somehow replicate the old US/Eastern default in case /etc/sysconfig/clock is missing.

Comment 4 Florian Weimer 2015-12-08 10:35:24 UTC
We also need to change tzdata-update to leave symbolic links alone.

I don't think this is related to RPM behavior at all, so I'm changing the summary to reflect that.

Comment 5 Florian Weimer 2015-12-08 13:45:36 UTC
The existing tzdata-update sources are not maintainable.  I had to rewrite them in standard C.  At the time the trigger for the tzdata installation runs, glibc is not necessarily installed, which means that static linking is needed to support the tzdata installation trigger.  This leads to a significant increase in package size.

I think we can write tzdata-update in Lua, which would enable us to to get rid of the trigger and avoid all dependency issues.  The Lua scriptlet would run directly in the RPM process, which can been loaded from outside the installation root.  The ideal place for this would be a %post scriptlet in the tzdata package, so that the installation-trigger in the glibc-common package would no longer be needed.

We still need to ship /usr/sbin/tzdata-update in glibc because it is a documented interface, but it can be a dynamically-linked binary.

Comment 17 errata-xmlrpc 2016-05-10 21:26:23 UTC
Since the problem described in this bug report should be
resolved in a recent advisory, it has been closed with a
resolution of ERRATA.

For information on the advisory, and where to find the updated
files, follow the link below.

If the solution does not work for you, open a new bug report.

https://rhn.redhat.com/errata/RHBA-2016-0834.html