exploit the possibilities
Home Files News &[SERVICES_TAB]About Contact Add New

touch2v2.c

touch2v2.c
Posted May 21, 2006
Authored by Ighighi

Touch2 is a utility which modifies the ctime. Touch(1) can be used to change the last-access & last-modification times on the files (or directories) you read or modify, but doing this will change the last-inode-change time to the current time. Touch2 can be run after touch(1) or other commands.

systems | unix
SHA-256 | beaa155ed43ff7c33a27410bfd5934b0bbf58517b6f6e389227e99ed03714bf0

touch2v2.c

Change Mirror Download
/*
* touch2 v2.0
* Change last-inode-change times on files
*
* (c) 2002, 2005, 2006 by Ighighi (ighighi at gmail dot com)
* Venezuela
*
* BSD License
*
* DISCLAIMER: USE AT YOUR OWN RISK. I'M NOT RESPONSIBLE FOR ANYTHING!
*
* OVERVIEW:
* You use touch(1) to change the last-access & last-modification times
* of the files (or directories) you read or modify. The problem is that
* doing this will change the last-inode-change time to the current time.
* Now you may use touch2 right after using touch(1) to erase all evidence.
* Stealth hacking is the motto!
* IT MUST BE RUN AS ROOT!
*
* DETAILS:
* Firstly, we set the system time to the desired ctime (you must be root).
* Then we call chmod(2) to force an update of the inode's ctime.
* Later, we restore the system time as if nothing happened.
*
* BUGS / LIMITATIONS:
* + Nanosecond resolution (if supported) it's impossible to get it right.
* + Newer *BSD restrict settimeofday(2) when running in secure mode.
*
* TO DO:
* + Low-level filesystem hacking to overcome limitations #1 & #2
* + lutimes() for symbolic links
*
* CHANGELOG v2.0:
* + Enhanced portability. Bug fixes. New options. Signal handling.
* + chmod() is a more cleaner way to touch the inode than utime/utimes
*/

#define _FILE_OFFSET_BITS 64

static char usage[] =
"Usage: ./touch2 [-a|-m] [-r file|-t timestamp] files...\n"
" Options:\n"
" -h Print this help and exit\n"
" -a Use the file's last-access time\n"
" -m Use the file's last-modification time\n"
" -r file Use this file's time instead of current time\n"
" -t [[[YYYY:]MM:]DD:]hh:mm:ss[.uuuuuu]\n"
" Use this timestamp instead of current time\n";

#define ERROR_MUTUALLY_EXCLUSIVE1 \
"ERROR: The -a, -m & -t options are mutually exclusive!\n"

#define ERROR_MUTUALLY_EXCLUSIVE2 \
"ERROR: The -r & -t options are mutually exclusive!\n"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <time.h>

#ifndef timerisset
#define timerisset(tvp) ((tvp)->tv_sec || (tvp)->tv_usec)
#endif

#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
#ifndef _POSIX_SOURCE
#define ST_ATIME_NSEC st_atimespec.tv_nsec
#define ST_MTIME_NSEC st_mtimespec.tv_nsec
#define ST_CTIME_NSEC st_ctimespec.tv_nsec
#else
#define ST_ATIME_NSEC st_atimensec
#define ST_MTIME_NSEC st_mtimensec
#define ST_CTIME_NSEC st_ctimensec
#endif
#elif defined(__linux__) && defined(_STATBUF_ST_NSEC)
#if defined(_BSD_SOURCE) || defined(_SVID_SOURCE)
#define ST_ATIME_NSEC st_atim.tv_nsec
#define ST_MTIME_NSEC st_mtim.tv_nsec
#define ST_CTIME_NSEC st_ctim.tv_nsec
#else
#define ST_ATIME_NSEC st_atimensec
#define ST_MTIME_NSEC st_mtimensec
#define ST_CTIME_NSEC st_ctimensec
#endif
#elif defined(sun) && (defined(__SVR4) || defined(__svr4__))
#if defined(_XOPEN_SOURCE) || defined(_POSIX_C_SOURCE)
#define ST_ATIME_NSEC st_atim.__tv_nsec
#define ST_MTIME_NSEC st_mtim.__tv_nsec
#define ST_CTIME_NSEC st_ctim.__tv_nsec
#else
#define ST_ATIME_NSEC st_atim.tv_nsec
#define ST_MTIME_NSEC st_mtim.tv_nsec
#define ST_CTIME_NSEC st_ctim.tv_nsec
#endif
#endif

/* Use the file's atime instead of ctime as reference */
static int use_atime = 0;
/* Use the file's mtime... */
static int use_mtime = 0;

/*
* Returns 0 on success, -1 on (system call) error
*/
static int change_ctime(const char *file, struct timeval ctime)
{
#ifdef SIG_SETMASK
sigset_t newsigmask, oldsigmask;
#endif
struct timeval now;
struct stat inode;
int status = 0;

if (file == NULL)
return -1;

/* Get file's inode information */
while (stat(file, &inode) < 0) {
if (errno != EINTR) {
perror("stat()");
return -1;
}
}

if (!timerisset(&ctime)) {
if (use_atime) { /* Use the file's own atime */
ctime.tv_sec = inode.st_atime;
#ifdef ST_ATIME_NSEC
ctime.tv_usec = inode.ST_ATIME_NSEC / 1000;
#endif
}
else
if (use_mtime) { /* Use the file's own mtime */
ctime.tv_sec = inode.st_mtime;
#ifdef ST_MTIME_NSEC
ctime.tv_usec = inode.ST_MTIME_NSEC / 1000;
#endif
}
}

/* Save current time */
if (gettimeofday(&now, NULL) < 0) {
perror("gettimeofday()");
return -1;
}

#ifdef SIG_SETMASK
/* Block ALL signals */
if (sigfillset(&newsigmask) < 0) {
perror("sigfillset()");
return -1;
}
if (sigprocmask(SIG_SETMASK, &newsigmask, &oldsigmask) < 0) {
perror("sigprocmask()");
return -1;
}
#endif

/* ----- BEGIN CRITICAL SECTION ----- */

/* If there's no time, it will be the current time */
if (timerisset(&ctime)) {
/* Set system time to ctime */
if (settimeofday(&ctime, NULL) < 0) {
perror("settimeofday(ctime)");
status--;
goto end; /* Restore signal mask */
}
}

/* Touch inode */
while (chmod(file, inode.st_mode) < 0) {
if (errno != EINTR) {
perror("chmod()");
status--;
}
}

if (timerisset(&ctime)) {
/* Restore system time */
if (settimeofday(&now, NULL) < 0) {
perror("settimeofday(now)");
status--;
}
}

/* ----- END CRITICAL SECTION ----- */

end:

#ifdef SIG_SETMASK
/* Unblock signals */
if (sigprocmask(SIG_SETMASK, &oldsigmask, NULL) < 0) {
perror("sigprocmask()");
return -1;
}
#endif

return ((status != 0) ? -1 : 0);
}

static int nstrchr(const char *s, char c)
{
int n = 0;

if (!s) return 0;

while (*s)
if (*s++ == c) n++;

return n;
}

/* converts from "[[[YYYY:]MM:]DD:]hh:mm:ss[.uuuuuu]" to struct timeval */
static void str2timeval(const char *s, struct timeval *tvp)
{
#define DELIM ':'
#define DOT '.'
struct tm *tp;
struct tm tm;
time_t now;
int n;

if (s == NULL || tvp == NULL)
return;

now = time(NULL);
tp = localtime(&now);

memset(&tm, 0, sizeof(tm));
/* Default is current date & time */
memcpy(&tm, tp, sizeof(tm));

tvp->tv_sec = tvp->tv_usec = 0;

n = nstrchr(s, DELIM);

if (n > 4) {
tm.tm_year = atoi(s) - 1900;
s = strchr(s, DELIM) + 1;
}
if (n > 3) {
tm.tm_mon = atoi(s) - 1;
s = strchr(s, DELIM) + 1;
}
if (n > 2) {
tm.tm_mday = atoi(s);
s = strchr(s, DELIM) + 1;
}
if (n > 1) {
tm.tm_hour = atoi(s);
s = strchr(s, DELIM) + 1;
}
if (n > 0) {
tm.tm_min = atoi(s);
s = strchr(s, DELIM) + 1;
}
tm.tm_sec = atoi(s);

tvp->tv_sec = mktime(&tm);

if ((s = strchr(s, DOT)) != NULL)
if (*++s != '\0')
tvp->tv_usec = atol(s);

return;
}

static void exit_usage(int status)
{
FILE *fp;

if (status) fp = stderr;
else fp = stdout;

fprintf(fp, "touch2 by Ighighi\n");
fprintf(fp, "%s\n", usage);

exit(status);
}

int main(int argc, char *argv[])
{
struct timeval new_ctime = { 0, 0 };
char *rfile = NULL; /* Reference file */
struct stat inode;
int i;

for (i = 1; i < argc; i++) {
if (argv[i][0] == '-') {
switch (argv[i][1]) {
case 'a': /* use atime */
if (use_mtime || timerisset(&new_ctime)) {
fprintf(stderr, "%s: %s\n", argv[0], ERROR_MUTUALLY_EXCLUSIVE1);
exit_usage(1);
}
use_atime = 1;
break;
case 'm': /* use mtime */
if (use_atime || timerisset(&new_ctime)) {
fprintf(stderr, "%s: %s\n", argv[0], ERROR_MUTUALLY_EXCLUSIVE1);
exit_usage(1);
}
use_mtime = 1;
break;
case 'r': /* use rfile's ctime */
if (timerisset(&new_ctime)) {
fprintf(stderr, "%s: %s\n", argv[0], ERROR_MUTUALLY_EXCLUSIVE2);
exit_usage(1);
}
if ((rfile = argv[++i]) == NULL)
exit_usage(1);
break;
case 't': /* use timestamp */
if (use_atime || use_mtime) {
fprintf(stderr, "%s: %s\n", argv[0], ERROR_MUTUALLY_EXCLUSIVE1);
exit_usage(1);
}
if (rfile != NULL) {
fprintf(stderr, "%s: %s\n", argv[0], ERROR_MUTUALLY_EXCLUSIVE2);
exit_usage(1);
}
if (argv[++i] == NULL)
exit_usage(1);
str2timeval(argv[i], &new_ctime);
break;
case 'h': /* help */
exit_usage(0);
default:
exit_usage(1);
}
}
else {
break;
}
}

if (i >= argc) {
exit_usage(1);
}

if (rfile != NULL) {
while (stat(rfile, &inode) < 0) {
if (errno != EINTR) {
perror(rfile);
exit(1);
}
}

if (use_atime) {
new_ctime.tv_sec = inode.st_atime;
#ifdef ST_ATIME_NSEC
new_ctime.tv_usec = inode.ST_ATIME_NSEC / 1000;
#endif
}
else if (use_mtime) {
new_ctime.tv_sec = inode.st_mtime;
#ifdef ST_MTIME_NSEC
new_ctime.tv_usec = inode.ST_MTIME_NSEC / 1000;
#endif
}
else {
new_ctime.tv_sec = inode.st_ctime;
#ifdef ST_CTIME_NSEC
new_ctime.tv_usec = inode.ST_CTIME_NSEC / 1000;
#endif
}

}

for (; i < argc; i++) {
if (change_ctime(argv[i], new_ctime) < 0) {
fprintf(stderr, "%s: There was an error processing \"%s\"\n",
argv[0], argv[i]);
}
}

exit(0);
}

Login or Register to add favorites

File Archive:

April 2024

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Apr 1st
    10 Files
  • 2
    Apr 2nd
    26 Files
  • 3
    Apr 3rd
    40 Files
  • 4
    Apr 4th
    6 Files
  • 5
    Apr 5th
    26 Files
  • 6
    Apr 6th
    0 Files
  • 7
    Apr 7th
    0 Files
  • 8
    Apr 8th
    22 Files
  • 9
    Apr 9th
    14 Files
  • 10
    Apr 10th
    10 Files
  • 11
    Apr 11th
    13 Files
  • 12
    Apr 12th
    14 Files
  • 13
    Apr 13th
    0 Files
  • 14
    Apr 14th
    0 Files
  • 15
    Apr 15th
    30 Files
  • 16
    Apr 16th
    10 Files
  • 17
    Apr 17th
    22 Files
  • 18
    Apr 18th
    45 Files
  • 19
    Apr 19th
    8 Files
  • 20
    Apr 20th
    0 Files
  • 21
    Apr 21st
    0 Files
  • 22
    Apr 22nd
    11 Files
  • 23
    Apr 23rd
    68 Files
  • 24
    Apr 24th
    23 Files
  • 25
    Apr 25th
    16 Files
  • 26
    Apr 26th
    0 Files
  • 27
    Apr 27th
    0 Files
  • 28
    Apr 28th
    0 Files
  • 29
    Apr 29th
    0 Files
  • 30
    Apr 30th
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2022 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close