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