parlib: slab: Fix ancient ctor off-by-one
[akaros.git] / user / ndblib / ndbopen.c
1 /* 
2  * This file is part of the UCB release of Plan 9. It is subject to the license
3  * terms in the LICENSE file found in the top-level directory of this
4  * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
5  * part of the UCB release of Plan 9, including this file, may be copied,
6  * modified, propagated, or distributed except according to the terms contained
7  * in the LICENSE file.
8  */
9 #include <stdlib.h>
10
11 #include <stdio.h>
12 #include <parlib/parlib.h>
13 #include <sys/types.h>
14 #include <sys/stat.h>
15 #include <unistd.h>
16 #include <signal.h>
17 #include <fcntl.h>
18 #include <iplib/iplib.h>
19 #include <ndblib/ndb.h>
20 #include <ndblib/ndbhf.h>
21
22 static struct ndb*      doopen(char*);
23 static void     hffree(struct ndb*);
24
25 static char *deffile = "/lib/ndb/local";
26
27 /*
28  *  the database entry in 'file' indicates the list of files
29  *  that makeup the database.  Open each one and search in
30  *  the same order.
31  */
32 struct ndb*
33 ndbopen(char *file)
34 {
35
36         struct ndb *db, *first, *last;
37         struct ndbs s;
38         struct ndbtuple *t, *nt;
39
40         if(file == 0)
41                 file = deffile;
42         db = doopen(file);
43         if(db == 0) {
44                 return 0;
45         }
46         first = last = db;
47         t = ndbsearch(db, &s, "database", "");
48         fseek(db->b, 0, 0);
49         if(t == 0) {
50                 return db;
51         }
52         for(nt = t; nt; nt = nt->entry){
53                 if(strcmp(nt->attr, "file") != 0)
54                         continue;
55                 if(strcmp(nt->val, file) == 0){
56                         /* default file can be reordered in the list */
57                         if(first->next == 0)
58                                 continue;
59                         if(strcmp(first->file, file) == 0){
60                                 db = first;
61                                 first = first->next;
62                                 last->next = db;
63                                 db->next = 0;
64                                 last = db;
65                         }
66                         continue;
67                 }
68                 db = doopen(nt->val);
69                 if(db == 0)
70                         continue;
71                 last->next = db;
72                 last = db;
73         }
74         ndbfree(t);
75         return first;
76 }
77
78 /*
79  *  open a single file
80  */
81 static struct ndb*
82 doopen(char *file)
83 {
84
85         struct ndb *db;
86
87         db = (struct ndb*)calloc(sizeof(struct ndb), 1);
88         if(db == 0) {
89                 return 0;
90         }
91         memset(db, 0, sizeof(struct ndb));
92         strncpy(db->file, file, sizeof(db->file)-1);
93
94         if(ndbreopen(db) < 0){
95                 free(db);
96                 return 0;
97         }
98
99         return db;
100 }
101
102 /*
103  *  dump any cached information, forget the hash tables, and reopen a single file
104  */
105 int
106 ndbreopen(struct ndb *db)
107 {
108
109         int fd;
110         struct dir *d;
111
112         /* forget what we know about the open files */
113         if(db->isopen){
114                 _ndbcacheflush(db);
115                 hffree(db);
116                 fclose(db->b);
117                 db->mtime = 0;
118                 db->isopen = 0;
119         }
120
121         /* try the open again */
122         db->b = fopen(db->file, "r");
123         if(! db->b) {
124                 return -1;
125         }
126 #if 0
127         d = dirfstat(fd);
128         if(d == NULL){
129                 close(fd);
130                 return -1;
131         }
132
133         db->qid.path = d->qid.path;
134         db->mtime = d->mtime;
135         db->length = d->length;
136         free(d);
137 #else
138         struct stat s;
139         /* we opened it, this WILL work */
140         stat(db->file, &s);
141         db->qid.path = s.st_ino;
142         db->mtime = s.st_mtime + 1;
143         db->length = s.st_size;
144 #endif
145         db->isopen = 1;
146         return 0;
147 }
148
149 /*
150  *  close the database files
151  */
152 void
153 ndbclose(struct ndb *db)
154 {
155
156         struct ndb *nextdb;
157
158         for(; db; db = nextdb){
159                 nextdb = db->next;
160                 _ndbcacheflush(db);
161                 hffree(db);
162                 fclose(db->b);
163                 free(db);
164         }
165 }
166
167 /*
168  *  free the hash files belonging to a db
169  */
170 static void
171 hffree(struct ndb *db)
172 {
173
174         struct ndbhf *hf, *next;
175
176         for(hf = db->hf; hf; hf = next){
177                 next = hf->next;
178                 close(hf->fd);
179                 free(hf);
180         }
181         db->hf = 0;
182 }
183
184 /*
185  *  return true if any part of the database has changed
186  */
187 int
188 ndbchanged(struct ndb *db)
189 {
190         /* TODO: implement me (no one calls this yet) */
191         assert(0);
192         return 0;
193 #if 0
194         struct ndb *ndb;
195         struct dir *d;
196
197 /* FIX ME */
198         for(ndb = db; ndb != NULL; ndb = ndb->next){
199                 d = dirfstat(Bfildes(&ndb->b));
200                 if(d == NULL)
201                         continue;
202                 if(ndb->qid.path != d->qid.path
203                 || ndb->qid.vers != d->qid.vers){
204                         free(d);
205                         return 1;
206                 }
207                 free(d);
208         }
209         return 0;
210 #endif
211 }