📄 backup.c
字号:
/* backup.c -- make Emacs style backup file names Copyright (C) 1992 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it without restriction. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. GNU/Emacs style backups -- This behaviour is controlled by two environment variables, VERSION_CONTROL and SIMPLE_BACKUP_SUFFIX. VERSION_CONTROL determines what kinds of backups are made. If it's value is "numbered", then the first modification of some file "eraserhead.c" will yield a backup file "eraserhead.c.~1~", the second modification will yield "eraserhead.c.~2~", and so on. It does not matter if the version numbers are not a sequence; the next version will be one greater than the highest in that directory. If the value of VERSION_CONTROL is "numbered_existing", then such numbered backups will be made if there are already numbered backup versions of the file. Otherwise, the backup name will be that of the original file with "~" (tilde) appended. E.g., "eraserhead.c~". If the value of VERSION_CONTROL is "simple", then the backup name will be that of the original file with "~" appended, regardless of whether or not there exist numbered versions in the directory. For simple backups, the value of SIMPLE_BACKUP_SUFFIX will be used rather than "~" if it is set. If VERSION_CONTROL is unset, "numbered_existing" is assumed. For Emacs lovers, "nil" is equivalent to "numbered_existing" and "t" is equivalent to "numbered". Finally, if VERSION_CONTROL is "none" or "never", backups are not made. I suggest you avoid this behaviour. *//* Written by jla, based on code from djm (see `patch') */#include "sys.h"#include "backup.h"#include <ctype.h>#ifndef isascii#define ISDIGIT(c) (isdigit ((unsigned char) (c)))#else#define ISDIGIT(c) (isascii (c) && isdigit (c))#endif#ifndef NODIR#include <sys/types.h>#ifdef DIRENT#include <dirent.h>#ifdef direct#undef direct#endif#define direct dirent#define NLENGTH(direct) (strlen((direct)->d_name))#else /* !DIRENT */#define NLENGTH(direct) ((direct)->d_namlen)#ifdef USG#ifdef SYSNDIR#include <sys/ndir.h>#else /* !SYSNDIR */#include <ndir.h>#endif /* !SYSNDIR */#else /* !USG */#include <sys/dir.h>#endif /* !USG */#endif /* !DIRENT */#if defined (HAVE_UNISTD_H)#include <unistd.h>#endif#if defined (_POSIX_VERSION) /* Might be defined in unistd.h. *//* POSIX does not require that the d_ino field be present, and some systems do not provide it. */#define REAL_DIR_ENTRY(dp) 1#else#define REAL_DIR_ENTRY(dp) ((dp)->d_ino != 0)#endif#else /* NODIR */#define generate_backup_filename(v,f) simple_backup_name((f))#endif /* NODIR */#ifndef SYS_BACKUP_SUFFIX#define SYS_BACKUP_SUFFIX "~"#endif#ifndef BACKUP_SUFFIX_STR#define BACKUP_SUFFIX_STR "~"#endif#ifndef BACKUP_SUFFIX_CHAR#define BACKUP_SUFFIX_CHAR '~'#endif#ifndef BACKUP_SUFFIX_FORMAT#define BACKUP_SUFFIX_FORMAT "%s.~%d~"#endif/* Default backup file suffix to use */static char *simple_backup_suffix = SYS_BACKUP_SUFFIX;/* What kinds of backup files to make -- see table `version_control_values' below. */enum backup_mode version_control = unknown;/* Construct a simple backup name for PATHNAME by appending the value of `simple_backup_suffix'. */static char *simple_backup_name (pathname) char *pathname;{ char *backup_name; backup_name = xmalloc (strlen (pathname) + strlen (simple_backup_suffix) + 2); sprintf (backup_name, "%s%s", pathname, simple_backup_suffix); return backup_name;}#ifndef NODIR/* If DIRENTRY is a numbered backup version of file BASE, return that number. BASE_LENGTH is the string length of BASE. */static intversion_number (base, direntry, base_length) char *base; char *direntry; int base_length;{ int version; char *p; version = 0; if (!strncmp (base, direntry, base_length) && ISDIGIT (direntry[base_length + 2])) { for (p = &direntry[base_length + 2]; ISDIGIT (*p); ++p) version = version * 10 + *p - '0'; if (p[0] != BACKUP_SUFFIX_CHAR || p[1]) version = 0; } return version;}/* Return the highest version of file FILENAME in directory DIRNAME. Return 0 if there are no numbered versions. */static inthighest_version (filename, dirname) char *filename, *dirname;{ DIR *dirp; struct direct *dp; int highest_version; int this_version; int file_name_length; dirp = opendir (dirname); if (!dirp) return 0; highest_version = 0; file_name_length = strlen (filename); while ((dp = readdir (dirp)) != 0) { if (!REAL_DIR_ENTRY (dp) || NLENGTH (dp) <= file_name_length + 2) continue; this_version = version_number (filename, dp->d_name, file_name_length); if (this_version > highest_version) highest_version = this_version; } closedir (dirp); return highest_version;}/* Return the highest version number for file PATHNAME. If there are no backups, or only a simple backup, return 0. */static intmax_version (pathname) char *pathname;{ register char *p; register char *filename; int pathlen = strlen (pathname); int version; p = pathname + pathlen - 1; while (p > pathname && *p != '/') p--; if (*p == '/') { int dirlen = p - pathname; register char *dirname; filename = p + 1; dirname = xmalloc (dirlen + 1); strncpy (dirname, pathname, (dirlen)); dirname[dirlen] = '\0'; version = highest_version (filename, dirname); free (dirname); return version; } filename = pathname; version = highest_version (filename, "."); return version;}/* Generate a backup filename for PATHNAME, dependent on the value of VERSION_CONTROL. */static char *generate_backup_filename (version_control, pathname) enum backup_mode version_control; char *pathname;{ int last_numbered_version; char *backup_name; if (version_control == none) return 0; if (version_control == simple) return simple_backup_name (pathname); last_numbered_version = max_version (pathname); if (version_control == numbered_existing && last_numbered_version == 0) return simple_backup_name (pathname); last_numbered_version++; backup_name = xmalloc (strlen (pathname) + 16); if (!backup_name) return 0; sprintf (backup_name, BACKUP_SUFFIX_STR, pathname, (int) last_numbered_version); return backup_name;}#endif /* !NODIR */static struct version_control_values values[] ={ {none, "never"}, /* Don't make backups. */ {simple, "simple"}, /* Only simple backups */ {numbered_existing, "existing"}, /* Numbered if they already exist */ {numbered_existing, "nil"}, /* Ditto */ {numbered, "numbered"}, /* Numbered backups */ {numbered, "t"}, /* Ditto */ {unknown, 0} /* Initial, undefined value. */};extern char *getenv ();/* Determine the value of `version_control' by looking in the environment variable "VERSION_CONTROL". Defaults to numbered_existing. */enum backup_modeversion_control_value (){ char *version; struct version_control_values *v; version = getenv ("VERSION_CONTROL"); if (version == 0 || *version == 0) return numbered_existing; v = &values[0]; while (v->name) { if (strcmp (version, v->name) == 0) return v->value; v++; } return unknown;}/* Initialize information used in determining backup filenames. */voidinitialize_backups (){ char *v = getenv ("SIMPLE_BACKUP_SUFFIX"); if (v && *v) simple_backup_suffix = v;#ifdef NODIR version_control = simple;#else /* !NODIR */ version_control = version_control_value (); if (version_control == unknown) { fprintf (stderr, "indent: Strange version-control value\n"); fprintf (stderr, "indent: Using numbered-existing\n"); version_control = numbered_existing; }#endif /* !NODIR */}/* Prints an error message using `perror' */extern void sys_error ();/* Make a backup copy of FILE, taking into account version-control. See the description at the beginning of the file for details. */voidmake_backup (file) struct file_buffer *file;{ int fd; register char *p = file->name + strlen (file->name) - 1; char *backup_filename; char *new_backup_name; backup_filename = generate_backup_filename (version_control, file->name); if (!backup_filename) { fprintf (stderr, "indent: Can't make backup filename of %s", file->name); exit (1); } fd = creat (backup_filename, 0666); if (fd < 0) sys_error (backup_filename); if (write (fd, file->data, file->size) != file->size) sys_error (backup_filename); close (fd); free (backup_filename);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -