diff options
Diffstat (limited to 'lib-src')
-rw-r--r-- | lib-src/ChangeLog | 56 | ||||
-rw-r--r-- | lib-src/Makefile.in | 55 | ||||
-rw-r--r-- | lib-src/ctags.c | 2 | ||||
-rw-r--r-- | lib-src/test-distrib.c | 88 | ||||
-rw-r--r-- | lib-src/testfile | bin | 222 -> 0 bytes | |||
-rw-r--r-- | lib-src/update-game-score.c | 315 |
6 files changed, 229 insertions, 287 deletions
diff --git a/lib-src/ChangeLog b/lib-src/ChangeLog index 42a44f9712d..cedd9ab8965 100644 --- a/lib-src/ChangeLog +++ b/lib-src/ChangeLog @@ -1,4 +1,4 @@ -2014-05-20 Paul Eggert <eggert@cs.ucla.edu> +2014-05-26 Paul Eggert <eggert@cs.ucla.edu> Fix rcs2log problems with CVS. Problem reported by Glenn Morris in @@ -8,12 +8,45 @@ (logdir, llogdir): Work even if TMPDIR begins with '-' or has spaces. (output_authors, main awk script): Parse more-recent CVS output format. -2014-05-03 Paul Eggert <eggert@cs.ucla.edu> +2014-05-19 Paul Eggert <eggert@cs.ucla.edu> + + Remove dependencies on getline and getdelim. + Also, remove update-game-scores's limits on game scores and + simplify its file-locking code. + * update-game-score.c (struct score_entry): Unify the username and + data members to a single user_data member, since they don't need to be + changed independently and getdelim and getline aren't helpful. + Make the score member char *, not intmax_t, so that scores are not + limited to intmax_t. All uses changed. + (lose_syserr): A zero errno stands for invalid data in score file. + (normalize_integer): New function. + (main): Use it. Check for invalid scores. Omit redundant stat check. + (read_score): First arg is now a string, not a FILE *. All uses + changed. Do not use getdelim or getline; that's way simpler. + (read_scores): Read the whole file, and let read_score handle each + line. + (score_compare): Compare strings representing integers, not integers. + (write_scores) [DOS_NT]: Eliminate unnecessary chmod. + (lock_file): Simplify locking code, eliminating goto. + Check for unlink failure. + +2014-05-18 Paul Eggert <eggert@cs.ucla.edu> + + Port ctags+etags build to Sun C 5.12. + * Makefile.in (etags_args): Remove, replacing with ... + (etags_cflags, etags_libs): New macros. All uses changed. + (ctags${EXEEXT}): Don't compile etags.c, as compiling etags.c in + parallel (once for ctags, once for etags) breaks parallel makes + with compilers that use the source file name to name temporaries, + such as Sun C 5.12. Instead, compile ctags.c. + * ctags.c: New file. + +2014-05-04 Paul Eggert <eggert@cs.ucla.edu> Handle systems without WCONTINUED consistently. (Bug#15110, 17339) * emacsclient.c (WCONTINUED): Move to ../src/syswait.h. -2014-04-29 Glenn Morris <rgm@gnu.org> +2014-04-30 Glenn Morris <rgm@gnu.org> * Makefile.in ($(DESTDIR)${archlibdir}): Avoid non-portable "`\" nesting. (Bug#17339) @@ -23,6 +56,23 @@ * update-game-score.c (write_scores): Condition fchmod call on DOS_NT, not WINDOWSNT. +2014-03-22 Glenn Morris <rgm@gnu.org> + + * Makefile.in (etags_deps, etags_args): New, to reduce duplication. + (etags${EXEEXT}, ctags${EXEEXT}): Use etags_deps, etags_args. + + * Makefile.in (etags${EXEEXT}, ebrowse${EXEEXT}, ctags${EXEEXT}) + (profile${EXEEXT}, make-docfile${EXEEXT}, movemail${EXEEXT}) + (emacsclient${EXEEXT}, emacsclientw${EXEEXT}, hexl${EXEEXT}) + (update-game-score${EXEEXT}, emacsclient.res): Use $@. + + * Makefile.in (../lib/libgnu.a): Explicitly pass MFLAGS. + + * Makefile.in (DONT_INSTALL): Remove test-distrib. + (test-distrib${EXEEXT}): Remove rule. + + * test-distrib.c, testfile: Remove. + 2014-03-10 Juanma Barranquero <lekktu@gmail.com> * emacsclient.c (main): #ifdef out previous change on Windows. diff --git a/lib-src/Makefile.in b/lib-src/Makefile.in index 4d9fdba7726..3009ff26745 100644 --- a/lib-src/Makefile.in +++ b/lib-src/Makefile.in @@ -128,7 +128,7 @@ INSTALLABLE_SCRIPTS = grep-changelog UTILITIES = profile${EXEEXT} movemail${EXEEXT} hexl${EXEEXT} \ update-game-score${EXEEXT} -DONT_INSTALL= test-distrib${EXEEXT} make-docfile${EXEEXT} +DONT_INSTALL= make-docfile${EXEEXT} # Like UTILITIES, but they're not system-dependent, and should not be # deleted by the distclean target. @@ -303,48 +303,43 @@ tags: TAGS TAGS: etags${EXEEXT} etags *.[ch] -## This verifies that the non-ASCII characters in the file \`testfile\' -## have not been clobbered by whatever means were used to copy and -## distribute Emacs. If they were clobbered, all the .elc files were -## clobbered too. -test-distrib${EXEEXT}: ${srcdir}/test-distrib.c - $(CC) ${ALL_CFLAGS} -o test-distrib${EXEEXT} ${srcdir}/test-distrib.c - ./test-distrib ${srcdir}/testfile - ../lib/libgnu.a: $(config_h) - cd ../lib && $(MAKE) libgnu.a + cd ../lib && $(MAKE) $(MFLAGS) libgnu.a regex.o: $(srcdir)/../src/regex.c $(srcdir)/../src/regex.h $(config_h) ${CC} -c ${CPP_CFLAGS} ${srcdir}/../src/regex.c -etags${EXEEXT}: ${srcdir}/etags.c regex.o $(NTLIB) $(config_h) - $(CC) ${ALL_CFLAGS} -DEMACS_NAME="\"GNU Emacs\"" \ - -DVERSION="\"${version}\"" ${srcdir}/etags.c \ - regex.o $(LOADLIBES) $(NTLIB) -o etags${EXEEXT} + +etags_deps = ${srcdir}/etags.c regex.o $(NTLIB) $(config_h) +etags_cflags = -DEMACS_NAME="\"GNU Emacs\"" -DVERSION="\"${version}\"" -o $@ +etags_libs = regex.o $(LOADLIBES) $(NTLIB) + +etags${EXEEXT}: ${etags_deps} + $(CC) ${ALL_CFLAGS} $(etags_cflags) $(srcdir)/etags.c $(etags_libs) + +## ctags.c is distinct from etags.c so that parallel makes do not write two +## etags.o files on top of each other. +## FIXME? +## Can't we use a wrapper that calls 'etags --ctags'? +ctags${EXEEXT}: ctags.c ${etags_deps} + $(CC) ${ALL_CFLAGS} $(etags_cflags) $(srcdir)/ctags.c $(etags_libs) ebrowse${EXEEXT}: ${srcdir}/ebrowse.c ${srcdir}/../lib/min-max.h $(NTLIB) \ $(config_h) $(CC) ${ALL_CFLAGS} -DVERSION="\"${version}\"" \ - ${srcdir}/ebrowse.c $(LOADLIBES) $(NTLIB) -o ebrowse${EXEEXT} - -## We depend on etags to assure that parallel makes do not write two -## etags.o files on top of each other. -ctags${EXEEXT}: etags${EXEEXT} - $(CC) ${ALL_CFLAGS} -DCTAGS -DEMACS_NAME="\"GNU Emacs\"" \ - -DVERSION="\"${version}\"" ${srcdir}/etags.c \ - regex.o $(LOADLIBES) $(NTLIB) -o ctags${EXEEXT} + ${srcdir}/ebrowse.c $(LOADLIBES) $(NTLIB) -o $@ profile${EXEEXT}: ${srcdir}/profile.c $(NTLIB) $(config_h) $(CC) ${ALL_CFLAGS} ${srcdir}/profile.c \ - $(LOADLIBES) $(NTLIB) $(LIB_CLOCK_GETTIME) -o profile${EXEEXT} + $(LOADLIBES) $(NTLIB) $(LIB_CLOCK_GETTIME) -o $@ make-docfile${EXEEXT}: ${srcdir}/make-docfile.c $(NTLIB) $(config_h) $(CC) ${ALL_CFLAGS} ${srcdir}/make-docfile.c $(LOADLIBES) $(NTLIB) \ - -o make-docfile${EXEEXT} + -o $@ movemail${EXEEXT}: ${srcdir}/movemail.c pop.o $(NTLIB) $(config_h) $(CC) ${ALL_CFLAGS} ${MOVE_FLAGS} ${srcdir}/movemail.c pop.o \ - $(LOADLIBES) $(NTLIB) $(LIBS_MOVE) -o movemail${EXEEXT} + $(LOADLIBES) $(NTLIB) $(LIBS_MOVE) -o $@ pop.o: ${srcdir}/pop.c ${srcdir}/pop.h ${srcdir}/../lib/min-max.h $(config_h) $(CC) -c ${CPP_CFLAGS} ${MOVE_FLAGS} ${srcdir}/pop.c @@ -352,12 +347,12 @@ pop.o: ${srcdir}/pop.c ${srcdir}/pop.h ${srcdir}/../lib/min-max.h $(config_h) emacsclient${EXEEXT}: ${srcdir}/emacsclient.c $(NTLIB) $(config_h) $(CC) ${ALL_CFLAGS} ${srcdir}/emacsclient.c \ -DVERSION="\"${version}\"" $(NTLIB) $(LOADLIBES) $(LIB_FDATASYNC) \ - $(LIB_WSOCK32) $(LIBS_ECLIENT) -o emacsclient${EXEEXT} + $(LIB_WSOCK32) $(LIBS_ECLIENT) -o $@ emacsclientw${EXEEXT}: ${srcdir}/emacsclient.c $(NTLIB) $(CLIENTRES) $(config_h) $(CC) ${ALL_CFLAGS} $(CLIENTRES) -mwindows ${srcdir}/emacsclient.c \ -DVERSION="\"${version}\"" $(LOADLIBES) $(LIB_FDATASYNC) \ - $(LIB_WSOCK32) $(LIBS_ECLIENT) -o emacsclientw${EXEEXT} + $(LIB_WSOCK32) $(LIBS_ECLIENT) -o $@ NTINC = ${srcdir}/../nt/inc NTDEPS = $(NTINC)/ms-w32.h $(NTINC)/sys/stat.h $(NTINC)/inttypes.h \ @@ -370,15 +365,15 @@ ntlib.o: ${srcdir}/ntlib.c ${srcdir}/ntlib.h $(NTDEPS) $(CC) -c ${CPP_CFLAGS} ${srcdir}/ntlib.c hexl${EXEEXT}: ${srcdir}/hexl.c $(NTLIB) $(config_h) - $(CC) ${ALL_CFLAGS} ${srcdir}/hexl.c $(LOADLIBES) -o hexl${EXEEXT} + $(CC) ${ALL_CFLAGS} ${srcdir}/hexl.c $(LOADLIBES) -o $@ update-game-score${EXEEXT}: ${srcdir}/update-game-score.c $(NTLIB) $(config_h) $(CC) ${ALL_CFLAGS} -DHAVE_SHARED_GAME_DIR="\"$(gamedir)\"" \ ${srcdir}/update-game-score.c $(LOADLIBES) $(NTLIB) \ - -o update-game-score${EXEEXT} + -o $@ emacsclient.res: $(NTINC)/../emacsclient.rc - $(WINDRES) -O coff --include-dir=$(NTINC)/.. -o emacsclient.res \ + $(WINDRES) -O coff --include-dir=$(NTINC)/.. -o $@ \ $(NTINC)/../emacsclient.rc ## Makefile ends here. diff --git a/lib-src/ctags.c b/lib-src/ctags.c new file mode 100644 index 00000000000..0a6838a9dbb --- /dev/null +++ b/lib-src/ctags.c @@ -0,0 +1,2 @@ +#define CTAGS 1 +#include "etags.c" diff --git a/lib-src/test-distrib.c b/lib-src/test-distrib.c deleted file mode 100644 index 88b95db9060..00000000000 --- a/lib-src/test-distrib.c +++ /dev/null @@ -1,88 +0,0 @@ -/* test-distrib.c --- testing distribution of nonprinting chars - -Copyright (C) 1987, 1993-1995, 1999, 2001-2014 Free Software Foundation, -Inc. - -This file is part of GNU Emacs. - -GNU Emacs 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. - -GNU Emacs 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 GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ - - -#include <config.h> -#include <stdio.h> -#include <fcntl.h> -#include <unistd.h> - -/* Break string in two parts to avoid buggy C compilers that ignore characters - after nulls in strings. */ - -static char string1[] = "Testing distribution of nonprinting chars:\n\ -Should be 0177: \177 Should be 0377: \377 Should be 0212: \212.\n\ -Should be 0000: "; - -static char string2[] = ".\n\ -This file is read by the `test-distribution' program.\n\ -If you change it, you will make that program fail.\n"; - -/* Like `read' but keeps trying until it gets SIZE bytes or reaches eof. */ -static int -cool_read (int fd, char *buf, size_t size) -{ - ssize_t num; - ssize_t sofar = 0; - - while (1) - { - if ((num = read (fd, buf + sofar, size - sofar)) == 0) - return sofar; - else if (num < 0) - return num; - sofar += num; - } -} - -int -main (int argc, char **argv) -{ - int fd; - char buf[300]; - - if (argc != 2) - { - fprintf (stderr, "Usage: %s testfile\n", argv[0]); - exit (EXIT_FAILURE); - } - fd = open (argv[1], O_RDONLY); - if (fd < 0) - { - perror (argv[1]); - exit (EXIT_FAILURE); - } - if (cool_read (fd, buf, sizeof string1) != sizeof string1 || - strcmp (buf, string1) || - cool_read (fd, buf, sizeof string2) != sizeof string2 - 1 || - strncmp (buf, string2, sizeof string2 - 1)) - { - fprintf (stderr, "Data in file `%s' has been damaged.\n\ -Most likely this means that many nonprinting characters\n\ -have been corrupted in the files of Emacs, and it will not work.\n", - argv[1]); - exit (EXIT_FAILURE); - } - close (fd); - return EXIT_SUCCESS; -} - - -/* test-distrib.c ends here */ diff --git a/lib-src/testfile b/lib-src/testfile Binary files differdeleted file mode 100644 index 8230c35f405..00000000000 --- a/lib-src/testfile +++ /dev/null diff --git a/lib-src/update-game-score.c b/lib-src/update-game-score.c index cb6fdf73590..7a64cd04f47 100644 --- a/lib-src/update-game-score.c +++ b/lib-src/update-game-score.c @@ -76,9 +76,8 @@ static int unlock_file (const char *filename, void *state); struct score_entry { - intmax_t score; - char *username; - char *data; + char *score; + char *user_data; }; #define MAX_SCORES min (PTRDIFF_MAX, SIZE_MAX / sizeof (struct score_entry)) @@ -102,7 +101,8 @@ lose (const char *msg) static _Noreturn void lose_syserr (const char *msg) { - fprintf (stderr, "%s: %s\n", msg, strerror (errno)); + fprintf (stderr, "%s: %s\n", msg, + errno ? strerror (errno) : "Invalid data in score file"); exit (EXIT_FAILURE); } @@ -137,6 +137,38 @@ get_prefix (bool running_suid, const char *user_prefix) return user_prefix; } +static char * +normalize_integer (char *num) +{ + bool neg; + char *p; + while (*num != '\n' && isspace (*num)) + num++; + neg = *num == '-'; + num += neg || *num == '-'; + + if (*num == '0') + { + while (*++num == '0') + continue; + neg &= !!*num; + num -= !*num; + } + + for (p = num; '0' <= *p && *p <= '9'; p++) + continue; + + if (*p || p == num) + { + errno = 0; + return 0; + } + + if (neg) + *--num = '-'; + return num; +} + int main (int argc, char **argv) { @@ -144,9 +176,8 @@ main (int argc, char **argv) bool running_suid; void *lockstate; char *scorefile; - char *nl; + char *end, *nl, *user, *data; const char *prefix, *user_prefix = NULL; - struct stat buf; struct score_entry *scores; struct score_entry newscore; bool reverse = false; @@ -169,8 +200,8 @@ main (int argc, char **argv) break; case 'm': { - intmax_t m = strtoimax (optarg, 0, 10); - if (m < 0) + intmax_t m = strtoimax (optarg, &end, 10); + if (optarg == end || *end || m < 0) usage (EXIT_FAILURE); max_scores = min (m, MAX_SCORES); } @@ -194,21 +225,26 @@ main (int argc, char **argv) strcat (scorefile, "/"); strcat (scorefile, argv[optind]); - newscore.score = strtoimax (argv[optind + 1], 0, 10); + newscore.score = normalize_integer (argv[optind + 1]); + if (! newscore.score) + { + fprintf (stderr, "%s: Invalid score\n", argv[optind + 1]); + return EXIT_FAILURE; + } - newscore.data = argv[optind + 2]; - if (strlen (newscore.data) > MAX_DATA_LEN) - newscore.data[MAX_DATA_LEN] = '\0'; - nl = strchr (newscore.data, '\n'); + user = get_user_id (); + if (! user) + lose_syserr ("Couldn't determine user id"); + data = argv[optind + 2]; + if (strlen (data) > MAX_DATA_LEN) + data[MAX_DATA_LEN] = '\0'; + nl = strchr (data, '\n'); if (nl) *nl = '\0'; - - newscore.username = get_user_id (); - if (! newscore.username) - lose_syserr ("Couldn't determine user id"); - - if (stat (scorefile, &buf) < 0) - lose_syserr ("Failed to access scores file"); + newscore.user_data = malloc (strlen (user) + 1 + strlen (data) + 1); + if (! newscore.user_data + || sprintf (newscore.user_data, "%s %s", user, data) < 0) + lose_syserr ("Memory exhausted"); if (lock_file (scorefile, &lockstate) < 0) lose_syserr ("Failed to lock scores file"); @@ -244,137 +280,75 @@ main (int argc, char **argv) exit (EXIT_SUCCESS); } -static int -read_score (FILE *f, struct score_entry *score) +static char * +read_score (char *p, struct score_entry *score) { - int c; - if ((c = getc (f)) != EOF) - ungetc (c, f); - if (feof (f)) - return 1; - for (score->score = 0; (c = getc (f)) != EOF && isdigit (c); ) - { - if (INTMAX_MAX / 10 < score->score) - return -1; - score->score *= 10; - if (INTMAX_MAX - (c - '0') < score->score) - return -1; - score->score += c - '0'; - } - while ((c = getc (f)) != EOF - && isspace (c)) - ; - if (c == EOF) - return -1; - ungetc (c, f); -#ifdef HAVE_GETDELIM - { - size_t count = 0; - score->username = 0; - if (getdelim (&score->username, &count, ' ', f) < 1 - || score->username == NULL) - return -1; - /* Trim the space */ - score->username[strlen (score->username)-1] = '\0'; - } -#else - { - ptrdiff_t unameread = 0; - ptrdiff_t unamelen = 30; - char *username = malloc (unamelen); - if (!username) - return -1; - - while ((c = getc (f)) != EOF && c != ' ') - { - if (unameread >= unamelen - 1) - { - ptrdiff_t unamelen_max = min (PTRDIFF_MAX, SIZE_MAX); - if (unamelen <= unamelen_max / 2) - unamelen *= 2; - else if (unamelen < unamelen_max) - unamelen = unamelen_max; - else - { - errno = ENOMEM; - return -1; - } - username = realloc (username, unamelen); - if (!username) - return -1; - } - username[unameread] = c; - unameread++; - } - if (c == EOF) - return -1; - username[unameread] = '\0'; - score->username = username; - } -#endif -#ifdef HAVE_GETLINE - score->data = NULL; - errno = 0; - { - size_t len; - if (getline (&score->data, &len, f) < 0) - return -1; - score->data[strlen (score->data)-1] = '\0'; - } -#else - { - ptrdiff_t cur = 0; - ptrdiff_t len = 16; - char *buf = malloc (len); - if (!buf) - return -1; - while ((c = getc (f)) != EOF - && c != '\n') - { - if (cur >= len-1) - { - if (min (PTRDIFF_MAX, SIZE_MAX) / 2 < len) - { - errno = ENOMEM; - return -1; - } - if (!(buf = realloc (buf, len *= 2))) - return -1; - } - buf[cur] = c; - cur++; - } - score->data = buf; - score->data[cur] = '\0'; - } -#endif - return 0; + score->score = p; + p = strchr (p, ' '); + if (!p) + return p; + *p++ = 0; + score->user_data = p; + p = strchr (p, '\n'); + if (!p) + return p; + *p++ = 0; + return p; } static int read_scores (const char *filename, struct score_entry **scores, ptrdiff_t *count, ptrdiff_t *alloc) { - int readval = -1; - ptrdiff_t scorecount = 0; - ptrdiff_t cursize = 0; - struct score_entry *ret = 0; - struct score_entry entry; + char *p, *filedata; + ptrdiff_t filesize, nread; + struct stat st; FILE *f = fopen (filename, "r"); - int retval = -1; if (!f) return -1; - while ((readval = read_score (f, &entry)) == 0) - if (push_score (&ret, &scorecount, &cursize, &entry) < 0) + if (fstat (fileno (f), &st) != 0) + return -1; + if (! (0 <= st.st_size && st.st_size < min (PTRDIFF_MAX, SIZE_MAX))) + { + errno = EOVERFLOW; + return -1; + } + filesize = st.st_size; + filedata = malloc (filesize + 1); + if (! filedata) + return -1; + nread = fread (filedata, 1, filesize + 1, f); + if (filesize < nread) + { + errno = 0; return -1; - if (readval > 0 && fclose (f) == 0) + } + if (nread < filesize) + filesize = nread; + if (ferror (f) || fclose (f) != 0) + return -1; + filedata[filesize] = 0; + if (strlen (filedata) != filesize) { - *count = scorecount; - *alloc = cursize; - *scores = ret; - retval = 0; + errno = 0; + return -1; } - return retval; + + *scores = 0; + *count = *alloc = 0; + for (p = filedata; p < filedata + filesize; ) + { + struct score_entry entry; + p = read_score (p, &entry); + if (!p) + { + errno = 0; + return -1; + } + if (push_score (scores, count, alloc, &entry) < 0) + return -1; + } + return 0; } static int @@ -382,7 +356,25 @@ score_compare (const void *a, const void *b) { const struct score_entry *sa = (const struct score_entry *) a; const struct score_entry *sb = (const struct score_entry *) b; - return (sb->score > sa->score) - (sb->score < sa->score); + char *sca = sa->score; + char *scb = sb->score; + size_t lena, lenb; + bool nega = *sca == '-'; + bool negb = *scb == '-'; + int diff = nega - negb; + if (diff) + return diff; + if (nega) + { + char *tmp = sca; + sca = scb + 1; + scb = tmp + 1; + } + lena = strlen (sca); + lenb = strlen (scb); + if (lena != lenb) + return lenb < lena ? -1 : 1; + return strcmp (scb, sca); } static int @@ -451,18 +443,12 @@ write_scores (const char *filename, const struct score_entry *scores, if (! f) return -1; for (i = 0; i < count; i++) - if (fprintf (f, "%"PRIdMAX" %s %s\n", - scores[i].score, scores[i].username, scores[i].data) - < 0) + if (fprintf (f, "%s %s\n", scores[i].score, scores[i].user_data) < 0) return -1; if (fclose (f) != 0) return -1; if (rename (tempfile, filename) != 0) return -1; -#ifdef DOS_NT - if (chmod (filename, 0644) < 0) - return -1; -#endif return 0; } @@ -479,30 +465,27 @@ lock_file (const char *filename, void **state) strcpy (lockpath, filename); strcat (lockpath, lockext); *state = lockpath; - trylock: - attempts++; - /* If the lock is over an hour old, delete it. */ - if (stat (lockpath, &buf) == 0 - && 60 * 60 < time (0) - buf.st_ctime) - unlink (lockpath); - fd = open (lockpath, O_CREAT | O_EXCL, 0600); - if (fd < 0) + + while ((fd = open (lockpath, O_CREAT | O_EXCL, 0600)) < 0) { - if (errno == EEXIST) + if (errno != EEXIST) + return -1; + attempts++; + + /* Break the lock if it is over an hour old, or if we've tried + more than MAX_ATTEMPTS times. We won't corrupt the file, but + we might lose some scores. */ + if (MAX_ATTEMPTS < attempts + || (stat (lockpath, &buf) == 0 && 60 * 60 < time (0) - buf.st_ctime)) { - /* Break the lock; we won't corrupt the file, but we might - lose some scores. */ - if (attempts > MAX_ATTEMPTS) - { - unlink (lockpath); - attempts = 0; - } - sleep ((rand () % 2)+1); - goto trylock; + if (unlink (lockpath) != 0 && errno != ENOENT) + return -1; + attempts = 0; } - else - return -1; + + sleep ((rand () & 1) + 1); } + close (fd); return 0; } |