X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Fbackupfile.c;h=2ad030f8dc5a9d2abed1ddd93dba56fa0732ac5f;hb=1276a2c5f24c0c932426aca9c899fa524d2443f2;hp=f48a1cde87ea22e440dadc43908ca4917c3a7c12;hpb=ad7c04fbfab45526a255d4e778de3cac58855874;p=gnulib.git diff --git a/lib/backupfile.c b/lib/backupfile.c index f48a1cde8..2ad030f8d 100644 --- a/lib/backupfile.c +++ b/lib/backupfile.c @@ -1,12 +1,11 @@ /* backupfile.c -- make Emacs style backup file names - Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + Copyright (C) 1990-2006, 2009-2014 Free Software Foundation, Inc. - This program is free software; you can redistribute it and/or modify + 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 version. + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -14,16 +13,12 @@ GNU General Public License for more details. You should have received a copy of the GNU General Public License - along with this program; see the file COPYING. - If not, write to the Free Software Foundation, - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + along with this program. If not, see . */ /* Written by Paul Eggert and David MacKenzie. Some algorithms adapted from GNU Emacs. */ -#if HAVE_CONFIG_H -# include -#endif +#include #include "backupfile.h" @@ -38,33 +33,12 @@ #include -#if HAVE_UNISTD_H -# include -#endif - -#if HAVE_DIRENT_H -# include -# define NLENGTH(direct) strlen ((direct)->d_name) -#else -# define dirent direct -# define NLENGTH(direct) ((size_t) (direct)->d_namlen) -# if HAVE_SYS_NDIR_H -# include -# endif -# if HAVE_SYS_DIR_H -# include -# endif -# if HAVE_NDIR_H -# include -# endif -#endif +#include -#if HAVE_DIRENT_H || HAVE_NDIR_H || HAVE_SYS_DIR_H || HAVE_SYS_NDIR_H -# define HAVE_DIR 1 -#else -# define HAVE_DIR 0 +#include "dirent--.h" +#ifndef _D_EXACT_NAMLEN +# define _D_EXACT_NAMLEN(dp) strlen ((dp)->d_name) #endif - #if D_INO_IN_DIRENT # define REAL_DIR_ENTRY(dp) ((dp)->d_ino != 0) #else @@ -96,12 +70,12 @@ #endif /* ISDIGIT differs from isdigit, as follows: - - Its arg may be any int or unsigned int; it need not be an unsigned char. - - It's guaranteed to evaluate its argument exactly once. + - Its arg may be any int or unsigned int; it need not be an unsigned char + or EOF. - It's typically faster. POSIX says that only '0' through '9' are digits. Prefer ISDIGIT to - ISDIGIT_LOCALE unless it's important to use the locale's definition - of `digit' even when the host does not conform to POSIX. */ + ISDIGIT unless it's important to use the locale's definition + of "digit" even when the host does not conform to POSIX. */ #define ISDIGIT(c) ((unsigned int) (c) - '0' <= 9) /* The extension added to file names to produce a simple (as opposed @@ -117,7 +91,7 @@ char const *simple_backup_suffix = "~"; static void check_extension (char *file, size_t filelen, char e) { - char *base = base_name (file); + char *base = last_component (file); size_t baselen = base_len (base); size_t baselen_max = HAVE_LONG_FILE_NAMES ? 255 : NAME_MAX_MINIMUM; @@ -127,18 +101,18 @@ check_extension (char *file, size_t filelen, char e) long name_max; /* Temporarily modify the buffer into its parent directory name, - invoke pathconf on the directory, and then restore the buffer. */ + invoke pathconf on the directory, and then restore the buffer. */ char tmp[sizeof "."]; memcpy (tmp, base, sizeof "."); strcpy (base, "."); errno = 0; name_max = pathconf (file, _PC_NAME_MAX); if (0 <= name_max || errno == 0) - { - long size = baselen_max = name_max; - if (name_max != size) - baselen_max = SIZE_MAX; - } + { + long size = baselen_max = name_max; + if (name_max != size) + baselen_max = SIZE_MAX; + } memcpy (base, tmp, sizeof "."); } @@ -147,28 +121,26 @@ check_extension (char *file, size_t filelen, char e) /* Live within DOS's 8.3 limit. */ char *dot = strchr (base, '.'); if (!dot) - baselen_max = 8; + baselen_max = 8; else - { - char const *second_dot = strchr (dot + 1, '.'); - baselen_max = (second_dot - ? second_dot - base - : dot + 1 - base + 3); - } + { + char const *second_dot = strchr (dot + 1, '.'); + baselen_max = (second_dot + ? second_dot - base + : dot + 1 - base + 3); + } } if (baselen_max < baselen) { baselen = file + filelen - base; if (baselen_max <= baselen) - baselen = baselen_max - 1; + baselen = baselen_max - 1; base[baselen] = e; base[baselen + 1] = '\0'; } } -#if HAVE_DIR - /* Returned values for NUMBERED_BACKUP. */ enum numbered_backup_result @@ -204,7 +176,7 @@ numbered_backup (char **buffer, size_t buffer_size, size_t filelen) struct dirent *dp; char *buf = *buffer; size_t versionlenmax = 1; - char *base = base_name (buf); + char *base = last_component (buf); size_t base_offset = base - buf; size_t baselen = base_len (base); @@ -228,42 +200,42 @@ numbered_backup (char **buffer, size_t buffer_size, size_t filelen) size_t versionlen; size_t new_buflen; - if (! REAL_DIR_ENTRY (dp) || NLENGTH (dp) < baselen + 4) - continue; + if (! REAL_DIR_ENTRY (dp) || _D_EXACT_NAMLEN (dp) < baselen + 4) + continue; if (memcmp (buf + base_offset, dp->d_name, baselen + 2) != 0) - continue; + continue; p = dp->d_name + baselen + 2; /* Check whether this file has a version number and if so, - whether it is larger. Use string operations rather than - integer arithmetic, to avoid problems with integer overflow. */ + whether it is larger. Use string operations rather than + integer arithmetic, to avoid problems with integer overflow. */ if (! ('1' <= *p && *p <= '9')) - continue; + continue; all_9s = (*p == '9'); for (versionlen = 1; ISDIGIT (p[versionlen]); versionlen++) - all_9s &= (p[versionlen] == '9'); + all_9s &= (p[versionlen] == '9'); if (! (p[versionlen] == '~' && !p[versionlen + 1] - && (versionlenmax < versionlen - || (versionlenmax == versionlen - && memcmp (buf + filelen + 2, p, versionlen) <= 0)))) - continue; + && (versionlenmax < versionlen + || (versionlenmax == versionlen + && memcmp (buf + filelen + 2, p, versionlen) <= 0)))) + continue; /* This directory has the largest version number seen so far. - Append this highest numbered extension to the file name, - prepending '0' to the number if it is all 9s. */ + Append this highest numbered extension to the file name, + prepending '0' to the number if it is all 9s. */ versionlenmax = all_9s + versionlen; result = (all_9s ? BACKUP_IS_LONGER : BACKUP_IS_SAME_LENGTH); new_buflen = filelen + 2 + versionlenmax + 1; if (buffer_size <= new_buflen) - { - buf = xnrealloc (buf, 2, new_buflen); - buffer_size = new_buflen * 2; - } + { + buf = xnrealloc (buf, 2, new_buflen); + buffer_size = new_buflen * 2; + } q = buf + filelen; *q++ = '.'; *q++ = '~'; @@ -275,7 +247,7 @@ numbered_backup (char **buffer, size_t buffer_size, size_t filelen) q += versionlen; while (*--q == '9') - *q = '0'; + *q = '0'; ++*q; } @@ -283,7 +255,6 @@ numbered_backup (char **buffer, size_t buffer_size, size_t filelen) *buffer = buf; return result; } -#endif /* HAVE_DIR */ /* Return the name of the new backup file for the existing file FILE, allocated with malloc. Report an error and fail if out of memory. @@ -302,29 +273,27 @@ find_backup_file_name (char const *file, enum backup_type backup_type) size_t simple_backup_suffix_size = strlen (simple_backup_suffix) + 1; size_t backup_suffix_size_guess = simple_backup_suffix_size; enum { GUESS = sizeof ".~12345~" }; - if (HAVE_DIR && backup_suffix_size_guess < GUESS) + if (backup_suffix_size_guess < GUESS) backup_suffix_size_guess = GUESS; ssize = filelen + backup_suffix_size_guess + 1; s = xmalloc (ssize); memcpy (s, file, filelen + 1); -#if HAVE_DIR if (backup_type != simple_backups) switch (numbered_backup (&s, ssize, filelen)) { case BACKUP_IS_SAME_LENGTH: - return s; + return s; case BACKUP_IS_LONGER: - simple = false; - break; + simple = false; + break; case BACKUP_IS_NEW: - simple = (backup_type == numbered_existing_backups); - break; + simple = (backup_type == numbered_existing_backups); + break; } -#endif if (simple) memcpy (s + filelen, simple_backup_suffix, simple_backup_suffix_size); @@ -334,7 +303,7 @@ find_backup_file_name (char const *file, enum backup_type backup_type) static char const * const backup_args[] = { - /* In a series of synonyms, present the most meaning full first, so + /* In a series of synonyms, present the most meaningful first, so that argmatch_valid be more readable. */ "none", "off", "simple", "never", @@ -351,6 +320,10 @@ static const enum backup_type backup_types[] = numbered_backups, numbered_backups }; +/* Ensure that these two vectors have the same number of elements, + not counting the final NULL in the first one. */ +ARGMATCH_VERIFY (backup_args, backup_types); + /* Return the type of backup specified by VERSION. If VERSION is NULL or the empty string, return numbered_existing_backups. If VERSION is invalid or ambiguous, fail with a diagnostic appropriate