From:	CSBVAX::MRGATE!IJAH400%INDYVAX.BITNET@CUNYVM.CUNY.EDU@SMTP 18-FEB-1988 17:44
To:	ARISIA::EVERHART
Subj:	RE: Setting file date/times from VMS


Received: from CUNYVM.CUNY.EDU by KL.SRI.COM with TCP; Sun 14 Feb 88 16:56:46-PST
Received: from INDYVAX.BITNET by CUNYVM.CUNY.EDU ; Sun, 14 Feb 88 19:56:57 EST
Date:     Sun, 14 Feb 88 19:56 EST
From:     <IJAH400%INDYVAX.BITNET@CUNYVM.CUNY.EDU>
Subject:  RE: Setting file date/times from VMS
To:       INFO-VAX@KL.SRI.COM
X-Original-To:  INFO-VAX@KL.SRI.COM


Rahul Dhesi <bsu-cs!dhesi@iuvax.cs.indiana.edu> writes:

< Does anybody have a C function that will set creation and/or
< modification time for a file?

Hello.  An old acquaintance who used to work here helped me out and sent me
this C function to set file dates.  He's going to be on INFO-VAX again soon,
but can't reply right now as it would cause mailing list problems.  I've
just finished testing this on a VAX 8800 running VMS 4.6, it worked fine
for me.

From Tom Allebrandi II:

------------------------------<<< Cut Here >>>----------------------------------
/******************************************************************************
* SET_DATES.C                                                                 *
* -----------                                                                 *
*                                                                             *
* Call upon the ACP-QIO interface to modify the various dates on a disk file. *
*                                                                             *
* Usage:  unsigned set_dates(file_name,                                       *
*                            creation_date,                                   *
*                            revision_date,                                   *
*                            expiration_date,                                 *
*                            backup_date)                                     *
*                                                                             *
* Where:                                                                      *
*         file_name is a null terminated string containing the specification  *
*                   of the file to be modified.                               *
*                                                                             *
*         ????_date is a null terminated string containing the new value for  *
*                   each date. The value must be in standard VMS date/time    *
*                   string format. Three special string values are recognized:*
*                                                                             *
*                       "" (null string) - don't modify the date.             *
*                                                                             *
*                        "NOW" - set the date to the current date/time.       *
*                                                                             *
*                        "NONE" - set the date/time to 0 which is inerpreted  *
*                                 by many utilities (like DIRECTORY and BACKUP*
*                                 as meaning no date. This is handy for set-  *
*                                 ting backup and expiration dates.           *
*                                                                             *
* WARNING:                                                                    *
*  This file must be compiled with VAX-C version 2.2 or later. The FIBDEF.H   *
* file prior to version 2.2 did not contain the definition of the fibdef      *
* structure.                                                                  *
*                                                                             *
*-----------------------------------------------------------------------------*
*                                                                             *
* Tom Allebrandi II, Advanced Computer Consulting, Inc.                       *
* Charlottesville, Virginia                                                   *
*                                                                             *
*-----------------------------------------------------------------------------*
*                                                                             *
* Edit history:                                                               *
*              TA2 = Tom Allebrandi II                                        *
*                                                                             *
*   Keyword     Date      Who   Note                                          *
*   -------  -----------  ---   ------------------------------                *
*   -none-   18-Jun-1986  TA2   Original coding.                              *
*                                                                             *
******************************************************************************/

/* Access VMS symbol definitions. */
#include        atrdef
#include        ctype
#include        descrip
#include        fibdef
#include        fab
#include        iodef
#include        nam
#include        ssdef
#include        stdio
#include        stsdef

/* The CHECK macro tests a VMS status code, or the return code from */
/* a service or library call for failure. When the code indicates a */
/* a failure, immediate return is made to the caller passing back   */
/* the bad code.                                                    */
#define CHECK(service_call)                                             \
                {                                                       \
                        register unsigned       status;                 \
                if (!$VMS_STATUS_SUCCESS((status = service_call)))      \
                        {                                               \
                        return(status);                                 \
                        }                                               \
                }


/* VMS binary date time values are 8 bytes long... */
#define quadword        struct  {unsigned : 32; unsigned : 32;}


/*****
*
* set_dates
*
*****/

unsigned set_dates (file_name,
                    creation_date,
                    revision_date,
                    expiration_date,
                    backup_date)
        char            *file_name;
        char            *creation_date;
        char            *revision_date;
        char            *expiration_date;
        char            *backup_date;
{
        /* RMS structures needed for $PARSE and $SEARCH */
        struct  FAB     fab;
        struct  NAM     nam;
        char            expanded_string[NAM$C_MAXRSS];
        char            resultant_string[NAM$C_MAXRSS];

        /* String descriptor for the name of the disk device and */
        /* storage for the I/O channel number.                   */
        struct  dsc$descriptor_s        disk_desc;
        short           disk_channel;

        /* Storage for ACP-QIO File Information Block */
        struct  fibdef  fib;
        struct  dsc$descriptor  fib_desc;

        /* Quadwords for storing binary time values */
        quadword        creation;
        quadword        revision;
        quadword        expiration;
        quadword        backup;

        /* Attribute Control Block for reading and writing dates */
        struct  {
                struct  atrdef  cdt;
                struct  atrdef  rdt;
                struct  atrdef  edt;
                struct  atrdef  bdt;
                long            terminator;
                } acb;

        /* I/O status block for $QIO operations */
        struct  {
                short           condition_value;
                short           transfer_count;
                long            device_specific_information;
                } iosb;

        /* Etc..... */
        unsigned        status;
        int             i;
        char            *p;
        char            temp_string[255];

extern  unsigned        convert_date();
extern  unsigned        sys$assign();
extern  unsigned        sys$dassgn();
extern  unsigned        sys$parse();
extern  unsigned        sys$qiow();
extern  unsigned        sys$search();


/* Parse and lookup the file specified by the user. If he gave an invalid    */
/* name or a non-existant file, there is no sense in going on. From the      */
/* parse and lookup, we will determine the name of the disk device containing*/
/* the file, and the file ID for the file itself.                            */

/*      - Initialize the FAB and the NAM. */
fab           = cc$rms_fab;             /* template FAB definition           */
fab.fab$b_fns = strlen(file_name);      /* length of input file specification*/
fab.fab$l_fna = file_name;              /* address of file specification     */
fab.fab$l_nam = &nam;                   /* link NAM block to FAB             */

nam           = cc$rms_nam;             /* template NAM definition           */
nam.nam$b_ess = NAM$C_MAXRSS;           /* size of expanded string area      */
nam.nam$l_esa = expanded_string;        /* address of resultant string area  */
nam.nam$b_rss = NAM$C_MAXRSS;           /* size of resultant string area     */
nam.nam$l_rsa = resultant_string;       /* address of resultant string area  */

/*      - Call upon RMS to parse the filespec and lookup the file. */
CHECK(sys$parse(&fab))
CHECK(sys$search(&fab))

/* Open a channel to the disk. Access the file to load the current date      */
/* settings.                                                                 */

/*      - Fill in a string descriptor for the device name */
disk_desc.dsc$w_length  = nam.nam$b_dev;        /* Length of device name     */
disk_desc.dsc$b_dtype   = DSC$K_DTYPE_T;        /* Character coded text      */
disk_desc.dsc$b_class   = DSC$K_CLASS_S;        /* String                    */
disk_desc.dsc$a_pointer = nam.nam$l_dev;        /* Address of device name    */

/*      - Open an I/O channel */
CHECK(sys$assign(&disk_desc,&disk_channel,0,0))

/*      - Initialize the File Information Block */
p = &fib;                                               /* Zero out the block*/

for (i=1;i<=sizeof(struct fibdef);i++)
        {
        *p++ = 0;
        }

fib.fib$r_fid_overlay.fib$w_fid[0]   = nam.nam$w_fid[0]; /* Copy the file ID */
fib.fib$r_fid_overlay.fib$w_fid[1]   = nam.nam$w_fid[1]; /*   from the NAM to*/
fib.fib$r_fid_overlay.fib$w_fid[2]   = nam.nam$w_fid[2]; /*   the FIB        */

/*      - The FIB is passed by descriptor. Initialize one. */
fib_desc.dsc$w_length  = sizeof(struct fibdef); /* Length of structure   */
fib_desc.dsc$b_dtype   = DSC$K_DTYPE_Z;         /* Unspecified data type */
fib_desc.dsc$b_class   = 0;                     /* No class specified    */
fib_desc.dsc$a_pointer = &fib;                  /* Addr of structure     */

/*      - Initialize the Attributes Control Block. */
acb.cdt.atr$w_size = sizeof(creation);          /* Access file creation date */
acb.cdt.atr$w_type = ATR$C_CREDATE;
acb.cdt.atr$l_addr = &creation;
acb.rdt.atr$w_size = sizeof(revision);          /* Access file revision date */
acb.rdt.atr$w_type = ATR$C_REVDATE;
acb.rdt.atr$l_addr = &revision;
acb.edt.atr$w_size = sizeof(expiration);        /* Access expiration date    */
acb.edt.atr$w_type = ATR$C_EXPDATE;
acb.edt.atr$l_addr = &expiration;
acb.bdt.atr$w_size = sizeof(backup);            /* Access file backup date   */
acb.bdt.atr$w_type = ATR$C_BAKDATE;
acb.bdt.atr$l_addr = &backup;
acb.terminator     = 0;                         /* End of list               */

/*      - Access the file (filling in the current dates for it) */
CHECK(sys$qiow(0,disk_channel,IO$_ACCESS,&iosb,NULL,0,&fib_desc,NULL,NULL,NULL,
   &acb,0))
CHECK(iosb.condition_value);


/* Convert the time values given by the user to binary. Set them in the */
/* appropriate vars.                                                    */
CHECK(convert_date(creation_date,&creation))
CHECK(convert_date(revision_date,&revision))
CHECK(convert_date(expiration_date,&expiration))
CHECK(convert_date(backup_date,&backup))

/* Call upon the ACP once more to set the new date values */
CHECK(sys$qiow(0,disk_channel,IO$_MODIFY,&iosb,NULL,0,&fib_desc,NULL,NULL,NULL,
   &acb,0))
CHECK(iosb.condition_value)

/* Release the I/O channel */
CHECK(sys$dassgn(disk_channel))

return (SS$_NORMAL);
}


/******
*
* convert_date
*
* Convert the passed in string to a date; return the date in the output
* variable. Watch out for the special strings.
*
*****/

unsigned convert_date(date_string,date_binary)
        char            *date_string;
        quadword        *date_binary;
{
        char            *in;
        char            *out;

        char            temp_string[255];
        struct dsc$descriptor_s temp_desc;

        int             i;

extern  unsigned        sys$bintim();
extern  unsigned        sys$gettim();

/* If the date_string is the null string; return taking no action. */
if (strcmp(date_string,"") == 0)
        {
        return(SS$_NORMAL);
        }

/* Convert to upper case so as not to annoy $BINTIM */
in  = date_string;
out = temp_string;

while (*out++ = _toupper(*in))
        {
        in++;
        }

/* Special cases... */
if (strcmp(temp_string,"NOW") == 0)
        {
        /* Set the output variable to the current system date/time */
        CHECK(sys$gettim(date_binary))
        }
 else if (strcmp(temp_string,"NONE") == 0)
        {
        /* Clear the time value */
        out = (char *) date_binary;
        for (i=1;i<=8;i++)
                {
                *out++ = 0;
                }
        }
 else   {
        /* Use $BINTIM to convert to binary time */
        temp_desc.dsc$w_length  = strlen(temp_string);
        temp_desc.dsc$b_dtype   = DSC$K_DTYPE_T;
        temp_desc.dsc$b_class   = DSC$K_CLASS_S;
        temp_desc.dsc$a_pointer = temp_string;

        CHECK(sys$bintim(&temp_desc,date_binary))
        }

return(SS$_NORMAL);
}
------------------------------<<< End Here >>>----------------------------------
--------------------------------------------------------------------------------
James A. Harvey, Analyst/Programmer                     BITNET: IJAH400@INDYVAX
Indiana University - Purdue University at Indianapolis  Phone:  (317)274-0747
E. & T. 1023, 799 W. Michigan Street
Indianapolis, IN  46220

    Blessed are They who keep Messy Offices, for only They shall know the
    Joy of Finding That which was thought to be Irretrievably Lost.
                        - Professor Nicholas Kira
