Atrinik Client  4.0
wrapper.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/string.h>
32 #include <toolkit/path.h>
33 #include <resources.h>
34 
38 void system_start(void)
39 {
40  SDL_Surface *icon = IMG_Load_wrapper("textures/"CLIENT_ICON_NAME);
41  if (icon != NULL) {
42  video_set_icon(icon);
43  }
44 
45  SDL_WM_SetCaption(PACKAGE_NAME, PACKAGE_NAME);
46 }
47 
51 void system_end(void)
52 {
54  object_deinit();
58  toolkit_widget_deinit();
64  sound_deinit();
65  intro_deinit();
69  text_deinit();
70  hfiles_deinit();
74  anims_deinit();
75  skills_deinit();
76  spells_deinit();
77  clioption_settings_deinit();
79  image_deinit();
80  toolkit_deinit();
81  SDL_Quit();
82 }
83 
93 static int mkdir_recurse(const char *path)
94 {
95  char *copy, *p;
96 
97  p = copy = estrdup(path);
98 
99  do {
100  p = strchr(p + 1, '/');
101 
102  if (p) {
103  *p = '\0';
104  }
105 
106  if (mkdir(copy, 0755) == -1 && errno != EEXIST) {
107  efree(copy);
108  return -1;
109  }
110 
111  if (p) {
112  *p = '/';
113  }
114  } while (p);
115 
116  efree(copy);
117 
118  return 0;
119 }
120 
130 void mkdir_ensure(const char *path)
131 {
132  char *stmp;
133 
134  stmp = strrchr(path, '/');
135 
136  if (stmp) {
137  char ctmp;
138 
139  ctmp = stmp[0];
140  stmp[0] = '\0';
141  mkdir_recurse(path);
142  stmp[0] = ctmp;
143  }
144 }
145 
153 void copy_file(const char *filename, const char *filename_out)
154 {
155  FILE *fp, *fp_out;
156  char buf[HUGE_BUF];
157 
158  fp = fopen(filename, "r");
159 
160  if (!fp) {
161  LOG(BUG, "Failed to open '%s' for reading.", filename);
162  return;
163  }
164 
165  mkdir_ensure(filename_out);
166 
167  fp_out = fopen(filename_out, "w");
168 
169  if (!fp_out) {
170  LOG(BUG, "Failed to open '%s' for writing.", filename_out);
171  fclose(fp);
172  return;
173  }
174 
175  while (fgets(buf, sizeof(buf), fp)) {
176  fputs(buf, fp_out);
177  }
178 
179  fclose(fp);
180  fclose(fp_out);
181 }
182 
194 void copy_if_exists(const char *from, const char *to, const char *src, const char *dst)
195 {
196  char src_path[HUGE_BUF], dst_path[HUGE_BUF];
197 
198  snprintf(src_path, sizeof(src_path), "%s/%s", from, src);
199  snprintf(dst_path, sizeof(dst_path), "%s/%s", to, dst);
200 
201  if (access(src_path, R_OK) == 0) {
202  copy_rec(src_path, dst_path);
203  }
204 }
205 
214 static void
215 _rmrf (DIR *dir, const char *path)
216 {
217  HARD_ASSERT(dir != NULL);
218 
219  struct dirent *file;
220  while ((file = readdir(dir)) != NULL) {
221  if (strcmp(file->d_name, ".") == 0 ||
222  strcmp(file->d_name, "..") == 0) {
223  continue;
224  }
225 
226  char buf[HUGE_BUF];
227  snprintf(VS(buf), "%s/%s", path, file->d_name);
228 
229  DIR *dir2 = opendir(buf);
230  if (dir2 != NULL) {
231  _rmrf(dir2, buf);
232  closedir(dir2);
233  rmdir(buf);
234  } else {
235  unlink(buf);
236  }
237  }
238 }
239 
248 void rmrf(const char *path)
249 {
250  HARD_ASSERT(path != NULL);
251 
252  DIR *dir = opendir(path);
253  if (dir == NULL) {
254  return;
255  }
256 
257  _rmrf(dir, path);
258  closedir(dir);
259  rmdir(path);
260 }
261 
269 void copy_rec(const char *src, const char *dst)
270 {
271  /* Copy directory contents. */
272  DIR *dir = opendir(src);
273  if (dir != NULL) {
274  struct dirent *currentfile;
275  char dir_src[HUGE_BUF], dir_dst[HUGE_BUF];
276 
277  /* Try to make the new directory. */
278  if (access(dst, R_OK) != 0) {
279  mkdir(dst, 0755);
280  }
281 
282  while ((currentfile = readdir(dir))) {
283  if (currentfile->d_name[0] == '.') {
284  continue;
285  }
286 
287  snprintf(dir_src, sizeof(dir_src), "%s/%s", src, currentfile->d_name);
288  snprintf(dir_dst, sizeof(dir_dst), "%s/%s", dst, currentfile->d_name);
289  copy_rec(dir_src, dir_dst);
290  }
291 
292  closedir(dir);
293  } else {
294  copy_file(src, dst);
295  }
296 }
297 
303 const char *get_config_dir(void)
304 {
305  const char *desc;
306 
307 #ifndef WIN32
308  desc = getenv("HOME");
309 #else
310  desc = getenv("APPDATA");
311 #endif
312 
313  /* Failed to find an usable destination, so store it in the
314  * current directory. */
315  if (!desc || !*desc) {
316  desc = ".";
317  }
318 
319  return desc;
320 }
321 
331 void get_data_dir_file(char *buf, size_t len, const char *fname)
332 {
333  /* Try the current directory first. */
334  snprintf(buf, len, "./%s", fname);
335 
336 #ifdef INSTALL_SUBDIR_SHARE
337 
338  /* Not found, try the share directory since it was defined... */
339  if (access(buf, R_OK)) {
340  char *prefix;
341 
342  /* Get the prefix. */
343  prefix = binreloc_find_prefix("./");
344  /* Construct the path. */
345  snprintf(buf, len, "%s/"INSTALL_SUBDIR_SHARE "/%s", prefix, fname);
346  efree(prefix);
347  }
348 #endif
349 }
350 
369 char *file_path(const char *path, const char *mode)
370 {
371  bool is_write, is_append;
372  StringBuffer *sb;
373  char version[MAX_BUF], client_path[HUGE_BUF], *new_path;
374 
375  HARD_ASSERT(path != NULL);
376  HARD_ASSERT(mode != NULL);
377 
378  SOFT_ASSERT_RC(path[0] != '/', estrdup(path),
379  "Path is already absolute: %s", path);
380 
381  sb = stringbuffer_new();
382  stringbuffer_append_printf(sb, "%s/.atrinik/%s/%s", get_config_dir(),
383  package_get_version_partial(VS(version)), path);
384  new_path = stringbuffer_sub(sb, 0, 0);
385 
386  is_write = is_append = false;
387 
388  if (strchr(mode, 'w') != NULL) {
389  is_write = true;
390  } else if (strchr(mode, '+') != NULL || strchr(mode, 'a') != NULL) {
391  is_append = true;
392  }
393 
394  if (is_write || is_append) {
395  if (access(new_path, W_OK) != 0) {
396  char *dirname;
397 
398  /* Ensure directories exist if we're going to use this path for
399  * writing/appending. */
400  dirname = path_dirname(new_path);
401  mkdir_recurse(dirname);
402  efree(dirname);
403 
404  if (is_append) {
405  get_data_dir_file(VS(client_path), path);
406  copy_file(client_path, new_path);
407  }
408  }
409  } else {
410  if (access(new_path, R_OK) != 0) {
411  get_data_dir_file(VS(client_path), path);
412  stringbuffer_seek(sb, 0);
413  stringbuffer_append_string(sb, client_path);
414  }
415  }
416 
417  efree(new_path);
418 
419  return stringbuffer_finish(sb);
420 }
421 
428 static StringBuffer *file_path_server_internal(void)
429 {
430  StringBuffer *sb;
431 
432  sb = stringbuffer_new();
433  stringbuffer_append_string(sb, "settings/");
434 
435  SOFT_ASSERT_RC(selected_server != NULL, sb, "Selected server is NULL.");
436  SOFT_ASSERT_RC(!string_isempty(selected_server->hostname), sb,
437  "Selected server has empty hostname.");
438 
439  stringbuffer_append_printf(sb, "servers/%s-%d/", selected_server->hostname,
441 
442  return sb;
443 }
444 
452 char *file_path_player(const char *path)
453 {
454  StringBuffer *sb;
455 
456  HARD_ASSERT(path != NULL);
457 
459 
460  SOFT_ASSERT_LABEL(*cpl.account != '\0', done, "Account name is empty.");
461  SOFT_ASSERT_LABEL(*cpl.name != '\0', done, "Player name is empty.");
462 
463  stringbuffer_append_printf(sb, "%s/%s/%s", cpl.account, cpl.name, path);
464 
465 done:
466  return stringbuffer_finish(sb);
467 }
468 
476 char *file_path_server(const char *path)
477 {
478  StringBuffer *sb;
479 
480  HARD_ASSERT(path != NULL);
481 
483  stringbuffer_append_printf(sb, ".common/%s", path);
484 
485  return stringbuffer_finish(sb);
486 }
487 
507 FILE *
508 client_fopen_wrapper (const char *fname, const char *mode)
509 {
510  char *path = file_path(fname, mode);
511  FILE *fp = fopen(path, mode);
512  efree(path);
513 
514  return fp;
515 }
516 
524 SDL_Surface *IMG_Load_wrapper(const char *file)
525 {
526  char *path;
527  SDL_Surface *surface;
528 
529  path = file_path(file, "r");
530  surface = IMG_Load(path);
531  efree(path);
532 
533  return surface;
534 }
535 
545 TTF_Font *TTF_OpenFont_wrapper(const char *file, int ptsize)
546 {
547  char *path;
548  TTF_Font *font;
549 
550  path = file_path(file, "r");
551  font = TTF_OpenFont(path, ptsize);
552  efree(path);
553 
554  return font;
555 }
void mkdir_ensure(const char *path)
Definition: wrapper.c:130
void system_end(void)
Definition: wrapper.c:51
void server_settings_deinit(void)
server_struct * selected_server
Definition: main.c:54
void hfiles_deinit(void)
Definition: help.c:70
void effects_deinit(void)
Definition: effects.c:267
FILE * client_fopen_wrapper(const char *fname, const char *mode)
Definition: wrapper.c:508
void notification_destroy(void)
Definition: notification.c:51
void text_deinit(void)
Definition: text.c:347
void copy_if_exists(const char *from, const char *to, const char *src, const char *dst)
Definition: wrapper.c:194
void skills_deinit(void)
Definition: skills.c:76
void cmd_aliases_deinit(void)
Definition: cmd_aliases.c:174
void sound_ambient_clear(void)
Definition: sound.c:833
TTF_Font * TTF_OpenFont_wrapper(const char *file, int ptsize)
Definition: wrapper.c:545
static int mkdir_recurse(const char *path)
Definition: wrapper.c:93
void copy_file(const char *filename, const char *filename_out)
Definition: wrapper.c:153
char * package_get_version_partial(char *dst, size_t dstlen)
Definition: misc.c:89
char * file_path_player(const char *path)
Definition: wrapper.c:452
char account[MAX_BUF]
Definition: player.h:227
void system_start(void)
Definition: wrapper.c:38
void resources_deinit(void)
Definition: resources.c:74
Client_Player cpl
Definition: client.c:50
SDL_Surface * IMG_Load_wrapper(const char *file)
Definition: wrapper.c:524
void rmrf(const char *path)
Definition: wrapper.c:248
#define CLIENT_ICON_NAME
Definition: config.h:45
void intro_deinit(void)
Definition: intro.c:152
char name[40]
Definition: player.h:173
void interface_deinit(void)
Definition: interface.c:664
void server_files_deinit(void)
Definition: server_files.c:81
static StringBuffer * file_path_server_internal(void)
Definition: wrapper.c:428
char * hostname
Definition: main.h:68
void sound_deinit(void)
Definition: sound.c:287
void keybind_deinit(void)
Definition: keybind.c:168
void tooltip_dismiss(void)
Definition: tooltip.c:175
char * file_path_server(const char *path)
Definition: wrapper.c:476
static void _rmrf(DIR *dir, const char *path)
Definition: wrapper.c:215
void settings_deinit(void)
Definition: settings.c:310
void metaserver_clear_data(void)
Definition: metaserver.c:697
void image_bmaps_deinit(void)
Definition: image.c:191
void anims_deinit(void)
Definition: animations.c:107
char * file_path(const char *path, const char *mode)
Definition: wrapper.c:369
void spells_deinit(void)
Definition: spells.c:85
int port
Definition: main.h:80
void client_socket_deinitialize(void)
Definition: socket.c:452
void copy_rec(const char *src, const char *dst)
Definition: wrapper.c:269
void get_data_dir_file(char *buf, size_t len, const char *fname)
Definition: wrapper.c:331
void video_set_icon(SDL_Surface *icon)
Definition: video.c:306
void texture_deinit(void)
Definition: texture.c:190
void object_deinit(void)
Definition: item.c:54
const char * get_config_dir(void)
Definition: wrapper.c:303