Atrinik Client 2.5
client/server_files.c
Go to the documentation of this file.
00001 /************************************************************************
00002 *            Atrinik, a Multiplayer Online Role Playing Game            *
00003 *                                                                       *
00004 *    Copyright (C) 2009-2011 Alex Tokar and Atrinik Development Team    *
00005 *                                                                       *
00006 * Fork from Daimonin (Massive Multiplayer Online Role Playing Game)     *
00007 * and Crossfire (Multiplayer game for X-windows).                       *
00008 *                                                                       *
00009 * This program is free software; you can redistribute it and/or modify  *
00010 * it under the terms of the GNU General Public License as published by  *
00011 * the Free Software Foundation; either version 2 of the License, or     *
00012 * (at your option) any later version.                                   *
00013 *                                                                       *
00014 * This program is distributed in the hope that it will be useful,       *
00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00017 * GNU General Public License for more details.                          *
00018 *                                                                       *
00019 * You should have received a copy of the GNU General Public License     *
00020 * along with this program; if not, write to the Free Software           *
00021 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.             *
00022 *                                                                       *
00023 * The author can be reached at admin@atrinik.org                        *
00024 ************************************************************************/
00025 
00030 #include <global.h>
00031 
00033 static const char *const server_file_names[SERVER_FILES_MAX] =
00034 {
00035     NULL, NULL, NULL, NULL, "bmaps",
00036     "hfiles", "updates", "spells", "settings",
00037     "anims", "effects", "skills"
00038 };
00039 
00041 static const char *const server_file_setup_names[SERVER_FILES_MAX] =
00042 {
00043     NULL, NULL, NULL, NULL, "bpf",
00044     "hpf", "upf", "spfv2", "ssf",
00045     "amfv2", "eff", "skfv2"
00046 };
00047 
00049 static void (*server_file_funcs[SERVER_FILES_MAX])() =
00050 {
00051     NULL, NULL, NULL, NULL, read_bmaps,
00052     read_help_files, file_updates_parse, spells_init, server_settings_init,
00053     read_anims, effects_init, skills_init
00054 };
00055 
00057 static void (*server_file_funcs_reload[SERVER_FILES_MAX])() =
00058 {
00059     NULL, NULL, NULL, NULL, NULL,
00060     NULL, NULL, spells_reload, NULL,
00061     anims_reset, effects_reinit, skills_reload
00062 };
00063 
00065 static server_files_struct server_files[SERVER_FILES_MAX];
00066 
00069 void server_files_init()
00070 {
00071     memset(&server_files, 0, sizeof(server_files));
00072 }
00073 
00078 void server_files_load(int post_load)
00079 {
00080     size_t i;
00081     FILE *fp;
00082     struct stat sb;
00083     size_t st_size, numread;
00084     char *contents;
00085 
00086     for (i = 0; i < SERVER_FILES_MAX; i++)
00087     {
00088         /* Invalid server file. */
00089         if (!server_file_names[i])
00090         {
00091             continue;
00092         }
00093 
00094         /* Server file was loaded previously. */
00095         if (post_load && server_files[i].loaded)
00096         {
00097             if (server_file_funcs_reload[i])
00098             {
00099                 server_file_funcs_reload[i]();
00100             }
00101 
00102             continue;
00103         }
00104 
00105         /* Open the file. */
00106         fp = server_file_open(i);
00107 
00108         if (!fp)
00109         {
00110             return;
00111         }
00112 
00113         /* Get and store the size. */
00114         fstat(fileno(fp), &sb);
00115         st_size = sb.st_size;
00116         server_files[i].size = st_size;
00117 
00118         /* Allocate temporary buffer and read into it the file. */
00119         contents = malloc(st_size);
00120         numread = fread(contents, 1, st_size, fp);
00121 
00122         /* Calculate and store the checksum, free the temporary buffer
00123          * and close the file pointer. */
00124         server_files[i].crc32 = crc32(1L, (const unsigned char FAR *) contents, numread);
00125         free(contents);
00126         fclose(fp);
00127 
00128         if (post_load)
00129         {
00130             /* Mark that we have loaded this file. */
00131             server_files[i].loaded = 1;
00132 
00133             if (server_file_funcs[i])
00134             {
00135                 server_file_funcs[i]();
00136             }
00137         }
00138     }
00139 }
00140 
00147 static char *server_file_path(size_t id, char *buf, size_t buf_size)
00148 {
00149     snprintf(buf, buf_size, "srv_files/%s", server_file_names[id]);
00150     return buf;
00151 }
00152 
00157 FILE *server_file_open(size_t id)
00158 {
00159     char buf[MAX_BUF];
00160 
00161     /* Doesn't exist. */
00162     if (!server_file_names[id])
00163     {
00164         return NULL;
00165     }
00166 
00167     server_file_path(id, buf, sizeof(buf));
00168     return fopen_wrapper(buf, "rb");
00169 }
00170 
00176 void server_file_save(size_t id, unsigned char *data, size_t len)
00177 {
00178     char path[MAX_BUF];
00179     FILE *fp;
00180 
00181     /* Finished updating. */
00182     server_files[id].update = 0;
00183 
00184     server_file_path(id, path, sizeof(path));
00185     fp = fopen_wrapper(path, "wb");
00186 
00187     if (!fp)
00188     {
00189         LOG(llevBug, "server_file_save(): Can't open %s for writing.\n", path);
00190         return;
00191     }
00192 
00193     if (fwrite(data, 1, len, fp) != len)
00194     {
00195         LOG(llevBug, "server_file_save(): Failed to write to %s.\n", path);
00196     }
00197     else
00198     {
00199         /* Mark the server file for reload. */
00200         server_files[id].loaded = 0;
00201     }
00202 
00203     fclose(fp);
00204 }
00205 
00209 int server_files_updating()
00210 {
00211     size_t i;
00212 
00213     /* Check all files. */
00214     for (i = 0; i < SERVER_FILES_MAX; i++)
00215     {
00216         /* The server file was marked for update previously, so start
00217          * updating. */
00218         if (server_files[i].update == 1)
00219         {
00220             char buf[MAX_BUF];
00221 
00222             snprintf(buf, sizeof(buf), "rf %"FMT64U, (uint64) i);
00223             cs_write_string(buf, strlen(buf));
00224             /* Mark the file as 'being updated'. */
00225             server_files[i].update = -1;
00226             return 1;
00227         }
00228         /* The file is being updated. */
00229         else if (server_files[i].update == -1)
00230         {
00231             return 1;
00232         }
00233     }
00234 
00235     return 0;
00236 }
00237 
00243 void server_files_setup_add(char *buf, size_t buf_size)
00244 {
00245     size_t i;
00246     char tmp[MAX_BUF];
00247 
00248     /* Load up the files. */
00249     server_files_load(0);
00250 
00251     for (i = 0; i < SERVER_FILES_MAX; i++)
00252     {
00253         /* Invalid file. */
00254         if (!server_file_setup_names[i])
00255         {
00256             continue;
00257         }
00258 
00259         /* Add the server file identifier, its size and the checksum. */
00260         snprintf(tmp, sizeof(tmp), " %s %"FMT64U"|%lx", server_file_setup_names[i], (uint64) server_files[i].size, server_files[i].crc32);
00261         strncat(buf, tmp, buf_size - strlen(buf) - 1);
00262     }
00263 }
00264 
00270 int server_files_parse_setup(const char *cmd, const char *param)
00271 {
00272     size_t i;
00273 
00274     for (i = 0; i < SERVER_FILES_MAX; i++)
00275     {
00276         /* Invalid file. */
00277         if (!server_file_setup_names[i])
00278         {
00279             continue;
00280         }
00281 
00282         /* Check if the command matches one of the names. */
00283         if (!strcmp(server_file_setup_names[i], cmd))
00284         {
00285             /* If the response is not 'OK', it's different, so mark for
00286              * update. */
00287             if (strcmp(param, "OK"))
00288             {
00289                 server_files[i].update = 1;
00290             }
00291 
00292             return 1;
00293         }
00294     }
00295 
00296     return 0;
00297 }
00298 
00301 void server_files_clear_update()
00302 {
00303     size_t i;
00304 
00305     for (i = 0; i < SERVER_FILES_MAX; i++)
00306     {
00307         /* Invalid file. */
00308         if (!server_file_setup_names[i])
00309         {
00310             continue;
00311         }
00312 
00313         server_files[i].update = 0;
00314     }
00315 }