From de3fbe3e8d4dd2a89f7755906d76055784c437cc Mon Sep 17 00:00:00 2001 From: Sergey Poznyakoff Date: Fri, 13 May 2011 10:21:43 +0300 Subject: Drop gnulib. * bootstrap: Rewrite. * bootstrap.conf: Remove. * configure.ac: Remove gl_EARLY/gl_INIT * src/backup.c: New file. * src/txtacc.c (txtacc_finish): Make sure a new entry is appended only once to the list. * (all sources): Use grecs memory allocation functions. * src/wydawca.h" Include fnmatch.h and regex.h (backup_type): New enum. (simple_backup_suffix): New extern. (find_backup_file_name): New proto. * tests/bkupname.c: New file. * tests/backup00.at: New file. * tests/backup01.at: New file. * tests/backup02.at: New file. * tests/backup03.at: New file. * tests/Makefile.am: Add new tests. * tests/testsuite.at: Add new tests. * grecs: Update. --- src/backup.c | 165 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 src/backup.c (limited to 'src/backup.c') diff --git a/src/backup.c b/src/backup.c new file mode 100644 index 0000000..312375d --- /dev/null +++ b/src/backup.c @@ -0,0 +1,165 @@ +/* wydawca - automatic release submission daemon + Copyright (C) 2011 Sergey Poznyakoff + + Wydawca 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 3 of the License, or (at your + option) any later version. + + Wydawca 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 wydawca. If not, see . */ + +#include "wydawca.h" + +char const *simple_backup_suffix = "~"; + +static const char * +split_filename (char const *file, char **pdir) +{ + const char *p = strrchr (file, '/'); + + if (!p) + { + *pdir = grecs_strdup ("."); + p = file; + } + else + { + size_t len = p - file; + char *dir = grecs_malloc (len + 1); + memcpy (dir, file, len); + dir[len] = 0; + *pdir = dir; + p++; + } + return p; +} + +#define MINSUFSIZE 8 +#define ISDIGIT(c) ('0' <= (c) && (c) <= '9') + +static char * +get_backup_suffix (char const *file, enum backup_type type) +{ + char *dirname; + const char *basename; + size_t baselen; + DIR *dir; + struct dirent *ent; + char *lastsuf = NULL; + size_t lastsuflen = 0; + size_t lastsufsize = 0; + int carry; + char *newsuf; + char *q; + + if (type == simple_backups) + return grecs_strdup (simple_backup_suffix); + + basename = split_filename (file, &dirname); + baselen = strlen (basename); + dir = opendir (dirname); + if (!dir) + { + int ec = errno; + free (dirname); + errno = ec; + return NULL; + } + + while ((ent = readdir (dir))) + { + size_t len = strlen (ent->d_name); + const char *p; + size_t suflen; + + if (len < baselen + 4 || memcmp (ent->d_name, basename, baselen)) + continue; + p = ent->d_name + baselen; + suflen = len - baselen; + if (p[0] == '.' && p[1] == '~' && p[suflen-1] == '~' && + (suflen > lastsuflen + || (suflen == lastsuflen && + memcmp (p, lastsuf, lastsuflen) > 0))) + { + carry = 1; + for (q = (char*) p + suflen - 2; q > p + 1 && ISDIGIT (*q); q--) + if (*q != '9') + carry = 0; + q++; + if (!ISDIGIT (*q)) + continue; + + if (suflen > lastsufsize) + { + lastsufsize = suflen; + if (!lastsuf) + { + if (lastsufsize < MINSUFSIZE) + lastsufsize = MINSUFSIZE; + lastsuf = grecs_malloc (lastsufsize); + } + else + lastsuf = grecs_realloc (lastsuf, lastsufsize); + } + memcpy (lastsuf, p, suflen); + lastsuflen = suflen; + } + } + closedir (dir); + free (dirname); + + if (lastsuf) + { + size_t newsuflen; + + newsuflen = lastsuflen + carry; + newsuf = grecs_malloc (newsuflen + 1); + newsuf[0] = '.'; + newsuf[1] = '~'; + newsuf[2] = '0'; + memcpy (newsuf + 2 + carry, lastsuf + 2, lastsuflen - 3); + newsuf[newsuflen-1] = '~'; + newsuf[newsuflen] = 0; + + for (q = newsuf + newsuflen - 2; *q == '9'; q--) + *q = '0'; + ++*q; + free (lastsuf); + } + else if (type == numbered_existing_backups) + newsuf = grecs_strdup (simple_backup_suffix); + else + newsuf = grecs_strdup (".~1~"); + return newsuf; +} + +char * +find_backup_file_name (char const *file, enum backup_type type) +{ + size_t flen; + char *suffix; + char *newname; + + if (type == no_backups) + { + errno = 0; + return NULL; + } + + suffix = get_backup_suffix (file, type); + if (!suffix) + return NULL; + flen = strlen (file); + newname = grecs_malloc (flen + strlen (suffix) + 1); + memcpy (newname, file, flen); + strcpy (newname + flen, suffix); + free (suffix); + /* FIXME: Check newname length */ + return newname; +} -- cgit v1.2.1