/* Copyright (C) 2020 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 2001 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ #include #include /* For utime() */ #include /* For localtime() */ #include /* For open() */ #include #include /* For errno */ #include #include #include #include /* An implementation of utime() for DJGPP. The utime() function specifies an access time and a modification time. DOS has only one time, so we will (arbitrarily) use the modification time. IF LFN is supported, then both times are used. */ int utime(const char *path, const struct utimbuf *times) { __dpmi_regs r = {0}; struct tm *tm; time_t modtime; int fildes; unsigned int dostime, dosdate; int retval = 0, e = 0; /* NULL times means use current time */ if (times == NULL) modtime = time((time_t *) 0); else modtime = times->modtime; /* Convert UNIX time to DOS date and time */ tm = localtime(&modtime); dosdate = tm->tm_mday + ((tm->tm_mon + 1) << 5) + ((tm->tm_year - 80) << 9); dostime = tm->tm_sec / 2 + (tm->tm_min << 5) + (tm->tm_hour << 11); if ((_USE_LFN) && (_os_trueversion == 0x532)) /* LFN and NT (or 2000 or XP) */ { _put_path(path); r.x.ds = __tb_segment; /* DS:DX -> ASCIZ filename */ r.x.dx = __tb_offset; r.x.cx = dostime; /* New time */ r.x.di = dosdate; /* New date */ r.x.si = 0x00; /* Set to zero just in case */ r.x.ax = 0x7143; /* LFN API for extended get and set time */ r.x.bx = 0x03; /* Set last write date / time */ __dpmi_int(0x21, &r); if (!(r.x.flags & 1)) /* Pass then continue */ { /* Uses date allready in r.x.di */ r.x.ax = 0x7143; /* LFN API for extended get and set time */ r.x.bx = 0x05; /* Set last access date / time */ __dpmi_int(0x21, &r); if (!(r.x.flags & 1)) /* Pass then continue */ return 0; } } /* DOS wants the file open */ fildes = open(path, O_RDONLY); if (fildes == -1) return -1; /* Set the file timestamp */ r.h.ah = 0x57; /* DOS FileTimes call */ r.h.al = 0x01; /* Set date/time request */ r.x.bx = fildes; /* File handle */ r.x.cx = dostime; /* New time */ r.x.dx = dosdate; /* New date */ __dpmi_int(0x21, &r); if (r.x.flags & 1) { e = EIO; retval = -1; } else if (_USE_LFN && (_os_trueversion == 0x532 || _os_trueversion == 0x700 || _os_trueversion == 0x710)) { /* We can set access time as well on Win95 and above but not on FreeDOS or any version of MS-DOS with or without LFN support. */ if (times) modtime = times->actime; tm = localtime(&modtime); dosdate = tm->tm_mday + ((tm->tm_mon + 1) << 5) + ((tm->tm_year - 80) << 9); dostime = tm->tm_sec / 2 + (tm->tm_min << 5) + (tm->tm_hour << 11); r.x.ax = 0x5705; r.x.bx = fildes; r.x.cx = _os_trueversion == 0x700 ? 0 : dostime; /* Acccording to RBIL this must be 0 for Win95 */ r.x.dx = dosdate; __dpmi_int(0x21, &r); if (r.x.flags & 1) { e = EIO; retval = -1; } } /* Close the file */ (void) close(fildes); if (e) errno = e; return retval; }