Commit 98a428c1 authored by Eli Zaretskii's avatar Eli Zaretskii
Browse files

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.
parent 5c0e57fe
2013-08-05 Eli Zaretskii <eliz@gnu.org>
* 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 <eliz@gnu.org> 2013-08-04 Eli Zaretskii <eliz@gnu.org>
* ntlib.h: Include fcntl.h. * ntlib.h: Include fcntl.h.
......
...@@ -424,14 +424,14 @@ lstat (const char * path, struct stat * buf) ...@@ -424,14 +424,14 @@ lstat (const char * path, struct stat * buf)
} }
/* Implementation of mkostemp for MS-Windows, to avoid race conditions /* 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 This is used only in update-game-score.c. It is overkill for that
use pid or tid with a letter on the front (in place of the 6 X's) use case, since update-game-score renames the temporary file into
and cycle through the letters to find a unique name. We extend the game score file, which isn't atomic on MS-Windows anyway, when
that to allow any reasonable character as the first of the 6 X's, the game score already existed before running the program, which it
so that the number of simultaneously used temporary files will be almost always does. But using a simpler implementation just to
greater. */ make a point is uneconomical... */
int int
mkostemp (char * template, int flags) mkostemp (char * template, int flags)
...@@ -477,3 +477,17 @@ 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. */ /* Template is badly formed or else we can't generate a unique name. */
return -1; 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;
}
...@@ -69,7 +69,6 @@ int mkostemp (char * template, int flags); ...@@ -69,7 +69,6 @@ int mkostemp (char * template, int flags);
#define pipe _pipe #define pipe _pipe
#undef read #undef read
#define read _read #define read _read
#undef rename
#undef rmdir #undef rmdir
#define rmdir _rmdir #define rmdir _rmdir
#undef unlink #undef unlink
......
...@@ -228,10 +228,11 @@ static int ...@@ -228,10 +228,11 @@ static int
read_score (FILE *f, struct score_entry *score) read_score (FILE *f, struct score_entry *score)
{ {
int c; int c;
if ((c = getc (f)) != EOF)
ungetc (c, f);
if (feof (f)) if (feof (f))
return 1; return 1;
while ((c = getc (f)) != EOF for (score->score = 0; (c = getc (f)) != EOF && isdigit (c); )
&& isdigit (c))
{ {
score->score *= 10; score->score *= 10;
score->score += (c-48); score->score += (c-48);
...@@ -311,21 +312,19 @@ read_score (FILE *f, struct score_entry *score) ...@@ -311,21 +312,19 @@ read_score (FILE *f, struct score_entry *score)
static int static int
read_scores (const char *filename, struct score_entry **scores, int *count) read_scores (const char *filename, struct score_entry **scores, int *count)
{ {
int readval, scorecount, cursize; int readval = -1, scorecount, cursize;
struct score_entry *ret; struct score_entry *ret;
FILE *f = fopen (filename, "r"); FILE *f = fopen (filename, "r");
int retval = -1;
if (!f) if (!f)
return -1; return -1;
scorecount = 0; scorecount = 0;
cursize = 16; cursize = 16;
ret = (struct score_entry *) malloc (sizeof (struct score_entry) * cursize); ret = (struct score_entry *) malloc (sizeof (struct score_entry) * cursize);
if (!ret) if (ret)
return -1; {
while ((readval = read_score (f, &ret[scorecount])) == 0) while ((readval = read_score (f, &ret[scorecount])) == 0)
{ {
/* We encountered an error. */
if (readval < 0)
return -1;
scorecount++; scorecount++;
if (scorecount >= cursize) if (scorecount >= cursize)
{ {
...@@ -333,12 +332,18 @@ read_scores (const char *filename, struct score_entry **scores, int *count) ...@@ -333,12 +332,18 @@ read_scores (const char *filename, struct score_entry **scores, int *count)
ret = (struct score_entry *) ret = (struct score_entry *)
realloc (ret, (sizeof (struct score_entry) * cursize)); realloc (ret, (sizeof (struct score_entry) * cursize));
if (!ret) if (!ret)
return -1; break;
}
} }
} }
if (readval > 0)
{
*count = scorecount; *count = scorecount;
*scores = ret; *scores = ret;
return 0; retval = 0;
}
fclose (f);
return retval;
} }
static int static int
...@@ -461,5 +466,4 @@ unlock_file (const char *filename, void *state) ...@@ -461,5 +466,4 @@ unlock_file (const char *filename, void *state)
return ret; return ret;
} }
/* update-game-score.c ends here */ /* update-game-score.c ends here */
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment