[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
touch --inside: new option for gzipped files
From: |
Bruno Haible |
Subject: |
touch --inside: new option for gzipped files |
Date: |
Tue, 27 May 2003 13:32:05 +0200 (CEST) |
Hi,
For many files downloaded from the internet - among them many .gz files -,
the download time is less significant than the creation time of the file.
So it's quite handy to have a program that gives back to a file the
original modification time. It seems to me that "touch" is the right
program for this, because a user will look there for the functionality.
Here is a patch implementing this. Relative to coreutils-5.0.
2003-05-25 Bruno Haible <address@hidden>
* src/touch.c (look_inside): New variable.
(longopts): Add --inside.
(time_from_inside): New function.
(touch): Handle look_inside case.
(usage): Document option -i.
(main): Recognize option -i.
* doc/coreutils.texi (touch invocation): Document option -i.
diff -r -c3 coreutils-5.0/doc/coreutils.texi
coreutils-5.0-touch/doc/coreutils.texi
*** coreutils-5.0/doc/coreutils.texi 2003-04-02 20:19:11.000000000 +0200
--- coreutils-5.0-touch/doc/coreutils.texi 2003-05-25 20:56:00.000000000
+0200
***************
*** 7836,7841 ****
--- 7836,7850 ----
@cindex BSD @command{touch} compatibility
Ignored; for compatibility with BSD versions of @command{touch}.
+ @item -i
+ @itemx --inside
+ @opindex -i
+ @opindex --inside
+ Use the time found inside the file instead of the current time. This
+ works for files in GZIP format; support for other file formats may be
+ added at a later date. If the file is not of one of the supported formats
+ or doesn't have a timestamp inside it, it is not touched.
+
@item -m
@itemx --time=mtime
@itemx --time=modify
diff -r -c3 coreutils-5.0/src/touch.c coreutils-5.0-touch/src/touch.c
*** coreutils-5.0/src/touch.c 2002-12-20 21:09:22.000000000 +0100
--- coreutils-5.0-touch/src/touch.c 2003-05-25 21:39:54.000000000 +0200
***************
*** 1,5 ****
/* touch -- change modification and access times of files
! Copyright (C) 87, 1989-1991, 1995-2002 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
--- 1,5 ----
/* touch -- change modification and access times of files
! Copyright (C) 87, 1989-1991, 1995-2003 Free Software Foundation, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
***************
*** 30,36 ****
#include "posixtm.h"
#include "posixver.h"
#include "quote.h"
! #include "safe-read.h"
/* The official name of this program (e.g., no `g' prefix). */
#define PROGRAM_NAME "touch"
--- 30,36 ----
#include "posixtm.h"
#include "posixver.h"
#include "quote.h"
! #include "full-read.h"
/* The official name of this program (e.g., no `g' prefix). */
#define PROGRAM_NAME "touch"
***************
*** 74,79 ****
--- 74,82 ----
/* (-d) If nonzero, date supplied on command line in get_date formats. */
static int flexible_date;
+ /* (-i) If nonzero, look for a time stamp inside the file. */
+ static int look_inside;
+
/* (-r) If nonzero, use times from a reference file. */
static int use_ref;
***************
*** 108,113 ****
--- 111,117 ----
{"time", required_argument, 0, TIME_OPTION},
{"no-create", no_argument, 0, 'c'},
{"date", required_argument, 0, 'd'},
+ {"inside", no_argument, 0, 'i'},
{"file", required_argument, 0, 'r'}, /* FIXME: phase out --file */
{"reference", required_argument, 0, 'r'},
{GETOPT_HELP_OPTION_DECL},
***************
*** 127,132 ****
--- 131,182 ----
CH_ATIME, CH_ATIME, CH_ATIME, CH_MTIME, CH_MTIME
};
+ /* Attempts to retrieve a timestamp from inside the file.
+ Returns 0 and sets *found if successful, otherwise returns 1. */
+
+ static int
+ time_from_inside (const char *file, time_t *found)
+ {
+ int fd = open (file, O_RDONLY,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
+
+ if (fd < 0)
+ return 1;
+
+ /* First supported file format: GZIP. */
+ {
+ unsigned char buf[8];
+
+ /* Not needed since this is the first access right after open(). */
+ /* lseek (fd, 0, SEEK_SET); */
+
+ /* Read the first 8 bytes of the file. */
+ if (full_read (fd, buf, 8) == 8
+ /* Test for the gzip magic. */
+ && buf[0] == 0x1f && buf[1] == 0x8b)
+ {
+ unsigned long time =
+ ((((((unsigned long) buf[7] << 8)
+ | (unsigned long) buf[6]) << 8)
+ | (unsigned long) buf[5]) << 8)
+ | (unsigned long) buf[4];
+
+ if (time)
+ {
+ *found = time;
+ close (fd);
+ return 0;
+ }
+ }
+ }
+
+ /* Other file formats can be added here. */
+
+ /* After trying all supported file formats, this function fails. */
+ close (fd);
+ return 1;
+ }
+
/* Update the time of file FILE according to the options given.
Return 0 if successful, 1 if an error occurs. */
***************
*** 194,200 ****
better than 1-second resolution, so discard any fractional
part of the source timestamp. */
! if (use_ref)
{
utb.actime = ref_stats.st_atime;
utb.modtime = ref_stats.st_mtime;
--- 245,274 ----
better than 1-second resolution, so discard any fractional
part of the source timestamp. */
! if (look_inside)
! {
! time_t found;
!
! if (time_from_inside (file, &found) == 0)
! utb.actime = utb.modtime = found;
! else
! {
! /* Looking into the file has modified its access time.
! If here we "return 0;" the st_atime remains modified,
! but the st_ctime is unchanged. Whereas if we set
! "utb.actime = sbuf.st_atime; utb.modtime = sbuf.st_mtime;"
! the st_atime will be unchanged, but the st_ctime is
! changed. The latter is more in line with touch's general
! behaviour. */
! utb.actime = sbuf.st_atime;
! utb.modtime = sbuf.st_mtime;
! utime (file, &utb);
! /* Ignore the return value from utime() here, since it didn't
! attempt to set a date given by the user. */
! return 0;
! }
! }
! else if (use_ref)
{
utb.actime = ref_stats.st_atime;
utb.modtime = ref_stats.st_mtime;
***************
*** 254,259 ****
--- 328,334 ----
-c, --no-create do not create any files\n\
-d, --date=STRING parse STRING and use it instead of current time\n\
-f (ignored)\n\
+ -i, --inside use timestamp inside the file instead of current
time\n\
-m change only the modification time\n\
"), stdout);
fputs (_("\
***************
*** 289,295 ****
change_times = no_create = use_ref = posix_date = flexible_date = 0;
! while ((c = getopt_long (argc, argv, "acd:fmr:t:", longopts, NULL)) != -1)
{
switch (c)
{
--- 364,370 ----
change_times = no_create = use_ref = posix_date = flexible_date = 0;
! while ((c = getopt_long (argc, argv, "acd:fimr:t:", longopts, NULL)) != -1)
{
switch (c)
{
***************
*** 315,320 ****
--- 390,400 ----
case 'f':
break;
+ case 'i':
+ look_inside = 1;
+ date_set++;
+ break;
+
case 'm':
change_times |= CH_MTIME;
break;
***************
*** 349,356 ****
if (change_times == 0)
change_times = CH_ATIME | CH_MTIME;
! if ((use_ref && (posix_date || flexible_date))
! || (posix_date && flexible_date))
{
error (0, 0, _("cannot specify times from more than one source"));
usage (EXIT_FAILURE);
--- 429,437 ----
if (change_times == 0)
change_times = CH_ATIME | CH_MTIME;
! if ((use_ref ? 1 : 0) + (posix_date ? 1 : 0) + (flexible_date ? 1 : 0)
! + (look_inside ? 1 : 0)
! > 1)
{
error (0, 0, _("cannot specify times from more than one source"));
usage (EXIT_FAILURE);
- touch --inside: new option for gzipped files,
Bruno Haible <=