[net.micro.pc] MS-DOS bug

bright@dataio.UUCP (Walter Bright) (08/23/85)

I have run into mysterious problems with MS-DOS's 57h Get/Set file's
date and time. They are:

	For get date, the MS-DOS documentation claims that the
	DX register returns with DH containing the low byte of the
	date, and DL containing the high byte. Experimentation has
	proven this to be false (DH has the high byte and DL has
	the low byte). I have seen this documented this way in 2
	different MS-DOS manuals (the 2.0 manual and the DOS Tech
	Ref). What is going on here?

	For set date, DOS seems to decrement the DX register before
	storing it. (That's right!) Not just the day portion of the
	register, but the whole register (try passing 0 in DX, when
	you read back the date it comes back FFFF!). Anybody got a
	clue?

By the way, I am running with MS-DOS 3.0 with an AT.

Here is a program which demonstrates these bugs. It should compile
with most MS-DOS C compilers.

/***************** CUT HERE ********************/

#include	<stdio.h>

/***********************
 */

main(argc,argv)
int argc;
char *argv[];
{
	test(argv[1]);
}

/******************************
 * Print out a file's date and time, get the current date and time,
 * set it to that, and get the file's new date and time.
 */

static test(name)
char *name;
{
    struct XREG { int ax,bx,cx,dx,si,di; };
    struct HREG { char al,ah,bl,bh,cl,ch,dl,dh; };
    union REGS { struct XREG x; struct HREG h; };

    union REGS inregs, outregs;
    unsigned date,time;
    unsigned handle;

    gettime(name);

    /* Get current date/time	*/
    inregs.h.ah = 0x2A;			/* get date			*/
    intdos(&inregs,&outregs);
    date = ((((outregs.x.cx - 1980) << 4) + outregs.h.dh) << 5) + outregs.h.dl;
    inregs.h.ah = 0x2C;			/* get time			*/
    intdos(&inregs,&outregs);
    time = (((outregs.h.ch << 6) + outregs.h.cl) << 5) + (outregs.h.dh >> 1);

    inregs.x.dx = (int) name;		/* DS:DX -> file name		*/
    inregs.h.al = 0;			/* open file for reading	*/
    inregs.h.ah = 0x3D;			/* open file function		*/
    if (intdos(&inregs,&outregs) & 1)	/* if error			*/
	printf("can't find file '%s'\n",name);
    handle = outregs.x.ax;

    inregs.x.ax = 0x5701;		/* set file's date/time		*/
    inregs.x.bx = handle;
    inregs.x.cx = time;
    inregs.x.dx = date;
    intdos(&inregs,&outregs);

    inregs.h.ah = 0x3E;
    intdos(&inregs,&outregs);		/* close file			*/
    printf("Set to x%x%04x\n",date,time);

    gettime(name);			/* let's see what DOS thinks it is */
}

/********************************
 * Print file's date and time.
 */

gettime(name)
char *name;
{
    struct XREG { int ax,bx,cx,dx,si,di; };
    struct HREG { char al,ah,bl,bh,cl,ch,dl,dh; };
    union REGS { struct XREG x; struct HREG h; };

    union REGS inregs, outregs;
    long datetime;
    unsigned handle;

    inregs.x.dx = (int) name;		/* DS:DX -> file name		*/
    inregs.h.al = 0;			/* open file for reading	*/
    inregs.h.ah = 0x3D;			/* open file function		*/
    if (intdos(&inregs,&outregs) & 1)	/* if error			*/
	return 0;			/* assume file doesn't exist	*/
    handle = outregs.x.ax;

    inregs.x.ax = 0x5700;		/* get file's date/time		*/
    inregs.x.bx = handle;
    intdos(&inregs,&outregs);
    datetime = ((long)outregs.x.dx << 16) + outregs.x.cx;
    printf("File's current data/time is %lx\n",datetime);

    inregs.h.ah = 0x3E;
    intdos(&inregs,&outregs);		/* close file			*/
}