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 0 && !invalid[i]) continue; /* delete this entry by moving the ones above down */ for(j=i;j