* lib/getloadavg.c: Use __VMS, not VMS.
[gnulib.git] / lib / backupfile.c
1 /* backupfile.c -- make Emacs style backup file names
2
3    Copyright (C) 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
4    1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software
5    Foundation, Inc.
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 2, or (at your option)
10    any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program; see the file COPYING.
19    If not, write to the Free Software Foundation,
20    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
21
22 /* Written by Paul Eggert and David MacKenzie.
23    Some algorithms adapted from GNU Emacs.  */
24
25 #ifdef HAVE_CONFIG_H
26 # include <config.h>
27 #endif
28
29 #include "backupfile.h"
30
31 #include "argmatch.h"
32 #include "dirname.h"
33 #include "xalloc.h"
34
35 #include <errno.h>
36 #include <stdbool.h>
37 #include <stdlib.h>
38 #include <string.h>
39
40 #include <limits.h>
41
42 #include <unistd.h>
43
44 #if HAVE_DIRENT_H
45 # include <dirent.h>
46 # define NLENGTH(direct) strlen ((direct)->d_name)
47 #else
48 # define dirent direct
49 # define NLENGTH(direct) ((size_t) (direct)->d_namlen)
50 # include <ndir.h>
51 #endif
52
53 #if D_INO_IN_DIRENT
54 # define REAL_DIR_ENTRY(dp) ((dp)->d_ino != 0)
55 #else
56 # define REAL_DIR_ENTRY(dp) 1
57 #endif
58
59 #if ! (HAVE_PATHCONF && defined _PC_NAME_MAX)
60 # define pathconf(file, option) (errno = -1)
61 #endif
62
63 #ifndef _POSIX_NAME_MAX
64 # define _POSIX_NAME_MAX 14
65 #endif
66 #ifndef SIZE_MAX
67 # define SIZE_MAX ((size_t) -1)
68 #endif
69
70 #if defined _XOPEN_NAME_MAX
71 # define NAME_MAX_MINIMUM _XOPEN_NAME_MAX
72 #else
73 # define NAME_MAX_MINIMUM _POSIX_NAME_MAX
74 #endif
75
76 #ifndef HAVE_DOS_FILE_NAMES
77 # define HAVE_DOS_FILE_NAMES 0
78 #endif
79 #ifndef HAVE_LONG_FILE_NAMES
80 # define HAVE_LONG_FILE_NAMES 0
81 #endif
82
83 /* ISDIGIT differs from isdigit, as follows:
84    - Its arg may be any int or unsigned int; it need not be an unsigned char
85      or EOF.
86    - It's typically faster.
87    POSIX says that only '0' through '9' are digits.  Prefer ISDIGIT to
88    ISDIGIT unless it's important to use the locale's definition
89    of `digit' even when the host does not conform to POSIX.  */
90 #define ISDIGIT(c) ((unsigned int) (c) - '0' <= 9)
91
92 /* The extension added to file names to produce a simple (as opposed
93    to numbered) backup file name. */
94 char const *simple_backup_suffix = "~";
95
96
97 /* If FILE (which was of length FILELEN before an extension was
98    appended to it) is too long, replace the extension with the single
99    char E.  If the result is still too long, remove the char just
100    before E.  */
101
102 static void
103 check_extension (char *file, size_t filelen, char e)
104 {
105   char *base = last_component (file);
106   size_t baselen = base_len (base);
107   size_t baselen_max = HAVE_LONG_FILE_NAMES ? 255 : NAME_MAX_MINIMUM;
108
109   if (HAVE_DOS_FILE_NAMES || NAME_MAX_MINIMUM < baselen)
110     {
111       /* The new base name is long enough to require a pathconf check.  */
112       long name_max;
113
114       /* Temporarily modify the buffer into its parent directory name,
115          invoke pathconf on the directory, and then restore the buffer.  */
116       char tmp[sizeof "."];
117       memcpy (tmp, base, sizeof ".");
118       strcpy (base, ".");
119       errno = 0;
120       name_max = pathconf (file, _PC_NAME_MAX);
121       if (0 <= name_max || errno == 0)
122         {
123           long size = baselen_max = name_max;
124           if (name_max != size)
125             baselen_max = SIZE_MAX;
126         }
127       memcpy (base, tmp, sizeof ".");
128     }
129
130   if (HAVE_DOS_FILE_NAMES && baselen_max <= 12)
131     {
132       /* Live within DOS's 8.3 limit.  */
133       char *dot = strchr (base, '.');
134       if (!dot)
135         baselen_max = 8;
136       else
137         {
138           char const *second_dot = strchr (dot + 1, '.');
139           baselen_max = (second_dot
140                          ? second_dot - base
141                          : dot + 1 - base + 3);
142         }
143     }
144
145   if (baselen_max < baselen)
146     {
147       baselen = file + filelen - base;
148       if (baselen_max <= baselen)
149         baselen = baselen_max - 1;
150       base[baselen] = e;
151       base[baselen + 1] = '\0';
152     }
153 }
154
155 /* Returned values for NUMBERED_BACKUP.  */
156
157 enum numbered_backup_result
158   {
159     /* The new backup name is the same length as an existing backup
160        name, so it's valid for that directory.  */
161     BACKUP_IS_SAME_LENGTH,
162
163     /* Some backup names already exist, but the returned name is longer
164        than any of them, and its length should be checked.  */
165     BACKUP_IS_LONGER,
166
167     /* There are no existing backup names.  The new name's length
168        should be checked.  */
169     BACKUP_IS_NEW
170   };
171
172 /* *BUFFER contains a file name.  Store into *BUFFER the next backup
173    name for the named file, with a version number greater than all the
174    existing numbered backups.  Reallocate *BUFFER as necessary; its
175    initial allocated size is BUFFER_SIZE, which must be at least 4
176    bytes longer than the file name to make room for the initially
177    appended ".~1".  FILELEN is the length of the original file name.
178    The returned value indicates what kind of backup was found.  If an
179    I/O or other read error occurs, use the highest backup number that
180    was found.  */
181
182 static enum numbered_backup_result
183 numbered_backup (char **buffer, size_t buffer_size, size_t filelen)
184 {
185   enum numbered_backup_result result = BACKUP_IS_NEW;
186   DIR *dirp;
187   struct dirent *dp;
188   char *buf = *buffer;
189   size_t versionlenmax = 1;
190   char *base = last_component (buf);
191   size_t base_offset = base - buf;
192   size_t baselen = base_len (base);
193
194   /* Temporarily modify the buffer into its parent directory name,
195      open the directory, and then restore the buffer.  */
196   char tmp[sizeof "."];
197   memcpy (tmp, base, sizeof ".");
198   strcpy (base, ".");
199   dirp = opendir (buf);
200   memcpy (base, tmp, sizeof ".");
201   strcpy (base + baselen, ".~1~");
202
203   if (!dirp)
204     return result;
205
206   while ((dp = readdir (dirp)) != NULL)
207     {
208       char const *p;
209       char *q;
210       bool all_9s;
211       size_t versionlen;
212       size_t new_buflen;
213
214       if (! REAL_DIR_ENTRY (dp) || NLENGTH (dp) < baselen + 4)
215         continue;
216
217       if (memcmp (buf + base_offset, dp->d_name, baselen + 2) != 0)
218         continue;
219
220       p = dp->d_name + baselen + 2;
221
222       /* Check whether this file has a version number and if so,
223          whether it is larger.  Use string operations rather than
224          integer arithmetic, to avoid problems with integer overflow.  */
225
226       if (! ('1' <= *p && *p <= '9'))
227         continue;
228       all_9s = (*p == '9');
229       for (versionlen = 1; ISDIGIT (p[versionlen]); versionlen++)
230         all_9s &= (p[versionlen] == '9');
231
232       if (! (p[versionlen] == '~' && !p[versionlen + 1]
233              && (versionlenmax < versionlen
234                  || (versionlenmax == versionlen
235                      && memcmp (buf + filelen + 2, p, versionlen) <= 0))))
236         continue;
237
238       /* This directory has the largest version number seen so far.
239          Append this highest numbered extension to the file name,
240          prepending '0' to the number if it is all 9s.  */
241
242       versionlenmax = all_9s + versionlen;
243       result = (all_9s ? BACKUP_IS_LONGER : BACKUP_IS_SAME_LENGTH);
244       new_buflen = filelen + 2 + versionlenmax + 1;
245       if (buffer_size <= new_buflen)
246         {
247           buf = xnrealloc (buf, 2, new_buflen);
248           buffer_size = new_buflen * 2;
249         }
250       q = buf + filelen;
251       *q++ = '.';
252       *q++ = '~';
253       *q = '0';
254       q += all_9s;
255       memcpy (q, p, versionlen + 2);
256
257       /* Add 1 to the version number.  */
258
259       q += versionlen;
260       while (*--q == '9')
261         *q = '0';
262       ++*q;
263     }
264
265   closedir (dirp);
266   *buffer = buf;
267   return result;
268 }
269
270 /* Return the name of the new backup file for the existing file FILE,
271    allocated with malloc.  Report an error and fail if out of memory.
272    Do not call this function if backup_type == no_backups.  */
273
274 char *
275 find_backup_file_name (char const *file, enum backup_type backup_type)
276 {
277   size_t filelen = strlen (file);
278   char *s;
279   size_t ssize;
280   bool simple = true;
281
282   /* Allow room for simple or ".~N~" backups.  The guess must be at
283      least sizeof ".~1~", but otherwise will be adjusted as needed.  */
284   size_t simple_backup_suffix_size = strlen (simple_backup_suffix) + 1;
285   size_t backup_suffix_size_guess = simple_backup_suffix_size;
286   enum { GUESS = sizeof ".~12345~" };
287   if (backup_suffix_size_guess < GUESS)
288     backup_suffix_size_guess = GUESS;
289
290   ssize = filelen + backup_suffix_size_guess + 1;
291   s = xmalloc (ssize);
292   memcpy (s, file, filelen + 1);
293
294   if (backup_type != simple_backups)
295     switch (numbered_backup (&s, ssize, filelen))
296       {
297       case BACKUP_IS_SAME_LENGTH:
298         return s;
299
300       case BACKUP_IS_LONGER:
301         simple = false;
302         break;
303
304       case BACKUP_IS_NEW:
305         simple = (backup_type == numbered_existing_backups);
306         break;
307       }
308
309   if (simple)
310     memcpy (s + filelen, simple_backup_suffix, simple_backup_suffix_size);
311   check_extension (s, filelen, '~');
312   return s;
313 }
314
315 static char const * const backup_args[] =
316 {
317   /* In a series of synonyms, present the most meaningful first, so
318      that argmatch_valid be more readable. */
319   "none", "off",
320   "simple", "never",
321   "existing", "nil",
322   "numbered", "t",
323   NULL
324 };
325
326 static const enum backup_type backup_types[] =
327 {
328   no_backups, no_backups,
329   simple_backups, simple_backups,
330   numbered_existing_backups, numbered_existing_backups,
331   numbered_backups, numbered_backups
332 };
333
334 /* Ensure that these two vectors have the same number of elements,
335    not counting the final NULL in the first one.  */
336 ARGMATCH_VERIFY (backup_args, backup_types);
337
338 /* Return the type of backup specified by VERSION.
339    If VERSION is NULL or the empty string, return numbered_existing_backups.
340    If VERSION is invalid or ambiguous, fail with a diagnostic appropriate
341    for the specified CONTEXT.  Unambiguous abbreviations are accepted.  */
342
343 enum backup_type
344 get_version (char const *context, char const *version)
345 {
346   if (version == 0 || *version == 0)
347     return numbered_existing_backups;
348   else
349     return XARGMATCH (context, version, backup_args, backup_types);
350 }
351
352
353 /* Return the type of backup specified by VERSION.
354    If VERSION is NULL, use the value of the envvar VERSION_CONTROL.
355    If the specified string is invalid or ambiguous, fail with a diagnostic
356    appropriate for the specified CONTEXT.
357    Unambiguous abbreviations are accepted.  */
358
359 enum backup_type
360 xget_version (char const *context, char const *version)
361 {
362   if (version && *version)
363     return get_version (context, version);
364   else
365     return get_version ("$VERSION_CONTROL", getenv ("VERSION_CONTROL"));
366 }