From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Bruno Haible Newsgroups: gmane.comp.lib.gnulib.bugs,gmane.emacs.devel Subject: Re: boot time on Linux Date: Thu, 10 Aug 2023 12:30:26 +0200 Message-ID: <5521870.8Rdponrqg9@nimes> References: <87tttmpt5h.fsf@turtle.gmx.de> <5962135.d8TiXCRyrx@nimes> <875y5nve2k.fsf@yahoo.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="nextPart4471464.J5mhb4JmE5" Content-Transfer-Encoding: 7Bit Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="27266"; mail-complaints-to="usenet@ciao.gmane.io" Cc: Paul Eggert , Robert Pluim , bug-gnulib@gnu.org, =?ISO-8859-1?Q?P=E1draig?= Brady , Sven Joachim , 64937@debbugs.gnu.org, Natanael Copa , Emacs-devel@gnu.org, Thorsten Kukuk To: Po Lu Original-X-From: bug-gnulib-bounces+gnu-bug-gnulib=m.gmane-mx.org@gnu.org Thu Aug 10 12:30:55 2023 Return-path: Envelope-to: gnu-bug-gnulib@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1qU2wR-0006qz-79 for gnu-bug-gnulib@m.gmane-mx.org; Thu, 10 Aug 2023 12:30:55 +0200 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qU2wH-0006Hy-Qn; Thu, 10 Aug 2023 06:30:45 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qU2wB-0006FT-QF; Thu, 10 Aug 2023 06:30:43 -0400 Original-Received: from mo4-p01-ob.smtp.rzone.de ([81.169.146.167]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qU2w9-0005pe-II; Thu, 10 Aug 2023 06:30:39 -0400 ARC-Seal: i=1; a=rsa-sha256; t=1691663427; cv=none; d=strato.com; s=strato-dkim-0002; b=AoE+IZrG6wRdJiHdaC45J9VnopqhDBEEnykDHmWd/yWzMaZvvyK3Nv2/+3qzhPe7N+ Z7XGJW0p465Yx0ehsokSwtEihtdMDXNMnGy7T4eChC7l77pB8DrIk2RhBRJtqJi4F450 kao6K6u2sQZMuW+v1Scxl9Ts9C9uDKrrBDKAq9oNVvHn/ScHLGBh+4yrq/PlKmnLTNdV SITnzU3NXFjap2CalCJrsKeh6VwXdOW9q1i+R5guwQbLfBXUL7V7l/r4m9rhx00CRfNf 2/gUyXSzYfmcAq5WyPoGQ6UfLl6QkyxBfwt3NoXGgSCswdUlaYoU2pfjIiF/cUKtp4T/ Xxdg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; t=1691663427; s=strato-dkim-0002; d=strato.com; h=References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From:Cc:Date: From:Subject:Sender; bh=JjClGFRZeyGqjzZJHDVjs4ion1tKJ4kFqc567h6sXDQ=; b=kjZehwMuvBbUif/F5gfKojlC7nI5p+lqtgLXaoFs2gXA6eBocbRjMmLfQuSgY1L2C8 F4KouKH5zYs7FLY6hiSOtcScDokyilVP/l7Lt2y4o/pL63uQsM2haKAmHIRwutm/BgGs kEUp5onl8etdzpmorNAxmbCtMalLmU7TjKpmi7PuhMDqfqZ/109ejE2uL6ANfRBBjcxb QidyGTOwvTdO1x7VHG6oc/h3fwnp18uhG44jJOsJptTrrw63cE80Dnt9SZvEwxMP8I2e CIwAWyPhN+KzXwd4gqjcR99VIksIscD7wLh6MJjn+F9uLK66WnioATuJV3DglD5y8hjJ 8s1g== ARC-Authentication-Results: i=1; strato.com; arc=none; dkim=none X-RZG-CLASS-ID: mo01 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; t=1691663427; s=strato-dkim-0002; d=clisp.org; h=References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From:Cc:Date: From:Subject:Sender; bh=JjClGFRZeyGqjzZJHDVjs4ion1tKJ4kFqc567h6sXDQ=; b=Q6UUg+/V8xQu/m5o1TXmCl1PiUbajnudx7PvJTDKSTbN9K3S47ESLSRPIRPoeoonsu fTq2BOK1/lOXeBoTyf01cfi3B8TVmYtkQ1oJXIc+aPFe0TkGycYA99umA6IFNEWDfQqA OARXI9mIzFpQQF3X7P6FX91AKp2ywNj64oUuQkYr3jRRWerKH8uIGUVGnQK99C0D/KWC hUeh2zU9ykW7fu5zCn1D+YzQF6fmpDjeXSl9LEKa63PEgEs7YADz9VrpyH/vKOhyBSbT 7U6RnV+LPfCN+F+gmlCAu+qCygnMpUZmXVS8WHOu/gNPv/kHXUomdgUH8zcX3gLa1W2N 0FBw== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; t=1691663427; s=strato-dkim-0003; d=clisp.org; h=References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From:Cc:Date: From:Subject:Sender; bh=JjClGFRZeyGqjzZJHDVjs4ion1tKJ4kFqc567h6sXDQ=; b=k42a3xYZDnG3tXV0EEMyz5ri0QM0qK90NLNMlRPUeEN0ASrX9JX8WzewQQUFsZxTsm jtM+F074sPlgcQsZR4BQ== X-RZG-AUTH: ":Ln4Re0+Ic/6oZXR1YgKryK8brlshOcZlIWs+iCP5vnk6shH0WWb0LN8XZoH94zq68+3cfpOV1PzvI5g5gRFjtxIUOVst8mjP7Q==" Original-Received: from nimes.localnet by smtp.strato.de (RZmta 49.6.6 AUTH) with ESMTPSA id x129eaz7AAUQuy5 (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256 bits)) (Client did not present a certificate); Thu, 10 Aug 2023 12:30:26 +0200 (CEST) In-Reply-To: <875y5nve2k.fsf@yahoo.com> Received-SPF: none client-ip=81.169.146.167; envelope-from=bruno@clisp.org; helo=mo4-p01-ob.smtp.rzone.de X-Spam_score_int: -27 X-Spam_score: -2.8 X-Spam_bar: -- X-Spam_report: (-2.8 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_PASS=-0.001, SPF_NONE=0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: bug-gnulib@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gnulib discussion list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnulib-bounces+gnu-bug-gnulib=m.gmane-mx.org@gnu.org Original-Sender: bug-gnulib-bounces+gnu-bug-gnulib=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.comp.lib.gnulib.bugs:48141 gmane.emacs.devel:308518 Archived-At: This is a multi-part message in MIME format. --nextPart4471464.J5mhb4JmE5 Content-Transfer-Encoding: 7Bit Content-Type: text/plain; charset="us-ascii" I wrote: > > No, it isn't. The attached file, when compiled and run under Termux (which > > doesn't have particular permissions), prints e.g.: > > > > from clock : 1691616762.476870660 = 2023-08-09 21:32:42.476870660 > > from sysinfo: 1691616762.329261637 = 2023-08-09 21:32:42.329261637 > > > > Note that this uses the kernel's uptime counter, so it will not work well > > when the user changes the current time manually. But this is rare on Android. It works well enough, that I'm adding it to Gnulib, through the attached patch. Po Lu wrote: > This uses the uptime counter (which also results in an SELinux denial > for me, but different Android distributions have SELinux policies of > varying strictness) How did you run the program, and which of the two calls (clock_gettime, sysinfo) failed for you? Maybe it depends not only on the Android version and device, but also on the permissions required by the app? Bruno --nextPart4471464.J5mhb4JmE5 Content-Disposition: attachment; filename="0001-readutmp-Return-a-boot-time-also-on-Android.patch" Content-Transfer-Encoding: quoted-printable Content-Type: text/x-patch; charset="UTF-8"; name="0001-readutmp-Return-a-boot-time-also-on-Android.patch" =46rom 9db6a91083ecca9c49bd5353c7624c6388f332fb Mon Sep 17 00:00:00 2001 =46rom: Bruno Haible Date: Thu, 10 Aug 2023 07:59:19 +0200 Subject: [PATCH] readutmp: Return a boot time also on Android. * lib/readutmp.c (get_linux_uptime): New function, extracted from get_boot_time_uncached. (read_utmp_from_file): Don't look for file time stamps on Android. Instead, use get_linux_uptime. (get_boot_time_uncached): Use get_linux_uptime. =2D-- ChangeLog | 9 +++ lib/readutmp.c | 196 +++++++++++++++++++++++++++++-------------------- 2 files changed, 124 insertions(+), 81 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3c2256a7b2..b167189c03 100644 =2D-- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2023-08-10 Bruno Haible + + readutmp: Return a boot time also on Android. + * lib/readutmp.c (get_linux_uptime): New function, extracted from + get_boot_time_uncached. + (read_utmp_from_file): Don't look for file time stamps on Android. + Instead, use get_linux_uptime. + (get_boot_time_uncached): Use get_linux_uptime. + 2023-08-09 Bruno Haible =20 readutmp: Fix a mistake (regression 2023-08-08). diff --git a/lib/readutmp.c b/lib/readutmp.c index ec21f5e16f..b344d8294d 100644 =2D-- a/lib/readutmp.c +++ b/lib/readutmp.c @@ -31,11 +31,13 @@ #include #include =20 +#if READUTMP_USE_SYSTEMD || defined __ANDROID__ +# include +# include +#endif #if READUTMP_USE_SYSTEMD # include =2D# include # include =2D# include #endif =20 #include "stat-time.h" @@ -284,6 +286,60 @@ finish_utmp (struct utmp_alloc a) return a; } =20 +# if READUTMP_USE_SYSTEMD || defined __ANDROID__ + +/* Store the uptime counter, as managed by the Linux kernel, in *P_UPTIME. + Return 0 upon success, -1 upon failure. */ +static int +get_linux_uptime (struct timespec *p_uptime) +{ + /* The clock_gettime facility returns the uptime with a resolution of 1 = =C2=B5sec. + It is available with glibc >=3D 2.14. In glibc < 2.17 it required li= nking + with librt. */ +# if (__GLIBC__ + (__GLIBC_MINOR__ >=3D 17) > 2) || defined __ANDROID__ + if (clock_gettime (CLOCK_BOOTTIME, p_uptime) >=3D 0) + return 0; +# endif + + /* /proc/uptime contains the uptime with a resolution of 0.01 sec. + But it does not have read permissions on Android. */ +# if !defined __ANDROID__ + FILE *fp =3D fopen ("/proc/uptime", "re"); + if (fp !=3D NULL) + { + char buf[32 + 1]; + size_t n =3D fread (buf, 1, sizeof (buf) - 1, fp); + fclose (fp); + if (n > 0) + { + buf[n] =3D '\0'; + /* buf now contains two values: the uptime and the idle time. */ + char *endptr; + double uptime =3D strtod (buf, &endptr); + if (endptr > buf) + { + p_uptime->tv_sec =3D (time_t) uptime; + p_uptime->tv_nsec =3D (uptime - p_uptime->tv_sec) * 1e9 + 0.= 5; + return 0; + } + } + } +# endif + + /* The sysinfo call returns the uptime with a resolution of 1 sec only. = */ + struct sysinfo info; + if (sysinfo (&info) >=3D 0) + { + p_uptime->tv_sec =3D info.uptime; + p_uptime->tv_nsec =3D 0; + return 0; + } + + return -1; +} + +# endif + # if !HAVE_UTMPX_H && HAVE_UTMP_H && defined UTMP_NAME_FUNCTION && !HAVE_D= ECL_GETUTENT struct utmp *getutent (void); # endif @@ -391,7 +447,7 @@ read_utmp_from_file (char const *file, idx_t *n_entries= , STRUCT_UTMP **utmp_buf, =20 END_UTMP_ENT (); =20 =2D# if defined __linux__ +# if defined __linux__ && !defined __ANDROID__ /* On Alpine Linux, UTMP_FILE is not filled. It is always empty. So, fake a BOOT_TIME entry, by getting the time stamp of a file that gets touched only during the boot process. */ @@ -436,6 +492,37 @@ read_utmp_from_file (char const *file, idx_t *n_entrie= s, STRUCT_UTMP **utmp_buf, } # endif =20 +# if defined __ANDROID__ + /* On Android, there is no /var, and normal processes don't have access + to system files. Therefore use the kernel's uptime counter, although + it produces wrong values after the date has been bumped in the running + system. */ + { + struct timespec uptime; + if (get_linux_uptime (&uptime) >=3D 0) + { + struct timespec result; + if (clock_gettime (CLOCK_REALTIME, &result) >=3D 0) + { + if (result.tv_nsec < uptime.tv_nsec) + { + result.tv_nsec +=3D 1000000000; + result.tv_sec -=3D 1; + } + result.tv_sec -=3D uptime.tv_sec; + result.tv_nsec -=3D uptime.tv_nsec; + struct timespec boot_time =3D result; + a =3D add_utmp (a, options, + "reboot", strlen ("reboot"), + "", 0, + "", 0, + "", 0, + 0, BOOT_TIME, boot_time, 0, 0, 0); + } + } + } +# endif + # else /* old FreeBSD, OpenBSD, HP-UX */ =20 FILE *f =3D fopen (file, "re"); @@ -522,7 +609,7 @@ read_utmp_from_file (char const *file, idx_t *n_entries= , STRUCT_UTMP **utmp_buf, a =3D add_utmp (a, options, "reboot", strlen ("reboot"), "", 0, =2D "", strlen (""), + "", 0, "", 0, 0, BOOT_TIME, boot_time, 0, 0, 0); break; @@ -562,87 +649,34 @@ get_boot_time_uncached (void) free (utmp); } =20 =2D /* The following approaches are only usable as fallbacks, because they= are =2D all of the form + /* The following approach is only usable as a fallback, because it is of + the form boot_time =3D (time now) - (kernel's ktime_get_boottime[_ts64] ()) =2D and therefore produce wrong values after the date has been bumped i= n the + and therefore produces wrong values after the date has been bumped in= the running system, which happens frequently if the system is running in a virtual machine and this VM has been put into "saved" or "sleep" state and then resumed. */ =2D =2D /* The clock_gettime facility returns the uptime with a resolution of = 1 =C2=B5sec. =2D It is available with glibc >=3D 2.14. In glibc < 2.17 it required = linking =2D with librt. */ =2D# if __GLIBC__ + (__GLIBC_MINOR__ >=3D 17) > 2 =2D struct timespec up; =2D if (clock_gettime (CLOCK_BOOTTIME, &up) >=3D 0) =2D { =2D struct timespec result; =2D /* equivalent to: =2D if (clock_gettime (CLOCK_REALTIME, &result) >=3D 0) =2D */ =2D if (timespec_get (&result, TIME_UTC) >=3D 0) =2D { =2D if (result.tv_nsec < up.tv_nsec) =2D { =2D result.tv_nsec +=3D 1000000000; =2D result.tv_sec -=3D 1; =2D } =2D result.tv_sec -=3D up.tv_sec; =2D result.tv_nsec -=3D up.tv_nsec; =2D return result; =2D } =2D } =2D# endif =2D =2D /* /proc/uptime contains the uptime with a resolution of 0.01 sec. */ =2D FILE *fp =3D fopen ("/proc/uptime", "re"); =2D if (fp !=3D NULL) =2D { =2D char buf[32 + 1]; =2D size_t n =3D fread (buf, 1, sizeof (buf) - 1, fp); =2D fclose (fp); =2D if (n > 0) =2D { =2D buf[n] =3D '\0'; =2D /* buf now contains two values: the uptime and the idle time. = */ =2D char *endptr; =2D double uptime =3D strtod (buf, &endptr); =2D if (endptr > buf) =2D { =2D struct timespec result; =2D if (0 <=3D timespec_get (&result, TIME_UTC)) =2D { =2D time_t uptime_sec =3D uptime; =2D struct timespec up =3D =2D { =2D .tv_sec =3D uptime_sec, =2D .tv_nsec =3D (uptime - uptime_sec) * 1e9 + 0.5 =2D }; =2D if (result.tv_nsec < up.tv_nsec) =2D { =2D result.tv_nsec +=3D 1000000000; =2D result.tv_sec -=3D 1; =2D } =2D result.tv_sec -=3D up.tv_sec; =2D result.tv_nsec -=3D up.tv_nsec; =2D return result; =2D } =2D } =2D } =2D } =2D =2D /* The sysinfo call returns the uptime with a resolution of 1 sec only= =2E */ =2D struct sysinfo info; =2D if (sysinfo (&info) >=3D 0) =2D { =2D struct timespec result; =2D if (0 <=3D timespec_get (&result, TIME_UTC)) =2D { =2D result.tv_sec -=3D info.uptime; =2D return result; =2D } =2D } + { + struct timespec uptime; + if (get_linux_uptime (&uptime) >=3D 0) + { + struct timespec result; + /* equivalent to: + if (clock_gettime (CLOCK_REALTIME, &result) >=3D 0) + */ + if (timespec_get (&result, TIME_UTC) >=3D 0) + { + if (result.tv_nsec < uptime.tv_nsec) + { + result.tv_nsec +=3D 1000000000; + result.tv_sec -=3D 1; + } + result.tv_sec -=3D uptime.tv_sec; + result.tv_nsec -=3D uptime.tv_nsec; + return result; + } + } + } =20 /* We shouldn't get here. */ return (struct timespec) {0}; =2D-=20 2.34.1 --nextPart4471464.J5mhb4JmE5--