bug-make
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] Port to 32-bit long + 64-bit time_t


From: Paul Eggert
Subject: [PATCH] Port to 32-bit long + 64-bit time_t
Date: Tue, 20 Sep 2022 14:22:05 -0700

Don't assume that time_t fits in long, as some hosts (e.g.,
glibc x86 -D_TIME_BITS=64) have 32-bit long and 64-bit time_t.
This fix uses C99 sprintf/scanf %jd and %ju, which is
safe to assume nowadays.
* bootstrap.conf (gnulib_modules): Add largefile, to support
files with timestamps after Y2038 on hosts with 32-bit long.
* configure.ac: Do not call AC_SYS_LARGEFILE,
as the largefile module does that for us.
* src/ar.c: Include intprops.h, for TYPE_MAXIMUM,
as INTEGER_TYPE_MAXIMUM does not work on time_t
without issuing a bunch of warnings.
(ar_member_date): Check that result is in time_t range.
* src/ar.c (ar_member_date, ar_glob_match):
* src/arscan.c (VMS_function, VMS_function_ret, ar_scan)
(parse_int, ar_scan, ar_member_pos, ar_member_touch)
(describe_member):
* src/file.c (file_timestamp_sprintf):
Use intmax_t/uintmax_t instead of long/unsigned long for values
that might be time_t.
---
 bootstrap.conf |  1 +
 configure.ac   |  5 -----
 src/ar.c       | 15 ++++++++-------
 src/arscan.c   | 44 ++++++++++++++++++++++++--------------------
 src/file.c     | 13 ++++++++-----
 src/makeint.h  |  7 ++++---
 6 files changed, 45 insertions(+), 40 deletions(-)

diff --git a/bootstrap.conf b/bootstrap.conf
index b1ee947d..1dc096db 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -60,5 +60,6 @@ fdl
 findprog-in
 getloadavg
 host-cpu-c-abi
+largefile
 make-glob
 make-macros"
diff --git a/configure.ac b/configure.ac
index e08e75ad..11e9ed12 100644
--- a/configure.ac
+++ b/configure.ac
@@ -57,11 +57,6 @@ AC_C_BIGENDIAN
 AM_GNU_GETTEXT_VERSION([0.19.4])
 AM_GNU_GETTEXT([external])
 
-# This test must come as early as possible after the compiler configuration
-# tests, because the choice of the file model can (in principle) affect
-# whether functions and headers are available, whether they work, etc.
-AC_SYS_LARGEFILE
-
 # Checks for libraries.
 AC_SEARCH_LIBS([strerror],[cposix])
 AC_SEARCH_LIBS([getpwnam], [sun])
diff --git a/src/ar.c b/src/ar.c
index 7a26662c..48ef5e44 100644
--- a/src/ar.c
+++ b/src/ar.c
@@ -22,6 +22,7 @@ this program.  If not, see <http://www.gnu.org/licenses/>.  */
 #include "filedef.h"
 #include "dep.h"
 #include <fnmatch.h>
+#include <intprops.h>
 
 /* Return nonzero if NAME is an archive-member reference, zero if not.  An
    archive-member reference is a name like 'lib(member)' where member is a
@@ -69,10 +70,10 @@ ar_parse_name (const char *name, char **arname_p, char 
**memname_p)
 /* This function is called by 'ar_scan' to find which member to look at.  */
 
 /* ARGSUSED */
-static long int
+static intmax_t
 ar_member_date_1 (int desc UNUSED, const char *mem, int truncated,
                   long int hdrpos UNUSED, long int datapos UNUSED,
-                  long int size UNUSED, long int date,
+                  long int size UNUSED, intmax_t date,
                   int uid UNUSED, int gid UNUSED, unsigned int mode UNUSED,
                   const void *name)
 {
@@ -86,7 +87,7 @@ ar_member_date (const char *name)
 {
   char *arname;
   char *memname;
-  long int val;
+  intmax_t val;
 
   ar_parse_name (name, &arname, &memname);
 
@@ -111,7 +112,7 @@ ar_member_date (const char *name)
 
   free (arname);
 
-  return (val <= 0 ? (time_t) -1 : (time_t) val);
+  return 0 < val && val <= TYPE_MAXIMUM (time_t) ? val : -1;
 }
 
 /* Set the archive-member NAME's modtime to now.  */
@@ -194,10 +195,10 @@ struct ar_glob_state
 /* This function is called by 'ar_scan' to match one archive
    element against the pattern in STATE.  */
 
-static long int
+static intmax_t
 ar_glob_match (int desc UNUSED, const char *mem, int truncated UNUSED,
                long int hdrpos UNUSED, long int datapos UNUSED,
-               long int size UNUSED, long int date UNUSED, int uid UNUSED,
+               long int size UNUSED, intmax_t date UNUSED, int uid UNUSED,
                int gid UNUSED, unsigned int mode UNUSED, const void *arg)
 {
   struct ar_glob_state *state = (struct ar_glob_state *)arg;
@@ -218,7 +219,7 @@ ar_glob_match (int desc UNUSED, const char *mem, int 
truncated UNUSED,
       ++state->n;
     }
 
-  return 0L;
+  return 0;
 }
 
 /* Return nonzero if PATTERN contains any metacharacters.
diff --git a/src/arscan.c b/src/arscan.c
index f22d21aa..78c6c06f 100644
--- a/src/arscan.c
+++ b/src/arscan.c
@@ -75,9 +75,9 @@ static void *VMS_lib_idx;
 
 static const void *VMS_saved_arg;
 
-static long int (*VMS_function) ();
+static intmax_t (*VMS_function) ();
 
-static long int VMS_function_ret;
+static intmax_t VMS_function_ret;
 
 
 /* This is a callback procedure for lib$get_index */
@@ -203,7 +203,7 @@ VMS_get_member_info(struct dsc$descriptor_s *module, 
unsigned long *rfa)
    Returns -2 if archive has invalid format.
    Returns 0 if have scanned successfully.  */
 
-long int
+intmax_t
 ar_scan (const char *archive, ar_member_func_t function, const void *varg)
 {
   char *vms_archive;
@@ -379,13 +379,13 @@ struct ar_hdr
 #include "output.h"
 
 
-static unsigned long int
+static uintmax_t
 parse_int (const char *ptr, const size_t len, const int base,
            const char *type, const char *archive, const char *name)
 {
   const char *const ep = ptr + len;
   const char max = '0' + base - 1;
-  long int val = 0;
+  uintmax_t val = 0;
 
   /* In all the versions I know of the spaces come last, but be safe.  */
   while (ptr < ep && *ptr == ' ')
@@ -430,7 +430,7 @@ parse_int (const char *ptr, const size_t len, const int 
base,
    Returns -2 if archive has invalid format.
    Returns 0 if have scanned successfully.  */
 
-long int
+intmax_t
 ar_scan (const char *archive, ar_member_func_t function, const void *arg)
 {
 #ifdef AIAMAG
@@ -550,7 +550,7 @@ ar_scan (const char *archive, ar_member_func_t function, 
const void *arg)
 # define ARNAME_MAX 255
         char name[ARNAME_MAX + 1];
         int name_len;
-        long int dateval;
+        intmax_t dateval;
         int uidval, gidval;
         long int data_offset;
 #else
@@ -562,7 +562,7 @@ ar_scan (const char *archive, ar_member_func_t function, 
const void *arg)
 #endif
         long int eltsize;
         unsigned int eltmode;
-        long int fnval;
+        intmax_t fnval;
         off_t o;
 
         memset(&member_header, '\0', sizeof (member_header));
@@ -593,7 +593,7 @@ ar_scan (const char *archive, ar_member_func_t function, 
const void *arg)
 
             name[name_len] = '\0';
 
-            sscanf (member_header_big.ar_date, "%12ld", &dateval);
+            sscanf (member_header_big.ar_date, "%12jd", &dateval);
             sscanf (member_header_big.ar_uid, "%12d", &uidval);
             sscanf (member_header_big.ar_gid, "%12d", &gidval);
             sscanf (member_header_big.ar_mode, "%12o", &eltmode);
@@ -621,7 +621,7 @@ ar_scan (const char *archive, ar_member_func_t function, 
const void *arg)
 
             name[name_len] = '\0';
 
-            sscanf (member_header.ar_date, "%12ld", &dateval);
+            sscanf (member_header.ar_date, "%12jd", &dateval);
             sscanf (member_header.ar_uid, "%12d", &uidval);
             sscanf (member_header.ar_gid, "%12d", &gidval);
             sscanf (member_header.ar_mode, "%12o", &eltmode);
@@ -887,10 +887,10 @@ ar_name_equal (const char *name, const char *mem, int 
truncated)
 
 #ifndef VMS
 /* ARGSUSED */
-static long int
+static intmax_t
 ar_member_pos (int desc UNUSED, const char *mem, int truncated,
                long int hdrpos, long int datapos UNUSED, long int size UNUSED,
-               long int date UNUSED, int uid UNUSED, int gid UNUSED,
+               intmax_t date UNUSED, int uid UNUSED, int gid UNUSED,
                unsigned int mode UNUSED, const void *name)
 {
   if (!ar_name_equal (name, mem, truncated))
@@ -913,7 +913,7 @@ ar_member_touch (const char *arname, const char *memname)
   struct ar_hdr ar_hdr;
   off_t o;
   int r;
-  unsigned int ui;
+  int datelen;
   struct stat statbuf;
 
   if (pos < 0)
@@ -937,10 +937,11 @@ ar_member_touch (const char *arname, const char *memname)
     goto lose;
   /* Advance member's time to that time */
 #if defined(ARFMAG) || defined(ARFZMAG) || defined(AIAMAG) || 
defined(WINDOWS32)
-  for (ui = 0; ui < sizeof ar_hdr.ar_date; ui++)
-    ar_hdr.ar_date[ui] = ' ';
-  sprintf (TOCHAR (ar_hdr.ar_date), "%lu", (long unsigned) statbuf.st_mtime);
-  ar_hdr.ar_date[strlen ((char *) ar_hdr.ar_date)] = ' ';
+  datelen = snprintf (TOCHAR (ar_hdr.ar_date), sizeof ar_hdr.ar_date,
+                      "%jd", (intmax_t) statbuf.st_mtime);
+  if (! (0 <= datelen && datelen <= (int) sizeof ar_hdr.ar_date))
+    goto lose;
+  memset (ar_hdr.ar_date + datelen, ' ', sizeof ar_hdr.ar_date - datelen);
 #else
   ar_hdr.ar_date = statbuf.st_mtime;
 #endif
@@ -964,18 +965,21 @@ ar_member_touch (const char *arname, const char *memname)
 
 #ifdef TEST
 
-long int
+intmax_t
 describe_member (int desc, const char *name, int truncated,
                  long int hdrpos, long int datapos, long int size,
-                 long int date, int uid, int gid, unsigned int mode,
+                 intmax_t date, int uid, int gid, unsigned int mode,
                  const void *arg)
 {
   extern char *ctime ();
+  time_t d = date;
+  char const *ds;
 
   printf (_("Member '%s'%s: %ld bytes at %ld (%ld).\n"),
           name, truncated ? _(" (name might be truncated)") : "",
           size, hdrpos, datapos);
-  printf (_("  Date %s"), ctime (&date));
+  ds = ctime (&d);
+  printf (_("  Date %s"), ds ? ds : "?");
   printf (_("  uid = %d, gid = %d, mode = 0%o.\n"), uid, gid, mode);
 
   return 0;
diff --git a/src/file.c b/src/file.c
index 6b7c52a2..a3bee95d 100644
--- a/src/file.c
+++ b/src/file.c
@@ -1018,13 +1018,16 @@ file_timestamp_sprintf (char *p, FILE_TIMESTAMP ts)
   struct tm *tm = localtime (&t);
 
   if (tm)
-    sprintf (p, "%04d-%02d-%02d %02d:%02d:%02d",
-             tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
-             tm->tm_hour, tm->tm_min, tm->tm_sec);
+    {
+      intmax_t year = tm->tm_year;
+      sprintf (p, "%04jd-%02d-%02d %02d:%02d:%02d",
+               year + 1900, tm->tm_mon + 1, tm->tm_mday,
+               tm->tm_hour, tm->tm_min, tm->tm_sec);
+    }
   else if (t < 0)
-    sprintf (p, "%ld", (long) t);
+    sprintf (p, "%jd", (intmax_t) t);
   else
-    sprintf (p, "%lu", (unsigned long) t);
+    sprintf (p, "%ju", (uintmax_t) t);
   p += strlen (p);
 
   /* Append nanoseconds as a fraction, but remove trailing zeros.  We don't
diff --git a/src/makeint.h b/src/makeint.h
index d941ff3d..f5a33bb7 100644
--- a/src/makeint.h
+++ b/src/makeint.h
@@ -566,13 +566,14 @@ void ar_parse_name (const char *, char **, char **);
 int ar_touch (const char *);
 time_t ar_member_date (const char *);
 
-typedef long int (*ar_member_func_t) (int desc, const char *mem, int truncated,
+typedef intmax_t (*ar_member_func_t) (int desc, const char *mem, int truncated,
                                       long int hdrpos, long int datapos,
-                                      long int size, long int date, int uid,
+                                      long int size, intmax_t date, int uid,
                                       int gid, unsigned int mode,
                                       const void *arg);
 
-long int ar_scan (const char *archive, ar_member_func_t function, const void 
*arg);
+intmax_t ar_scan (const char *archive, ar_member_func_t function,
+                  const void *arg);
 int ar_name_equal (const char *name, const char *mem, int truncated);
 #ifndef VMS
 int ar_member_touch (const char *arname, const char *memname);
-- 
2.37.3




reply via email to

[Prev in Thread] Current Thread [Next in Thread]