static void SaveMetasCache()
{
FILE *cache;
char cacheFileName[PATH_MAX];
char tmpFileName[PATH_MAX];
char str[LINE];
int i, len;
/* overwrite existing file if possible */
if (metaUDPCache && !findfile(metaUDPCache, cacheFileName))
strcpy(cacheFileName, metaUDPCache);
if (metaUDPCache)
{
len = strlen(cacheFileName);
strcpy(tmpFileName, cacheFileName);
/* create a temporary file with roughly the same name */
if ((cacheFileName[len - 1] == 'T') || (cacheFileName[len - 1] == 't'))
tmpFileName[len-1] = 'R';
else
tmpFileName[len-1] = 'T';
cache = fopen(tmpFileName, "w");
if (cache == NULL)
{
LineToConsole ("Cannot create a metaUDPCache temporary file `%s'\n",
tmpFileName);
LineToConsole("Meta-server read will not be cached.\n");
}
}
else
{
cache = NULL;
}
if (cache != NULL)
{
/* Save status level and number of servers on first line - these variables
determine whether to use the cache during LoadMetasCache() */
sprintf (str, "%d,%d\n", statusLevel, num_servers);
fputs (str, cache);
/* Save important data in a similar, but not identical, manner to how the
metaserver sends the UDP metadata. The internal status types are not saved,
instead they default to "Active". */
for (i = 0; i < num_servers; i++)
{
sprintf(str,"%s,%d,%lld,%d,%d,%d,%d,%c\n",
serverlist[i].address,
serverlist[i].port,
serverlist[i].when,
serverlist[i].age,
serverlist[i].lifetime,
serverlist[i].players,
((serverlist[i].status <= statusNull) ? serverlist[i].status : statusNull),
serverlist[i].typeflag);
fputs (str, cache);
}
fclose(cache);
/* Can't rename file to existing name under NT */
#ifdef _MSC_VER
_unlink(metaUDPCache);
#else
unlink(metaUDPCache);
#endif
if (rename(tmpFileName, metaUDPCache) == -1)
perror("Could not rename new cache file");
}
}
static void LoadMetasCache()
{
FILE *cache;
char *buffer;
char *p;
char cacheFileName[PATH_MAX];
long lSize;
int i, j;
int invalid[MAX_SERVERS] = {0};
if(!metaUDPCache)
{
num_servers = 0;
return;
}
cache = fopen(cacheFileName, "r");
if (cache == NULL)
{
num_servers = 0;
return;
}
/* Obtain file size. */
fseek (cache , 0 , SEEK_END);
lSize = ftell (cache);
rewind (cache);
/* Allocate memory to contain the whole file. */
buffer = (char*) malloc (lSize);
if (buffer == NULL)
{
num_servers = 0;
fclose(cache);
return;
}
/* Copy the file into the buffer. */
fread (buffer,1,lSize,cache);
/* Read in statusLevel */
p = strtok(buffer,",");
if (p == NULL)
{
num_servers = 0;
fclose(cache);
return;
}
i = atoi(p);
/* Ignore the cache if user changed statusLevel */
if (i != statusLevel)
{
num_servers = 0;
fclose(cache);
return;
}
/* Read in number of servers */
p = strtok(NULL,"\n");
if (p == NULL)
{
num_servers = 0;
fclose(cache);
return;
}
num_servers = atoi(p);
/* Allocate memory for server list */
serverlist = (struct servers *) malloc(sizeof(struct servers)*num_servers);
/* Load servers into server list */
for(i = 0; i < num_servers; i++)
{
p = strtok(NULL,","); /* hostname */
if (p == NULL) {
invalid[i] = 1;
continue;
}
strcpy(serverlist[i].address, p);
p = strtok(NULL,","); /* port */
if (p == NULL) {
invalid[i] = 1;
continue;
}
serverlist[i].port = atoi(p);
p = strtok(NULL,","); /* when */
if (p == NULL) {
invalid[i] = 1;
continue;
}
serverlist[i].when = atoi(p);
p = strtok(NULL,","); /* age */
if (p == NULL) {
invalid[i] = 1;
continue;
}
serverlist[i].age = atoi(p);
p = strtok(NULL,","); /* lifetime */
if (p == NULL) {
invalid[i] = 1;
continue;
}
serverlist[i].lifetime = atoi(p);
p = strtok(NULL,","); /* players */
if (p == NULL) {
invalid[i] = 1;
continue;
}
serverlist[i].players = atoi(p);
p = strtok(NULL,","); /* status */
if (p == NULL) {
invalid[i] = 1;
continue;
}
serverlist[i].status = atoi(p);
p = strtok(NULL,"\n"); /* type */
if (p == NULL) {
invalid[i] = 1;
continue;
}
serverlist[i].typeflag = p[0];
strcpy(serverlist[i].comment, "");
/* mark each server as needing to be refreshed */
serverlist[i].refresh = 1;
#ifdef METAPING
/* Initialize the ping rtt fields */
for (j = 0; j < RTT_AVG_BUFLEN; ++j )
serverlist[i].pkt_rtt[j] = (unsigned long) -1;
#endif
}
fclose(cache);
/* hunt and kill old server lines from cache */
for(i=0;i<num_servers;i++)
{
/* skip the deletion below if the entry was received recently,
and all the data was valid */
if (serverlist[i].lifetime-- > 0 && !invalid[i]) continue;
/* delete this entry by moving the ones above down */
for(j=i;j<num_servers-1;j++)
{
memcpy(&serverlist[j],&serverlist[j+1],sizeof(struct servers));
}
/* adjust the current entry pointer, limit, and resize the memory */
i--;
num_servers--;
serverlist =
(struct servers *) realloc(serverlist,
sizeof(struct servers) * ( num_servers ));
}
}