database-plain.c 16.1 KB
Newer Older
Moritz Lipp's avatar
Moritz Lipp committed
1
2
/* See LICENSE file for license and copyright information */

3
4
#define _POSIX_SOURCE

5
6
7
#include <glib.h>
#include <stdlib.h>
#include <string.h>
8
9
#include <sys/stat.h>
#include <fcntl.h>
10
#include <unistd.h>
11
12
#include <girara/utils.h>
#include <girara/datastructures.h>
Moritz Lipp's avatar
Moritz Lipp committed
13

14
#include "database-plain.h"
Moritz Lipp's avatar
Moritz Lipp committed
15

Moritz Lipp's avatar
Moritz Lipp committed
16
17
18
#define BOOKMARKS "bookmarks"
#define HISTORY "history"

19
20
21
#define KEY_PAGE "page"
#define KEY_OFFSET "offset"
#define KEY_SCALE "scale"
Sebastian Ramacher's avatar
Sebastian Ramacher committed
22
#define KEY_ROTATE "rotate"
23
#define KEY_PAGES_PER_ROW "pages-per-row"
24
#define KEY_FIRST_PAGE_COLUMN "first-page-column"
25
26
#define KEY_POSITION_X "position-x"
#define KEY_POSITION_Y "position-y"
27

28
29
30
31
#ifdef __GNU__
#include <sys/file.h>
#define file_lock_set(fd, cmd) flock(fd, cmd)
#else
32
33
34
#define file_lock_set(fd, cmd) \
  { \
  struct flock lock = { .l_type = cmd, .l_start = 0, .l_whence = SEEK_SET, .l_len = 0}; \
Sebastian Ramacher's avatar
Sebastian Ramacher committed
35
  fcntl(fd, F_SETLK, lock); \
36
  }
37
#endif
38

39
40
41
static void zathura_database_interface_init(ZathuraDatabaseInterface* iface);

G_DEFINE_TYPE_WITH_CODE(ZathuraPlainDatabase, zathura_plaindatabase, G_TYPE_OBJECT,
Moritz Lipp's avatar
Moritz Lipp committed
42
                        G_IMPLEMENT_INTERFACE(ZATHURA_TYPE_DATABASE, zathura_database_interface_init))
43
44
45

static void plain_finalize(GObject* object);
static bool plain_add_bookmark(zathura_database_t* db, const char* file,
Moritz Lipp's avatar
Moritz Lipp committed
46
                               zathura_bookmark_t* bookmark);
Moritz Lipp's avatar
Moritz Lipp committed
47
static bool plain_remove_bookmark(zathura_database_t* db, const char* file,
Moritz Lipp's avatar
Moritz Lipp committed
48
                                  const char* id);
Moritz Lipp's avatar
Moritz Lipp committed
49
50
51
static girara_list_t* plain_load_bookmarks(zathura_database_t* db,
    const char* file);
static bool plain_set_fileinfo(zathura_database_t* db, const char* file,
Moritz Lipp's avatar
Moritz Lipp committed
52
                               zathura_fileinfo_t* file_info);
Moritz Lipp's avatar
Moritz Lipp committed
53
static bool plain_get_fileinfo(zathura_database_t* db, const char* file,
Moritz Lipp's avatar
Moritz Lipp committed
54
                               zathura_fileinfo_t* file_info);
Moritz Lipp's avatar
Moritz Lipp committed
55
static void plain_set_property(GObject* object, guint prop_id,
Moritz Lipp's avatar
Moritz Lipp committed
56
                               const GValue* value, GParamSpec* pspec);
57

58
59
/* forward declaration */
static bool zathura_db_check_file(const char* path);
60
static GKeyFile* zathura_db_read_key_file_from_file(const char* path);
61
static void zathura_db_write_key_file_to_file(const char* file, GKeyFile* key_file);
62
static void cb_zathura_db_watch_file(GFileMonitor* monitor, GFile* file, GFile*
Moritz Lipp's avatar
Moritz Lipp committed
63
                                     other_file, GFileMonitorEvent event, zathura_database_t* database);
64

65
typedef struct zathura_plaindatabase_private_s {
66
  char* bookmark_path;
67
  GKeyFile* bookmarks;
68
69
70
  GFileMonitor* bookmark_monitor;

  char* history_path;
71
  GKeyFile* history;
72
  GFileMonitor* history_monitor;
73
74
75
76
77
} zathura_plaindatabase_private_t;

#define ZATHURA_PLAINDATABASE_GET_PRIVATE(obj) \
  (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ZATHURA_TYPE_PLAINDATABASE, zathura_plaindatabase_private_t))

Moritz Lipp's avatar
Moritz Lipp committed
78
enum {
79
80
  PROP_0,
  PROP_PATH
Moritz Lipp's avatar
Moritz Lipp committed
81
82
};

83
84
85
86
87
88
89
90
91
92
93
94
95
96
static char*
prepare_filename(const char* file)
{
  if (file == NULL) {
    return NULL;
  }

  if (strchr(file, '[') == NULL && strchr(file, ']') == NULL) {
    return g_strdup(file);
  }

  return g_base64_encode((const guchar*) file, strlen(file));
}

97
98
99
100
static void
zathura_database_interface_init(ZathuraDatabaseInterface* iface)
{
  /* initialize interface */
Moritz Lipp's avatar
Moritz Lipp committed
101
  iface->add_bookmark    = plain_add_bookmark;
102
  iface->remove_bookmark = plain_remove_bookmark;
Moritz Lipp's avatar
Moritz Lipp committed
103
104
105
  iface->load_bookmarks  = plain_load_bookmarks;
  iface->set_fileinfo    = plain_set_fileinfo;
  iface->get_fileinfo    = plain_get_fileinfo;
106
107
108
109
110
111
112
113
114
115
}

static void
zathura_plaindatabase_class_init(ZathuraPlainDatabaseClass* class)
{
  /* add private members */
  g_type_class_add_private(class, sizeof(zathura_plaindatabase_private_t));

  /* override methods */
  GObjectClass* object_class = G_OBJECT_CLASS(class);
Moritz Lipp's avatar
Moritz Lipp committed
116
  object_class->finalize     = plain_finalize;
117
118
119
  object_class->set_property = plain_set_property;

  g_object_class_install_property(object_class, PROP_PATH,
Moritz Lipp's avatar
Moritz Lipp committed
120
121
                                  g_param_spec_string("path", "path", "path to directory where the bookmarks and history are locates",
                                      NULL, G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
122
123
124
125
126
127
}

static void
zathura_plaindatabase_init(ZathuraPlainDatabase* db)
{
  zathura_plaindatabase_private_t* priv = ZATHURA_PLAINDATABASE_GET_PRIVATE(db);
Moritz Lipp's avatar
Moritz Lipp committed
128
129

  priv->bookmark_path    = NULL;
130
  priv->bookmark_monitor = NULL;
Moritz Lipp's avatar
Moritz Lipp committed
131
132
133
134
  priv->bookmarks        = NULL;
  priv->history_path     = NULL;
  priv->history_monitor  = NULL;
  priv->history          = NULL;
135
136
}

Moritz Lipp's avatar
Moritz Lipp committed
137
zathura_database_t*
138
zathura_plaindatabase_new(const char* path)
Moritz Lipp's avatar
Moritz Lipp committed
139
{
140
  g_return_val_if_fail(path != NULL && strlen(path) != 0, NULL);
141

142
143
144
145
146
  zathura_database_t* db = g_object_new(ZATHURA_TYPE_PLAINDATABASE, "path", path, NULL);
  zathura_plaindatabase_private_t* priv = ZATHURA_PLAINDATABASE_GET_PRIVATE(db);
  if (priv->bookmark_path == NULL) {
    g_object_unref(db);
    return NULL;
147
  }
Moritz Lipp's avatar
Moritz Lipp committed
148

149
150
151
152
153
154
155
  return db;
}

static void
plain_db_init(ZathuraPlainDatabase* db, const char* dir)
{
  zathura_plaindatabase_private_t* priv = ZATHURA_PLAINDATABASE_GET_PRIVATE(db);
156
157

  /* bookmarks */
158
159
  priv->bookmark_path = g_build_filename(dir, BOOKMARKS, NULL);
  if (zathura_db_check_file(priv->bookmark_path) == false) {
160
161
162
    goto error_free;
  }

163
  GFile* bookmark_file = g_file_new_for_path(priv->bookmark_path);
164
  if (bookmark_file != NULL) {
165
    priv->bookmark_monitor = g_file_monitor(bookmark_file, G_FILE_MONITOR_NONE, NULL, NULL);
166
167
168
  } else {
    goto error_free;
  }
Moritz Lipp's avatar
Moritz Lipp committed
169

170
171
  g_object_unref(bookmark_file);

172
  g_signal_connect(
Moritz Lipp's avatar
Moritz Lipp committed
173
174
175
176
    G_OBJECT(priv->bookmark_monitor),
    "changed",
    G_CALLBACK(cb_zathura_db_watch_file),
    db
177
178
  );

179
180
  priv->bookmarks = zathura_db_read_key_file_from_file(priv->bookmark_path);
  if (priv->bookmarks == NULL) {
181
182
183
    goto error_free;
  }

184
  /* history */
185
186
  priv->history_path = g_build_filename(dir, HISTORY, NULL);
  if (zathura_db_check_file(priv->history_path) == false) {
187
188
189
    goto error_free;
  }

190
  GFile* history_file = g_file_new_for_path(priv->history_path);
191
  if (history_file != NULL) {
192
    priv->history_monitor = g_file_monitor(history_file, G_FILE_MONITOR_NONE, NULL, NULL);
193
194
195
  } else {
    goto error_free;
  }
Moritz Lipp's avatar
Moritz Lipp committed
196

197
198
  g_object_unref(history_file);

199
  g_signal_connect(
Moritz Lipp's avatar
Moritz Lipp committed
200
201
202
203
    G_OBJECT(priv->history_monitor),
    "changed",
    G_CALLBACK(cb_zathura_db_watch_file),
    db
204
205
  );

206
207
  priv->history = zathura_db_read_key_file_from_file(priv->history_path);
  if (priv->history == NULL) {
208
209
    goto error_free;
  }
Moritz Lipp's avatar
Moritz Lipp committed
210

Sebastian Ramacher's avatar
Sebastian Ramacher committed
211
  return;
212
213
214

error_free:

215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
  /* bookmarks */
  g_free(priv->bookmark_path);
  priv->bookmark_path = NULL;

  if (priv->bookmark_monitor != NULL) {
    g_object_unref(priv->bookmark_monitor);
    priv->bookmark_monitor = NULL;
  }

  if (priv->bookmarks != NULL) {
    g_key_file_free(priv->bookmarks);
    priv->bookmarks = NULL;
  }

  /* history */
  g_free(priv->history_path);
  priv->history_path = NULL;
232

233
234
235
236
  if (priv->history_monitor != NULL) {
    g_object_unref(priv->history_monitor);
    priv->history_monitor = NULL;
  }
237

238
239
240
241
  if (priv->history != NULL) {
    g_key_file_free(priv->history);
    priv->history = NULL;
  }
Moritz Lipp's avatar
Moritz Lipp committed
242
243
}

244
245
static void
plain_set_property(GObject* object, guint prop_id, const GValue* value, GParamSpec* pspec)
Moritz Lipp's avatar
Moritz Lipp committed
246
{
247
248
249
250
251
252
253
254
  ZathuraPlainDatabase* db = ZATHURA_PLAINDATABASE(object);

  switch (prop_id) {
    case PROP_PATH:
      plain_db_init(db, g_value_get_string(value));
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
255
  }
256
}
257

258
259
260
261
262
static void
plain_finalize(GObject* object)
{
  ZathuraPlainDatabase* db = ZATHURA_PLAINDATABASE(object);
  zathura_plaindatabase_private_t* priv = ZATHURA_PLAINDATABASE_GET_PRIVATE(db);
Moritz Lipp's avatar
Moritz Lipp committed
263

264
  /* bookmarks */
265
  g_free(priv->bookmark_path);
266

267
268
  if (priv->bookmark_monitor != NULL) {
    g_object_unref(priv->bookmark_monitor);
269
270
  }

271
272
  if (priv->bookmarks != NULL) {
    g_key_file_free(priv->bookmarks);
273
  }
274
275

  /* history */
276
  g_free(priv->history_path);
277

278
279
  if (priv->history_monitor != NULL) {
    g_object_unref(priv->history_monitor);
280
281
  }

282
283
284
285
286
  if (priv->history != NULL) {
    g_key_file_free(priv->history);
  }

  G_OBJECT_CLASS(zathura_plaindatabase_parent_class)->finalize(object);
Moritz Lipp's avatar
Moritz Lipp committed
287
288
}

289
290
static bool
plain_add_bookmark(zathura_database_t* db, const char* file,
Moritz Lipp's avatar
Moritz Lipp committed
291
                   zathura_bookmark_t* bookmark)
Moritz Lipp's avatar
Moritz Lipp committed
292
{
293
  zathura_plaindatabase_private_t* priv = ZATHURA_PLAINDATABASE_GET_PRIVATE(db);
Moritz Lipp's avatar
Moritz Lipp committed
294
  if (priv->bookmarks == NULL || priv->bookmark_path == NULL ||
295
      bookmark->id == NULL) {
296
297
298
    return false;
  }

299
300
301
  char* name = prepare_filename(file);
  g_key_file_set_integer(priv->bookmarks, name, bookmark->id, bookmark->page);
  g_free(name);
302

303
  zathura_db_write_key_file_to_file(priv->bookmark_path, priv->bookmarks);
304
305

  return true;
Moritz Lipp's avatar
Moritz Lipp committed
306
307
}

308
309
static bool
plain_remove_bookmark(zathura_database_t* db, const char* file, const char*
Moritz Lipp's avatar
Moritz Lipp committed
310
                      GIRARA_UNUSED(id))
Moritz Lipp's avatar
Moritz Lipp committed
311
{
312
313
  zathura_plaindatabase_private_t* priv = ZATHURA_PLAINDATABASE_GET_PRIVATE(db);
  if (priv->bookmarks == NULL || priv->bookmark_path == NULL) {
314
315
316
    return false;
  }

317
318
319
  char* name = prepare_filename(file);
  if (g_key_file_has_group(priv->bookmarks, name) == TRUE) {
    g_key_file_remove_group(priv->bookmarks, name, NULL);
320

321
    zathura_db_write_key_file_to_file(priv->bookmark_path, priv->bookmarks);
322
    g_free(name);
323
324
325

    return true;
  }
326
  g_free(name);
327

Moritz Lipp's avatar
Moritz Lipp committed
328
329
330
  return false;
}

331
332
static girara_list_t*
plain_load_bookmarks(zathura_database_t* db, const char* file)
Moritz Lipp's avatar
Moritz Lipp committed
333
{
334
335
  zathura_plaindatabase_private_t* priv = ZATHURA_PLAINDATABASE_GET_PRIVATE(db);
  if (priv->bookmarks == NULL) {
336
337
338
    return NULL;
  }

339
340
341
  char* name = prepare_filename(file);
  if (g_key_file_has_group(priv->bookmarks, name) == FALSE) {
    g_free(name);
342
343
344
    return NULL;
  }

Moritz Lipp's avatar
Moritz Lipp committed
345
  girara_list_t* result = girara_sorted_list_new2((girara_compare_function_t)
Moritz Lipp's avatar
Moritz Lipp committed
346
347
                          zathura_bookmarks_compare, (girara_free_function_t)
                          zathura_bookmark_free);
348
349

  gsize length;
350
  char** keys = g_key_file_get_keys(priv->bookmarks, name, &length, NULL);
351
352
  if (keys == NULL) {
    girara_list_free(result);
353
    g_free(name);
354
355
356
357
358
359
360
    return NULL;
  }

  for (gsize i = 0; i < length; i++) {
    zathura_bookmark_t* bookmark = g_malloc0(sizeof(zathura_bookmark_t));

    bookmark->id   = g_strdup(keys[i]);
361
    bookmark->page = g_key_file_get_integer(priv->bookmarks, name, keys[i], NULL);
362
363
364
365

    girara_list_append(result, bookmark);
  }

366
  g_free(name);
Moritz Lipp's avatar
Moritz Lipp committed
367
368
  g_strfreev(keys);

369
  return result;
Moritz Lipp's avatar
Moritz Lipp committed
370
371
}

372
static bool
373
plain_set_fileinfo(zathura_database_t* db, const char* file, zathura_fileinfo_t*
Moritz Lipp's avatar
Moritz Lipp committed
374
                   file_info)
Moritz Lipp's avatar
Moritz Lipp committed
375
{
376
  zathura_plaindatabase_private_t* priv = ZATHURA_PLAINDATABASE_GET_PRIVATE(db);
377
  if (priv->history == NULL || file_info == NULL || file == NULL) {
Moritz Lipp's avatar
Moritz Lipp committed
378
379
380
    return false;
  }

381
  char* name = prepare_filename(file);
Moritz Lipp's avatar
Moritz Lipp committed
382

383
384
  g_key_file_set_integer(priv->history, name, KEY_PAGE,   file_info->current_page);
  g_key_file_set_integer(priv->history, name, KEY_OFFSET, file_info->page_offset);
Moritz Lipp's avatar
Moritz Lipp committed
385

386
387
  char* tmp = g_strdup_printf("%f", file_info->scale);
  g_key_file_set_string (priv->history, name, KEY_SCALE, tmp);
Moritz Lipp's avatar
Moritz Lipp committed
388
  g_free(tmp);
389

390
391
392
  g_key_file_set_integer(priv->history, name, KEY_ROTATE,            file_info->rotation);
  g_key_file_set_integer(priv->history, name, KEY_PAGES_PER_ROW,     file_info->pages_per_row);
  g_key_file_set_integer(priv->history, name, KEY_FIRST_PAGE_COLUMN, file_info->first_page_column);
393
394
395

  tmp = g_strdup_printf("%f", file_info->position_x);
  g_key_file_set_string(priv->history,  name, KEY_POSITION_X, tmp);
Moritz Lipp's avatar
Moritz Lipp committed
396
  g_free(tmp);
397
398
399

  tmp = g_strdup_printf("%f", file_info->position_y);
  g_key_file_set_string(priv->history,  name, KEY_POSITION_Y, tmp);
400
  g_free(tmp);
Moritz Lipp's avatar
Moritz Lipp committed
401

402
403
  g_free(name);

404
  zathura_db_write_key_file_to_file(priv->history_path, priv->history);
Moritz Lipp's avatar
Moritz Lipp committed
405

Moritz Lipp's avatar
Moritz Lipp committed
406
  return true;
Moritz Lipp's avatar
Moritz Lipp committed
407
408
}

409
static bool
410
plain_get_fileinfo(zathura_database_t* db, const char* file, zathura_fileinfo_t*
Moritz Lipp's avatar
Moritz Lipp committed
411
                   file_info)
Moritz Lipp's avatar
Moritz Lipp committed
412
{
413
414
415
416
  if (db == NULL || file == NULL || file_info == NULL) {
    return false;
  }

417
418
  zathura_plaindatabase_private_t* priv = ZATHURA_PLAINDATABASE_GET_PRIVATE(db);
  if (priv->history == NULL) {
419
420
421
    return false;
  }

422
423
  char* name = prepare_filename(file);
  if (g_key_file_has_group(priv->history, name) == FALSE) {
Moritz Lipp's avatar
Moritz Lipp committed
424
    g_free(name);
425
    return false;
Moritz Lipp's avatar
Moritz Lipp committed
426
427
  }

428
429
430
431
432
  file_info->current_page      = g_key_file_get_integer(priv->history, name, KEY_PAGE, NULL);
  file_info->page_offset       = g_key_file_get_integer(priv->history, name, KEY_OFFSET, NULL);
  file_info->rotation          = g_key_file_get_integer(priv->history, name, KEY_ROTATE, NULL);
  file_info->pages_per_row     = g_key_file_get_integer(priv->history, name, KEY_PAGES_PER_ROW, NULL);
  file_info->first_page_column = g_key_file_get_integer(priv->history, name, KEY_FIRST_PAGE_COLUMN, NULL);
433

434
  char* scale_string = g_key_file_get_string(priv->history, name, KEY_SCALE, NULL);
435
436
437
438
  if (scale_string != NULL) {
    file_info->scale  = strtod(scale_string, NULL);
    g_free(scale_string);
  }
439
440

  char* position_x_string = g_key_file_get_string(priv->history, name, KEY_POSITION_X, NULL);
441
442
443
444
  if (position_x_string != NULL) {
    file_info->position_x = strtod(position_x_string, NULL);
    g_free(position_x_string);
  }
445
446

  char* position_y_string = g_key_file_get_string(priv->history, name, KEY_POSITION_Y, NULL);
447
448
449
450
  if (position_y_string != NULL) {
    file_info->position_y = strtod(position_y_string, NULL);
    g_free(position_y_string);
  }
451

452
  g_free(name);
453

454
  return true;
Moritz Lipp's avatar
Moritz Lipp committed
455
}
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477

static bool
zathura_db_check_file(const char* path)
{
  if (path == NULL) {
    return false;
  }

  if (g_file_test(path, G_FILE_TEST_EXISTS) == false) {
    FILE* file = fopen(path, "w");
    if (file != NULL) {
      fclose(file);
    } else {
      return false;
    }
  } else if (g_file_test(path, G_FILE_TEST_IS_REGULAR) == false) {
    return false;
  }

  return true;
}

478
static GKeyFile*
479
zathura_db_read_key_file_from_file(const char* path)
480
481
482
483
484
{
  if (path == NULL) {
    return NULL;
  }

485
  /* open file */
486
  FILE* file = fopen(path, "rw");
487
  if (file == NULL) {
488
489
490
    return NULL;
  }

491
492
  GKeyFile* key_file = g_key_file_new();
  if (key_file == NULL) {
493
    fclose(file);
494
495
496
497
    return NULL;
  }

  /* read config file */
498
499
500
501
  file_lock_set(fileno(file), F_WRLCK);
  char* content = girara_file_read2(file);
  file_lock_set(fileno(file), F_UNLCK);
  fclose(file);
502
  if (content == NULL) {
503
    g_key_file_free(key_file);
Moritz Lipp's avatar
Moritz Lipp committed
504
505
    return NULL;
  }
506
507

  /* parse config file */
508
509
510
511
512
513
514
  size_t contentlen = strlen(content);
  if (contentlen == 0) {
    static const char dummy_content[] = "# nothing";
    static const size_t dummy_len = sizeof(dummy_content) - 1;

    free(content);
    content = malloc(sizeof(char) * (dummy_len + 1));
515
    content = memcpy(content, dummy_content, dummy_len + 1);
516
517
518
    contentlen = dummy_len;
  }

519
  GError* error = NULL;
520
  if (g_key_file_load_from_data(key_file, content, contentlen,
Moritz Lipp's avatar
Moritz Lipp committed
521
                                G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS, &error) ==
522
      FALSE) {
Moritz Lipp's avatar
Moritz Lipp committed
523
    if (error->code != 1) { /* ignore empty file */
524
      free(content);
525
526
      g_key_file_free(key_file);
      g_error_free(error);
527
      return NULL;
528
529
530
531
532
    }

    g_error_free(error);
  }

533
534
  free(content);

535
536
537
538
  return key_file;
}

static void
539
zathura_db_write_key_file_to_file(const char* file, GKeyFile* key_file)
540
{
541
  if (file == NULL || key_file == NULL) {
542
543
544
    return;
  }

545
  gchar* content = g_key_file_to_data(key_file, NULL, NULL);
546
547
548
549
  if (content == NULL) {
    return;
  }

550
551
552
  /* open file */
  int fd = open(file, O_RDWR);
  if (fd == -1) {
553
554
555
556
    g_free(content);
    return;
  }

557
  file_lock_set(fd, F_WRLCK);
558
559
560
  if (write(fd, content, strlen(content)) == 0) {
    girara_error("Failed to write to %s", file);
  }
561
562
563
564
  file_lock_set(fd, F_UNLCK);

  close(fd);

565
  g_free(content);
566
567
}

568
569
static void
cb_zathura_db_watch_file(GFileMonitor* UNUSED(monitor), GFile* file, GFile* UNUSED(other_file),
Moritz Lipp's avatar
Moritz Lipp committed
570
                         GFileMonitorEvent event, zathura_database_t* database)
571
572
573
574
575
576
577
578
579
580
{
  if (event != G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT || database == NULL) {
    return;
  }

  char* path = g_file_get_path(file);
  if (path == NULL) {
    return;
  }

581
582
  zathura_plaindatabase_private_t* priv = ZATHURA_PLAINDATABASE_GET_PRIVATE(database);
  if (priv->bookmark_path && strcmp(priv->bookmark_path, path) == 0) {
Sebastian Ramacher's avatar
Sebastian Ramacher committed
583
584
585
    if (priv->bookmarks != NULL) {
      g_key_file_free(priv->bookmarks);
    }
Moritz Lipp's avatar
Moritz Lipp committed
586

587
588
    priv->bookmarks = zathura_db_read_key_file_from_file(priv->bookmark_path);
  } else if (priv->history_path && strcmp(priv->history_path, path) == 0) {
Sebastian Ramacher's avatar
Sebastian Ramacher committed
589
590
591
    if (priv->history != NULL) {
      g_key_file_free(priv->history);
    }
Moritz Lipp's avatar
Moritz Lipp committed
592

593
    priv->history = zathura_db_read_key_file_from_file(priv->history_path);
594
  }
595
596

  g_free(path);
597
}