Subject: Pine c-client patch for DG/UX: utime() problem

From: Ken Weaverling <[email-masked]>
Date: Wed, 5 Oct 1994 07:13:46 -0400 (EDT)

Pine 3.90 has a problem on DG/UX systems when using utime() to modify folder
access and mod times.  The result, folders getting weird modification 
dates, especially after an expunge operation. The folders most often were
set to Dec 31, 1969 (epoch) or some other strange date.

The problem is, the code defines...

time_t tp[2];

... and then passes tp into utime().  On DG/UX, utime actually is looking
for four doubles. Each time is actually two time_t's, the second being in
microseconds!!!

If the struct utimbuf is used, it will work on DG/UX. I checked a SunOS
and Solaris system and they both define utimbuf with members actime and 
modtime as well. 

The patch that is mime-attached to this message just patches the files to
use utimbuf and does NOT put #ifdefs around anything. If this is a bad 
thing, then this patch will break some other system out there.

I, and other DG users who told me they seen the same problem at other sites, 
would appreciate it if some type of fix for this could be folded into 
future releases ... and we all really appreciate the d-g build option in 
there already!  Compiling was a breeze!

-- 
Ken Weaverling          [email-masked] |*|  Wilmington: +1 302 573-5460
    Manager of Computer Services       |*|     Stanton: +1 302 454-3978
   Stanton/Wilmington Campuses of      |*|       WHOIS: KJW
Delaware Technical & Community College |*|
This patch changes the utime() calls to use a utimbuf struct instead of
assuming utime expects utimbuf to be a struct of two time_t variables. This
breaks the call on DG/UX since utimbuf actually is four longs in length and
includes longs to measure microseconds. The result was that the modtime was
usually set to 0 or some other random value, so if utime was ever called, 
mtime's on the folders were always botched up, but usually the beginning
of (unix) time.     ([email-masked])

First, add the line

#include <utime.h>

... somewhere. I added it to os_d-g.h in the c-client directory, or I guess
it could be added to each of the four files patched below.

Apply the below patches to the files tenex2.c mmdf.c mtx.c and bezerk.c.

*** tenex2.c.orig	Wed Oct  5 05:52:38 1994
--- tenex2.c	Wed Oct  5 05:47:19 1994
***************
*** 117,121 ****
    char *s,file[MAILTMPLEN];
    struct stat sbuf;
!   time_t tp[2];
    errno = EINVAL;		/* assume invalid argument */
  				/* if file, get its status */
--- 117,121 ----
    char *s,file[MAILTMPLEN];
    struct stat sbuf;
!   struct utimbuf tp;
    errno = EINVAL;		/* assume invalid argument */
  				/* if file, get its status */
***************
*** 133,139 ****
  	       (s = strchr (tmp+20,',')) && strchr (s+2,';')) ? T : NIL;
        }
!       tp[0] = sbuf.st_atime;	/* preserve atime and mtime */
!       tp[1] = sbuf.st_mtime;
!       utime (file,tp);		/* set the times */
      }
  				/* allow empty file if INBOX */
--- 133,139 ----
  	       (s = strchr (tmp+20,',')) && strchr (s+2,';')) ? T : NIL;
        }
!       tp.actime = sbuf.st_atime;	/* preserve atime and mtime */
!       tp.modtime = sbuf.st_mtime;
!       utime (file,&tp);		/* set the times */
      }
  				/* allow empty file if INBOX */
***************
*** 1055,1059 ****
    int fd,ld;
    char c,*s,*t,tmp[MAILTMPLEN],file[MAILTMPLEN],lock[MAILTMPLEN];
!   time_t tp[2];
    MESSAGECACHE elt;
    long i = SIZE (message);
--- 1055,1059 ----
    int fd,ld;
    char c,*s,*t,tmp[MAILTMPLEN],file[MAILTMPLEN],lock[MAILTMPLEN];
!   struct utimbuf tp;
    MESSAGECACHE elt;
    long i = SIZE (message);
***************
*** 1128,1134 ****
    }
    fsync (fd);			/* force out the update */
!   tp[0] = sbuf.st_atime;	/* preserve atime and mtime */
!   tp[1] = sbuf.st_mtime;
!   utime (file,tp);		/* set the times */
    tenex_unlock (ld,lock);	/* release exclusive parse/append permission */
    close (fd);			/* close the file */
--- 1128,1134 ----
    }
    fsync (fd);			/* force out the update */
!   tp.actime = sbuf.st_atime;	/* preserve atime and mtime */
!   tp.modtime = sbuf.st_mtime;
!   utime (file,&tp);		/* set the times */
    tenex_unlock (ld,lock);	/* release exclusive parse/append permission */
    close (fd);			/* close the file */
***************
*** 1397,1401 ****
  {
    struct stat sbuf;
!   time_t tp[2];
    MESSAGECACHE *elt;
    unsigned long i,j,k;
--- 1397,1401 ----
  {
    struct stat sbuf;
!   struct utimbuf tp;
    MESSAGECACHE *elt;
    unsigned long i,j,k;
***************
*** 1454,1460 ****
      }
    fsync (fd);			/* force out the update */
!   tp[0] = sbuf.st_atime;	/* preserve atime and mtime */
!   tp[1] = sbuf.st_mtime;
!   utime (file,tp);		/* set the times */
    tenex_unlock (ld,lock);	/* release exclusive parse/append permission */
    close (fd);			/* close the file */
--- 1454,1460 ----
      }
    fsync (fd);			/* force out the update */
!   tp.actime = sbuf.st_atime;	/* preserve atime and mtime */
!   tp.modtime = sbuf.st_mtime;
!   utime (file,&tp);		/* set the times */
    tenex_unlock (ld,lock);	/* release exclusive parse/append permission */
    close (fd);			/* close the file */
*** mtx.c.orig	Wed Oct  5 04:57:06 1994
--- mtx.c	Wed Oct  5 05:50:07 1994
***************
*** 117,121 ****
    char *s,file[MAILTMPLEN];
    struct stat sbuf;
!   time_t tp[2];
    errno = EINVAL;		/* assume invalid argument */
  				/* if file, get its status */
--- 117,121 ----
    char *s,file[MAILTMPLEN];
    struct stat sbuf;
!   struct utimbuf tp;
    errno = EINVAL;		/* assume invalid argument */
  				/* if file, get its status */
***************
*** 133,139 ****
  	       (s = strchr (tmp+20,',')) && strchr (s+2,';')) ? T : NIL;
        }
!       tp[0] = sbuf.st_atime;	/* preserve atime and mtime */
!       tp[1] = sbuf.st_mtime;
!       utime (file,tp);		/* set the times */
      }
  				/* allow empty file if INBOX */
--- 133,139 ----
  	       (s = strchr (tmp+20,',')) && strchr (s+2,';')) ? T : NIL;
        }
!       tp.actime = sbuf.st_atime;	/* preserve atime and mtime */
!       tp.modtime = sbuf.st_mtime;
!       utime (file,&tp);		/* set the times */
      }
  				/* allow empty file if INBOX */
***************
*** 1080,1084 ****
    int fd,ld;
    char *s,*t,tmp[MAILTMPLEN],file[MAILTMPLEN],lock[MAILTMPLEN];
!   time_t tp[2];
    MESSAGECACHE elt;
    long i;
--- 1080,1084 ----
    int fd,ld;
    char *s,*t,tmp[MAILTMPLEN],file[MAILTMPLEN],lock[MAILTMPLEN];
!   struct utimbuf tp;
    MESSAGECACHE elt;
    long i;
***************
*** 1152,1158 ****
    }
    fsync (fd);			/* force out the update */
!   tp[0] = sbuf.st_atime;	/* preserve atime and mtime */
!   tp[1] = sbuf.st_mtime;
!   utime (file,tp);		/* set the times */
    mtx_unlock (ld,lock);		/* release exclusive parse/append permission */
    close (fd);			/* close the file */
--- 1152,1158 ----
    }
    fsync (fd);			/* force out the update */
!   tp.actime = sbuf.st_atime;	/* preserve atime and mtime */
!   tp.modtime = sbuf.st_mtime;
!   utime (file,&tp);		/* set the times */
    mtx_unlock (ld,lock);		/* release exclusive parse/append permission */
    close (fd);			/* close the file */
***************
*** 1410,1414 ****
  {
    struct stat sbuf;
!   time_t tp[2];
    MESSAGECACHE *elt;
    unsigned long i,j,k;
--- 1410,1414 ----
  {
    struct stat sbuf;
!   struct utimbuf tp;
    MESSAGECACHE *elt;
    unsigned long i,j,k;
***************
*** 1467,1473 ****
      }
    fsync (fd);			/* force out the update */
!   tp[0] = sbuf.st_atime;	/* preserve atime and mtime */
!   tp[1] = sbuf.st_mtime;
!   utime (file,tp);		/* set the times */
    mtx_unlock (ld,lock);		/* release exclusive parse/append permission */
    close (fd);			/* close the file */
--- 1467,1473 ----
      }
    fsync (fd);			/* force out the update */
!   tp.actime = sbuf.st_atime;	/* preserve atime and mtime */
!   tp.modtime = sbuf.st_mtime;
!   utime (file,&tp);		/* set the times */
    mtx_unlock (ld,lock);		/* release exclusive parse/append permission */
    close (fd);			/* close the file */
*** mmdf.c.orig	Wed Oct  5 04:57:45 1994
--- mmdf.c	Wed Oct  5 05:51:44 1994
***************
*** 119,123 ****
    char *s = tmp,*t,file[MAILTMPLEN];
    struct stat sbuf;
!   time_t tp[2];
    errno = EINVAL;		/* assume invalid argument */
  				/* must be non-empty file */
--- 119,123 ----
    char *s = tmp,*t,file[MAILTMPLEN];
    struct stat sbuf;
!   struct utimbuf tp;
    errno = EINVAL;		/* assume invalid argument */
  				/* must be non-empty file */
***************
*** 127,133 ****
      ret = ((sbuf.st_size > 0) && (read (fd,tmp,MAILTMPLEN-1) >= 0) &&
  	   ISMMDF (tmp)) ? T : NIL;
!     tp[0] = sbuf.st_atime;	/* preserve atime and mtime */
!     tp[1] = sbuf.st_mtime;
!     utime (file,tp);		/* set the times */
      close (fd);			/* close the file */
  				/* no error if file empty */
--- 127,133 ----
      ret = ((sbuf.st_size > 0) && (read (fd,tmp,MAILTMPLEN-1) >= 0) &&
  	   ISMMDF (tmp)) ? T : NIL;
!     tp.actime = sbuf.st_atime;	/* preserve atime and mtime */
!     tp.modtime = sbuf.st_mtime;
!     utime (file,&tp);		/* set the times */
      close (fd);			/* close the file */
  				/* no error if file empty */
***************
*** 917,921 ****
    int fd,ok = T;
    char c,buf[MAILTMPLEN],file[MAILTMPLEN],lock[MAILTMPLEN];
!   time_t tp[2];
    MESSAGECACHE elt;
    int i = 0;
--- 917,921 ----
    int fd,ok = T;
    char c,buf[MAILTMPLEN],file[MAILTMPLEN],lock[MAILTMPLEN];
!   struct utimbuf tp;
    MESSAGECACHE elt;
    int i = 0;
***************
*** 990,996 ****
      ok = NIL;
    }
!   tp[0] = sbuf.st_atime;	/* preserve atime */
!   tp[1] = time (0);		/* set mtime to now */
!   utime (file,tp);		/* set the times */
    mmdf_unlock (fd,NIL,lock);	/* unlock and close mailbox */
    mm_nocritical (stream);	/* release critical */
--- 990,996 ----
      ok = NIL;
    }
!   tp.actime = sbuf.st_atime;	/* preserve atime */
!   tp.modtime = time (0);		/* set mtime to now */
!   utime (file,&tp);		/* set the times */
    mmdf_unlock (fd,NIL,lock);	/* unlock and close mailbox */
    mm_nocritical (stream);	/* release critical */
***************
*** 1148,1160 ****
  {
    struct stat sbuf;
!   time_t tp[2];
    fstat (fd,&sbuf);		/* get file times */
  				/* if stream and csh would think new mail */
    if (stream && (sbuf.st_atime <= sbuf.st_mtime)) {
!     tp[0] = time (0);		/* set atime to now */
  				/* set mtime to (now - 1) if necessary */
!     tp[1] = tp[0] > sbuf.st_mtime ? sbuf.st_mtime : tp[0] - 1;
  				/* set the times, note change */
!     if (!utime (LOCAL->name,tp)) LOCAL->filetime = tp[1];
    }
    flock (fd,LOCK_UN);		/* release flock'ers */
--- 1148,1160 ----
  {
    struct stat sbuf;
!   struct utimbuf tp;
    fstat (fd,&sbuf);		/* get file times */
  				/* if stream and csh would think new mail */
    if (stream && (sbuf.st_atime <= sbuf.st_mtime)) {
!     tp.actime = time (0);		/* set atime to now */
  				/* set mtime to (now - 1) if necessary */
!     tp.modtime = tp.actime > sbuf.st_mtime ? sbuf.st_mtime : tp.actime - 1;
  				/* set the times, note change */
!     if (!utime (LOCAL->name,&tp)) LOCAL->filetime = tp.modtime;
    }
    flock (fd,LOCK_UN);		/* release flock'ers */
***************
*** 1609,1613 ****
    int fd;
    struct stat sbuf;
!   time_t tp[2];
    long i;
    int ok = T;
--- 1609,1613 ----
    int fd;
    struct stat sbuf;
!   struct utimbuf tp;
    long i;
    int ok = T;
***************
*** 1653,1659 ****
      ok = NIL;			/* oops */
    }
!   tp[0] = sbuf.st_atime;	/* preserve atime */
!   tp[1] = time (0);		/* set mtime to now */
!   utime (file,tp);		/* set the times */
    mmdf_unlock (fd,NIL,lock);	/* unlock and close mailbox */
    mm_nocritical (stream);	/* release critical */
--- 1653,1659 ----
      ok = NIL;			/* oops */
    }
!   tp.actime = sbuf.st_atime;	/* preserve atime */
!   tp.modtime = time (0);	/* set mtime to now */
!   utime (file,&tp);		/* set the times */
    mmdf_unlock (fd,NIL,lock);	/* unlock and close mailbox */
    mm_nocritical (stream);	/* release critical */
*** bezerk.c.orig	Wed Oct  5 04:48:00 1994
--- bezerk.c	Wed Oct  5 05:14:43 1994
***************
*** 131,135 ****
    char *s = tmp,*t,file[MAILTMPLEN];
    struct stat sbuf;
!   time_t tp[2];
    errno = EINVAL;		/* assume invalid argument */
  				/* must be non-empty file */
--- 131,135 ----
    char *s = tmp,*t,file[MAILTMPLEN];
    struct stat sbuf;
!   struct utimbuf tp;
    errno = EINVAL;		/* assume invalid argument */
  				/* must be non-empty file */
***************
*** 139,145 ****
      if ((sbuf.st_size > 0) && (read (fd,tmp,MAILTMPLEN-1) >= 0))
        VALID (s,t,ret,zn);
!     tp[0] = sbuf.st_atime;	/* preserve atime and mtime */
!     tp[1] = sbuf.st_mtime;
!     utime (file,tp);		/* set the times */
      close (fd);			/* close the file */
  				/* no error if file empty */
--- 139,145 ----
      if ((sbuf.st_size > 0) && (read (fd,tmp,MAILTMPLEN-1) >= 0))
        VALID (s,t,ret,zn);
!     tp.actime = sbuf.st_atime;	/* preserve atime and mtime */
!     tp.modtime = sbuf.st_mtime;
!     utime (file,&tp);		/* set the times */
      close (fd);			/* close the file */
  				/* no error if file empty */
***************
*** 967,971 ****
    int i,fd,ti,zn;
    char *s,*x,buf[BUFLEN],file[MAILTMPLEN],lock[MAILTMPLEN];
!   time_t tp[2];
    MESSAGECACHE elt;
    char c = '\n';
--- 967,971 ----
    int i,fd,ti,zn;
    char *s,*x,buf[BUFLEN],file[MAILTMPLEN],lock[MAILTMPLEN];
!   struct utimbuf tp;
    MESSAGECACHE elt;
    char c = '\n';
***************
*** 1049,1055 ****
      ftruncate (fd,sbuf.st_size);
    }
!   tp[0] = sbuf.st_atime;	/* preserve atime */
!   tp[1] = time (0);		/* set mtime to now */
!   utime (file,tp);		/* set the times */
    bezerk_unlock (fd,NIL,lock);	/* unlock and close mailbox */
    mm_nocritical (stream);	/* release critical */
--- 1049,1055 ----
      ftruncate (fd,sbuf.st_size);
    }
!   tp.actime = sbuf.st_atime;	/* preserve atime */
!   tp.modtime = time (0);	/* set mtime to now */
!   utime (file,&tp);		/* set the times */
    bezerk_unlock (fd,NIL,lock);	/* unlock and close mailbox */
    mm_nocritical (stream);	/* release critical */
***************
*** 1225,1237 ****
  {
    struct stat sbuf;
!   time_t tp[2];
    fstat (fd,&sbuf);		/* get file times */
  				/* if stream and csh would think new mail */
    if (stream && (sbuf.st_atime <= sbuf.st_mtime)) {
!     tp[0] = time (0);		/* set atime to now */
  				/* set mtime to (now - 1) if necessary */
!     tp[1] = tp[0] > sbuf.st_mtime ? sbuf.st_mtime : tp[0] - 1;
  				/* set the times, note change */
!     if (!utime (LOCAL->name,tp)) LOCAL->filetime = tp[1];
    }
    flock (fd,LOCK_UN);		/* release flock'ers */
--- 1225,1237 ----
  {
    struct stat sbuf;
!   struct utimbuf tp;
    fstat (fd,&sbuf);		/* get file times */
  				/* if stream and csh would think new mail */
    if (stream && (sbuf.st_atime <= sbuf.st_mtime)) {
!     tp.actime = time (0);	/* set atime to now */
  				/* set mtime to (now - 1) if necessary */
!     tp.modtime = tp.actime > sbuf.st_mtime ? sbuf.st_mtime : tp.actime - 1;
  				/* set the times, note change */
!     if (!utime (LOCAL->name,&tp)) LOCAL->filetime = tp.modtime;
    }
    flock (fd,LOCK_UN);		/* release flock'ers */
***************
*** 1708,1712 ****
    int fd,iovc;
    struct stat sbuf;
!   time_t tp[2];
    long i;
    int ok = T;
--- 1708,1712 ----
    int fd,iovc;
    struct stat sbuf;
!   struct utimbuf tp;
    long i;
    int ok = T;
***************
*** 1757,1763 ****
      ok = NIL;			/* oops */
    }
!   tp[0] = sbuf.st_atime;	/* preserve atime */
!   tp[1] = time (0);		/* set mtime to now */
!   utime (file,tp);		/* set the times */
    bezerk_unlock (fd,NIL,lock);	/* unlock and close mailbox */
    mm_nocritical (stream);	/* release critical */
--- 1757,1763 ----
      ok = NIL;			/* oops */
    }
!   tp.actime = sbuf.st_atime;	/* preserve atime */
!   tp.modtime = time (0);	/* set mtime to now */
!   utime (file,&tp);		/* set the times */
    bezerk_unlock (fd,NIL,lock);	/* unlock and close mailbox */
    mm_nocritical (stream);	/* release critical */