"Rod Pemberton" <do_not_h
...@nohavenot.cmm> wrote:
>In C, you might (lots of options...)
Excellent post! Yes lots of options...
// ------------------------------------------------------------------------
// System : Win9X/NT
// Program : touch.c
// Description : modify file times
// handles long filenames under Win9X/NT
// Written by : Bill Buckels
// Date Written : March 2000
// Revision : 1.0 First Release
// Errata : Used Workarounds for incorrect adjustment of localtime
// For some reason the conversion from clock date to
// file date is out by an hour... and I don't completely
// understand why. But if workarounds are OK then
// no plan to fix.
// ------------------------------------------------------------------------
#include <stdlib.h>
#include <stdio.h>
#include <io.h>
#include <string.h>
#include <direct.h>
#include <time.h>
#include <sys/types.h>
#include <sys/utime.h>
#include <sys/stat.h>
/* global vars. */
struct tm TouchTime; /* global structure */
char *timestr = "29:59:59", /* verification pattern */
*alttime = "29:59",
*datestr = "19-39-2999",
*altdate = "19-39-99",
*timearg = "HH:MM:SS", /* command line args - intial values */
*datearg = "MM-DD-CCYY",
searcharg[_MAX_PATH] = "*.*"; /* file spec - initial value */
int force = 0,
nocreate = 0,
verbose = 0,
TouchNow = 0; /* if this flag is set, the filetime is now */
/* positions in the date string MM-DD-CCYY or HH:MM:SS */
#define POS_1 0
#define POS_2 3
#define POS_3 6
/* get the command line options */
/* assign the values to the globals */
int GetOptions(char *arg)
{
int len,
idx,
val,
found = 0;
char c;
/* parse switches */
if (arg[0] == '-') {
for (idx = 0; arg[idx] != 0; idx++) {
c = tolower(arg[idx]);
switch(c) {
case 'f': force = 1; break; /* force readonly */
case 'c': nocreate = 1; break; /* don't create 0 length */
case 'v': verbose = 1; break; /* verbose mode */
}
}
return (found);
}
len = strlen(arg);
/* check for time pattern HH:MM:SS */
if (len == strlen(timestr)) {
found = 1;
for (idx = 0; arg[idx] != 0; idx++) {
if (timestr[idx] == ':' && arg[idx] == ':')
continue;
if (arg[idx] >= '0' && arg[idx] <= timestr[idx])
continue;
found = 0;
break;
}
if (found) {
strcpy(timearg, arg);
TouchTime.tm_hour = atoi(&timearg[POS_1]);
TouchTime.tm_min = atoi(&timearg[POS_2]);
TouchTime.tm_sec = atoi(&timearg[POS_3]);
return found;
}
}
/* check for alternate time pattern HH:MM */
if (len == strlen(alttime)) {
found = 1;
for (idx = 0; arg[idx] != 0; idx++) {
if (alttime[idx] == ':' && arg[idx] == ':')
continue;
if (arg[idx] >= '0' && arg[idx] <= alttime[idx])
continue;
found = 0;
break;
}
if (found) {
TouchTime.tm_hour = atoi(&arg[POS_1]);
TouchTime.tm_min = atoi(&arg[POS_2]);
TouchTime.tm_sec = 0;
sprintf(timearg, "%002d:%002d:%002d",
TouchTime.tm_hour, TouchTime.tm_min, TouchTime.tm_sec);
return found;
}
}
/* check for date pattern - MM-DD-CCYY */
if (len == strlen(datestr)) {
found = 1;
for (idx = 0; arg[idx] != 0; idx++) {
if (datestr[idx] == '-' && arg[idx] == '-')
continue;
if (arg[idx] >= '0' && arg[idx] <= datestr[idx])
continue;
found = 0;
break;
}
if (found) {
strcpy(datearg, arg);
TouchTime.tm_mon = atoi(&datearg[POS_1]) - 1;
TouchTime.tm_mday = atoi(&datearg[POS_2]);
TouchTime.tm_year = atoi(&datearg[POS_3]) - 1900;
return found;
}
}
/* check for alternate date pattern MM-DD-YY */
if (len == strlen(altdate)) {
found = 1;
for (idx = 0; arg[idx] != 0; idx++) {
if (altdate[idx] == '-' && arg[idx] == '-')
continue;
if (arg[idx] >= '0' && arg[idx] <= altdate[idx])
continue;
found = 0;
break;
}
if (found) {
TouchTime.tm_mon = atoi(&arg[POS_1]) - 1;
TouchTime.tm_mday = atoi(&arg[POS_2]);
TouchTime.tm_year = atoi(&arg[POS_3]);
/* no file times in DOS before 1980 - use fixed date window of 1980 */
/* for Y2K rollover... */
if (TouchTime.tm_year < 80)
TouchTime.tm_year += 100;
sprintf(datearg, "%002d-%002d-%4d",
TouchTime.tm_mon + 1, TouchTime.tm_mday, TouchTime.tm_year + 1900);
return found;
}
}
/* usually assume arg is a filename unless it's a date or a time */
/* in this day and age almost anything goes for filenames */
if (len < 3 || (arg[2] != ':' && arg[2] != '-')) {
found = 1;
strcpy(searcharg, arg);
}
return (found);
}
/* function Touch() - the crux of the biscuit */
/* uses the _utime function to modify file times */
/* In DOS we used the _dos_setftime function to modify the file time
after opening a file. In Windows we can do basically the same thing
with the SetFileTime API function. But we don't want to use Windows
calls since this is a console application and we can't use DOS
calls since DOS is dead and didn't handle long names anyways.
Fortunately the Unix Style _utime function offers us a way to modify
the file times without even opening the file.
The _utime function sets the modification time for the file specified
by filename. The process must have write access to the file in order
to change the time. Under Windows NT and Windows 95, you can change
the access time and the modication time in the _utimbuf structure. If
times is a NULL pointer, the modification time is set to the current
local time. Otherwise, times must point to a structure of type
_utimbuf, defined in SYS\UTIME.H.
The _utimbuf structure stores file access and modification times used
by _utime to change file-modification dates. The structure has the
following fields, which are both of type time_t:
actime
Time of file access
modtime
Time of file modification
_utime is identical to _futime except that the filename argument of
_utime is a filename or a path to a file, rather than a handle to an
open file.
_wutime is a wide-character version of _utime; the filename argument
to _wutime is a wide-character string. These functions behave
identically otherwise.
*/
int Touch(unsigned char *fname, time_t time_access, time_t time_write)
{
struct _utimbuf timbuf, *ptimbuf = NULL; /* structure for call to _utime
*/
struct tm *worktime, OldTime;
time_t worktime_t;
int status = 0,
readonly = 0;
/* sometimes we will need to reset the filedate without resetting the time
*/
/* and sometimes we will need to reset the filetime without the date */
/* so we need to save the original file date in case this occurs and */
/* reset only the portion that the user has requested */
worktime = localtime(&time_write);
memcpy(&OldTime, worktime, sizeof(struct tm));
/* preserve orginal time or date if no args */
if (strcmp(timearg, "HH:MM:SS") == 0) {
TouchTime.tm_hour = OldTime.tm_hour;
TouchTime.tm_min = OldTime.tm_min;
TouchTime.tm_sec = OldTime.tm_sec;
}
if (strcmp(datearg, "MM-DD-CCYY") == 0) {
TouchTime.tm_year = OldTime.tm_year;
TouchTime.tm_mon = OldTime.tm_mon;
TouchTime.tm_mday = OldTime.tm_mday;
}
/* build the new time */
/* incorrect behaviour if date and time were current time */
/* daylight saving time was not adjusting properly in mktime */
/* out by an hour - so cludge required */
/* now using a NULL _timbuf structure if setting to current time */
if (TouchNow == 0) {
timbuf.modtime = timbuf.actime = mktime(&TouchTime);
ptimbuf = (struct _utimbuf *)&timbuf;
}
if (force) {
/* if readonly try to set write mode before touching */
/* save old mode to reset readonly after touching */
readonly = _access(fname, 2);
if (readonly) {
_chmod(fname, _S_IWRITE);
}
}
if( _utime( fname, ptimbuf ) == -1 )
status = 0; /* _utime failed so return 0 */
else
status = 1;
if (force && readonly) {
_chmod(fname, _S_IREAD); /* try to force old mode back for read only */
}
if (status && verbose) {
printf("%002d:%002d:%002d ",
TouchTime.tm_hour, TouchTime.tm_min, TouchTime.tm_sec);
printf("%002d-%002d-%4d ",
TouchTime.tm_mon + 1, TouchTime.tm_mday, TouchTime.tm_year + 1900);
printf("%s\n", fname);
}
return status;
}
void main(int argc, char **argv)
{
int idx,
found = 0;
unsigned char path_buffer[_MAX_PATH],
drive[_MAX_DRIVE],
dir[_MAX_DIR],
rootname[_MAX_FNAME],
ext[_MAX_EXT],
buf[11]; /* work buffer for date and time */
long findhandle;
struct _finddata_t wild_card;
time_t now_t;
struct tm *today, /* work structures for date and time */
CurrentTime;
FILE *fp;
puts("Touch(C) v1.0 CopyLeft Bill Buckels 2000. All Rights Reversed.");
if(argc < 2) {
puts("Usage is : \"touch -cfv mm-dd-ccyy hh:mm:ss FileName*.*\"");
puts("- or - : \"touch -cfv mm-dd-yy hh:mm FileName*.*\"");
exit (1);
}
/* parse the command line */
for (idx = 1; idx < argc; idx++) {
GetOptions(argv[idx]);
}
/* if no date and time have been entered at all, use current time */
/* also we set the filetime slightly differently because wierd */
/* behaviour cause conversion to be out by an hour in some cases */
if (strcmp(timearg, "HH:MM:SS") == 0 &&
strcmp(datearg, "MM-DD-CCYY") == 0) {
time(&now_t);
today = localtime(&now_t);
memcpy(&CurrentTime, today, sizeof(struct tm));
sprintf(buf, "%002d:%002d:%002d",
CurrentTime.tm_hour, CurrentTime.tm_min,
...
read more »