Ruby  2.4.2p198(2017-09-14revision59899)
dbm.c
Go to the documentation of this file.
1 /************************************************
2 
3  dbm.c -
4 
5  $Author: nobu $
6  created at: Mon Jan 24 15:59:52 JST 1994
7 
8  Copyright (C) 1995-2001 Yukihiro Matsumoto
9 
10 ************************************************/
11 
12 #include "ruby.h"
13 
14 #ifdef HAVE_CDEFS_H
15 # include <cdefs.h>
16 #endif
17 #ifdef HAVE_SYS_CDEFS_H
18 # include <sys/cdefs.h>
19 #endif
20 #include DBM_HDR
21 #include <fcntl.h>
22 #include <errno.h>
23 
24 #define DSIZE_TYPE TYPEOF_DATUM_DSIZE
25 #if SIZEOF_DATUM_DSIZE > SIZEOF_INT
26 # define RSTRING_DSIZE(s) RSTRING_LEN(s)
27 # define TOO_LONG(n) 0
28 #else
29 # define RSTRING_DSIZE(s) RSTRING_LENINT(s)
30 # define TOO_LONG(n) ((long)(+(DSIZE_TYPE)(n)) != (n))
31 #endif
32 
34 
35 #define RUBY_DBM_RW_BIT 0x20000000
36 
37 struct dbmdata {
38  long di_size;
40 };
41 
42 static void
44 {
45  rb_raise(rb_eDBMError, "closed DBM file");
46 }
47 
48 #define GetDBM(obj, dbmp) do {\
49  TypedData_Get_Struct((obj), struct dbmdata, &dbm_type, (dbmp));\
50  if ((dbmp) == 0) closed_dbm();\
51  if ((dbmp)->di_dbm == 0) closed_dbm();\
52 } while (0)
53 
54 #define GetDBM2(obj, dbmp, dbm) do {\
55  GetDBM((obj), (dbmp));\
56  (dbm) = (dbmp)->di_dbm;\
57 } while (0)
58 
59 static void
60 free_dbm(void *ptr)
61 {
62  struct dbmdata *dbmp = ptr;
63  if (dbmp) {
64  if (dbmp->di_dbm) dbm_close(dbmp->di_dbm);
65  xfree(dbmp);
66  }
67 }
68 
69 static size_t
70 memsize_dbm(const void *ptr)
71 {
72  size_t size = 0;
73  const struct dbmdata *dbmp = ptr;
74  if (dbmp) {
75  size += sizeof(*dbmp);
76  if (dbmp->di_dbm) size += DBM_SIZEOF_DBM;
77  }
78  return size;
79 }
80 
81 static const rb_data_type_t dbm_type = {
82  "dbm",
83  {0, free_dbm, memsize_dbm,},
84  0, 0,
86 };
87 
88 /*
89  * call-seq:
90  * dbm.close
91  *
92  * Closes the database.
93  */
94 static VALUE
96 {
97  struct dbmdata *dbmp;
98 
99  GetDBM(obj, dbmp);
100  dbm_close(dbmp->di_dbm);
101  dbmp->di_dbm = 0;
102 
103  return Qnil;
104 }
105 
106 /*
107  * call-seq:
108  * dbm.closed? -> true or false
109  *
110  * Returns true if the database is closed, false otherwise.
111  */
112 static VALUE
114 {
115  struct dbmdata *dbmp;
116 
117  TypedData_Get_Struct(obj, struct dbmdata, &dbm_type, dbmp);
118  if (dbmp == 0)
119  return Qtrue;
120  if (dbmp->di_dbm == 0)
121  return Qtrue;
122 
123  return Qfalse;
124 }
125 
126 static VALUE
128 {
129  return TypedData_Wrap_Struct(klass, &dbm_type, 0);
130 }
131 
132 /*
133  * call-seq:
134  * DBM.new(filename[, mode[, flags]]) -> dbm
135  *
136  * Open a dbm database with the specified name, which can include a directory
137  * path. Any file extensions needed will be supplied automatically by the dbm
138  * library. For example, Berkeley DB appends '.db', and GNU gdbm uses two
139  * physical files with extensions '.dir' and '.pag'.
140  *
141  * The mode should be an integer, as for Unix chmod.
142  *
143  * Flags should be one of READER, WRITER, WRCREAT or NEWDB.
144  */
145 static VALUE
147 {
148  VALUE file, vmode, vflags;
149  DBM *dbm;
150  struct dbmdata *dbmp;
151  int mode, flags = 0;
152 
153  if (rb_scan_args(argc, argv, "12", &file, &vmode, &vflags) == 1) {
154  mode = 0666; /* default value */
155  }
156  else if (NIL_P(vmode)) {
157  mode = -1; /* return nil if DB not exist */
158  }
159  else {
160  mode = NUM2INT(vmode);
161  }
162 
163  if (!NIL_P(vflags))
164  flags = NUM2INT(vflags);
165 
166  FilePathValue(file);
167 
168  /*
169  * Note:
170  * gdbm 1.10 works with O_CLOEXEC. gdbm 1.9.1 silently ignore it.
171  */
172 #ifndef O_CLOEXEC
173 # define O_CLOEXEC 0
174 #endif
175 
176  if (flags & RUBY_DBM_RW_BIT) {
177  flags &= ~RUBY_DBM_RW_BIT;
178  dbm = dbm_open(RSTRING_PTR(file), flags|O_CLOEXEC, mode);
179  }
180  else {
181  dbm = 0;
182  if (mode >= 0) {
183  dbm = dbm_open(RSTRING_PTR(file), O_RDWR|O_CREAT|O_CLOEXEC, mode);
184  }
185  if (!dbm) {
186  dbm = dbm_open(RSTRING_PTR(file), O_RDWR|O_CLOEXEC, 0);
187  }
188  if (!dbm) {
189  dbm = dbm_open(RSTRING_PTR(file), O_RDONLY|O_CLOEXEC, 0);
190  }
191  }
192 
193  if (dbm) {
194  /*
195  * History of dbm_pagfno() and dbm_dirfno() in ndbm and its compatibles.
196  * (dbm_pagfno() and dbm_dirfno() is not standardized.)
197  *
198  * 1986: 4.3BSD provides ndbm.
199  * It provides dbm_pagfno() and dbm_dirfno() as macros.
200  * 1991: gdbm-1.5 provides them as functions.
201  * They returns a same descriptor.
202  * (Earlier releases may have the functions too.)
203  * 1991: Net/2 provides Berkeley DB.
204  * It doesn't provide dbm_pagfno() and dbm_dirfno().
205  * 1992: 4.4BSD Alpha provides Berkeley DB with dbm_dirfno() as a function.
206  * dbm_pagfno() is a macro as DBM_PAGFNO_NOT_AVAILABLE.
207  * 1997: Berkeley DB 2.0 is released by Sleepycat Software, Inc.
208  * It defines dbm_pagfno() and dbm_dirfno() as macros.
209  * 2011: gdbm-1.9 creates a separate dir file.
210  * dbm_pagfno() and dbm_dirfno() returns different descriptors.
211  */
212 #if defined(HAVE_DBM_PAGFNO)
213  rb_fd_fix_cloexec(dbm_pagfno(dbm));
214 #endif
215 #if defined(HAVE_DBM_DIRFNO)
216  rb_fd_fix_cloexec(dbm_dirfno(dbm));
217 #endif
218 
219 #if defined(RUBYDBM_DB_HEADER) && defined(HAVE_TYPE_DBC)
220  /* Disable Berkeley DB error messages such as:
221  * DB->put: attempt to modify a read-only database */
222  ((DBC*)dbm)->dbp->set_errfile(((DBC*)dbm)->dbp, NULL);
223 #endif
224  }
225 
226  if (!dbm) {
227  if (mode == -1) return Qnil;
228  rb_sys_fail_str(file);
229  }
230 
231  dbmp = ALLOC(struct dbmdata);
232  DATA_PTR(obj) = dbmp;
233  dbmp->di_dbm = dbm;
234  dbmp->di_size = -1;
235 
236  return obj;
237 }
238 
239 /*
240  * call-seq:
241  * DBM.open(filename[, mode[, flags]]) -> dbm
242  * DBM.open(filename[, mode[, flags]]) {|dbm| block}
243  *
244  * Open a dbm database and yields it if a block is given. See also
245  * <code>DBM.new</code>.
246  */
247 static VALUE
249 {
250  VALUE obj = fdbm_alloc(klass);
251 
252  if (NIL_P(fdbm_initialize(argc, argv, obj))) {
253  return Qnil;
254  }
255 
256  if (rb_block_given_p()) {
257  return rb_ensure(rb_yield, obj, fdbm_close, obj);
258  }
259 
260  return obj;
261 }
262 
263 static VALUE
264 fdbm_fetch(VALUE obj, VALUE keystr, VALUE ifnone)
265 {
266  datum key, value;
267  struct dbmdata *dbmp;
268  DBM *dbm;
269  long len;
270 
271  ExportStringValue(keystr);
272  len = RSTRING_LEN(keystr);
273  if (TOO_LONG(len)) goto not_found;
274  key.dptr = RSTRING_PTR(keystr);
275  key.dsize = (DSIZE_TYPE)len;
276 
277  GetDBM2(obj, dbmp, dbm);
278  value = dbm_fetch(dbm, key);
279  if (value.dptr == 0) {
280  not_found:
281  if (NIL_P(ifnone) && rb_block_given_p()) {
282  keystr = rb_str_dup(keystr);
283  OBJ_TAINT(keystr);
284  return rb_yield(keystr);
285  }
286  return ifnone;
287  }
288  return rb_tainted_str_new(value.dptr, value.dsize);
289 }
290 
291 /*
292  * call-seq:
293  * dbm[key] -> string value or nil
294  *
295  * Return a value from the database by locating the key string
296  * provided. If the key is not found, returns nil.
297  */
298 static VALUE
299 fdbm_aref(VALUE obj, VALUE keystr)
300 {
301  return fdbm_fetch(obj, keystr, Qnil);
302 }
303 
304 /*
305  * call-seq:
306  * dbm.fetch(key[, ifnone]) -> value
307  *
308  * Return a value from the database by locating the key string
309  * provided. If the key is not found, returns +ifnone+. If +ifnone+
310  * is not given, raises IndexError.
311  */
312 static VALUE
314 {
315  VALUE keystr, valstr, ifnone;
316 
317  rb_scan_args(argc, argv, "11", &keystr, &ifnone);
318  valstr = fdbm_fetch(obj, keystr, ifnone);
319  if (argc == 1 && !rb_block_given_p() && NIL_P(valstr))
320  rb_raise(rb_eIndexError, "key not found");
321 
322  return valstr;
323 }
324 
325 /*
326  * call-seq:
327  * dbm.key(value) -> string
328  *
329  * Returns the key for the specified value.
330  */
331 static VALUE
332 fdbm_key(VALUE obj, VALUE valstr)
333 {
334  datum key, val;
335  struct dbmdata *dbmp;
336  DBM *dbm;
337  long len;
338 
339  ExportStringValue(valstr);
340  len = RSTRING_LEN(valstr);
341  if (TOO_LONG(len)) return Qnil;
342  val.dptr = RSTRING_PTR(valstr);
343  val.dsize = (DSIZE_TYPE)len;
344 
345  GetDBM2(obj, dbmp, dbm);
346  for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
347  val = dbm_fetch(dbm, key);
348  if ((long)val.dsize == RSTRING_LEN(valstr) &&
349  memcmp(val.dptr, RSTRING_PTR(valstr), val.dsize) == 0) {
350  return rb_tainted_str_new(key.dptr, key.dsize);
351  }
352  }
353  return Qnil;
354 }
355 
356 /* :nodoc: */
357 static VALUE
359 {
360  rb_warn("DBM#index is deprecated; use DBM#key");
361  return fdbm_key(hash, value);
362 }
363 
364 /*
365  * call-seq:
366  * dbm.select {|key, value| block} -> array
367  *
368  * Returns a new array consisting of the [key, value] pairs for which the code
369  * block returns true.
370  */
371 static VALUE
373 {
374  VALUE new = rb_ary_new();
375  datum key, val;
376  DBM *dbm;
377  struct dbmdata *dbmp;
378 
379  GetDBM2(obj, dbmp, dbm);
380  for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
381  VALUE assoc, v;
382  val = dbm_fetch(dbm, key);
383  assoc = rb_assoc_new(rb_tainted_str_new(key.dptr, key.dsize),
384  rb_tainted_str_new(val.dptr, val.dsize));
385  v = rb_yield(assoc);
386  if (RTEST(v)) {
387  rb_ary_push(new, assoc);
388  }
389  GetDBM2(obj, dbmp, dbm);
390  }
391 
392  return new;
393 }
394 
395 /*
396  * call-seq:
397  * dbm.values_at(key, ...) -> Array
398  *
399  * Returns an array containing the values associated with the given keys.
400  */
401 static VALUE
403 {
404  VALUE new = rb_ary_new2(argc);
405  int i;
406 
407  for (i=0; i<argc; i++) {
408  rb_ary_push(new, fdbm_fetch(obj, argv[i], Qnil));
409  }
410 
411  return new;
412 }
413 
414 static void
416 {
417  if (OBJ_FROZEN(obj)) rb_error_frozen("DBM");
418 }
419 
420 /*
421  * call-seq:
422  * dbm.delete(key)
423  *
424  * Deletes an entry from the database.
425  */
426 static VALUE
427 fdbm_delete(VALUE obj, VALUE keystr)
428 {
429  datum key, value;
430  struct dbmdata *dbmp;
431  DBM *dbm;
432  VALUE valstr;
433  long len;
434 
435  fdbm_modify(obj);
436  ExportStringValue(keystr);
437  len = RSTRING_LEN(keystr);
438  if (TOO_LONG(len)) goto not_found;
439  key.dptr = RSTRING_PTR(keystr);
440  key.dsize = (DSIZE_TYPE)len;
441 
442  GetDBM2(obj, dbmp, dbm);
443 
444  value = dbm_fetch(dbm, key);
445  if (value.dptr == 0) {
446  not_found:
447  if (rb_block_given_p()) return rb_yield(keystr);
448  return Qnil;
449  }
450 
451  /* need to save value before dbm_delete() */
452  valstr = rb_tainted_str_new(value.dptr, value.dsize);
453 
454  if (dbm_delete(dbm, key)) {
455  dbmp->di_size = -1;
456  rb_raise(rb_eDBMError, "dbm_delete failed");
457  }
458  else if (dbmp->di_size >= 0) {
459  dbmp->di_size--;
460  }
461  return valstr;
462 }
463 
464 /*
465  * call-seq:
466  * dbm.shift() -> [key, value]
467  *
468  * Removes a [key, value] pair from the database, and returns it.
469  * If the database is empty, returns nil.
470  * The order in which values are removed/returned is not guaranteed.
471  */
472 static VALUE
474 {
475  datum key, val;
476  struct dbmdata *dbmp;
477  DBM *dbm;
478  VALUE keystr, valstr;
479 
480  fdbm_modify(obj);
481  GetDBM2(obj, dbmp, dbm);
482  dbmp->di_size = -1;
483 
484  key = dbm_firstkey(dbm);
485  if (!key.dptr) return Qnil;
486  val = dbm_fetch(dbm, key);
487  keystr = rb_tainted_str_new(key.dptr, key.dsize);
488  valstr = rb_tainted_str_new(val.dptr, val.dsize);
489  dbm_delete(dbm, key);
490 
491  return rb_assoc_new(keystr, valstr);
492 }
493 
494 /*
495  * call-seq:
496  * dbm.reject! {|key, value| block} -> self
497  * dbm.delete_if {|key, value| block} -> self
498  *
499  * Deletes all entries for which the code block returns true.
500  * Returns self.
501  */
502 static VALUE
504 {
505  datum key, val;
506  struct dbmdata *dbmp;
507  DBM *dbm;
508  VALUE keystr, valstr;
509  VALUE ret, ary = rb_ary_tmp_new(0);
510  int status = 0;
511  long i, n;
512 
513  fdbm_modify(obj);
514  GetDBM2(obj, dbmp, dbm);
515  n = dbmp->di_size;
516  dbmp->di_size = -1;
517 
518  for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
519  val = dbm_fetch(dbm, key);
520  keystr = rb_tainted_str_new(key.dptr, key.dsize);
521  OBJ_FREEZE(keystr);
522  valstr = rb_tainted_str_new(val.dptr, val.dsize);
523  ret = rb_protect(rb_yield, rb_assoc_new(rb_str_dup(keystr), valstr), &status);
524  if (status != 0) break;
525  if (RTEST(ret)) rb_ary_push(ary, keystr);
526  GetDBM2(obj, dbmp, dbm);
527  }
528 
529  for (i = 0; i < RARRAY_LEN(ary); i++) {
530  keystr = RARRAY_AREF(ary, i);
531  key.dptr = RSTRING_PTR(keystr);
532  key.dsize = (DSIZE_TYPE)RSTRING_LEN(keystr);
533  if (dbm_delete(dbm, key)) {
534  rb_raise(rb_eDBMError, "dbm_delete failed");
535  }
536  }
537  if (status) rb_jump_tag(status);
538  if (n > 0) dbmp->di_size = n - RARRAY_LEN(ary);
539  rb_ary_clear(ary);
540 
541  return obj;
542 }
543 
544 /*
545  * call-seq:
546  * dbm.clear
547  *
548  * Deletes all data from the database.
549  */
550 static VALUE
552 {
553  datum key;
554  struct dbmdata *dbmp;
555  DBM *dbm;
556 
557  fdbm_modify(obj);
558  GetDBM2(obj, dbmp, dbm);
559  dbmp->di_size = -1;
560  while (key = dbm_firstkey(dbm), key.dptr) {
561  if (dbm_delete(dbm, key)) {
562  rb_raise(rb_eDBMError, "dbm_delete failed");
563  }
564  }
565  dbmp->di_size = 0;
566 
567  return obj;
568 }
569 
570 /*
571  * call-seq:
572  * dbm.invert -> hash
573  *
574  * Returns a Hash (not a DBM database) created by using each value in the
575  * database as a key, with the corresponding key as its value.
576  */
577 static VALUE
579 {
580  datum key, val;
581  struct dbmdata *dbmp;
582  DBM *dbm;
583  VALUE keystr, valstr;
584  VALUE hash = rb_hash_new();
585 
586  GetDBM2(obj, dbmp, dbm);
587  for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
588  val = dbm_fetch(dbm, key);
589  keystr = rb_tainted_str_new(key.dptr, key.dsize);
590  valstr = rb_tainted_str_new(val.dptr, val.dsize);
591  rb_hash_aset(hash, valstr, keystr);
592  }
593  return hash;
594 }
595 
597 
598 static VALUE
600 {
601  const VALUE *ptr;
602  Check_Type(pair, T_ARRAY);
603  if (RARRAY_LEN(pair) < 2) {
604  rb_raise(rb_eArgError, "pair must be [key, value]");
605  }
606  ptr = RARRAY_CONST_PTR(pair);
607  fdbm_store(dbm, ptr[0], ptr[1]);
608  return Qnil;
609 }
610 
611 /*
612  * call-seq:
613  * dbm.update(obj)
614  *
615  * Updates the database with multiple values from the specified object.
616  * Takes any object which implements the each_pair method, including
617  * Hash and DBM objects.
618  */
619 static VALUE
621 {
622  rb_block_call(other, rb_intern("each_pair"), 0, 0, update_i, obj);
623  return obj;
624 }
625 
626 /*
627  * call-seq:
628  * dbm.replace(obj)
629  *
630  * Replaces the contents of the database with the contents of the specified
631  * object. Takes any object which implements the each_pair method, including
632  * Hash and DBM objects.
633  */
634 static VALUE
636 {
637  fdbm_clear(obj);
638  rb_block_call(other, rb_intern("each_pair"), 0, 0, update_i, obj);
639  return obj;
640 }
641 
642 /*
643  * call-seq:
644  * dbm.store(key, value) -> value
645  * dbm[key] = value
646  *
647  * Stores the specified string value in the database, indexed via the
648  * string key provided.
649  */
650 static VALUE
651 fdbm_store(VALUE obj, VALUE keystr, VALUE valstr)
652 {
653  datum key, val;
654  struct dbmdata *dbmp;
655  DBM *dbm;
656 
657  fdbm_modify(obj);
658  keystr = rb_obj_as_string(keystr);
659  valstr = rb_obj_as_string(valstr);
660 
661  key.dptr = RSTRING_PTR(keystr);
662  key.dsize = RSTRING_DSIZE(keystr);
663 
664  val.dptr = RSTRING_PTR(valstr);
665  val.dsize = RSTRING_DSIZE(valstr);
666 
667  GetDBM2(obj, dbmp, dbm);
668  dbmp->di_size = -1;
669  if (dbm_store(dbm, key, val, DBM_REPLACE)) {
670  dbm_clearerr(dbm);
671  if (errno == EPERM) rb_sys_fail(0);
672  rb_raise(rb_eDBMError, "dbm_store failed");
673  }
674 
675  return valstr;
676 }
677 
678 /*
679  * call-seq:
680  * dbm.length -> integer
681  * dbm.size -> integer
682  *
683  * Returns the number of entries in the database.
684  */
685 static VALUE
687 {
688  datum key;
689  struct dbmdata *dbmp;
690  DBM *dbm;
691  int i = 0;
692 
693  GetDBM2(obj, dbmp, dbm);
694  if (dbmp->di_size > 0) return INT2FIX(dbmp->di_size);
695 
696  for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
697  i++;
698  }
699  dbmp->di_size = i;
700 
701  return INT2FIX(i);
702 }
703 
704 /*
705  * call-seq:
706  * dbm.empty?
707  *
708  * Returns true if the database is empty, false otherwise.
709  */
710 static VALUE
712 {
713  datum key;
714  struct dbmdata *dbmp;
715  DBM *dbm;
716 
717  GetDBM2(obj, dbmp, dbm);
718  if (dbmp->di_size < 0) {
719  dbm = dbmp->di_dbm;
720 
721  for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
722  return Qfalse;
723  }
724  }
725  else {
726  if (dbmp->di_size)
727  return Qfalse;
728  }
729  return Qtrue;
730 }
731 
732 /*
733  * call-seq:
734  * dbm.each_value {|value| block} -> self
735  *
736  * Calls the block once for each value string in the database. Returns self.
737  */
738 static VALUE
740 {
741  datum key, val;
742  struct dbmdata *dbmp;
743  DBM *dbm;
744 
745  RETURN_ENUMERATOR(obj, 0, 0);
746 
747  GetDBM2(obj, dbmp, dbm);
748  for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
749  val = dbm_fetch(dbm, key);
751  GetDBM2(obj, dbmp, dbm);
752  }
753  return obj;
754 }
755 
756 /*
757  * call-seq:
758  * dbm.each_key {|key| block} -> self
759  *
760  * Calls the block once for each key string in the database. Returns self.
761  */
762 static VALUE
764 {
765  datum key;
766  struct dbmdata *dbmp;
767  DBM *dbm;
768 
769  RETURN_ENUMERATOR(obj, 0, 0);
770 
771  GetDBM2(obj, dbmp, dbm);
772  for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
774  GetDBM2(obj, dbmp, dbm);
775  }
776  return obj;
777 }
778 
779 /*
780  * call-seq:
781  * dbm.each_pair {|key,value| block} -> self
782  *
783  * Calls the block once for each [key, value] pair in the database.
784  * Returns self.
785  */
786 static VALUE
788 {
789  datum key, val;
790  DBM *dbm;
791  struct dbmdata *dbmp;
792  VALUE keystr, valstr;
793 
794  RETURN_ENUMERATOR(obj, 0, 0);
795 
796  GetDBM2(obj, dbmp, dbm);
797 
798  for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
799  val = dbm_fetch(dbm, key);
800  keystr = rb_tainted_str_new(key.dptr, key.dsize);
801  valstr = rb_tainted_str_new(val.dptr, val.dsize);
802  rb_yield(rb_assoc_new(keystr, valstr));
803  GetDBM2(obj, dbmp, dbm);
804  }
805 
806  return obj;
807 }
808 
809 /*
810  * call-seq:
811  * dbm.keys -> array
812  *
813  * Returns an array of all the string keys in the database.
814  */
815 static VALUE
817 {
818  datum key;
819  struct dbmdata *dbmp;
820  DBM *dbm;
821  VALUE ary;
822 
823  GetDBM2(obj, dbmp, dbm);
824 
825  ary = rb_ary_new();
826  for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
827  rb_ary_push(ary, rb_tainted_str_new(key.dptr, key.dsize));
828  }
829 
830  return ary;
831 }
832 
833 /*
834  * call-seq:
835  * dbm.values -> array
836  *
837  * Returns an array of all the string values in the database.
838  */
839 static VALUE
841 {
842  datum key, val;
843  struct dbmdata *dbmp;
844  DBM *dbm;
845  VALUE ary;
846 
847  GetDBM2(obj, dbmp, dbm);
848  ary = rb_ary_new();
849  for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
850  val = dbm_fetch(dbm, key);
851  rb_ary_push(ary, rb_tainted_str_new(val.dptr, val.dsize));
852  }
853 
854  return ary;
855 }
856 
857 /*
858  * call-seq:
859  * dbm.include?(key) -> boolean
860  * dbm.has_key?(key) -> boolean
861  * dbm.member?(key) -> boolean
862  * dbm.key?(key) -> boolean
863  *
864  * Returns true if the database contains the specified key, false otherwise.
865  */
866 static VALUE
868 {
869  datum key, val;
870  struct dbmdata *dbmp;
871  DBM *dbm;
872  long len;
873 
874  ExportStringValue(keystr);
875  len = RSTRING_LEN(keystr);
876  if (TOO_LONG(len)) return Qfalse;
877  key.dptr = RSTRING_PTR(keystr);
878  key.dsize = (DSIZE_TYPE)len;
879 
880  GetDBM2(obj, dbmp, dbm);
881  val = dbm_fetch(dbm, key);
882  if (val.dptr) return Qtrue;
883  return Qfalse;
884 }
885 
886 /*
887  * call-seq:
888  * dbm.has_value?(value) -> boolean
889  * dbm.value?(value) -> boolean
890  *
891  * Returns true if the database contains the specified string value, false
892  * otherwise.
893  */
894 static VALUE
896 {
897  datum key, val;
898  struct dbmdata *dbmp;
899  DBM *dbm;
900  long len;
901 
902  ExportStringValue(valstr);
903  len = RSTRING_LEN(valstr);
904  if (TOO_LONG(len)) return Qfalse;
905  val.dptr = RSTRING_PTR(valstr);
906  val.dsize = (DSIZE_TYPE)len;
907 
908  GetDBM2(obj, dbmp, dbm);
909  for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
910  val = dbm_fetch(dbm, key);
911  if ((DSIZE_TYPE)val.dsize == (DSIZE_TYPE)RSTRING_LEN(valstr) &&
912  memcmp(val.dptr, RSTRING_PTR(valstr), val.dsize) == 0)
913  return Qtrue;
914  }
915  return Qfalse;
916 }
917 
918 /*
919  * call-seq:
920  * dbm.to_a -> array
921  *
922  * Converts the contents of the database to an array of [key, value] arrays,
923  * and returns it.
924  */
925 static VALUE
927 {
928  datum key, val;
929  struct dbmdata *dbmp;
930  DBM *dbm;
931  VALUE ary;
932 
933  GetDBM2(obj, dbmp, dbm);
934  ary = rb_ary_new();
935  for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
936  val = dbm_fetch(dbm, key);
938  rb_tainted_str_new(val.dptr, val.dsize)));
939  }
940 
941  return ary;
942 }
943 
944 /*
945  * call-seq:
946  * dbm.to_hash -> hash
947  *
948  * Converts the contents of the database to an in-memory Hash object, and
949  * returns it.
950  */
951 static VALUE
953 {
954  datum key, val;
955  struct dbmdata *dbmp;
956  DBM *dbm;
957  VALUE hash;
958 
959  GetDBM2(obj, dbmp, dbm);
960  hash = rb_hash_new();
961  for (key = dbm_firstkey(dbm); key.dptr; key = dbm_nextkey(dbm)) {
962  val = dbm_fetch(dbm, key);
963  rb_hash_aset(hash, rb_tainted_str_new(key.dptr, key.dsize),
964  rb_tainted_str_new(val.dptr, val.dsize));
965  }
966 
967  return hash;
968 }
969 
970 /*
971  * call-seq:
972  * dbm.reject {|key,value| block} -> Hash
973  *
974  * Converts the contents of the database to an in-memory Hash, then calls
975  * Hash#reject with the specified code block, returning a new Hash.
976  */
977 static VALUE
979 {
980  return rb_hash_delete_if(fdbm_to_hash(obj));
981 }
982 
983 /*
984  * == Introduction
985  *
986  * The DBM class provides a wrapper to a Unix-style
987  * {dbm}[http://en.wikipedia.org/wiki/Dbm] or Database Manager library.
988  *
989  * Dbm databases do not have tables or columns; they are simple key-value
990  * data stores, like a Ruby Hash except not resident in RAM. Keys and values
991  * must be strings.
992  *
993  * The exact library used depends on how Ruby was compiled. It could be any
994  * of the following:
995  *
996  * - The original ndbm library is released in 4.3BSD.
997  * It is based on dbm library in Unix Version 7 but has different API to
998  * support multiple databases in a process.
999  * - {Berkeley DB}[http://en.wikipedia.org/wiki/Berkeley_DB] versions
1000  * 1 thru 5, also known as BDB and Sleepycat DB, now owned by Oracle
1001  * Corporation.
1002  * - Berkeley DB 1.x, still found in 4.4BSD derivatives (FreeBSD, OpenBSD, etc).
1003  * - {gdbm}[http://www.gnu.org/software/gdbm/], the GNU implementation of dbm.
1004  * - {qdbm}[http://fallabs.com/qdbm/index.html], another open source
1005  * reimplementation of dbm.
1006  *
1007  * All of these dbm implementations have their own Ruby interfaces
1008  * available, which provide richer (but varying) APIs.
1009  *
1010  * == Cautions
1011  *
1012  * Before you decide to use DBM, there are some issues you should consider:
1013  *
1014  * - Each implementation of dbm has its own file format. Generally, dbm
1015  * libraries will not read each other's files. This makes dbm files
1016  * a bad choice for data exchange.
1017  *
1018  * - Even running the same OS and the same dbm implementation, the database
1019  * file format may depend on the CPU architecture. For example, files may
1020  * not be portable between PowerPC and 386, or between 32 and 64 bit Linux.
1021  *
1022  * - Different versions of Berkeley DB use different file formats. A change to
1023  * the OS may therefore break DBM access to existing files.
1024  *
1025  * - Data size limits vary between implementations. Original Berkeley DB was
1026  * limited to 2GB of data. Dbm libraries also sometimes limit the total
1027  * size of a key/value pair, and the total size of all the keys that hash
1028  * to the same value. These limits can be as little as 512 bytes. That said,
1029  * gdbm and recent versions of Berkeley DB do away with these limits.
1030  *
1031  * Given the above cautions, DBM is not a good choice for long term storage of
1032  * important data. It is probably best used as a fast and easy alternative
1033  * to a Hash for processing large amounts of data.
1034  *
1035  * == Example
1036  *
1037  * require 'dbm'
1038  * db = DBM.open('rfcs', 0666, DBM::WRCREAT)
1039  * db['822'] = 'Standard for the Format of ARPA Internet Text Messages'
1040  * db['1123'] = 'Requirements for Internet Hosts - Application and Support'
1041  * db['3068'] = 'An Anycast Prefix for 6to4 Relay Routers'
1042  * puts db['822']
1043  */
1044 void
1046 {
1048  /* Document-class: DBMError
1049  * Exception class used to return errors from the dbm library.
1050  */
1053 
1056 
1057  rb_define_method(rb_cDBM, "initialize", fdbm_initialize, -1);
1058  rb_define_method(rb_cDBM, "close", fdbm_close, 0);
1059  rb_define_method(rb_cDBM, "closed?", fdbm_closed, 0);
1060  rb_define_method(rb_cDBM, "[]", fdbm_aref, 1);
1061  rb_define_method(rb_cDBM, "fetch", fdbm_fetch_m, -1);
1062  rb_define_method(rb_cDBM, "[]=", fdbm_store, 2);
1063  rb_define_method(rb_cDBM, "store", fdbm_store, 2);
1064  rb_define_method(rb_cDBM, "index", fdbm_index, 1);
1065  rb_define_method(rb_cDBM, "key", fdbm_key, 1);
1066  rb_define_method(rb_cDBM, "select", fdbm_select, 0);
1067  rb_define_method(rb_cDBM, "values_at", fdbm_values_at, -1);
1068  rb_define_method(rb_cDBM, "length", fdbm_length, 0);
1069  rb_define_method(rb_cDBM, "size", fdbm_length, 0);
1070  rb_define_method(rb_cDBM, "empty?", fdbm_empty_p, 0);
1072  rb_define_method(rb_cDBM, "each_value", fdbm_each_value, 0);
1073  rb_define_method(rb_cDBM, "each_key", fdbm_each_key, 0);
1074  rb_define_method(rb_cDBM, "each_pair", fdbm_each_pair, 0);
1075  rb_define_method(rb_cDBM, "keys", fdbm_keys, 0);
1076  rb_define_method(rb_cDBM, "values", fdbm_values, 0);
1077  rb_define_method(rb_cDBM, "shift", fdbm_shift, 0);
1078  rb_define_method(rb_cDBM, "delete", fdbm_delete, 1);
1079  rb_define_method(rb_cDBM, "delete_if", fdbm_delete_if, 0);
1080  rb_define_method(rb_cDBM, "reject!", fdbm_delete_if, 0);
1081  rb_define_method(rb_cDBM, "reject", fdbm_reject, 0);
1082  rb_define_method(rb_cDBM, "clear", fdbm_clear, 0);
1083  rb_define_method(rb_cDBM, "invert", fdbm_invert, 0);
1084  rb_define_method(rb_cDBM, "update", fdbm_update, 1);
1085  rb_define_method(rb_cDBM, "replace", fdbm_replace, 1);
1086 
1087  rb_define_method(rb_cDBM, "include?", fdbm_has_key, 1);
1088  rb_define_method(rb_cDBM, "has_key?", fdbm_has_key, 1);
1089  rb_define_method(rb_cDBM, "member?", fdbm_has_key, 1);
1090  rb_define_method(rb_cDBM, "has_value?", fdbm_has_value, 1);
1091  rb_define_method(rb_cDBM, "key?", fdbm_has_key, 1);
1092  rb_define_method(rb_cDBM, "value?", fdbm_has_value, 1);
1093 
1094  rb_define_method(rb_cDBM, "to_a", fdbm_to_a, 0);
1095  rb_define_method(rb_cDBM, "to_hash", fdbm_to_hash, 0);
1096 
1097  /* Indicates that dbm_open() should open the database in read-only mode */
1098  rb_define_const(rb_cDBM, "READER", INT2FIX(O_RDONLY|RUBY_DBM_RW_BIT));
1099 
1100  /* Indicates that dbm_open() should open the database in read/write mode */
1101  rb_define_const(rb_cDBM, "WRITER", INT2FIX(O_RDWR|RUBY_DBM_RW_BIT));
1102 
1103  /* Indicates that dbm_open() should open the database in read/write mode,
1104  * and create it if it does not already exist
1105  */
1106  rb_define_const(rb_cDBM, "WRCREAT", INT2FIX(O_RDWR|O_CREAT|RUBY_DBM_RW_BIT));
1107 
1108  /* Indicates that dbm_open() should open the database in read/write mode,
1109  * create it if it does not already exist, and delete all contents if it
1110  * does already exist.
1111  */
1112  rb_define_const(rb_cDBM, "NEWDB", INT2FIX(O_RDWR|O_CREAT|O_TRUNC|RUBY_DBM_RW_BIT));
1113 
1114  {
1115  VALUE version;
1116 #if defined(_DBM_IOERR)
1117  version = rb_str_new2("ndbm (4.3BSD)");
1118 #elif defined(RUBYDBM_GDBM_HEADER)
1119 # if defined(HAVE_DECLARED_LIBVAR_GDBM_VERSION)
1120  /* since gdbm 1.9 */
1121  version = rb_str_new2(gdbm_version);
1122 # elif defined(HAVE_UNDECLARED_LIBVAR_GDBM_VERSION)
1123  /* ndbm.h doesn't declare gdbm_version until gdbm 1.8.3.
1124  * See extconf.rb for more information. */
1125  RUBY_EXTERN char *gdbm_version;
1126  version = rb_str_new2(gdbm_version);
1127 # else
1128  version = rb_str_new2("GDBM (unknown)");
1129 # endif
1130 #elif defined(RUBYDBM_DB_HEADER)
1131 # if defined(HAVE_DB_VERSION)
1132  /* The version of the dbm library, if using Berkeley DB */
1133  version = rb_str_new2(db_version(NULL, NULL, NULL));
1134 # else
1135  version = rb_str_new2("Berkeley DB (unknown)");
1136 # endif
1137 #elif defined(_RELIC_H)
1138 # if defined(HAVE_DPVERSION)
1139  version = rb_sprintf("QDBM %s", dpversion);
1140 # else
1141  version = rb_str_new2("QDBM (unknown)");
1142 # endif
1143 #else
1144  version = rb_str_new2("ndbm (unknown)");
1145 #endif
1146  /*
1147  * Identifies ndbm library version.
1148  *
1149  * Examples:
1150  *
1151  * - "ndbm (4.3BSD)"
1152  * - "Berkeley DB 4.8.30: (April 9, 2010)"
1153  * - "Berkeley DB (unknown)" (4.4BSD, maybe)
1154  * - "GDBM version 1.8.3. 10/15/2002 (built Jul 1 2011 12:32:45)"
1155  * - "QDBM 1.8.78"
1156  *
1157  */
1158  rb_define_const(rb_cDBM, "VERSION", version);
1159  }
1160 }
DBM * di_dbm
Definition: dbm.c:39
static VALUE fdbm_delete(VALUE obj, VALUE keystr)
Definition: dbm.c:427
VALUE rb_eStandardError
Definition: error.c:760
static size_t memsize_dbm(const void *ptr)
Definition: dbm.c:70
static VALUE fdbm_length(VALUE obj)
Definition: dbm.c:686
#define RARRAY_LEN(a)
Definition: ruby.h:1026
#define RUBY_TYPED_FREE_IMMEDIATELY
Definition: ruby.h:1145
#define GetDBM2(obj, dbmp, dbm)
Definition: dbm.c:54
#define NUM2INT(x)
Definition: ruby.h:684
static VALUE fdbm_s_open(int argc, VALUE *argv, VALUE klass)
Definition: dbm.c:248
static unsigned int hash(str, len) register const char *str
static VALUE fdbm_store(VALUE, VALUE, VALUE)
Definition: dbm.c:651
void rb_define_singleton_method(VALUE obj, const char *name, VALUE(*func)(ANYARGS), int argc)
Defines a singleton method for obj.
Definition: class.c:1716
#define FilePathValue(v)
Definition: ruby.h:594
#define Qtrue
Definition: ruby.h:437
static VALUE fdbm_index(VALUE hash, VALUE value)
Definition: dbm.c:358
void rb_error_frozen(const char *what)
Definition: error.c:2447
#define TypedData_Wrap_Struct(klass, data_type, sval)
Definition: ruby.h:1169
static VALUE fdbm_values(VALUE obj)
Definition: dbm.c:840
#define TypedData_Get_Struct(obj, type, data_type, sval)
Definition: ruby.h:1190
VALUE rb_ary_push(VALUE ary, VALUE item)
Definition: array.c:905
static VALUE fdbm_replace(VALUE obj, VALUE other)
Definition: dbm.c:635
long di_size
Definition: dbm.c:38
VALUE rb_ary_tmp_new(long capa)
Definition: array.c:532
VALUE rb_protect(VALUE(*proc)(VALUE), VALUE data, int *state)
Definition: eval.c:891
#define Check_Type(v, t)
Definition: ruby.h:562
void rb_raise(VALUE exc, const char *fmt,...)
Definition: error.c:2207
VALUE rb_ary_clear(VALUE ary)
Definition: array.c:3487
void rb_define_alloc_func(VALUE, rb_alloc_func_t)
Definition: dbm.c:37
#define DATA_PTR(dta)
Definition: ruby.h:1113
void rb_include_module(VALUE klass, VALUE module)
Definition: class.c:864
char * dptr
Definition: sdbm.h:51
VALUE rb_block_call(VALUE, ID, int, const VALUE *, rb_block_call_func_t, VALUE)
#define T_ARRAY
Definition: ruby.h:498
#define DSIZE_TYPE
Definition: dbm.c:24
#define TOO_LONG(n)
Definition: dbm.c:30
static VALUE fdbm_has_key(VALUE obj, VALUE keystr)
Definition: dbm.c:867
#define rb_ary_new2
Definition: intern.h:90
static VALUE fdbm_values_at(int argc, VALUE *argv, VALUE obj)
Definition: dbm.c:402
#define RB_BLOCK_CALL_FUNC_ARGLIST(yielded_arg, callback_arg)
Definition: ruby.h:1830
static VALUE fdbm_empty_p(VALUE obj)
Definition: dbm.c:711
#define RSTRING_DSIZE(s)
Definition: dbm.c:29
static VALUE fdbm_reject(VALUE obj)
Definition: dbm.c:978
#define O_CLOEXEC
Definition: sdbm.h:50
int rb_block_given_p(void)
Definition: eval.c:797
VALUE rb_hash_aset(VALUE hash, VALUE key, VALUE val)
Definition: hash.c:1576
#define DBM_REPLACE
Definition: sdbm.h:67
#define val
RUBY_EXTERN VALUE rb_cObject
Definition: ruby.h:1872
static VALUE fdbm_aref(VALUE obj, VALUE keystr)
Definition: dbm.c:299
static VALUE fdbm_to_a(VALUE obj)
Definition: dbm.c:926
static VALUE fdbm_select(VALUE obj)
Definition: dbm.c:372
VALUE rb_obj_as_string(VALUE)
Definition: string.c:1364
VALUE rb_ary_new(void)
Definition: array.c:493
static VALUE fdbm_close(VALUE obj)
Definition: dbm.c:95
static void fdbm_modify(VALUE obj)
Definition: dbm.c:415
#define NIL_P(v)
Definition: ruby.h:451
VALUE rb_define_class(const char *name, VALUE super)
Defines a top-level class.
Definition: class.c:646
void rb_define_const(VALUE, const char *, VALUE)
Definition: variable.c:2734
void rb_sys_fail_str(VALUE mesg)
Definition: error.c:2332
static const rb_data_type_t dbm_type
Definition: dbm.c:81
#define OBJ_FROZEN(x)
Definition: ruby.h:1306
#define RUBY_DBM_RW_BIT
Definition: dbm.c:35
int argc
Definition: ruby.c:183
static VALUE fdbm_shift(VALUE obj)
Definition: dbm.c:473
#define Qfalse
Definition: ruby.h:436
#define rb_str_new2
Definition: intern.h:857
void Init_dbm(void)
Definition: dbm.c:1045
#define OBJ_FREEZE(x)
Definition: ruby.h:1308
VALUE rb_eIndexError
Definition: error.c:764
static VALUE fdbm_each_key(VALUE obj)
Definition: dbm.c:763
#define ALLOC(type)
Definition: ruby.h:1588
#define RSTRING_LEN(str)
Definition: ruby.h:978
VALUE rb_yield(VALUE)
Definition: vm_eval.c:1020
#define RARRAY_CONST_PTR(a)
Definition: ruby.h:1028
static VALUE fdbm_clear(VALUE obj)
Definition: dbm.c:551
int errno
#define RUBY_EXTERN
Definition: missing.h:77
VALUE rb_mEnumerable
Definition: enum.c:18
VALUE rb_sprintf(const char *format,...)
Definition: sprintf.c:1440
Definition: sdbm.h:20
VALUE rb_hash_new(void)
Definition: hash.c:441
int rb_scan_args(int argc, const VALUE *argv, const char *fmt,...)
Definition: class.c:1919
VALUE rb_assoc_new(VALUE car, VALUE cdr)
Definition: array.c:623
#define Qnil
Definition: ruby.h:438
static VALUE fdbm_to_hash(VALUE obj)
Definition: dbm.c:952
int dsize
Definition: sdbm.h:52
#define OBJ_TAINT(x)
Definition: ruby.h:1300
unsigned long VALUE
Definition: ruby.h:85
#define EPERM
Definition: _sdbm.c:93
VALUE rb_ensure(VALUE(*b_proc)(ANYARGS), VALUE data1, VALUE(*e_proc)(ANYARGS), VALUE data2)
Definition: eval.c:923
int memcmp(const void *s1, const void *s2, size_t len)
Definition: memcmp.c:7
void rb_sys_fail(const char *mesg)
Definition: error.c:2326
void rb_jump_tag(int tag)
Definition: eval.c:788
VALUE rb_str_dup(VALUE)
Definition: string.c:1436
static VALUE rb_eDBMError
Definition: dbm.c:33
static VALUE fdbm_alloc(VALUE klass)
Definition: dbm.c:127
static VALUE rb_cDBM
Definition: dbm.c:33
register unsigned int len
Definition: zonetab.h:51
#define RSTRING_PTR(str)
Definition: ruby.h:982
int size
Definition: encoding.c:57
#define INT2FIX(i)
Definition: ruby.h:232
static VALUE fdbm_fetch(VALUE obj, VALUE keystr, VALUE ifnone)
Definition: dbm.c:264
#define ExportStringValue(v)
Definition: ruby.h:587
#define RARRAY_AREF(a, i)
Definition: ruby.h:1040
static VALUE fdbm_initialize(int argc, VALUE *argv, VALUE obj)
Definition: dbm.c:146
void rb_fd_fix_cloexec(int fd)
Definition: io.c:231
static void free_dbm(void *ptr)
Definition: dbm.c:60
static VALUE fdbm_closed(VALUE obj)
Definition: dbm.c:113
static VALUE fdbm_each_value(VALUE obj)
Definition: dbm.c:739
static VALUE fdbm_keys(VALUE obj)
Definition: dbm.c:816
#define RTEST(v)
Definition: ruby.h:450
static VALUE fdbm_update(VALUE obj, VALUE other)
Definition: dbm.c:620
static VALUE fdbm_invert(VALUE obj)
Definition: dbm.c:578
#define RETURN_ENUMERATOR(obj, argc, argv)
Definition: intern.h:240
static VALUE fdbm_has_value(VALUE obj, VALUE valstr)
Definition: dbm.c:895
static void closed_dbm(void)
Definition: dbm.c:43
#define GetDBM(obj, dbmp)
Definition: dbm.c:48
VALUE rb_hash_delete_if(VALUE hash)
Definition: hash.c:1272
void void xfree(void *)
VALUE rb_tainted_str_new(const char *, long)
Definition: string.c:853
#define rb_intern(str)
#define NULL
Definition: _sdbm.c:102
static VALUE fdbm_key(VALUE obj, VALUE valstr)
Definition: dbm.c:332
static VALUE fdbm_delete_if(VALUE obj)
Definition: dbm.c:503
void rb_define_method(VALUE klass, const char *name, VALUE(*func)(ANYARGS), int argc)
Definition: class.c:1515
void rb_warn(const char *fmt,...)
Definition: error.c:221
int version
Definition: ossl_ssl.c:55
static VALUE fdbm_each_pair(VALUE obj)
Definition: dbm.c:787
VALUE rb_eArgError
Definition: error.c:763
static VALUE fdbm_fetch_m(int argc, VALUE *argv, VALUE obj)
Definition: dbm.c:313
char ** argv
Definition: ruby.c:184
static VALUE update_i(RB_BLOCK_CALL_FUNC_ARGLIST(pair, dbm))
Definition: dbm.c:599