X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Fmisc.c;h=951449eb0c0b035246b02fc50f27d7a7c7e1a49f;hb=1428b7f1764ae29ca1e975a0762872569fccb8df;hp=7322dd2a0f56c89cde3db3d24c14c51bb4ad1a4a;hpb=3209329337c87a102fa12d7eb60a3df323ba56c1;p=chaz%2Ftar diff --git a/src/misc.c b/src/misc.c index 7322dd2..951449e 100644 --- a/src/misc.c +++ b/src/misc.c @@ -1,11 +1,11 @@ /* Miscellaneous functions, not really specific to GNU tar. Copyright (C) 1988, 1992, 1994, 1995, 1996, 1997, 1999, 2000, 2001, - 2003, 2004, 2005 Free Software Foundation, Inc. + 2003, 2004, 2005, 2006, 2007 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 the - Free Software Foundation; either version 2, or (at your option) any later + Free Software Foundation; either version 3, or (at your option) any later version. This program is distributed in the hope that it will be useful, but @@ -22,7 +22,16 @@ #include "common.h" #include #include +#include #include +#include + +#if HAVE_STROPTS_H +# include +#endif +#if HAVE_SYS_FILIO_H +# include +#endif /* Handling strings. */ @@ -404,7 +413,7 @@ remove_any_file (const char *file_name, enum remove_option option) so, we do not have to backup block or character devices, nor remote entities. */ bool -maybe_backup_file (const char *file_name, int this_is_the_archive) +maybe_backup_file (const char *file_name, bool this_is_the_archive) { struct stat file_stat; @@ -490,6 +499,26 @@ deref_stat (bool deref, char const *name, struct stat *buf) return deref ? stat (name, buf) : lstat (name, buf); } +/* Set FD's (i.e., FILE's) access time to TIMESPEC[0]. If that's not + possible to do by itself, set its access and data modification + times to TIMESPEC[0] and TIMESPEC[1], respectively. */ +int +set_file_atime (int fd, char const *file, struct timespec const timespec[2]) +{ +#ifdef _FIOSATIME + if (0 <= fd) + { + struct timeval timeval; + timeval.tv_sec = timespec[0].tv_sec; + timeval.tv_usec = timespec[0].tv_nsec / 1000; + if (ioctl (fd, _FIOSATIME, &timeval) == 0) + return 0; + } +#endif + + return gl_futimens (fd, file, timespec); +} + /* A description of a working directory. */ struct wd { @@ -514,8 +543,14 @@ chdir_arg (char const *dir) { if (wds == wd_alloc) { - wd_alloc = 2 * (wd_alloc + 1); - wd = xrealloc (wd, sizeof *wd * wd_alloc); + if (wd_alloc == 0) + { + wd_alloc = 2; + wd = xmalloc (sizeof *wd * wd_alloc); + } + else + wd = x2nrealloc (wd, &wd_alloc, sizeof *wd); + if (! wds) { wd[wds].name = "."; @@ -554,9 +589,30 @@ chdir_do (int i) if (! prev->saved) { + int err = 0; prev->saved = 1; if (save_cwd (&prev->saved_cwd) != 0) - FATAL_ERROR ((0, 0, _("Cannot save working directory"))); + err = errno; + else if (0 <= prev->saved_cwd.desc) + { + /* Make sure we still have at least one descriptor available. */ + int fd1 = prev->saved_cwd.desc; + int fd2 = dup (fd1); + if (0 <= fd2) + close (fd2); + else if (errno == EMFILE) + { + /* Force restore_cwd to use chdir_long. */ + close (fd1); + prev->saved_cwd.desc = -1; + prev->saved_cwd.name = xgetcwd (); + } + else + err = errno; + } + + if (err) + FATAL_ERROR ((0, err, _("Cannot save working directory"))); } if (curr->saved)