Atrinik Server  4.0
updates.c
Go to the documentation of this file.
1 /*************************************************************************
2  * Atrinik, a Multiplayer Online Role Playing Game *
3  * *
4  * Copyright (C) 2009-2014 Alex Tokar and Atrinik Development Team *
5  * *
6  * Fork from Crossfire (Multiplayer game for X-windows). *
7  * *
8  * This program is free software; you can redistribute it and/or modify *
9  * it under the terms of the GNU General Public License as published by *
10  * the Free Software Foundation; either version 2 of the License, or *
11  * (at your option) any later version. *
12  * *
13  * This program is distributed in the hope that it will be useful, *
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16  * GNU General Public License for more details. *
17  * *
18  * You should have received a copy of the GNU General Public License *
19  * along with this program; if not, write to the Free Software *
20  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
21  * *
22  * The author can be reached at admin@atrinik.org *
23  ************************************************************************/
24 
30 #include <global.h>
31 #include <toolkit/packet.h>
32 #include <toolkit/string.h>
33 #include <toolkit/path.h>
34 #include <zlib.h>
35 
42 static size_t update_files_num;
43 
51 static void updates_file_new(const char *filename, struct stat *sb)
52 {
53  char *contents, *compressed;
54  size_t st_size, numread;
55  FILE *fp;
56 
57  update_files = erealloc(update_files, sizeof(update_file_struct) * (update_files_num + 1));
58 
59  st_size = sb->st_size;
60  /* Allocate a buffer to hold the whole file. */
61  contents = emalloc(st_size);
62 
63  fp = fopen(filename, "rb");
64 
65  if (!fp) {
66  LOG(ERROR, "Could not open file '%s' for reading.", filename);
67  exit(1);
68  }
69 
70  numread = fread(contents, 1, st_size, fp);
71  fclose(fp);
72 
73  update_files[update_files_num].filename = estrdup(filename + strlen(UPDATES_DIR_NAME) + 1);
74  update_files[update_files_num].checksum = crc32(1L, (const unsigned char FAR *) contents, numread);
75  update_files[update_files_num].ucomp_len = numread;
76  /* Calculate the upper bound of the compressed size. */
77  numread = compressBound(st_size);
78  /* Allocate a buffer to hold the compressed file. */
79  compressed = emalloc(numread);
80  compress2((Bytef *) compressed, (uLong *) & numread, (const unsigned char FAR *) contents, st_size, Z_BEST_COMPRESSION);
81  update_files[update_files_num].contents = emalloc(numread);
82  memcpy(update_files[update_files_num].contents, compressed, numread);
83  update_files[update_files_num].len = numread;
84 
85  /* Free temporary buffers. */
86  efree(contents);
87  efree(compressed);
88 
89  update_files[update_files_num].packet = packet_new(CLIENT_CMD_FILE_UPDATE, 0, 0);
90  packet_debug_data(update_files[update_files_num].packet, 0, "Filename");
91  packet_append_string_terminated(update_files[update_files_num].packet, update_files[update_files_num].filename);
92  packet_debug_data(update_files[update_files_num].packet, 0, "File size");
93  packet_append_uint32(update_files[update_files_num].packet, update_files[update_files_num].ucomp_len);
94  packet_debug_data(update_files[update_files_num].packet, 0, "File data");
95  packet_append_data_len(update_files[update_files_num].packet, update_files[update_files_num].contents, update_files[update_files_num].len);
97 }
98 
108 static int updates_file_compare(const void *a, const void *b)
109 {
110  return strcmp(((const update_file_struct *) a)->filename, ((const update_file_struct *) b)->filename);
111 }
112 
120 static update_file_struct *updates_file_find(const char *filename)
121 {
122  update_file_struct key;
123 
124  key.filename = (char *) filename;
125  return bsearch(&key, update_files, update_files_num, sizeof(update_file_struct), updates_file_compare);
126 }
127 
133 static void updates_traverse(const char *path)
134 {
135  DIR *dir = opendir(path);
136  struct dirent *d;
137  char filename[HUGE_BUF];
138  struct stat sb;
139 
140  if (!dir) {
141  LOG(ERROR, "Could not open directory '%s'.", path);
142  exit(1);
143  }
144 
145  while ((d = readdir(dir))) {
146  /* Ignore . and .. entries. */
147  if (!strncmp(d->d_name, ".", NAMLEN(d)) || !strncmp(d->d_name, "..", NAMLEN(d))) {
148  continue;
149  }
150 
151  snprintf(filename, sizeof(filename), "%s/%s", path, d->d_name);
152  stat(filename, &sb);
153 
154  /* Go recursively through directories. */
155  if (S_ISDIR(sb.st_mode)) {
156  updates_traverse(filename);
157  continue;
158  }
159 
160  updates_file_new(filename, &sb);
161  }
162 
163  closedir(dir);
164 }
165 
170 void updates_init(void)
171 {
172  char path[HUGE_BUF];
173  FILE *fp;
174  size_t i;
175 
176  update_files = NULL;
177  update_files_num = 0;
178 
179  if (path_exists(UPDATES_DIR_NAME)) {
181 
182  /* Sort the entries. */
183  if (update_files != NULL) {
184  qsort(update_files, update_files_num, sizeof(update_file_struct), updates_file_compare);
185  }
186  }
187 
188  snprintf(path, sizeof(path), "%s/%s", settings.datapath, UPDATES_FILE_NAME);
189  fp = fopen(path, "wb");
190 
191  if (!fp) {
192  LOG(ERROR, "Could not open file '%s' for writing.", path);
193  exit(1);
194  }
195 
196  for (i = 0; i < update_files_num; i++) {
197  update_file_struct *tmp = &update_files[i];
198 
199  fprintf(fp, "%s %"PRIu64 " %lx\n", tmp->filename, (uint64_t) tmp->ucomp_len, tmp->checksum);
200  }
201 
202  fclose(fp);
203 }
204 
205 void socket_command_request_update(socket_struct *ns, player *pl, uint8_t *data, size_t len, size_t pos)
206 {
207  char buf[MAX_BUF];
208  update_file_struct *tmp;
209 
210  if (ns->state != ST_LOGIN) {
211  return;
212  }
213 
214  /* Try to find the file. */
215  tmp = updates_file_find(packet_to_string(data, len, &pos, buf, sizeof(buf)));
216 
217  /* Invalid file. */
218  if (!tmp) {
219  return;
220  }
221 
222  socket_send_packet(ns, packet_dup(tmp->packet));
223 }
char datapath[MAX_BUF]
Definition: global.h:343
static size_t update_files_num
Definition: updates.c:42
#define UPDATES_DIR_NAME
Definition: newserver.h:236
void updates_init(void)
Definition: updates.c:170
#define UPDATES_FILE_NAME
Definition: newserver.h:231
uint8_t * contents
Definition: newserver.h:224
static update_file_struct * updates_file_find(const char *filename)
Definition: updates.c:120
union @21 data
Data about the rule.
static update_file_struct * update_files
Definition: updates.c:40
static void updates_file_new(const char *filename, struct stat *sb)
Definition: updates.c:51
struct packet_struct * packet
Definition: newserver.h:227
static void updates_traverse(const char *path)
Definition: updates.c:133
static int updates_file_compare(const void *a, const void *b)
Definition: updates.c:108
struct settings_struct settings
Definition: init.c:55
unsigned long checksum
Definition: newserver.h:212