~ubuntu-branches/ubuntu/hoary/indent/hoary

« back to all changes in this revision

Viewing changes to src/backup.c

  • Committer: Bazaar Package Importer
  • Author(s): Santiago Vila
  • Date: 2002-01-27 18:47:28 UTC
  • Revision ID: james.westby@ubuntu.com-20020127184728-5w6lnpj072bqil91
Tags: upstream-2.2.7
ImportĀ upstreamĀ versionĀ 2.2.7

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (c) 1993,1994, Joseph Arceneaux.  All rights reserved.
 
2
 *
 
3
 * This file is subject to the terms of the GNU General Public License as
 
4
 * published by the Free Software Foundation.  A copy of this license is
 
5
 * included with this software distribution in the file COPYING.  If you
 
6
 * do not have a copy, you may obtain a copy by writing to the Free
 
7
 * Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
 
8
 *
 
9
 * This software is distributed in the hope that it will be useful,
 
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
 * GNU General Public License for more details. */
 
13
 
 
14
/* GNU/Emacs style backups --
 
15
 * This behaviour is controlled by two environment variables,
 
16
 * VERSION_CONTROL and SIMPLE_BACKUP_SUFFIX.
 
17
 *
 
18
 * VERSION_CONTROL determines what kinds of backups are made.  If it's
 
19
 * value is "numbered", then the first modification of some file
 
20
 * "eraserhead.c" will yield a backup file "eraserhead.c.~1~", the
 
21
 * second modification will yield "eraserhead.c.~2~", and so on.  It
 
22
 * does not matter if the version numbers are not a sequence;  the next
 
23
 * version will be one greater than the highest in that directory.
 
24
 *
 
25
 * If the value of VERSION_CONTROL is "numbered_existing", then such
 
26
 * numbered backups will be made if there are already numbered backup
 
27
 * versions of the file.  Otherwise, the backup name will be that of
 
28
 * the original file with "~" (tilde) appended.  E.g., "eraserhead.c~".
 
29
 *
 
30
 * If the value of VERSION_CONTROL is "simple", then the backup name
 
31
 * will be that of the original file with "~" appended, regardless of
 
32
 * whether or not there exist numbered versions in the directory.
 
33
 *
 
34
 * For simple backups, the value of SIMPLE_BACKUP_SUFFIX will be used
 
35
 * rather than "~" if it is set.
 
36
 *
 
37
 * If VERSION_CONTROL is unset, "numbered_existing" is assumed.  For
 
38
 * Emacs lovers, "nil" is equivalent to "numbered_existing" and "t" is
 
39
 * equivalent to "numbered".
 
40
 *
 
41
 * Finally, if VERSION_CONTROL is "none" or "never", backups are not
 
42
 * made.  I suggest you avoid this behaviour.
 
43
 *
 
44
 * Added, october 1999 (by Chris F.A. Johnson):
 
45
 *
 
46
 * If VERSION_WIDTH is set, then it controls zero padding of a numbered
 
47
 * suffix. */
 
48
 
 
49
/* Written by jla, based on code from djm (see `patch') */
 
50
 
 
51
#include "sys.h"
 
52
#include <ctype.h>
 
53
#include <stdlib.h>
 
54
#if defined (HAVE_UNISTD_H)
 
55
#include <unistd.h>
 
56
#endif
 
57
#ifdef PRESERVE_MTIME
 
58
#include <time.h>
 
59
#ifdef HAVE_UTIME_H
 
60
#include <utime.h>
 
61
#elif defined(HAVE_SYS_UTIME_H)
 
62
#include <sys/utime.h>
 
63
#endif
 
64
#endif
 
65
#include <sys/stat.h>
 
66
#if defined (_WIN32) && !defined (__CYGWIN__)
 
67
#include <io.h>
 
68
#else
 
69
#include <fcntl.h>
 
70
#endif
 
71
#include <string.h>
 
72
#ifndef isascii
 
73
#define ISDIGIT(c) (isdigit ((unsigned char) (c)))
 
74
#else
 
75
#define ISDIGIT(c) (isascii (c) && isdigit (c))
 
76
#endif
 
77
#include <sys/types.h>
 
78
#if HAVE_DIRENT_H
 
79
# include <dirent.h>
 
80
# define NAMLEN(dirent) strlen((dirent)->d_name)
 
81
#else
 
82
# define dirent direct
 
83
# define NAMLEN(dirent) (dirent)->d_namlen
 
84
# if HAVE_SYS_NDIR_H
 
85
#  include <sys/ndir.h>
 
86
# endif
 
87
# if HAVE_SYS_DIR_H
 
88
#  include <sys/dir.h>
 
89
# endif
 
90
# if HAVE_NDIR_H
 
91
#  include <ndir.h>
 
92
# endif
 
93
# if !defined(HAVE_SYS_NDIR_H) && !defined(HAVE_SYS_DIR_H) && !defined(HAVE_NDIR_H)
 
94
#  define NODIR 1
 
95
# endif
 
96
#endif
 
97
#include "backup.h"
 
98
#include "indent.h"
 
99
#include "globs.h"
 
100
#include "io.h"
 
101
 
 
102
RCSTAG_CC ("$Id: backup.c,v 1.17 2001/10/16 18:23:48 david Exp $");
 
103
 
 
104
#ifndef NODIR
 
105
#if defined (_POSIX_VERSION)    /* Might be defined in unistd.h.  */
 
106
/* POSIX does not require that the d_ino field be present, and some
 
107
   systems do not provide it. */
 
108
#define REAL_DIR_ENTRY(dp) 1
 
109
#else
 
110
#define REAL_DIR_ENTRY(dp) ((dp)->d_ino != 0)
 
111
#endif
 
112
#else /* NODIR */
 
113
#define generate_backup_filename(v,f) simple_backup_name((f))
 
114
#endif /* NODIR */
 
115
 
 
116
#ifndef BACKUP_SUFFIX_STR
 
117
#define BACKUP_SUFFIX_STR    "~"
 
118
#endif
 
119
 
 
120
#ifndef BACKUP_SUFFIX_CHAR
 
121
#define BACKUP_SUFFIX_CHAR   '~'
 
122
#endif
 
123
 
 
124
#ifndef BACKUP_SUFFIX_FORMAT
 
125
#define BACKUP_SUFFIX_FORMAT "%s.~%0*d~"
 
126
#endif
 
127
 
 
128
/* Default backup file suffix to use */
 
129
static char *simple_backup_suffix = BACKUP_SUFFIX_STR;
 
130
 
 
131
/* What kinds of backup files to make -- see
 
132
   table `version_control_values' below. */
 
133
enum backup_mode version_control = unknown;
 
134
int version_width = 1;
 
135
 
 
136
/* Construct a simple backup name for PATHNAME by appending
 
137
   the value of `simple_backup_suffix'. */
 
138
 
 
139
static char *
 
140
simple_backup_name (
 
141
                    char *pathname)
 
142
{
 
143
  char *backup_name;
 
144
 
 
145
  backup_name = xmalloc (strlen (pathname) + strlen (simple_backup_suffix) + 2);
 
146
  sprintf (backup_name, "%s%s", pathname, simple_backup_suffix);
 
147
  return backup_name;
 
148
}
 
149
 
 
150
#ifndef NODIR
 
151
/* If DIRENTRY is a numbered backup version of file BASE, return
 
152
   that number.  BASE_LENGTH is the string length of BASE. */
 
153
 
 
154
static int
 
155
version_number (
 
156
                char *base,
 
157
                char *direntry,
 
158
                int base_length)
 
159
{
 
160
  int version;
 
161
  char *p;
 
162
 
 
163
  version = 0;
 
164
  if (!strncmp (base, direntry, base_length) && ISDIGIT (direntry[base_length + 2]))
 
165
    {
 
166
        for (p = &direntry[base_length + 2]; ISDIGIT (*p); ++p)
 
167
        {
 
168
            version = version * 10 + *p - '0';
 
169
        }
 
170
        
 
171
        if (p[0] != BACKUP_SUFFIX_CHAR || p[1])
 
172
        {
 
173
            version = 0;
 
174
        }
 
175
    }
 
176
 
 
177
  return version;
 
178
}
 
179
 
 
180
 
 
181
/* Return the highest version of file FILENAME in directory
 
182
   DIRNAME.  Return 0 if there are no numbered versions. */
 
183
 
 
184
static int
 
185
highest_version (
 
186
     char *filename,
 
187
     char *dirname)
 
188
{
 
189
  DIR *dirp;
 
190
  struct dirent *dp;
 
191
  int highest_version;
 
192
  int this_version;
 
193
  int file_name_length;
 
194
 
 
195
  dirp = opendir (dirname);
 
196
  if (!dirp)
 
197
  {
 
198
      return 0;
 
199
  }
 
200
 
 
201
  highest_version = 0;
 
202
  file_name_length = strlen (filename);
 
203
 
 
204
  while ((dp = readdir (dirp)) != 0)
 
205
    {
 
206
        if (!REAL_DIR_ENTRY (dp) || NAMLEN (dp) <= file_name_length + 2)
 
207
        {
 
208
            continue;
 
209
        }
 
210
        
 
211
 
 
212
      this_version = version_number (filename, dp->d_name, file_name_length);
 
213
      if (this_version > highest_version)
 
214
      {
 
215
          highest_version = this_version;
 
216
      }
 
217
    }
 
218
 
 
219
  closedir (dirp);
 
220
  return highest_version;
 
221
}
 
222
 
 
223
 
 
224
/* Return the highest version number for file PATHNAME.  If there
 
225
   are no backups, or only a simple backup, return 0. */
 
226
 
 
227
static int
 
228
max_version (
 
229
             char *pathname)
 
230
{
 
231
  char *p;
 
232
  char *filename;
 
233
  int pathlen = strlen (pathname);
 
234
  int version;
 
235
 
 
236
  p = pathname + pathlen - 1;
 
237
  while (p > pathname && *p != '/')
 
238
  {
 
239
      p--;
 
240
  }
 
241
 
 
242
  if (*p == '/')
 
243
    {
 
244
      int dirlen = p - pathname;
 
245
      char *dirname;
 
246
 
 
247
      filename = p + 1;
 
248
      dirname = xmalloc (dirlen + 1);
 
249
      strncpy (dirname, pathname, (dirlen));
 
250
      dirname[dirlen] = '\0';
 
251
      version = highest_version (filename, dirname);
 
252
      free (dirname);
 
253
      return version;
 
254
    }
 
255
 
 
256
  filename = pathname;
 
257
  version = highest_version (filename, ".");
 
258
  return version;
 
259
}
 
260
 
 
261
 
 
262
/* Generate a backup filename for PATHNAME, dependent on the
 
263
   value of VERSION_CONTROL. */
 
264
 
 
265
static char *
 
266
generate_backup_filename (
 
267
                          enum backup_mode version_control,
 
268
                          char *pathname)
 
269
{
 
270
  int last_numbered_version;
 
271
  char *backup_name;
 
272
 
 
273
  if (version_control == none)
 
274
  {
 
275
      return 0;
 
276
  }
 
277
 
 
278
  if (version_control == simple)
 
279
  {
 
280
      return simple_backup_name (pathname);
 
281
  }
 
282
 
 
283
  last_numbered_version = max_version (pathname);
 
284
  if (version_control == numbered_existing && last_numbered_version == 0)
 
285
  {
 
286
      return simple_backup_name (pathname);
 
287
  }
 
288
 
 
289
  last_numbered_version++;
 
290
  backup_name = xmalloc (strlen (pathname) + 16);
 
291
  
 
292
  if (!backup_name)
 
293
  {
 
294
      return 0;
 
295
  }
 
296
 
 
297
  sprintf (backup_name, BACKUP_SUFFIX_FORMAT, pathname, version_width, (int) last_numbered_version);
 
298
 
 
299
  return backup_name;
 
300
}
 
301
 
 
302
#endif /* !NODIR */
 
303
 
 
304
static struct version_control_values values[] = {
 
305
  {none, "never"},              /* Don't make backups. */
 
306
  {none, "none"},               /* Ditto */
 
307
  {simple, "simple"},           /* Only simple backups */
 
308
  {numbered_existing, "existing"},      /* Numbered if they already exist */
 
309
  {numbered_existing, "nil"},   /* Ditto */
 
310
  {numbered, "numbered"},       /* Numbered backups */
 
311
  {numbered, "t"},              /* Ditto */
 
312
  {unknown, 0}                  /* Initial, undefined value. */
 
313
};
 
314
 
 
315
 
 
316
/* Determine the value of `version_control' by looking in the
 
317
   environment variable "VERSION_CONTROL".  Defaults to
 
318
   numbered_existing. */
 
319
 
 
320
enum backup_mode
 
321
version_control_value (void)
 
322
{
 
323
    char *version;
 
324
    struct version_control_values *v;
 
325
 
 
326
    version = getenv ("VERSION_CONTROL");
 
327
    if (version == 0 || *version == 0)
 
328
    {
 
329
        return numbered_existing;
 
330
    }
 
331
 
 
332
    v = &values[0];
 
333
    while (v->name)
 
334
    {
 
335
        if (strcmp (version, v->name) == 0)
 
336
        {
 
337
            return v->value;
 
338
        }
 
339
 
 
340
        v++;
 
341
    }
 
342
 
 
343
    return unknown;
 
344
}
 
345
 
 
346
 
 
347
/* Initialize information used in determining backup filenames. */
 
348
 
 
349
void
 
350
set_version_width (void)
 
351
{
 
352
  char *v = getenv ("VERSION_WIDTH");
 
353
 
 
354
  if (v && ISDIGIT (*v))
 
355
    version_width = atoi (v);
 
356
  if (version_width > 16)
 
357
    version_width = 16;
 
358
}
 
359
 
 
360
void
 
361
initialize_backups (void)
 
362
{
 
363
    char *v = getenv ("SIMPLE_BACKUP_SUFFIX");
 
364
 
 
365
    if (v && *v)
 
366
    {
 
367
        simple_backup_suffix = v;
 
368
    }
 
369
  
 
370
#ifdef NODIR
 
371
    version_control = simple;
 
372
#else /* !NODIR */
 
373
    version_control = version_control_value ();
 
374
    if (version_control == unknown)
 
375
    {
 
376
        fprintf (stderr, _("indent:  Strange version-control value\n"));
 
377
        fprintf (stderr, _("indent:  Using numbered-existing\n"));
 
378
        version_control = numbered_existing;
 
379
    }
 
380
#endif /* !NODIR */
 
381
    set_version_width ();
 
382
}
 
383
 
 
384
 
 
385
/* Make a backup copy of FILE, taking into account version-control.
 
386
   See the description at the beginning of the file for details. */
 
387
 
 
388
void
 
389
make_backup (
 
390
             struct file_buffer *file,
 
391
             const struct stat *file_stats)
 
392
{
 
393
    FILE *bf;
 
394
    char *backup_filename;
 
395
    unsigned int size;
 
396
 
 
397
    if (version_control == none)
 
398
    {
 
399
        return;
 
400
    }
 
401
 
 
402
    backup_filename = generate_backup_filename (version_control, file->name);
 
403
    if (!backup_filename)
 
404
    {
 
405
        fprintf (stderr, _("indent: Can't make backup filename of %s\n"), file->name);
 
406
        exit (system_error);
 
407
    }
 
408
 
 
409
    bf = fopen (backup_filename, "w");
 
410
    if (!bf)
 
411
    {
 
412
        fatal (_("Can't open backup file %s"), backup_filename);
 
413
    }
 
414
  
 
415
    size = fwrite (file->data, file->size, 1, bf);
 
416
    if (size != 1)
 
417
    {
 
418
        fatal (_("Can't write to backup file %s"), backup_filename);
 
419
    }
 
420
  
 
421
 
 
422
    fclose (bf);
 
423
#ifdef PRESERVE_MTIME
 
424
    {
 
425
        struct utimbuf buf;
 
426
 
 
427
        buf.actime = time (NULL);
 
428
        buf.modtime = file_stats->st_mtime;
 
429
        if (utime (backup_filename, &buf) != 0)
 
430
        {
 
431
            WARNING (_("Can't preserve modification time on backup file %s"), backup_filename, 0);
 
432
        }
 
433
    
 
434
    }
 
435
#endif
 
436
    free (backup_filename);
 
437
}