ruby_odeum 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. data/COPYING +504 -0
  2. data/LICENSE +504 -0
  3. data/README +50 -0
  4. data/bin/odeum_mgr +106 -0
  5. data/doc/rdoc/classes/Odeum.html +235 -0
  6. data/doc/rdoc/classes/Odeum.src/M000010.html +25 -0
  7. data/doc/rdoc/classes/Odeum.src/M000011.html +22 -0
  8. data/doc/rdoc/classes/Odeum.src/M000012.html +27 -0
  9. data/doc/rdoc/classes/Odeum.src/M000013.html +27 -0
  10. data/doc/rdoc/classes/Odeum.src/M000014.html +28 -0
  11. data/doc/rdoc/classes/Odeum/Document.html +382 -0
  12. data/doc/rdoc/classes/Odeum/Document.src/M000040.html +25 -0
  13. data/doc/rdoc/classes/Odeum/Document.src/M000041.html +22 -0
  14. data/doc/rdoc/classes/Odeum/Document.src/M000042.html +23 -0
  15. data/doc/rdoc/classes/Odeum/Document.src/M000043.html +23 -0
  16. data/doc/rdoc/classes/Odeum/Document.src/M000044.html +24 -0
  17. data/doc/rdoc/classes/Odeum/Document.src/M000045.html +32 -0
  18. data/doc/rdoc/classes/Odeum/Document.src/M000046.html +22 -0
  19. data/doc/rdoc/classes/Odeum/Document.src/M000047.html +22 -0
  20. data/doc/rdoc/classes/Odeum/Document.src/M000048.html +22 -0
  21. data/doc/rdoc/classes/Odeum/Document.src/M000049.html +22 -0
  22. data/doc/rdoc/classes/Odeum/Document.src/M000050.html +24 -0
  23. data/doc/rdoc/classes/Odeum/Document.src/M000051.html +27 -0
  24. data/doc/rdoc/classes/Odeum/Index.html +662 -0
  25. data/doc/rdoc/classes/Odeum/Index.src/M000015.html +46 -0
  26. data/doc/rdoc/classes/Odeum/Index.src/M000016.html +33 -0
  27. data/doc/rdoc/classes/Odeum/Index.src/M000017.html +35 -0
  28. data/doc/rdoc/classes/Odeum/Index.src/M000018.html +23 -0
  29. data/doc/rdoc/classes/Odeum/Index.src/M000019.html +22 -0
  30. data/doc/rdoc/classes/Odeum/Index.src/M000020.html +22 -0
  31. data/doc/rdoc/classes/Odeum/Index.src/M000021.html +22 -0
  32. data/doc/rdoc/classes/Odeum/Index.src/M000022.html +22 -0
  33. data/doc/rdoc/classes/Odeum/Index.src/M000023.html +22 -0
  34. data/doc/rdoc/classes/Odeum/Index.src/M000024.html +29 -0
  35. data/doc/rdoc/classes/Odeum/Index.src/M000025.html +23 -0
  36. data/doc/rdoc/classes/Odeum/Index.src/M000026.html +24 -0
  37. data/doc/rdoc/classes/Odeum/Index.src/M000027.html +23 -0
  38. data/doc/rdoc/classes/Odeum/Index.src/M000028.html +26 -0
  39. data/doc/rdoc/classes/Odeum/Index.src/M000029.html +24 -0
  40. data/doc/rdoc/classes/Odeum/Index.src/M000030.html +20 -0
  41. data/doc/rdoc/classes/Odeum/Index.src/M000031.html +22 -0
  42. data/doc/rdoc/classes/Odeum/Index.src/M000032.html +22 -0
  43. data/doc/rdoc/classes/Odeum/Index.src/M000033.html +22 -0
  44. data/doc/rdoc/classes/Odeum/Index.src/M000034.html +22 -0
  45. data/doc/rdoc/classes/Odeum/Index.src/M000035.html +20 -0
  46. data/doc/rdoc/classes/Odeum/Index.src/M000036.html +20 -0
  47. data/doc/rdoc/classes/Odeum/Index.src/M000037.html +22 -0
  48. data/doc/rdoc/classes/Odeum/Index.src/M000038.html +22 -0
  49. data/doc/rdoc/classes/Odeum/Index.src/M000039.html +22 -0
  50. data/doc/rdoc/classes/OdeumTest.html +257 -0
  51. data/doc/rdoc/classes/OdeumTest.src/M000001.html +18 -0
  52. data/doc/rdoc/classes/OdeumTest.src/M000002.html +19 -0
  53. data/doc/rdoc/classes/OdeumTest.src/M000003.html +27 -0
  54. data/doc/rdoc/classes/OdeumTest.src/M000004.html +25 -0
  55. data/doc/rdoc/classes/OdeumTest.src/M000005.html +44 -0
  56. data/doc/rdoc/classes/OdeumTest.src/M000006.html +20 -0
  57. data/doc/rdoc/classes/OdeumTest.src/M000007.html +39 -0
  58. data/doc/rdoc/classes/OdeumTest.src/M000008.html +59 -0
  59. data/doc/rdoc/classes/OdeumTest.src/M000009.html +41 -0
  60. data/doc/rdoc/created.rid +1 -0
  61. data/doc/rdoc/files/COPYING.html +756 -0
  62. data/doc/rdoc/files/LICENSE.html +756 -0
  63. data/doc/rdoc/files/README.html +175 -0
  64. data/doc/rdoc/files/ext/odeum_index/odeum_index_c.html +101 -0
  65. data/doc/rdoc/files/test/test_odeum_rb.html +109 -0
  66. data/doc/rdoc/fr_class_index.html +30 -0
  67. data/doc/rdoc/fr_file_index.html +31 -0
  68. data/doc/rdoc/fr_method_index.html +77 -0
  69. data/doc/rdoc/index.html +24 -0
  70. data/doc/rdoc/rdoc-style.css +208 -0
  71. data/ext/odeum_index/cabin.c +2735 -0
  72. data/ext/odeum_index/cabin.h +1040 -0
  73. data/ext/odeum_index/curia.c +1114 -0
  74. data/ext/odeum_index/curia.h +430 -0
  75. data/ext/odeum_index/depot.c +1910 -0
  76. data/ext/odeum_index/depot.h +439 -0
  77. data/ext/odeum_index/extconf.rb +10 -0
  78. data/ext/odeum_index/myconf.c +668 -0
  79. data/ext/odeum_index/myconf.h +523 -0
  80. data/ext/odeum_index/odeum.c +1743 -0
  81. data/ext/odeum_index/odeum.h +541 -0
  82. data/ext/odeum_index/odeum_index.c +991 -0
  83. data/ext/odeum_index/villa.c +1923 -0
  84. data/ext/odeum_index/villa.h +470 -0
  85. data/ext/odeum_index/vista.c +159 -0
  86. data/ext/odeum_index/vista.h +111 -0
  87. data/test/test_odeum.rb +174 -0
  88. metadata +138 -0
@@ -0,0 +1,1114 @@
1
+ /*************************************************************************************************
2
+ * Implementation of Curia
3
+ * Copyright (C) 2000-2005 Mikio Hirabayashi
4
+ * This file is part of QDBM, Quick Database Manager.
5
+ * QDBM is free software; you can redistribute it and/or modify it under the terms of the GNU
6
+ * Lesser General Public License as published by the Free Software Foundation; either version
7
+ * 2.1 of the License or any later version. QDBM is distributed in the hope that it will be
8
+ * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
9
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
10
+ * details.
11
+ * You should have received a copy of the GNU Lesser General Public License along with QDBM; if
12
+ * not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
13
+ * 02111-1307 USA.
14
+ *************************************************************************************************/
15
+
16
+
17
+ #include "curia.h"
18
+ #include "myconf.h"
19
+
20
+ #define CR_NAMEMAX 512 /* max size of a database name */
21
+ #define CR_DPMAX 512 /* max number of division of a database */
22
+ #define CR_DIRMODE 00755 /* permission of a creating directory */
23
+ #define CR_FILEMODE 00644 /* permission of a creating file */
24
+ #define CR_PATHBUFSIZ 1024 /* size of a path buffer */
25
+ #define CR_DEFDNUM 5 /* default number of division of a database */
26
+ #define CR_ATTRBNUM 16 /* bucket number of attrubute database */
27
+ #define CR_DPNAME "depot" /* name of each sub database */
28
+ #define CR_KEYDNUM "dnum" /* key of division number */
29
+ #define CR_KEYLRNUM "lrnum" /* key of the number of large objects */
30
+ #define CR_TMPFSUF MYEXTSTR "crtmp" /* suffix of a temporary directory */
31
+ #define CR_LOBDIR "lob" /* name of the directory of large objects */
32
+ #define CR_LOBDDEPTH 2 /* depth of the directories of large objects */
33
+ #define CR_NUMBUFSIZ 32 /* size of a buffer for a number */
34
+ #define CR_IOBUFSIZ 8192 /* size of an I/O buffer */
35
+
36
+
37
+ /* private function prototypes */
38
+ static char *crstrdup(const char *str);
39
+ static int crdpgetnum(DEPOT *depot, const char *kbuf, int ksiz);
40
+ static char *crgetlobpath(CURIA *curia, const char *kbuf, int ksiz);
41
+ static int crmklobdir(const char *path);
42
+ static int crrmlobdir(const char *path);
43
+ static int crcplobdir(CURIA *curia, const char *path);
44
+ static int crwrite(int fd, const void *buf, int size);
45
+ static int crread(int fd, void *buf, int size);
46
+
47
+
48
+
49
+ /*************************************************************************************************
50
+ * public objects
51
+ *************************************************************************************************/
52
+
53
+
54
+ /* Get a database handle. */
55
+ CURIA *cropen(const char *name, int omode, int bnum, int dnum){
56
+ DEPOT *attr, **depots;
57
+ char path[CR_PATHBUFSIZ], *tname;
58
+ int i, j, dpomode, inode, lrnum;
59
+ struct stat sbuf;
60
+ CURIA *curia;
61
+ assert(name);
62
+ if(dnum < 1) dnum = CR_DEFDNUM;
63
+ if(dnum > CR_DPMAX) dnum = CR_DPMAX;
64
+ if(strlen(name) > CR_NAMEMAX){
65
+ dpecodeset(DP_EMISC, __FILE__, __LINE__);
66
+ return NULL;
67
+ }
68
+ dpomode = DP_OREADER;
69
+ if(omode & CR_OWRITER){
70
+ dpomode = DP_OWRITER;
71
+ if(omode & CR_OCREAT) dpomode |= DP_OCREAT;
72
+ if(omode & CR_OTRUNC) dpomode |= DP_OTRUNC;
73
+ if(omode & CR_OSPARSE) dpomode |= DP_OSPARSE;
74
+ }
75
+ if(omode & CR_ONOLCK) dpomode |= DP_ONOLCK;
76
+ attr = NULL;
77
+ lrnum = 0;
78
+ if((omode & CR_OWRITER) && (omode & CR_OCREAT)){
79
+ if(mkdir(name, CR_DIRMODE) == -1 && errno != EEXIST){
80
+ dpecodeset(DP_EMKDIR, __FILE__, __LINE__);
81
+ return NULL;
82
+ }
83
+ for(i = 0; i < dnum; i++){
84
+ sprintf(path, "%s%c%04d", name, MYPATHCHR, i + 1);
85
+ if(mkdir(path, CR_DIRMODE) == -1 && errno != EEXIST){
86
+ dpecodeset(DP_EMKDIR, __FILE__, __LINE__);
87
+ return NULL;
88
+ }
89
+ }
90
+ sprintf(path, "%s%c%s", name, MYPATHCHR, CR_DPNAME);
91
+ if(!(attr = dpopen(path, dpomode, CR_ATTRBNUM))) return NULL;
92
+ if(dprnum(attr) > 0){
93
+ if((dnum = crdpgetnum(attr, CR_KEYDNUM, -1)) < 1 ||
94
+ (lrnum = crdpgetnum(attr, CR_KEYLRNUM, -1)) < 0){
95
+ dpclose(attr);
96
+ dpecodeset(DP_EBROKEN, __FILE__, __LINE__);
97
+ return NULL;
98
+ }
99
+ } else {
100
+ if(!dpput(attr, CR_KEYDNUM, -1, (char *)&dnum, sizeof(int), DP_DOVER)){
101
+ dpclose(attr);
102
+ return NULL;
103
+ }
104
+ }
105
+ }
106
+ if(!attr){
107
+ sprintf(path, "%s%c%s", name, MYPATHCHR, CR_DPNAME);
108
+ if(!(attr = dpopen(path, dpomode, 1))) return NULL;
109
+ if(!(omode & CR_OTRUNC)){
110
+ if((dnum = crdpgetnum(attr, CR_KEYDNUM, -1)) < 1 ||
111
+ (lrnum = crdpgetnum(attr, CR_KEYLRNUM, -1)) < 0){
112
+ dpclose(attr);
113
+ dpecodeset(DP_EBROKEN, __FILE__, __LINE__);
114
+ return NULL;
115
+ }
116
+ }
117
+ }
118
+ if(omode & CR_OTRUNC){
119
+ for(i = 0; i < CR_DPMAX; i++){
120
+ sprintf(path, "%s%c%04d%c%s", name, MYPATHCHR, i + 1, MYPATHCHR, CR_DPNAME);
121
+ if(unlink(path) == -1 && errno != ENOENT){
122
+ dpclose(attr);
123
+ dpecodeset(DP_EUNLINK, __FILE__, __LINE__);
124
+ return NULL;
125
+ }
126
+ sprintf(path, "%s%c%04d%c%s", name, MYPATHCHR, i + 1, MYPATHCHR, CR_LOBDIR);
127
+ if(!crrmlobdir(path)){
128
+ dpclose(attr);
129
+ return NULL;
130
+ }
131
+ if(i >= dnum){
132
+ sprintf(path, "%s%c%04d", name, MYPATHCHR, i + 1);
133
+ if(rmdir(path) == -1 && errno != ENOENT){
134
+ dpclose(attr);
135
+ dpecodeset(DP_ERMDIR, __FILE__, __LINE__);
136
+ return NULL;
137
+ }
138
+ }
139
+ }
140
+ errno = 0;
141
+ }
142
+ if(stat(name, &sbuf) == -1){
143
+ dpclose(attr);
144
+ dpecodeset(DP_ESTAT, __FILE__, __LINE__);
145
+ return NULL;
146
+ }
147
+ inode = sbuf.st_ino;
148
+ if(!(depots = malloc(dnum * sizeof(DEPOT *)))){
149
+ dpclose(attr);
150
+ dpecodeset(DP_EALLOC, __FILE__, __LINE__);
151
+ return NULL;
152
+ }
153
+ for(i = 0; i < dnum; i++){
154
+ sprintf(path, "%s%c%04d%c%s", name, MYPATHCHR, i + 1, MYPATHCHR, CR_DPNAME);
155
+ if(!(depots[i] = dpopen(path, dpomode, bnum))){
156
+ for(j = 0; j < i; j++){
157
+ dpclose(depots[j]);
158
+ }
159
+ free(depots);
160
+ dpclose(attr);
161
+ return NULL;
162
+ }
163
+ }
164
+ curia = malloc(sizeof(CURIA));
165
+ tname = crstrdup(name);
166
+ if(!curia || !tname){
167
+ free(curia);
168
+ free(tname);
169
+ for(i = 0; i < dnum; i++){
170
+ dpclose(depots[i]);
171
+ }
172
+ free(depots);
173
+ dpclose(attr);
174
+ dpecodeset(DP_EALLOC, __FILE__, __LINE__);
175
+ return NULL;
176
+ }
177
+ curia->name = tname;
178
+ curia->wmode = (omode & CR_OWRITER);
179
+ curia->inode = inode;
180
+ curia->attr = attr;
181
+ curia->depots = depots;
182
+ curia->dnum = dnum;
183
+ curia->inum = 0;
184
+ curia->lrnum = lrnum;
185
+ return curia;
186
+ }
187
+
188
+
189
+ /* Close a database handle. */
190
+ int crclose(CURIA *curia){
191
+ int i, err;
192
+ assert(curia);
193
+ err = FALSE;
194
+ for(i = 0; i < curia->dnum; i++){
195
+ if(!dpclose(curia->depots[i])) err = TRUE;
196
+ }
197
+ free(curia->depots);
198
+ if(curia->wmode){
199
+ if(!dpput(curia->attr, CR_KEYLRNUM, -1, (char *)&(curia->lrnum), sizeof(int), DP_DOVER))
200
+ err = TRUE;
201
+ }
202
+ if(!dpclose(curia->attr)) err = TRUE;
203
+ free(curia->name);
204
+ free(curia);
205
+ return err ? FALSE : TRUE;
206
+ }
207
+
208
+
209
+ /* Store a record. */
210
+ int crput(CURIA *curia, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode){
211
+ int dpdmode;
212
+ int tnum;
213
+ assert(curia && kbuf && vbuf);
214
+ if(!curia->wmode){
215
+ dpecodeset(DP_EMODE, __FILE__, __LINE__);
216
+ return FALSE;
217
+ }
218
+ switch(dmode){
219
+ case CR_DKEEP: dpdmode = DP_DKEEP; break;
220
+ case CR_DCAT: dpdmode = DP_DCAT; break;
221
+ default: dpdmode = DP_DOVER; break;
222
+ }
223
+ tnum = dpouterhash(kbuf, ksiz) % curia->dnum;
224
+ return dpput(curia->depots[tnum], kbuf, ksiz, vbuf, vsiz, dpdmode);
225
+ }
226
+
227
+
228
+ /* Delete a record. */
229
+ int crout(CURIA *curia, const char *kbuf, int ksiz){
230
+ int tnum;
231
+ assert(curia && kbuf);
232
+ if(!curia->wmode){
233
+ dpecodeset(DP_EMODE, __FILE__, __LINE__);
234
+ return FALSE;
235
+ }
236
+ tnum = dpouterhash(kbuf, ksiz) % curia->dnum;
237
+ return dpout(curia->depots[tnum], kbuf, ksiz);
238
+ }
239
+
240
+
241
+ /* Retrieve a record. */
242
+ char *crget(CURIA *curia, const char *kbuf, int ksiz, int start, int max, int *sp){
243
+ int tnum;
244
+ assert(curia && kbuf && start >= 0);
245
+ tnum = dpouterhash(kbuf, ksiz) % curia->dnum;
246
+ return dpget(curia->depots[tnum], kbuf, ksiz, start, max, sp);
247
+ }
248
+
249
+
250
+ /* Retrieve a record and write the value into a buffer. */
251
+ int crgetwb(CURIA *curia, const char *kbuf, int ksiz, int start, int max, char *vbuf){
252
+ int tnum;
253
+ assert(curia && kbuf && start >= 0 && max >= 0 && vbuf);
254
+ tnum = dpouterhash(kbuf, ksiz) % curia->dnum;
255
+ return dpgetwb(curia->depots[tnum], kbuf, ksiz, start, max, vbuf);
256
+ }
257
+
258
+
259
+ /* Get the size of the value of a record. */
260
+ int crvsiz(CURIA *curia, const char *kbuf, int ksiz){
261
+ int tnum;
262
+ assert(curia && kbuf);
263
+ tnum = dpouterhash(kbuf, ksiz) % curia->dnum;
264
+ return dpvsiz(curia->depots[tnum], kbuf, ksiz);
265
+ }
266
+
267
+
268
+ /* Initialize the iterator of a database handle. */
269
+ int criterinit(CURIA *curia){
270
+ int i, err;
271
+ assert(curia);
272
+ err = FALSE;
273
+ for(i = 0; i < curia->dnum; i++){
274
+ if(!dpiterinit(curia->depots[i])){
275
+ err = TRUE;
276
+ break;
277
+ }
278
+ }
279
+ curia->inum = 0;
280
+ return err ? FALSE : TRUE;
281
+ }
282
+
283
+
284
+ /* Get the next key of the iterator. */
285
+ char *criternext(CURIA *curia, int *sp){
286
+ char *kbuf;
287
+ assert(curia);
288
+ kbuf = NULL;
289
+ while(curia->inum < curia->dnum && !(kbuf = dpiternext(curia->depots[curia->inum], sp))){
290
+ if(dpecode != DP_ENOITEM) return NULL;
291
+ (curia->inum)++;
292
+ }
293
+ return kbuf;
294
+ }
295
+
296
+
297
+ /* Set alignment of a database handle. */
298
+ int crsetalign(CURIA *curia, int align){
299
+ int i, err;
300
+ assert(curia);
301
+ if(!curia->wmode){
302
+ dpecodeset(DP_EMODE, __FILE__, __LINE__);
303
+ return FALSE;
304
+ }
305
+ err = FALSE;
306
+ for(i = 0; i < curia->dnum; i++){
307
+ if(!dpsetalign(curia->depots[i], align)){
308
+ err = TRUE;
309
+ break;
310
+ }
311
+ }
312
+ return err ? FALSE : TRUE;
313
+ }
314
+
315
+
316
+ /* Synchronize contents of updating a database with the files and the devices. */
317
+ int crsync(CURIA *curia){
318
+ int i, err;
319
+ assert(curia);
320
+ if(!curia->wmode){
321
+ dpecodeset(DP_EMODE, __FILE__, __LINE__);
322
+ return FALSE;
323
+ }
324
+ err = FALSE;
325
+ if(!dpput(curia->attr, CR_KEYLRNUM, -1, (char *)&(curia->lrnum), sizeof(int), DP_DOVER) ||
326
+ !dpsync(curia->attr)) err = TRUE;
327
+ for(i = 0; i < curia->dnum; i++){
328
+ if(!dpsync(curia->depots[i])){
329
+ err = TRUE;
330
+ break;
331
+ }
332
+ }
333
+ return err ? FALSE : TRUE;
334
+ }
335
+
336
+
337
+ /* Optimize a database. */
338
+ int croptimize(CURIA *curia, int bnum){
339
+ int i, err;
340
+ assert(curia);
341
+ if(!curia->wmode){
342
+ dpecodeset(DP_EMODE, __FILE__, __LINE__);
343
+ return FALSE;
344
+ }
345
+ err = FALSE;
346
+ for(i = 0; i < curia->dnum; i++){
347
+ if(!dpoptimize(curia->depots[i], bnum)){
348
+ err = TRUE;
349
+ break;
350
+ }
351
+ }
352
+ curia->inum = 0;
353
+ return err ? FALSE : TRUE;
354
+ }
355
+
356
+
357
+ /* Get the name of a database. */
358
+ char *crname(CURIA *curia){
359
+ char *name;
360
+ assert(curia);
361
+ if(!(name = crstrdup(curia->name))){
362
+ dpecodeset(DP_EALLOC, __FILE__, __LINE__);
363
+ return NULL;
364
+ }
365
+ return name;
366
+ }
367
+
368
+
369
+ /* Get the total size of database files. */
370
+ int crfsiz(CURIA *curia){
371
+ int i, sum, rv;
372
+ assert(curia);
373
+ sum = 0;
374
+ for(i = 0; i < curia->dnum; i++){
375
+ rv = dpfsiz(curia->depots[i]);
376
+ if(rv == -1) return -1;
377
+ sum += rv;
378
+ }
379
+ return sum;
380
+ }
381
+
382
+
383
+ /* Get the total size of database files as double-precision value. */
384
+ double crfsizd(CURIA *curia){
385
+ double sum;
386
+ int i, rv;
387
+ assert(curia);
388
+ sum = 0.0;
389
+ for(i = 0; i < curia->dnum; i++){
390
+ rv = dpfsiz(curia->depots[i]);
391
+ if(rv == -1) return -1.0;
392
+ sum += rv;
393
+ }
394
+ return sum;
395
+ }
396
+
397
+
398
+ /* Get the total number of the elements of each bucket array. */
399
+ int crbnum(CURIA *curia){
400
+ int i, sum, rv;
401
+ assert(curia);
402
+ sum = 0;
403
+ for(i = 0; i < curia->dnum; i++){
404
+ rv = dpbnum(curia->depots[i]);
405
+ if(rv == -1) return -1;
406
+ sum += rv;
407
+ }
408
+ return sum;
409
+ }
410
+
411
+
412
+ /* Get the total number of the used elements of each bucket array. */
413
+ int crbusenum(CURIA *curia){
414
+ int i, sum, rv;
415
+ assert(curia);
416
+ sum = 0;
417
+ for(i = 0; i < curia->dnum; i++){
418
+ rv = dpbusenum(curia->depots[i]);
419
+ if(rv == -1) return -1;
420
+ sum += rv;
421
+ }
422
+ return sum;
423
+ }
424
+
425
+
426
+ /* Get the number of the records stored in a database. */
427
+ int crrnum(CURIA *curia){
428
+ int i, sum, rv;
429
+ assert(curia);
430
+ sum = 0;
431
+ for(i = 0; i < curia->dnum; i++){
432
+ rv = dprnum(curia->depots[i]);
433
+ if(rv == -1) return -1;
434
+ sum += rv;
435
+ }
436
+ return sum;
437
+ }
438
+
439
+
440
+ /* Check whether a database handle is a writer or not. */
441
+ int crwritable(CURIA *curia){
442
+ assert(curia);
443
+ return curia->wmode;
444
+ }
445
+
446
+
447
+ /* Check whether a database has a fatal error or not. */
448
+ int crfatalerror(CURIA *curia){
449
+ int i;
450
+ assert(curia);
451
+ if(dpfatalerror(curia->attr)) return TRUE;
452
+ for(i = 0; i < curia->dnum; i++){
453
+ if(dpfatalerror(curia->depots[i])) return TRUE;
454
+ }
455
+ return FALSE;
456
+ }
457
+
458
+
459
+ /* Get the inode number of a database directory. */
460
+ int crinode(CURIA *curia){
461
+ assert(curia);
462
+ return curia->inode;
463
+ }
464
+
465
+
466
+ /* Get the last modified time of a database. */
467
+ int crmtime(CURIA *curia){
468
+ assert(curia);
469
+ return dpmtime(curia->attr);
470
+ }
471
+
472
+
473
+ /* Remove a database directory. */
474
+ int crremove(const char *name){
475
+ struct stat sbuf;
476
+ CURIA *curia;
477
+ char path[CR_PATHBUFSIZ];
478
+ assert(name);
479
+ if(stat(name, &sbuf) == -1){
480
+ dpecodeset(DP_ESTAT, __FILE__, __LINE__);
481
+ return FALSE;
482
+ }
483
+ if((curia = cropen(name, CR_OWRITER | CR_OTRUNC, 1, 1)) != NULL) crclose(curia);
484
+ sprintf(path, "%s%c0001%c%s", name, MYPATHCHR, MYPATHCHR, CR_DPNAME);
485
+ dpremove(path);
486
+ sprintf(path, "%s%c0001", name, MYPATHCHR);
487
+ if(rmdir(path) == -1){
488
+ dpecodeset(DP_ERMDIR, __FILE__, __LINE__);
489
+ return FALSE;
490
+ }
491
+ sprintf(path, "%s%c%s", name, MYPATHCHR, CR_DPNAME);
492
+ if(!dpremove(path)) return FALSE;
493
+ if(rmdir(name) == -1){
494
+ dpecodeset(DP_ERMDIR, __FILE__, __LINE__);
495
+ return FALSE;
496
+ }
497
+ return TRUE;
498
+ }
499
+
500
+
501
+ /* Repair a broken database directory. */
502
+ int crrepair(const char *name){
503
+ CURIA *tcuria;
504
+ DEPOT *tdepot;
505
+ char path[CR_PATHBUFSIZ], *kbuf, *vbuf;
506
+ struct stat sbuf;
507
+ int i, j, err, bnum, dnum, ksiz, vsiz;
508
+ assert(name);
509
+ err = FALSE;
510
+ bnum = 0;
511
+ dnum = 0;
512
+ for(i = 1; i <= CR_DPMAX; i++){
513
+ sprintf(path, "%s%c%04d%c%s", name, MYPATHCHR, i, MYPATHCHR, CR_DPNAME);
514
+ if(stat(path, &sbuf) != -1){
515
+ dnum++;
516
+ if(!dprepair(path)) err = TRUE;
517
+ if((tdepot = dpopen(path, DP_OREADER, -1)) != NULL){
518
+ bnum += dpbnum(tdepot);
519
+ dpclose(tdepot);
520
+ }
521
+ }
522
+ }
523
+ if(dnum < CR_DEFDNUM) dnum = CR_DEFDNUM;
524
+ bnum /= dnum;
525
+ sprintf(path, "%s%s", name, CR_TMPFSUF);
526
+ if((tcuria = cropen(path, CR_OWRITER | CR_OCREAT | CR_OTRUNC, bnum, dnum)) != NULL){
527
+ for(i = 1; i <= CR_DPMAX; i++){
528
+ sprintf(path, "%s%c%04d%c%s", name, MYPATHCHR, i, MYPATHCHR, CR_DPNAME);
529
+ if(stat(path, &sbuf) != -1){
530
+ if((tdepot = dpopen(path, DP_OREADER, -1)) != NULL){
531
+ if(!dpiterinit(tdepot)) err = TRUE;
532
+ while((kbuf = dpiternext(tdepot, &ksiz)) != NULL){
533
+ if((vbuf = dpget(tdepot, kbuf, ksiz, 0, -1, &vsiz)) != NULL){
534
+ if(!crput(tcuria, kbuf, ksiz, vbuf, vsiz, CR_DKEEP)) err = TRUE;
535
+ free(vbuf);
536
+ }
537
+ free(kbuf);
538
+ }
539
+ dpclose(tdepot);
540
+ } else {
541
+ err = TRUE;
542
+ }
543
+ }
544
+ for(j = 0; j <= CR_DPMAX; j++){
545
+ sprintf(path, "%s%c%04d%c%s", name, MYPATHCHR, j, MYPATHCHR, CR_LOBDIR);
546
+ if(stat(path, &sbuf) != -1){
547
+ if(!crcplobdir(tcuria, path)) err = TRUE;
548
+ }
549
+ }
550
+ }
551
+ if(!crclose(tcuria)) err = TRUE;
552
+ if(!crremove(name)) err = TRUE;
553
+ sprintf(path, "%s%s", name, CR_TMPFSUF);
554
+ if(rename(path, name) == -1){
555
+ if(!err) dpecodeset(DP_EMISC, __FILE__, __LINE__);
556
+ err = TRUE;
557
+ }
558
+ } else {
559
+ err = TRUE;
560
+ }
561
+ return err ? FALSE : TRUE;
562
+ }
563
+
564
+
565
+ /* Dump all records as endian independent data. */
566
+ int crexportdb(CURIA *curia, const char *name){
567
+ char path[CR_PATHBUFSIZ], *kbuf, *vbuf, *pbuf;
568
+ int i, err, *fds, ksiz, vsiz, psiz;
569
+ assert(curia && name);
570
+ if(!(criterinit(curia))) return FALSE;
571
+ if(mkdir(name, CR_DIRMODE) == -1 && errno != EEXIST){
572
+ dpecodeset(DP_EMKDIR, __FILE__, __LINE__);
573
+ return FALSE;
574
+ }
575
+ err = FALSE;
576
+ fds = malloc(sizeof(int) * curia->dnum);
577
+ for(i = 0; i < curia->dnum; i++){
578
+ sprintf(path, "%s%c%04d", name, MYPATHCHR, i + 1);
579
+ if((fds[i] = open(path, O_RDWR | O_CREAT | O_TRUNC, CR_FILEMODE)) == -1){
580
+ if(!err) dpecodeset(DP_EOPEN, __FILE__, __LINE__);
581
+ err = TRUE;
582
+ break;
583
+ }
584
+ }
585
+ while(!err && (kbuf = criternext(curia, &ksiz)) != NULL){
586
+ if((vbuf = crget(curia, kbuf, ksiz, 0, -1, &vsiz)) != NULL){
587
+ if((pbuf = malloc(ksiz + vsiz + CR_NUMBUFSIZ * 2)) != NULL){
588
+ psiz = 0;
589
+ psiz += sprintf(pbuf + psiz, "%X\n%X\n", ksiz, vsiz);
590
+ memcpy(pbuf + psiz, kbuf, ksiz);
591
+ psiz += ksiz;
592
+ pbuf[psiz++] = '\n';
593
+ memcpy(pbuf + psiz, vbuf, vsiz);
594
+ psiz += vsiz;
595
+ pbuf[psiz++] = '\n';
596
+ if(!crwrite(fds[curia->inum], pbuf, psiz)){
597
+ dpecodeset(DP_EWRITE, __FILE__, __LINE__);
598
+ err = TRUE;
599
+ }
600
+ free(pbuf);
601
+ } else {
602
+ dpecodeset(DP_EALLOC, __FILE__, __LINE__);
603
+ err = TRUE;
604
+ }
605
+ free(vbuf);
606
+ } else {
607
+ err = TRUE;
608
+ }
609
+ free(kbuf);
610
+ }
611
+ for(i = 0; i < curia->dnum; i++){
612
+ if(fds[i] != -1 && close(fds[i]) == -1){
613
+ if(!err) dpecodeset(DP_ECLOSE, __FILE__, __LINE__);
614
+ err = TRUE;
615
+ }
616
+ }
617
+ free(fds);
618
+ return !err && !crfatalerror(curia);
619
+ }
620
+
621
+
622
+ /* Load all records from endian independent data. */
623
+ int crimportdb(CURIA *curia, const char *name){
624
+ DEPOT *depot;
625
+ char ipath[CR_PATHBUFSIZ], opath[CR_PATHBUFSIZ], *kbuf, *vbuf;
626
+ int i, err, ksiz, vsiz;
627
+ struct stat sbuf;
628
+ assert(curia && name);
629
+ if(!curia->wmode){
630
+ dpecodeset(DP_EMODE, __FILE__, __LINE__);
631
+ return FALSE;
632
+ }
633
+ if(crrnum(curia) > 0){
634
+ dpecodeset(DP_EMISC, __FILE__, __LINE__);
635
+ return FALSE;
636
+ }
637
+ err = FALSE;
638
+ for(i = 0; !err && i < CR_DPMAX; i++){
639
+ sprintf(ipath, "%s%c%04d", name, MYPATHCHR, i + 1);
640
+ if(stat(ipath, &sbuf) == -1 || !S_ISREG(sbuf.st_mode)) break;
641
+ sprintf(opath, "%s%c%04d%s", curia->name, MYPATHCHR, i + 1, CR_TMPFSUF);
642
+ if((depot = dpopen(opath, DP_OWRITER | DP_OCREAT | DP_OTRUNC, -1)) != NULL){
643
+ if(dpimportdb(depot, ipath)){
644
+ dpiterinit(depot);
645
+ while((kbuf = dpiternext(depot, &ksiz)) != NULL){
646
+ if((vbuf = dpget(depot, kbuf, ksiz, 0, -1, &vsiz)) != NULL){
647
+ if(!crput(curia, kbuf, ksiz, vbuf, vsiz, CR_DKEEP)) err = TRUE;
648
+ free(vbuf);
649
+ } else {
650
+ err = TRUE;
651
+ }
652
+ free(kbuf);
653
+ }
654
+ } else {
655
+ err = TRUE;
656
+ }
657
+ if(!dpclose(depot)) err = TRUE;
658
+ if(!dpremove(opath)) err = TRUE;
659
+ } else {
660
+ err = TRUE;
661
+ }
662
+ }
663
+ return !err && !crfatalerror(curia);
664
+ }
665
+
666
+
667
+ /* Store a large object. */
668
+ int crputlob(CURIA *curia, const char *kbuf, int ksiz, const char *vbuf, int vsiz, int dmode){
669
+ char *path;
670
+ int mode, fd, err, be;
671
+ struct stat sbuf;
672
+ assert(curia && kbuf && vbuf);
673
+ if(!curia->wmode){
674
+ dpecodeset(DP_EMODE, __FILE__, __LINE__);
675
+ return FALSE;
676
+ }
677
+ if(ksiz < 0) ksiz = strlen(kbuf);
678
+ if(vsiz < 0) vsiz = strlen(vbuf);
679
+ if(!(path = crgetlobpath(curia, kbuf, ksiz))) return FALSE;
680
+ if(!crmklobdir(path)){
681
+ free(path);
682
+ return FALSE;
683
+ }
684
+ be = stat(path, &sbuf) != -1 && S_ISREG(sbuf.st_mode);
685
+ mode = O_RDWR | O_CREAT;
686
+ if(dmode & CR_DKEEP) mode |= O_EXCL;
687
+ if(dmode & CR_DCAT){
688
+ mode |= O_APPEND;
689
+ } else {
690
+ mode |= O_TRUNC;
691
+ }
692
+ if((fd = open(path, mode, CR_FILEMODE)) == -1){
693
+ free(path);
694
+ dpecodeset(DP_EOPEN, __FILE__, __LINE__);
695
+ if(dmode == CR_DKEEP) dpecodeset(DP_EKEEP, __FILE__, __LINE__);
696
+ return FALSE;
697
+ }
698
+ free(path);
699
+ err = FALSE;
700
+ if(crwrite(fd, vbuf, vsiz) == -1){
701
+ err = TRUE;
702
+ dpecodeset(DP_EWRITE, __FILE__, __LINE__);
703
+ }
704
+ if(close(fd) == -1){
705
+ err = TRUE;
706
+ dpecodeset(DP_ECLOSE, __FILE__, __LINE__);
707
+ }
708
+ if(!err && !be) (curia->lrnum)++;
709
+ return err ? FALSE : TRUE;
710
+ }
711
+
712
+
713
+ /* Delete a large object. */
714
+ int croutlob(CURIA *curia, const char *kbuf, int ksiz){
715
+ char *path;
716
+ int err, be;
717
+ struct stat sbuf;
718
+ assert(curia && kbuf);
719
+ if(!curia->wmode){
720
+ dpecodeset(DP_EMODE, __FILE__, __LINE__);
721
+ return FALSE;
722
+ }
723
+ if(ksiz < 0) ksiz = strlen(kbuf);
724
+ if(!(path = crgetlobpath(curia, kbuf, ksiz))) return FALSE;
725
+ be = stat(path, &sbuf) != -1 && S_ISREG(sbuf.st_mode);
726
+ err = FALSE;
727
+ if(unlink(path) == -1){
728
+ err = TRUE;
729
+ dpecodeset(DP_ENOITEM, __FILE__, __LINE__);
730
+ }
731
+ free(path);
732
+ if(!err && be) (curia->lrnum)--;
733
+ return err ? FALSE : TRUE;
734
+ }
735
+
736
+
737
+ /* Retrieve a large object. */
738
+ char *crgetlob(CURIA *curia, const char *kbuf, int ksiz, int start, int max, int *sp){
739
+ char *path, *buf;
740
+ struct stat sbuf;
741
+ int fd, size;
742
+ assert(curia && kbuf && start >= 0);
743
+ if(ksiz < 0) ksiz = strlen(kbuf);
744
+ if(!(path = crgetlobpath(curia, kbuf, ksiz))) return NULL;
745
+ if((fd = open(path, O_RDONLY, CR_FILEMODE)) == -1){
746
+ free(path);
747
+ dpecodeset(DP_ENOITEM, __FILE__, __LINE__);
748
+ return NULL;
749
+ }
750
+ free(path);
751
+ if(fstat(fd, &sbuf) == -1){
752
+ close(fd);
753
+ dpecodeset(DP_ESTAT, __FILE__, __LINE__);
754
+ return NULL;
755
+ }
756
+ if(start > sbuf.st_size){
757
+ close(fd);
758
+ dpecodeset(DP_ENOITEM, __FILE__, __LINE__);
759
+ return NULL;
760
+ }
761
+ if(lseek(fd, start, SEEK_SET) == -1){
762
+ close(fd);
763
+ dpecodeset(DP_ESEEK, __FILE__, __LINE__);
764
+ return NULL;
765
+ }
766
+ if(max < 0) max = sbuf.st_size;
767
+ if(!(buf = malloc(max + 1))){
768
+ close(fd);
769
+ dpecodeset(DP_EALLOC, __FILE__, __LINE__);
770
+ return NULL;
771
+ }
772
+ size = crread(fd, buf, max);
773
+ close(fd);
774
+ if(size == -1){
775
+ free(buf);
776
+ dpecodeset(DP_EREAD, __FILE__, __LINE__);
777
+ return NULL;
778
+ }
779
+ buf[size] = '\0';
780
+ if(sp) *sp = size;
781
+ return buf;
782
+ }
783
+
784
+
785
+ /* Get the file descriptor of a large object. */
786
+ int crgetlobfd(CURIA *curia, const char *kbuf, int ksiz){
787
+ char *path;
788
+ int fd;
789
+ assert(curia && kbuf);
790
+ if(ksiz < 0) ksiz = strlen(kbuf);
791
+ if(!(path = crgetlobpath(curia, kbuf, ksiz))) return -1;
792
+ if((fd = open(path, curia->wmode ? O_RDWR: O_RDONLY, CR_FILEMODE)) == -1){
793
+ free(path);
794
+ dpecodeset(DP_ENOITEM, __FILE__, __LINE__);
795
+ return -1;
796
+ }
797
+ free(path);
798
+ return fd;
799
+ }
800
+
801
+
802
+ /* Get the size of the value of a large object. */
803
+ int crvsizlob(CURIA *curia, const char *kbuf, int ksiz){
804
+ char *path;
805
+ struct stat sbuf;
806
+ assert(curia && kbuf);
807
+ if(ksiz < 0) ksiz = strlen(kbuf);
808
+ if(!(path = crgetlobpath(curia, kbuf, ksiz))) return -1;
809
+ if(stat(path, &sbuf) == -1){
810
+ free(path);
811
+ dpecodeset(DP_ENOITEM, __FILE__, __LINE__);
812
+ return -1;
813
+ }
814
+ free(path);
815
+ return sbuf.st_size;
816
+ }
817
+
818
+
819
+ /* Get the number of the large objects stored in a database. */
820
+ int crrnumlob(CURIA *curia){
821
+ assert(curia);
822
+ return curia->lrnum;
823
+ }
824
+
825
+
826
+
827
+ /*************************************************************************************************
828
+ * features for experts
829
+ *************************************************************************************************/
830
+
831
+
832
+ /* Synchronize updating contents on memory. */
833
+ int crmemsync(CURIA *curia){
834
+ int i, err;
835
+ assert(curia);
836
+ if(!curia->wmode){
837
+ dpecodeset(DP_EMODE, __FILE__, __LINE__);
838
+ return FALSE;
839
+ }
840
+ err = FALSE;
841
+ if(!dpput(curia->attr, CR_KEYLRNUM, -1, (char *)&(curia->lrnum), sizeof(int), DP_DOVER) ||
842
+ !dpmemsync(curia->attr)) err = TRUE;
843
+ for(i = 0; i < curia->dnum; i++){
844
+ if(!dpmemsync(curia->depots[i])){
845
+ err = TRUE;
846
+ break;
847
+ }
848
+ }
849
+ return err ? FALSE : TRUE;
850
+ }
851
+
852
+
853
+ /* Get flags of a database. */
854
+ int crgetflags(CURIA *curia){
855
+ assert(curia);
856
+ return dpgetflags(curia->attr);
857
+ }
858
+
859
+
860
+ /* Set flags of a database. */
861
+ int crsetflags(CURIA *curia, int flags){
862
+ assert(curia);
863
+ if(!curia->wmode){
864
+ dpecodeset(DP_EMODE, __FILE__, __LINE__);
865
+ return FALSE;
866
+ }
867
+ return dpsetflags(curia->attr, flags);
868
+ }
869
+
870
+
871
+
872
+ /*************************************************************************************************
873
+ * private objects
874
+ *************************************************************************************************/
875
+
876
+
877
+ /* Get a copied string.
878
+ `str' specifies an original string.
879
+ The return value is a copied string whose region is allocated by `malloc'. */
880
+ static char *crstrdup(const char *str){
881
+ int len;
882
+ char *buf;
883
+ assert(str);
884
+ len = strlen(str);
885
+ if(!(buf = malloc(len + 1))) return NULL;
886
+ memcpy(buf, str, len + 1);
887
+ return buf;
888
+ }
889
+
890
+
891
+ /* Get an integer from a database.
892
+ `depot' specifies an inner database handle.
893
+ `kbuf' specifies the pointer to the region of a key.
894
+ `ksiz' specifies the size of the key.
895
+ The return value is the integer of the corresponding record. */
896
+ static int crdpgetnum(DEPOT *depot, const char *kbuf, int ksiz){
897
+ char *vbuf;
898
+ int vsiz, rv;
899
+ if(!(vbuf = dpget(depot, kbuf, ksiz, 0, -1, &vsiz)) || vsiz != sizeof(int)){
900
+ free(vbuf);
901
+ return INT_MIN;
902
+ }
903
+ rv = *(int *)vbuf;
904
+ free(vbuf);
905
+ return rv;
906
+ }
907
+
908
+
909
+ /* Get the path of a large object.
910
+ `curia' specifies a database handle.
911
+ `kbuf' specifies the pointer to the region of a key.
912
+ `ksiz' specifies the size of the key.
913
+ The return value is a path string whose region is allocated by `malloc'. */
914
+ static char *crgetlobpath(CURIA *curia, const char *kbuf, int ksiz){
915
+ char prefix[CR_PATHBUFSIZ], *wp, *path;
916
+ int i, hash;
917
+ assert(curia && kbuf && ksiz >= 0);
918
+ wp = prefix;
919
+ wp += sprintf(wp, "%s%c%04d%c%s%c",
920
+ curia->name, MYPATHCHR, dpouterhash(kbuf, ksiz) % curia->dnum + 1,
921
+ MYPATHCHR, CR_LOBDIR, MYPATHCHR);
922
+ hash = dpinnerhash(kbuf, ksiz);
923
+ for(i = 0; i < CR_LOBDDEPTH; i++){
924
+ wp += sprintf(wp, "%02X%c", hash % 0x100, MYPATHCHR);
925
+ hash /= 0x100;
926
+ }
927
+ if(!(path = malloc(strlen(prefix) + ksiz * 2 + 1))){
928
+ dpecodeset(DP_EALLOC, __FILE__, __LINE__);
929
+ return NULL;
930
+ }
931
+ wp = path;
932
+ wp += sprintf(path, "%s", prefix);
933
+ for(i = 0; i < ksiz; i++){
934
+ wp += sprintf(wp, "%02X", ((unsigned char *)kbuf)[i]);
935
+ }
936
+ return path;
937
+ }
938
+
939
+
940
+ /* Create directories included in a path.
941
+ `path' specifies a path.
942
+ The return value is true if successful, else, it is false. */
943
+ static int crmklobdir(const char *path){
944
+ char elem[CR_PATHBUFSIZ], *wp;
945
+ const char *dp;
946
+ int err, len;
947
+ wp = elem;
948
+ err = FALSE;
949
+ while(*path != '\0' && (dp = strchr(path, MYPATHCHR)) != NULL){
950
+ len = dp - path;
951
+ if(wp != elem) wp += sprintf(wp, "%c", MYPATHCHR);
952
+ memcpy(wp, path, len);
953
+ wp[len] = '\0';
954
+ wp += len;
955
+ if(mkdir(elem, CR_DIRMODE) == -1 && errno != EEXIST) err = TRUE;
956
+ path = dp + 1;
957
+ }
958
+ if(err) dpecodeset(DP_EMKDIR, __FILE__, __LINE__);
959
+ return err ? FALSE : TRUE;
960
+ }
961
+
962
+
963
+ /* Remove file and directories under a directory.
964
+ `path' specifies a path.
965
+ The return value is true if successful, else, it is false. */
966
+ static int crrmlobdir(const char *path){
967
+ char elem[CR_PATHBUFSIZ];
968
+ DIR *DD;
969
+ struct dirent *dp;
970
+ assert(path);
971
+ if(unlink(path) != -1){
972
+ return TRUE;
973
+ } else {
974
+ if(errno == ENOENT) return TRUE;
975
+ if(!(DD = opendir(path))){
976
+ dpecodeset(DP_EMISC, __FILE__, __LINE__);
977
+ return FALSE;
978
+ }
979
+ while((dp = readdir(DD)) != NULL){
980
+ if(!strcmp(dp->d_name, MYCDIRSTR) || !strcmp(dp->d_name, MYPDIRSTR)) continue;
981
+ sprintf(elem, "%s%c%s", path, MYPATHCHR, dp->d_name);
982
+ if(!crrmlobdir(elem)){
983
+ closedir(DD);
984
+ return FALSE;
985
+ }
986
+ }
987
+ }
988
+ if(closedir(DD) == -1){
989
+ dpecodeset(DP_EMISC, __FILE__, __LINE__);
990
+ return FALSE;
991
+ }
992
+ if(rmdir(path) == -1){
993
+ dpecodeset(DP_ERMDIR, __FILE__, __LINE__);
994
+ return FALSE;
995
+ }
996
+ return TRUE;
997
+ }
998
+
999
+
1000
+ /* Copy file and directories under a directory for repairing.
1001
+ `path' specifies a path.
1002
+ The return value is true if successful, else, it is false. */
1003
+ static int crcplobdir(CURIA *curia, const char *path){
1004
+ char elem[CR_PATHBUFSIZ], numbuf[3], *rp, *kbuf, *vbuf;
1005
+ DIR *DD;
1006
+ struct dirent *dp;
1007
+ struct stat sbuf;
1008
+ int i, ksiz, vsiz, fd;
1009
+ assert(curia && path);
1010
+ if(stat(path, &sbuf) == -1){
1011
+ dpecodeset(DP_ESTAT, __FILE__, __LINE__);
1012
+ return FALSE;
1013
+ }
1014
+ if(S_ISREG(sbuf.st_mode)){
1015
+ rp = strrchr(path, MYPATHCHR) + 1;
1016
+ for(i = 0; rp[i] != '\0'; i += 2){
1017
+ numbuf[0] = rp[i];
1018
+ numbuf[1] = rp[i+1];
1019
+ numbuf[2] = '\0';
1020
+ elem[i/2] = (int)strtol(numbuf, NULL, 16);
1021
+ }
1022
+ kbuf = elem;
1023
+ ksiz = i / 2;
1024
+ vsiz = sbuf.st_size;
1025
+ if(!(vbuf = malloc(vsiz + 1))){
1026
+ dpecodeset(DP_EALLOC, __FILE__, __LINE__);
1027
+ return FALSE;
1028
+ }
1029
+ if((fd = open(path, O_RDONLY, CR_FILEMODE)) == -1){
1030
+ free(vbuf);
1031
+ dpecodeset(DP_EOPEN, __FILE__, __LINE__);
1032
+ return FALSE;
1033
+ }
1034
+ if(crread(fd, vbuf, vsiz) == -1){
1035
+ close(fd);
1036
+ free(vbuf);
1037
+ dpecodeset(DP_EOPEN, __FILE__, __LINE__);
1038
+ return FALSE;
1039
+ }
1040
+ if(!crputlob(curia, kbuf, ksiz, vbuf, vsiz, DP_DOVER)){
1041
+ close(fd);
1042
+ free(vbuf);
1043
+ return FALSE;
1044
+ }
1045
+ close(fd);
1046
+ free(vbuf);
1047
+ return TRUE;
1048
+ }
1049
+ if(!(DD = opendir(path))){
1050
+ dpecodeset(DP_EMISC, __FILE__, __LINE__);
1051
+ return FALSE;
1052
+ }
1053
+ while((dp = readdir(DD)) != NULL){
1054
+ if(!strcmp(dp->d_name, MYCDIRSTR) || !strcmp(dp->d_name, MYPDIRSTR)) continue;
1055
+ sprintf(elem, "%s%c%s", path, MYPATHCHR, dp->d_name);
1056
+ if(!crcplobdir(curia, elem)){
1057
+ closedir(DD);
1058
+ return FALSE;
1059
+ }
1060
+ }
1061
+ if(closedir(DD) == -1){
1062
+ dpecodeset(DP_EMISC, __FILE__, __LINE__);
1063
+ return FALSE;
1064
+ }
1065
+ return TRUE;
1066
+ }
1067
+
1068
+
1069
+ /* Write into a file.
1070
+ `fd' specifies a file descriptor.
1071
+ `buf' specifies a buffer to write.
1072
+ `size' specifies the size of the buffer.
1073
+ The return value is the size of the written buffer, or, -1 on failure. */
1074
+ static int crwrite(int fd, const void *buf, int size){
1075
+ char *lbuf;
1076
+ int rv, wb;
1077
+ assert(fd >= 0 && buf && size >= 0);
1078
+ lbuf = (char *)buf;
1079
+ rv = 0;
1080
+ do {
1081
+ wb = write(fd, lbuf, size);
1082
+ switch(wb){
1083
+ case -1: if(errno != EINTR) return -1;
1084
+ case 0: break;
1085
+ default:
1086
+ lbuf += wb;
1087
+ size -= wb;
1088
+ rv += wb;
1089
+ break;
1090
+ }
1091
+ } while(size > 0);
1092
+ return rv;
1093
+ }
1094
+
1095
+
1096
+ /* Read from a file and store the data into a buffer.
1097
+ `fd' specifies a file descriptor.
1098
+ `buffer' specifies a buffer to store into.
1099
+ `size' specifies the size to read with.
1100
+ The return value is the size read with, or, -1 on failure. */
1101
+ static int crread(int fd, void *buf, int size){
1102
+ char *lbuf;
1103
+ int i, bs;
1104
+ assert(fd >= 0 && buf && size >= 0);
1105
+ lbuf = buf;
1106
+ for(i = 0; i < size && (bs = read(fd, lbuf + i, size - i)) != 0; i += bs){
1107
+ if(bs == -1 && errno != EINTR) return -1;
1108
+ }
1109
+ return i;
1110
+ }
1111
+
1112
+
1113
+
1114
+ /* END OF FILE */