1 /* backupfile.c -- make Emacs style backup file names
3 Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
4 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; see the file COPYING.
18 If not, write to the Free Software Foundation,
19 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
21 /* Written by Paul Eggert and David MacKenzie.
22 Some algorithms adapted from GNU Emacs. */
28 #include "backupfile.h"
45 # define NLENGTH(direct) strlen ((direct)->d_name)
47 # define dirent direct
48 # define NLENGTH(direct) ((size_t) (direct)->d_namlen)
50 # include <sys/ndir.h>
60 #if HAVE_DIRENT_H || HAVE_NDIR_H || HAVE_SYS_DIR_H || HAVE_SYS_NDIR_H
67 # define REAL_DIR_ENTRY(dp) ((dp)->d_ino != 0)
69 # define REAL_DIR_ENTRY(dp) 1
72 #if ! (HAVE_PATHCONF && defined _PC_NAME_MAX)
73 # define pathconf(file, option) (errno = -1)
76 #ifndef _POSIX_NAME_MAX
77 # define _POSIX_NAME_MAX 14
80 # define SIZE_MAX ((size_t) -1)
83 #if defined _XOPEN_NAME_MAX
84 # define NAME_MAX_MINIMUM _XOPEN_NAME_MAX
86 # define NAME_MAX_MINIMUM _POSIX_NAME_MAX
89 #ifndef HAVE_DOS_FILE_NAMES
90 # define HAVE_DOS_FILE_NAMES 0
92 #ifndef HAVE_LONG_FILE_NAMES
93 # define HAVE_LONG_FILE_NAMES 0
96 /* ISDIGIT differs from isdigit, as follows:
97 - Its arg may be any int or unsigned int; it need not be an unsigned char.
98 - It's guaranteed to evaluate its argument exactly once.
99 - It's typically faster.
100 POSIX says that only '0' through '9' are digits. Prefer ISDIGIT to
101 ISDIGIT_LOCALE unless it's important to use the locale's definition
102 of `digit' even when the host does not conform to POSIX. */
103 #define ISDIGIT(c) ((unsigned int) (c) - '0' <= 9)
105 /* The extension added to file names to produce a simple (as opposed
106 to numbered) backup file name. */
107 char const *simple_backup_suffix = "~";
110 /* If FILE (which was of length FILELEN before an extension was
111 appended to it) is too long, replace the extension with the single
112 char E. If the result is still too long, remove the char just
116 check_extension (char *file, size_t filelen, char e)
118 char *base = base_name (file);
119 size_t baselen = base_len (base);
120 size_t baselen_max = HAVE_LONG_FILE_NAMES ? 255 : NAME_MAX_MINIMUM;
122 if (HAVE_DOS_FILE_NAMES || NAME_MAX_MINIMUM < baselen)
124 /* The new base name is long enough to require a pathconf check. */
127 /* Temporarily modify the buffer into its parent directory name,
128 invoke pathconf on the directory, and then restore the buffer. */
129 char tmp[sizeof "."];
130 memcpy (tmp, base, sizeof ".");
133 name_max = pathconf (file, _PC_NAME_MAX);
134 if (0 <= name_max || errno == 0)
136 long size = baselen_max = name_max;
137 if (name_max != size)
138 baselen_max = SIZE_MAX;
140 memcpy (base, tmp, sizeof ".");
143 if (HAVE_DOS_FILE_NAMES && baselen_max <= 12)
145 /* Live within DOS's 8.3 limit. */
146 char *dot = strchr (base, '.');
151 char const *second_dot = strchr (dot + 1, '.');
152 baselen_max = (second_dot
154 : dot + 1 - base + 3);
158 if (baselen_max < baselen)
160 baselen = file + filelen - base;
161 if (baselen_max <= baselen)
162 baselen = baselen_max - 1;
164 base[baselen + 1] = '\0';
170 /* Returned values for NUMBERED_BACKUP. */
172 enum numbered_backup_result
174 /* The new backup name is the same length as an existing backup
175 name, so it's valid for that directory. */
176 BACKUP_IS_SAME_LENGTH,
178 /* Some backup names already exist, but the returned name is longer
179 than any of them, and its length should be checked. */
182 /* There are no existing backup names. The new name's length
183 should be checked. */
187 /* *BUFFER contains a file name. Store into *BUFFER the next backup
188 name for the named file, with a version number greater than all the
189 existing numbered backups. Reallocate *BUFFER as necessary; its
190 initial allocated size is BUFFER_SIZE, which must be at least 4
191 bytes longer than the file name to make room for the initially
192 appended ".~1". FILELEN is the length of the original file name.
193 The returned value indicates what kind of backup was found. If an
194 I/O or other read error occurs, use the highest backup number that
197 static enum numbered_backup_result
198 numbered_backup (char **buffer, size_t buffer_size, size_t filelen)
200 enum numbered_backup_result result = BACKUP_IS_NEW;
204 size_t versionlenmax = 1;
205 char *base = base_name (buf);
206 size_t base_offset = base - buf;
207 size_t baselen = base_len (base);
209 /* Temporarily modify the buffer into its parent directory name,
210 open the directory, and then restore the buffer. */
211 char tmp[sizeof "."];
212 memcpy (tmp, base, sizeof ".");
214 dirp = opendir (buf);
215 memcpy (base, tmp, sizeof ".");
216 strcpy (base + baselen, ".~1~");
221 while ((dp = readdir (dirp)) != NULL)
229 if (! REAL_DIR_ENTRY (dp) || NLENGTH (dp) < baselen + 4)
232 if (memcmp (buf + base_offset, dp->d_name, baselen + 2) != 0)
235 p = dp->d_name + baselen + 2;
237 /* Check whether this file has a version number and if so,
238 whether it is larger. Use string operations rather than
239 integer arithmetic, to avoid problems with integer overflow. */
241 if (! ('1' <= *p && *p <= '9'))
243 all_9s = (*p == '9');
244 for (versionlen = 1; ISDIGIT (p[versionlen]); versionlen++)
245 all_9s &= (p[versionlen] == '9');
247 if (! (p[versionlen] == '~' && !p[versionlen + 1]
248 && (versionlenmax < versionlen
249 || (versionlenmax == versionlen
250 && memcmp (buf + filelen + 2, p, versionlen) <= 0))))
253 /* This directory has the largest version number seen so far.
254 Append this highest numbered extension to the file name,
255 prepending '0' to the number if it is all 9s. */
257 versionlenmax = all_9s + versionlen;
258 result = (all_9s ? BACKUP_IS_LONGER : BACKUP_IS_SAME_LENGTH);
259 new_buflen = filelen + 2 + versionlenmax + 1;
260 if (buffer_size <= new_buflen)
262 buf = xnrealloc (buf, 2, new_buflen);
263 buffer_size = new_buflen * 2;
270 memcpy (q, p, versionlen + 2);
272 /* Add 1 to the version number. */
284 #endif /* HAVE_DIR */
286 /* Return the name of the new backup file for the existing file FILE,
287 allocated with malloc. Report an error and fail if out of memory.
288 Do not call this function if backup_type == no_backups. */
291 find_backup_file_name (char const *file, enum backup_type backup_type)
293 size_t filelen = strlen (file);
298 /* Allow room for simple or ".~N~" backups. The guess must be at
299 least sizeof ".~1~", but otherwise will be adjusted as needed. */
300 size_t simple_backup_suffix_size = strlen (simple_backup_suffix) + 1;
301 size_t backup_suffix_size_guess = simple_backup_suffix_size;
302 enum { GUESS = sizeof ".~12345~" };
303 if (HAVE_DIR && backup_suffix_size_guess < GUESS)
304 backup_suffix_size_guess = GUESS;
306 ssize = filelen + backup_suffix_size_guess + 1;
308 memcpy (s, file, filelen + 1);
311 if (backup_type != simple_backups)
312 switch (numbered_backup (&s, ssize, filelen))
314 case BACKUP_IS_SAME_LENGTH:
317 case BACKUP_IS_LONGER:
322 simple = (backup_type == numbered_existing_backups);
328 memcpy (s + filelen, simple_backup_suffix, simple_backup_suffix_size);
329 check_extension (s, filelen, '~');
333 static char const * const backup_args[] =
335 /* In a series of synonyms, present the most meaningful first, so
336 that argmatch_valid be more readable. */
344 static const enum backup_type backup_types[] =
346 no_backups, no_backups,
347 simple_backups, simple_backups,
348 numbered_existing_backups, numbered_existing_backups,
349 numbered_backups, numbered_backups
352 /* Ensure that these two vectors have the same number of elements,
353 not counting the final NULL in the first one. */
354 ARGMATCH_VERIFY (backup_args, backup_types);
356 /* Return the type of backup specified by VERSION.
357 If VERSION is NULL or the empty string, return numbered_existing_backups.
358 If VERSION is invalid or ambiguous, fail with a diagnostic appropriate
359 for the specified CONTEXT. Unambiguous abbreviations are accepted. */
362 get_version (char const *context, char const *version)
364 if (version == 0 || *version == 0)
365 return numbered_existing_backups;
367 return XARGMATCH (context, version, backup_args, backup_types);
371 /* Return the type of backup specified by VERSION.
372 If VERSION is NULL, use the value of the envvar VERSION_CONTROL.
373 If the specified string is invalid or ambiguous, fail with a diagnostic
374 appropriate for the specified CONTEXT.
375 Unambiguous abbreviations are accepted. */
378 xget_version (char const *context, char const *version)
380 if (version && *version)
381 return get_version (context, version);
383 return get_version ("$VERSION_CONTROL", getenv ("VERSION_CONTROL"));