From 4b1afddab3d7015a71d4358aa4c05b102ecddac5 Mon Sep 17 00:00:00 2001 From: hniksic Date: Tue, 16 Sep 2003 14:47:49 -0700 Subject: [PATCH] [svn] Allow unique_name to return the FILE argument unmodified. Streamline and optimize unique_name_1. --- src/ChangeLog | 7 +++++ src/log.c | 2 +- src/mswindows.c | 2 +- src/url.c | 10 +++---- src/utils.c | 70 ++++++++++++++++++++++++++++++------------------- src/utils.h | 2 +- 6 files changed, 58 insertions(+), 35 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index 6ec4e7c3..b31cdc75 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,10 @@ +2003-09-16 Hrvoje Niksic + + * url.c (url_file_name): Don't reallocate FNAME if the file + doesn't exist, as is usually the case. + + * utils.c (unique_name): New flag allow_passthrough. + 2003-09-16 Hrvoje Niksic * utils.c (wtimer_sys_diff): Convert the time difference to signed diff --git a/src/log.c b/src/log.c index 0ac45b76..1f829e49 100644 --- a/src/log.c +++ b/src/log.c @@ -660,7 +660,7 @@ static const char *redirect_request_signal_name; static void redirect_output (void) { - char *logfile = unique_name (DEFAULT_LOGFILE); + char *logfile = unique_name (DEFAULT_LOGFILE, 0); fprintf (stderr, _("\n%s received, redirecting output to `%s'.\n"), redirect_request_signal_name, logfile); logfp = fopen (logfile, "w"); diff --git a/src/mswindows.c b/src/mswindows.c index 95a0099f..53219812 100644 --- a/src/mswindows.c +++ b/src/mswindows.c @@ -136,7 +136,7 @@ fork_to_background (void) if (!opt.lfilename) { - opt.lfilename = unique_name (DEFAULT_LOGFILE); + opt.lfilename = unique_name (DEFAULT_LOGFILE, 0); changedp = 1; } printf (_("Continuing in background.\n")); diff --git a/src/url.c b/src/url.c index 9776cc3e..57cec64c 100644 --- a/src/url.c +++ b/src/url.c @@ -1694,15 +1694,15 @@ url_file_name (const struct url *u) 4) Hierarchy is built. The exception is the case when file does exist and is a - directory (actually support for bad httpd-s). */ + directory (see `mkalldirs' for explanation). */ if ((opt.noclobber || opt.always_rest || opt.timestamping || opt.dirstruct) && !(file_exists_p (fname) && !file_non_directory_p (fname))) - return fnres.base; + return fname; - /* Find a unique name. */ - unique = unique_name (fname); - xfree (fname); + unique = unique_name (fname, 1); + if (unique != fname) + xfree (fname); return unique; } diff --git a/src/utils.c b/src/utils.c index 0f443411..481e5b78 100644 --- a/src/utils.c +++ b/src/utils.c @@ -470,7 +470,7 @@ fork_to_background (void) if (!opt.lfilename) { - opt.lfilename = unique_name (DEFAULT_LOGFILE); + opt.lfilename = unique_name (DEFAULT_LOGFILE, 0); changedp = 1; } pid = fork (); @@ -580,39 +580,55 @@ file_size (const char *filename) return size; } -/* Return a unique filename, given a prefix and count */ +/* stat file names named PREFIX.1, PREFIX.2, etc., until one that + doesn't exist is found. Return a freshly allocated copy of the + unused file name. */ + static char * -unique_name_1 (const char *fileprefix, int count) +unique_name_1 (const char *prefix) { - char *filename; + int count = 1; + int plen = strlen (prefix); + char *template = (char *)alloca (plen + 1 + 24); + char *template_tail = template + plen; - if (count) - { - filename = (char *)xmalloc (strlen (fileprefix) + numdigit (count) + 2); - sprintf (filename, "%s.%d", fileprefix, count); - } - else - filename = xstrdup (fileprefix); + memcpy (template, prefix, plen); + *template_tail++ = '.'; - if (!file_exists_p (filename)) - return filename; - else - { - xfree (filename); - return NULL; - } + do + number_to_string (template_tail, count++); + while (file_exists_p (template)); + + return xstrdup (template); } -/* Return a unique file name, based on PREFIX. */ -char * -unique_name (const char *prefix) -{ - char *file = NULL; - int count = 0; +/* Return a unique file name, based on FILE. - while (!file) - file = unique_name_1 (prefix, count++); - return file; + More precisely, if FILE doesn't exist, it is returned unmodified. + If not, FILE.1 is tried, then FILE.2, etc. The first FILE. + file name that doesn't exist is returned. + + The resulting file is not created, only verified that it didn't + exist at the point in time when the function was called. + Therefore, where security matters, don't rely that the file created + by this function exists until you open it with O_EXCL or + something. + + If ALLOW_PASSTHROUGH is 0, it always returns a freshly allocated + string. Otherwise, it may return FILE if the file doesn't exist + (and therefore doesn't need changing). */ + +char * +unique_name (const char *file, int allow_passthrough) +{ + /* If the FILE itself doesn't exist, return it without + modification. */ + if (!file_exists_p (file)) + return allow_passthrough ? (char *)file : xstrdup (file); + + /* Otherwise, find a numeric suffix that results in unused file name + and return it. */ + return unique_name_1 (file); } /* Create DIRECTORY. If some of the pathname components of DIRECTORY diff --git a/src/utils.h b/src/utils.h index 3ae279cf..18752a5f 100644 --- a/src/utils.h +++ b/src/utils.h @@ -73,7 +73,7 @@ int file_exists_p PARAMS ((const char *)); int file_non_directory_p PARAMS ((const char *)); long file_size PARAMS ((const char *)); int make_directory PARAMS ((const char *)); -char *unique_name PARAMS ((const char *)); +char *unique_name PARAMS ((const char *, int)); char *file_merge PARAMS ((const char *, const char *)); int acceptable PARAMS ((const char *));