1 /*
2 * db_delete.c: dbdelete(), database delete routine.
3 *
4 * Copyright (C) 1994, 1995 Graeme W. Wilford. (Wilf.)
5 * Copyright (C) 2001, 2002 Colin Watson.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 *
21 * Mon Aug 8 20:35:30 BST 1994 Wilf. (G.Wilford@ee.surrey.ac.uk)
22 */
23
24 #ifdef HAVE_CONFIG_H
25 #include "config.h"
26 #endif /* HAVE_CONFIG_H */
27
28 #include <stdio.h>
29 #include <string.h>
30 #include <stdlib.h>
31 #include <unistd.h>
32
33 #include "error.h"
34 #include "gl_list.h"
35 #include "xalloc.h"
36
37 #include "gettext.h"
38 #define _(String) gettext (String)
39
40 #include "manconfig.h"
41
42 #include "appendstr.h"
43 #include "debug.h"
44 #include "filenames.h"
45 #include "glcontainers.h"
46
47 #include "mydbm.h"
48 #include "db_storage.h"
49
50 /* Delete an entry for a page.
51 Again, 3 possibilities:
52
53 1) page is singular reference, just delete it :)
54 2) page has 2+ companions. Delete page and alter multi entry to not
55 point to it anymore.
56 3) page has 1 companion. Could do as (2), but we'd waste an entry in
57 the db. Should delete page, extract friend and reinsert as singular,
58 overwriting the old multi entry.
59 */
60
61 #define NO_ENTRY 1;
62
63 int dbdelete (MYDBM_FILE dbf, const char *name, struct mandata *info)
64 {
65 datum key, cont;
66
67 memset (&key, 0, sizeof key);
68 memset (&cont, 0, sizeof cont);
69
70 /* get entry for info */
71
72 debug ("Attempting delete of %s(%s) entry.\n", name, info->ext);
73
74 MYDBM_SET (key, name_to_key (name));
75 cont = MYDBM_FETCH (dbf, key);
76
77 if (!MYDBM_DPTR (cont)) { /* 0 entries */
78 MYDBM_FREE_DPTR (key);
79 return NO_ENTRY;
80 } else if (*MYDBM_DPTR (cont) != '\t') { /* 1 entry */
81 MYDBM_DELETE (dbf, key);
82 MYDBM_FREE_DPTR (cont);
83 } else { /* 2+ entries */
84 gl_list_t refs;
85 struct name_ext this_ref, *ref;
86 size_t this_index;
87 char *multi_content = NULL;
88 datum multi_key;
89
90 /* Extract all of the extensions associated with
91 this key */
92
93 refs = list_extensions (MYDBM_DPTR (cont) + 1);
94
95 this_ref.name = name;
96 this_ref.ext = info->ext;
97 this_index = gl_list_indexof (refs, &this_ref);
98
99 if (this_index == (size_t) -1) {
100 gl_list_free (refs);
101 MYDBM_FREE_DPTR (cont);
102 MYDBM_FREE_DPTR (key);
103 return NO_ENTRY;
104 }
105
106 multi_key = make_multi_key (name, info->ext);
107 if (!MYDBM_EXISTS (dbf, multi_key)) {
108 error (0, 0,
109 _( "multi key %s does not exist"),
110 MYDBM_DPTR (multi_key));
111 gripe_corrupt_data (dbf);
112 }
113 MYDBM_DELETE (dbf, multi_key);
114 MYDBM_FREE_DPTR (multi_key);
115 gl_list_remove_at (refs, this_index);
116
117 /* If all manual pages with this name have been deleted,
118 we'll have to remove the key too. */
119
120 if (!gl_list_size (refs)) {
121 gl_list_free (refs);
122 MYDBM_FREE_DPTR (cont);
123 MYDBM_DELETE (dbf, key);
124 MYDBM_FREE_DPTR (key);
125 return 0;
126 }
127
128 /* create our new multi content */
129 multi_content = xstrdup ("");
130 GL_LIST_FOREACH (refs, ref)
131 multi_content = appendstr (multi_content,
132 "\t", ref->name,
133 "\t", ref->ext,
134 (void *) 0);
135
136 MYDBM_FREE_DPTR (cont);
137 MYDBM_SET (cont, multi_content);
138 if (MYDBM_REPLACE (dbf, key, cont))
139 gripe_replace_key (dbf, MYDBM_DPTR (key));
140
141 gl_list_free (refs);
142 }
143
144 MYDBM_FREE_DPTR (key);
145 return 0;
146 }