X-Git-Url: https://git.dogcows.com/gitweb?a=blobdiff_plain;f=src%2Fmisc.c;h=328591ca4b77beb26b216a86499f82687e353282;hb=8ad985ea6c89f2bb21d4655973ebdb542f7bb39a;hp=78844ffcc8f6ed5adca60b9f6cd9fb9a8bab8c74;hpb=aa976a517088ba75fa0168b47803b3988f89c9c3;p=chaz%2Ftar diff --git a/src/misc.c b/src/misc.c index 78844ff..328591c 100644 --- a/src/misc.c +++ b/src/misc.c @@ -18,10 +18,13 @@ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include +#include +#include #include #include "common.h" #include #include +#include #include #include @@ -412,7 +415,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; @@ -542,8 +545,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 = "."; @@ -568,13 +577,41 @@ chdir_arg (char const *dir) return wds++; } +/* Return maximum number of open files */ +int +get_max_open_files () +{ +#if defined _SC_OPEN_MAX + return sysconf (_SC_OPEN_MAX); +#elif defined RLIMIT_NOFILE + struct rlimit rlim; + + if (getrlimit(RLIMIT_NOFILE, &rlim) == 0) + return rlim.rlim_max; +#elif defined HAVE_GETDTABLESIZE + return getdtablesize (); +#endif + return -1; +} + +/* Close all descriptors, except the first three */ +void +closeopen () +{ + int i; + + for (i = get_max_open_files () - 1; i > 2; i--) + close (i); +} + /* Change to directory I. If I is 0, change to the initial working directory; otherwise, I must be a value returned by chdir_arg. */ void chdir_do (int i) { static int previous; - + static int saved_count; + if (previous != i) { struct wd *prev = &wd[previous]; @@ -583,7 +620,15 @@ chdir_do (int i) if (! prev->saved) { prev->saved = 1; - if (save_cwd (&prev->saved_cwd) != 0) + saved_count++; + /* Make sure we still have at least one descriptor available */ + if (saved_count >= get_max_open_files () - 4) + { + /* Force restore_cwd to use chdir_long */ + prev->saved_cwd.desc = -1; + prev->saved_cwd.name = xgetcwd (); + } + else if (save_cwd (&prev->saved_cwd) != 0) FATAL_ERROR ((0, 0, _("Cannot save working directory"))); }