Atrinik Client 2.5
client/updates.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 
00036 static size_t file_updates_requested = 0;
00037 
00041 static void file_updates_request(char *filename)
00042 {
00043     SockList sl;
00044     unsigned char buf[HUGE_BUF];
00045 
00046     sl.buf = buf;
00047     sl.len = 0;
00048     SockList_AddString(&sl, "upf ");
00049     SockList_AddString(&sl, filename);
00050     send_socklist(sl);
00051 
00052     file_updates_requested++;
00053 }
00054 
00060 void cmd_request_update(unsigned char *data, int len)
00061 {
00062     char filename[MAX_BUF], c;
00063     size_t pos = 0, i = 0;
00064     unsigned long ucomp_len;
00065     unsigned char *dest;
00066     FILE *fp;
00067 
00068     filename[0] = '\0';
00069     file_updates_requested--;
00070 
00071     while ((c = (char) (data[pos++])))
00072     {
00073         filename[i++] = c;
00074     }
00075 
00076     filename[i] = '\0';
00077     len -= i;
00078     ucomp_len = GetInt_String(data + pos);
00079     pos += 4;
00080     len -= 4;
00081 
00082     /* Uncompress it. */
00083     dest = malloc(ucomp_len);
00084     uncompress((Bytef *) dest, (uLongf *) &ucomp_len, (const Bytef *) data + pos, (uLong) len);
00085     data = dest;
00086     len = ucomp_len;
00087 
00088     fp = fopen_wrapper(filename, "wb");
00089 
00090     if (!fp)
00091     {
00092         LOG(llevBug, "Could not open file '%s' for writing.\n", filename);
00093         free(dest);
00094         return;
00095     }
00096 
00097     /* Update the file. */
00098     fwrite(data, 1, len, fp);
00099     fclose(fp);
00100     free(dest);
00101     LOG(llevInfo, "Updated file '%s'.\n", filename);
00102 }
00103 
00107 int file_updates_finished()
00108 {
00109     return file_updates_requested == 0;
00110 }
00111 
00114 void file_updates_parse()
00115 {
00116     FILE *fp;
00117     char buf[HUGE_BUF];
00118 
00119     /* Is the feature disabled? */
00120     if (setting_get_int(OPT_CAT_CLIENT, OPT_DISABLE_FILE_UPDATES))
00121     {
00122         return;
00123     }
00124 
00125     fp = server_file_open(SERVER_FILE_UPDATES);
00126 
00127     if (!fp)
00128     {
00129         return;
00130     }
00131 
00132     while (fgets(buf, sizeof(buf) - 1, fp))
00133     {
00134         char filename[MAX_BUF], crc_buf[MAX_BUF], *contents;
00135         uint64 size;
00136         size_t st_size, numread;
00137         FILE *fp2;
00138         unsigned long crc;
00139         struct stat sb;
00140 
00141         if (sscanf(buf, "%s %"FMT64U" %s", filename, &size, crc_buf) != 3)
00142         {
00143             continue;
00144         }
00145 
00146         fp2 = fopen_wrapper(filename, "rb");
00147 
00148         /* No such file? Then we'll want to update this. */
00149         if (!fp2)
00150         {
00151             file_updates_request(filename);
00152             continue;
00153         }
00154 
00155         fstat(fileno(fp2), &sb);
00156         st_size = sb.st_size;
00157         contents = malloc(st_size);
00158         numread = fread(contents, 1, st_size, fp2);
00159         fclose(fp2);
00160 
00161         /* Get the CRC32... */
00162         crc = crc32(1L, (const unsigned char FAR *) contents, numread);
00163         free(contents);
00164 
00165         /* If the checksum or the size doesn't match, we'll want to update it. */
00166         if (crc != strtoul(crc_buf, NULL, 16) || st_size != (size_t) size)
00167         {
00168             file_updates_request(filename);
00169         }
00170     }
00171 
00172     fclose(fp);
00173 }