From: Eli Zaretskii Date: Mon, 5 Aug 2013 17:09:28 +0000 (+0300) Subject: Fix bugs in update-game-score, on MS-Windows and elsewhere. X-Git-Tag: emacs-24.3.90~173^2^2~42^2~45^2~387^2~1686^2~415 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=98a428c15ad48f8579b00b68aae6a89b34238b12;p=emacs.git Fix bugs in update-game-score, on MS-Windows and elsewhere. lib-src/update-game-score.c (read_score): Try reading a character before probing the stream for EOF. Initialize score->score to zero, before reading and accumulating the score. (read_scores): Fix logic that determines which value to return. Close the input stream when finished reading the scores (avoids failures in overwriting the file with a new one on MS-Windows, since a file that is open cannot be deleted). lib-src/ntlib.h (rename): Don't undefine. lib-src/ntlib.c (sys_rename): New function, needed for update-game-score. --- diff --git a/lib-src/ChangeLog b/lib-src/ChangeLog index ace62d9d8f7..0336eae0981 100644 --- a/lib-src/ChangeLog +++ b/lib-src/ChangeLog @@ -1,3 +1,18 @@ +2013-08-05 Eli Zaretskii + + * update-game-score.c (read_score): Try reading a character before + probing the stream for EOF. Initialize score->score to zero, + before reading and accumulating the score. + (read_scores): Fix logic that determines which value to return. + Close the input stream when finished reading the scores (avoids + failures in overwriting the file with a new one on MS-Windows, + since a file that is open cannot be deleted). + + * ntlib.h (rename): Don't undefine. + + * ntlib.c (sys_rename): New function, needed for + update-game-score. + 2013-08-04 Eli Zaretskii * ntlib.h: Include fcntl.h. diff --git a/lib-src/ntlib.c b/lib-src/ntlib.c index 0d0642d1bf2..ab7d8b590df 100644 --- a/lib-src/ntlib.c +++ b/lib-src/ntlib.c @@ -424,14 +424,14 @@ lstat (const char * path, struct stat * buf) } /* Implementation of mkostemp for MS-Windows, to avoid race conditions - when using mktemp. + when using mktemp. Copied from w32.c. - Standard algorithm for generating a temporary file name seems to be - use pid or tid with a letter on the front (in place of the 6 X's) - and cycle through the letters to find a unique name. We extend - that to allow any reasonable character as the first of the 6 X's, - so that the number of simultaneously used temporary files will be - greater. */ + This is used only in update-game-score.c. It is overkill for that + use case, since update-game-score renames the temporary file into + the game score file, which isn't atomic on MS-Windows anyway, when + the game score already existed before running the program, which it + almost always does. But using a simpler implementation just to + make a point is uneconomical... */ int mkostemp (char * template, int flags) @@ -477,3 +477,17 @@ mkostemp (char * template, int flags) /* Template is badly formed or else we can't generate a unique name. */ return -1; } + +/* On Windows, you cannot rename into an existing file. */ +int +sys_rename (const char *from, const char *to) +{ + int retval = rename (from, to); + + if (retval < 0 && errno == EEXIST) + { + if (unlink (to) == 0) + retval = rename (from, to); + } + return retval; +} diff --git a/lib-src/ntlib.h b/lib-src/ntlib.h index c30958365ca..ab5f5ea3b89 100644 --- a/lib-src/ntlib.h +++ b/lib-src/ntlib.h @@ -69,7 +69,6 @@ int mkostemp (char * template, int flags); #define pipe _pipe #undef read #define read _read -#undef rename #undef rmdir #define rmdir _rmdir #undef unlink diff --git a/lib-src/update-game-score.c b/lib-src/update-game-score.c index 1699e305c8d..92c1663f658 100644 --- a/lib-src/update-game-score.c +++ b/lib-src/update-game-score.c @@ -228,10 +228,11 @@ static int read_score (FILE *f, struct score_entry *score) { int c; + if ((c = getc (f)) != EOF) + ungetc (c, f); if (feof (f)) return 1; - while ((c = getc (f)) != EOF - && isdigit (c)) + for (score->score = 0; (c = getc (f)) != EOF && isdigit (c); ) { score->score *= 10; score->score += (c-48); @@ -311,34 +312,38 @@ read_score (FILE *f, struct score_entry *score) static int read_scores (const char *filename, struct score_entry **scores, int *count) { - int readval, scorecount, cursize; + int readval = -1, scorecount, cursize; struct score_entry *ret; FILE *f = fopen (filename, "r"); + int retval = -1; if (!f) return -1; scorecount = 0; cursize = 16; ret = (struct score_entry *) malloc (sizeof (struct score_entry) * cursize); - if (!ret) - return -1; - while ((readval = read_score (f, &ret[scorecount])) == 0) + if (ret) { - /* We encountered an error. */ - if (readval < 0) - return -1; - scorecount++; - if (scorecount >= cursize) + while ((readval = read_score (f, &ret[scorecount])) == 0) { - cursize *= 2; - ret = (struct score_entry *) - realloc (ret, (sizeof (struct score_entry) * cursize)); - if (!ret) - return -1; + scorecount++; + if (scorecount >= cursize) + { + cursize *= 2; + ret = (struct score_entry *) + realloc (ret, (sizeof (struct score_entry) * cursize)); + if (!ret) + break; + } } } - *count = scorecount; - *scores = ret; - return 0; + if (readval > 0) + { + *count = scorecount; + *scores = ret; + retval = 0; + } + fclose (f); + return retval; } static int @@ -461,5 +466,4 @@ unlock_file (const char *filename, void *state) return ret; } - /* update-game-score.c ends here */