summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorBruno Haible <bruno@clisp.org>2001-10-20 13:13:38 +0000
committerBruno Haible <bruno@clisp.org>2001-10-20 13:13:38 +0000
commitd1fe019e0c462757506c10be89fa706de40d37dd (patch)
treed52d3011681d2909d3b4dd9bb4280aaf0f713d51 /lib
parente8bde484c69801c2aa848c03005022eee062dcac (diff)
downloadexternal_gettext-d1fe019e0c462757506c10be89fa706de40d37dd.zip
external_gettext-d1fe019e0c462757506c10be89fa706de40d37dd.tar.gz
external_gettext-d1fe019e0c462757506c10be89fa706de40d37dd.tar.bz2
Subroutines for backing up a regular file.
Diffstat (limited to 'lib')
-rw-r--r--lib/ChangeLog8
-rw-r--r--lib/Makefile.am22
-rw-r--r--lib/addext.c108
-rw-r--r--lib/backupfile.c273
-rw-r--r--lib/backupfile.h63
5 files changed, 463 insertions, 11 deletions
diff --git a/lib/ChangeLog b/lib/ChangeLog
index bab7212..80e56dd 100644
--- a/lib/ChangeLog
+++ b/lib/ChangeLog
@@ -1,5 +1,13 @@
2001-09-17 Bruno Haible <haible@clisp.cons.org>
+ * backupfile.h: New file, from fileutils-4.1 with modifications.
+ * backupfile.c: New file, from fileutils-4.1 with modifications.
+ * addext.c: New file, from fileutils-4.1 with modifications.
+ * Makefile.am (libnlsut_a_SOURCES): Add backupfile.c, addext.c.
+ (libnlsut_a_HEADER): Add backupfile.h.
+
+2001-09-17 Bruno Haible <haible@clisp.cons.org>
+
* argmatch.h: New file, from fileutils-4.1 with simplifications.
* argmatch.c: New file, from fileutils-4.1 with simplifications.
* Makefile.am (libnlsut_a_SOURCES): Add argmatch.c.
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 079fa14..324a20a 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -23,17 +23,17 @@ noinst_LIBRARIES = libnlsut.a
# Sources that are compiled on all platforms.
-libnlsut_a_SOURCES = argmatch.c basename.c c-ctype.c concatpath.c copy-file.c \
-execute.c findprog.c fstrcmp.c full-write.c gcd.c getopt.c getopt1.c hash.c \
-javacomp.c javaexec.c linebreak.c localcharset.c mbswidth.c obstack.c \
-pipe-bidi.c pipe-in.c pipe-out.c progname.c sh-quote.c tmpdir.c \
-wait-process.c xerror.c xgetcwd.c xmalloc.c xstrdup.c
-
-libnlsut_a_HEADER = argmatch.h basename.h c-ctype.h copy-file.h execute.h \
-findprog.h fstrcmp.h full-write.h gcd.h getopt.h hash.h javacomp.h javaexec.h \
-lbrkprop.h linebreak.h mbswidth.h obstack.h pathmax.h pipe.h progname.h \
-sh-quote.h system.h tmpdir.h utf8-ucs4.h utf16-ucs4.h wait-process.h xerror.h \
-xmalloc.h
+libnlsut_a_SOURCES = addext.c argmatch.c backupfile.c basename.c c-ctype.c \
+concatpath.c copy-file.c execute.c findprog.c fstrcmp.c full-write.c gcd.c \
+getopt.c getopt1.c hash.c javacomp.c javaexec.c linebreak.c localcharset.c \
+mbswidth.c obstack.c pipe-bidi.c pipe-in.c pipe-out.c progname.c sh-quote.c \
+tmpdir.c wait-process.c xerror.c xgetcwd.c xmalloc.c xstrdup.c
+
+libnlsut_a_HEADER = argmatch.h backupfile.h basename.h c-ctype.h copy-file.h \
+execute.h findprog.h fstrcmp.h full-write.h gcd.h getopt.h hash.h javacomp.h \
+javaexec.h lbrkprop.h linebreak.h mbswidth.h obstack.h pathmax.h pipe.h \
+progname.h sh-quote.h system.h tmpdir.h utf8-ucs4.h utf16-ucs4.h \
+wait-process.h xerror.h xmalloc.h
# Sources that are compiled only on platforms that lack the functions.
diff --git a/lib/addext.c b/lib/addext.c
new file mode 100644
index 0000000..9e601bd
--- /dev/null
+++ b/lib/addext.c
@@ -0,0 +1,108 @@
+/* addext.c -- add an extension to a file name
+ Copyright (C) 1990, 1997-1999, 2001 Free Software Foundation, Inc.
+
+ 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.
+
+ 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. See the
+ 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,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Written by David MacKenzie <djm@gnu.ai.mit.edu> and Paul Eggert */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifndef HAVE_DOS_FILE_NAMES
+# define HAVE_DOS_FILE_NAMES 0
+#endif
+#ifndef HAVE_LONG_FILE_NAMES
+# define HAVE_LONG_FILE_NAMES 0
+#endif
+
+#include "backupfile.h"
+
+#if HAVE_LIMITS_H
+# include <limits.h>
+#endif
+#ifndef _POSIX_NAME_MAX
+# define _POSIX_NAME_MAX 14
+#endif
+
+#include <sys/types.h>
+#if HAVE_STRING_H
+# include <string.h>
+#else
+# include <strings.h>
+#endif
+
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#include "basename.h"
+
+/* Append to FILENAME the extension EXT, unless the result would be too long,
+ in which case just append the character E. */
+
+void
+addext (filename, ext, e)
+ char *filename;
+ char const *ext;
+ int e;
+{
+ char *s = basename (filename);
+ size_t slen = strlen (s), extlen = strlen (ext);
+ long slen_max = -1;
+
+#if HAVE_PATHCONF && defined _PC_NAME_MAX
+ if (slen + extlen <= _POSIX_NAME_MAX && ! HAVE_DOS_FILE_NAMES)
+ /* The file name is so short there's no need to call pathconf. */
+ slen_max = _POSIX_NAME_MAX;
+ else if (s == filename)
+ slen_max = pathconf (".", _PC_NAME_MAX);
+ else
+ {
+ char c = *s;
+ *s = 0;
+ slen_max = pathconf (filename, _PC_NAME_MAX);
+ *s = c;
+ }
+#endif
+ if (slen_max < 0)
+ slen_max = HAVE_LONG_FILE_NAMES ? 255 : 14;
+
+ if (HAVE_DOS_FILE_NAMES && slen_max <= 12)
+ {
+ /* Live within DOS's 8.3 limit. */
+ char *dot = strchr (s, '.');
+ if (dot)
+ {
+ slen -= dot + 1 - s;
+ s = dot + 1;
+ slen_max = 3;
+ }
+ else
+ slen_max = 8;
+ extlen = 9; /* Don't use EXT. */
+ }
+
+ if (slen + extlen <= slen_max)
+ strcpy (s + slen, ext);
+ else
+ {
+ if (slen_max <= slen)
+ slen = slen_max - 1;
+ s[slen] = e;
+ s[slen + 1] = 0;
+ }
+}
diff --git a/lib/backupfile.c b/lib/backupfile.c
new file mode 100644
index 0000000..78f2ad0
--- /dev/null
+++ b/lib/backupfile.c
@@ -0,0 +1,273 @@
+/* backupfile.c -- make Emacs style backup file names
+ Copyright (C) 1990-1999, 2000, 2001 Free Software Foundation, Inc.
+
+ 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.
+
+ 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. See the
+ 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,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+/* Written by David MacKenzie <djm@gnu.ai.mit.edu>.
+ Some algorithms adapted from GNU Emacs. */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "argmatch.h"
+#include "backupfile.h"
+
+#include <stdio.h>
+#include <sys/types.h>
+#if HAVE_STRING_H
+# include <string.h>
+#else
+# include <strings.h>
+#endif
+
+#if HAVE_DIRENT_H
+# include <dirent.h>
+# 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 <sys/ndir.h>
+# endif
+# if HAVE_SYS_DIR_H
+# include <sys/dir.h>
+# endif
+# if HAVE_NDIR_H
+# include <ndir.h>
+# endif
+#endif
+
+#if CLOSEDIR_VOID
+/* Fake a return value. */
+# define CLOSEDIR(d) (closedir (d), 0)
+#else
+# define CLOSEDIR(d) closedir (d)
+#endif
+
+#include <stdlib.h>
+
+#include "basename.h"
+
+#if HAVE_DIRENT_H || HAVE_NDIR_H || HAVE_SYS_DIR_H || HAVE_SYS_NDIR_H
+# define HAVE_DIR 1
+#else
+# define HAVE_DIR 0
+#endif
+
+#if HAVE_LIMITS_H
+# include <limits.h>
+#endif
+#ifndef CHAR_BIT
+# define CHAR_BIT 8
+#endif
+/* Upper bound on the string length of an integer converted to string.
+ 302 / 1000 is ceil (log10 (2.0)). Subtract 1 for the sign bit;
+ add 1 for integer division truncation; add 1 more for a minus sign. */
+#define INT_STRLEN_BOUND(t) ((sizeof (t) * CHAR_BIT - 1) * 302 / 1000 + 2)
+
+/* 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.
+ - It's typically faster.
+ Posix 1003.2-1992 section 2.5.2.1 page 50 lines 1556-1558 says that
+ only '0' through '9' are digits. Prefer ISDIGIT to 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) (c) - '0' <= 9)
+
+#if D_INO_IN_DIRENT
+# define REAL_DIR_ENTRY(dp) ((dp)->d_ino != 0)
+#else
+# define REAL_DIR_ENTRY(dp) 1
+#endif
+
+/* The extension added to file names to produce a simple (as opposed
+ to numbered) backup file name. */
+const char *simple_backup_suffix = "~";
+
+#if HAVE_DIR
+static int max_backup_version PARAMS ((const char *, const char *));
+static int version_number PARAMS ((const char *, const char *, size_t));
+#endif
+
+/* Return the name of the new backup file for file FILE,
+ allocated with malloc. Return 0 if out of memory.
+ FILE must not end with a '/' unless it is the root directory.
+ Do not call this function if backup_type == none. */
+
+char *
+find_backup_file_name (file, backup_type)
+ const char *file;
+ enum backup_type backup_type;
+{
+ size_t backup_suffix_size_max;
+ size_t file_len = strlen (file);
+ size_t numbered_suffix_size_max = INT_STRLEN_BOUND (int) + 4;
+ char *s;
+ const char *suffix = simple_backup_suffix;
+
+ /* Allow room for simple or `.~N~' backups. */
+ backup_suffix_size_max = strlen (simple_backup_suffix) + 1;
+ if (HAVE_DIR && backup_suffix_size_max < numbered_suffix_size_max)
+ backup_suffix_size_max = numbered_suffix_size_max;
+
+ s = malloc (file_len + backup_suffix_size_max + numbered_suffix_size_max);
+ if (s)
+ {
+ strcpy (s, file);
+
+#if HAVE_DIR
+ if (backup_type != simple)
+ {
+ int highest_backup;
+ size_t dir_len = basename (s) - s;
+
+ strcpy (s + dir_len, ".");
+ highest_backup = max_backup_version (file + dir_len, s);
+ if (! (backup_type == numbered_existing && highest_backup == 0))
+ {
+ char *numbered_suffix = s + (file_len + backup_suffix_size_max);
+ sprintf (numbered_suffix, ".~%d~", highest_backup + 1);
+ suffix = numbered_suffix;
+ }
+ strcpy (s, file);
+ }
+#endif /* HAVE_DIR */
+
+ addext (s, suffix, '~');
+ }
+ return s;
+}
+
+#if HAVE_DIR
+
+/* Return the number of the highest-numbered backup file for file
+ FILE in directory DIR. If there are no numbered backups
+ of FILE in DIR, or an error occurs reading DIR, return 0.
+ */
+
+static int
+max_backup_version (file, dir)
+ const char *file;
+ const char *dir;
+{
+ DIR *dirp;
+ struct dirent *dp;
+ int highest_version;
+ int this_version;
+ size_t file_name_length;
+
+ dirp = opendir (dir);
+ if (!dirp)
+ return 0;
+
+ highest_version = 0;
+ file_name_length = strlen (file);
+
+ while ((dp = readdir (dirp)) != 0)
+ {
+ if (!REAL_DIR_ENTRY (dp) || NLENGTH (dp) < file_name_length + 4)
+ continue;
+
+ this_version = version_number (file, dp->d_name, file_name_length);
+ if (this_version > highest_version)
+ highest_version = this_version;
+ }
+ if (CLOSEDIR (dirp))
+ return 0;
+ return highest_version;
+}
+
+/* If BACKUP is a numbered backup of BASE, return its version number;
+ otherwise return 0. BASE_LENGTH is the length of BASE.
+ */
+
+static int
+version_number (base, backup, base_length)
+ const char *base;
+ const char *backup;
+ size_t base_length;
+{
+ int version;
+ const char *p;
+
+ version = 0;
+ if (strncmp (base, backup, base_length) == 0
+ && backup[base_length] == '.'
+ && backup[base_length + 1] == '~')
+ {
+ for (p = &backup[base_length + 2]; ISDIGIT (*p); ++p)
+ version = version * 10 + *p - '0';
+ if (p[0] != '~' || p[1])
+ version = 0;
+ }
+ return version;
+}
+#endif /* HAVE_DIR */
+
+static const char * const backup_args[] =
+{
+ /* In a series of synonyms, present the most meaning full first, so
+ that argmatch_valid be more readable. */
+ "none", "off",
+ "simple", "never",
+ "existing", "nil",
+ "numbered", "t",
+ 0
+};
+
+static const enum backup_type backup_types[] =
+{
+ none, none,
+ simple, simple,
+ numbered_existing, numbered_existing,
+ numbered, numbered
+};
+
+/* Return the type of backup specified by VERSION.
+ If VERSION is NULL or the empty string, return numbered_existing.
+ If VERSION is invalid or ambiguous, fail with a diagnostic appropriate
+ for the specified CONTEXT. Unambiguous abbreviations are accepted. */
+
+enum backup_type
+get_version (context, version)
+ const char *context;
+ const char *version;
+{
+ if (version == 0 || *version == 0)
+ return numbered_existing;
+ else
+ return XARGMATCH (context, version, backup_args, backup_types);
+}
+
+
+/* Return the type of backup specified by VERSION.
+ If VERSION is NULL, use the value of the envvar VERSION_CONTROL.
+ If the specified string is invalid or ambiguous, fail with a diagnostic
+ appropriate for the specified CONTEXT.
+ Unambiguous abbreviations are accepted. */
+
+enum backup_type
+xget_version (context, version)
+ const char *context;
+ const char *version;
+{
+ if (version && *version)
+ return get_version (context, version);
+ else
+ return get_version ("$VERSION_CONTROL", getenv ("VERSION_CONTROL"));
+}
diff --git a/lib/backupfile.h b/lib/backupfile.h
new file mode 100644
index 0000000..b061161
--- /dev/null
+++ b/lib/backupfile.h
@@ -0,0 +1,63 @@
+/* backupfile.h -- declarations for making Emacs style backup file names
+ Copyright (C) 1990-1992, 1997-1999, 2001 Free Software Foundation, Inc.
+
+ 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.
+
+ 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. See the
+ 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,
+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+#ifndef BACKUPFILE_H_
+# define BACKUPFILE_H_
+
+/* When to make backup files. */
+enum backup_type
+{
+ /* Never make backups. */
+ none,
+
+ /* Make simple backups of every file. */
+ simple,
+
+ /* Make numbered backups of files that already have numbered backups,
+ and simple backups of the others. */
+ numbered_existing,
+
+ /* Make numbered backups of every file. */
+ numbered
+};
+
+# define VALID_BACKUP_TYPE(Type) \
+ ((Type) == none \
+ || (Type) == simple \
+ || (Type) == numbered_existing \
+ || (Type) == numbered)
+
+extern char const *simple_backup_suffix;
+
+# ifndef PARAMS
+# if defined PROTOTYPES || (defined __STDC__ && __STDC__)
+# define PARAMS(Args) Args
+# else
+# define PARAMS(Args) ()
+# endif
+# endif
+
+extern char *find_backup_file_name PARAMS ((char const *file,
+ enum backup_type backup_type));
+extern enum backup_type get_version PARAMS ((char const *context,
+ char const *arg));
+extern enum backup_type xget_version PARAMS ((char const *context,
+ char const *arg));
+extern void addext PARAMS ((char *, char const *, int));
+
+#endif /* ! BACKUPFILE_H_ */