/* * call-seq: * test(int_cmd, file1 [, file2] ) => obj * * Uses the integer <i>aCmd</i> to perform various tests on * <i>file1</i> (first table below) or on <i>file1</i> and * <i>file2</i> (second table). * * File tests on a single file: * * Test Returns Meaning * ?A | Time | Last access time for file1 * ?b | boolean | True if file1 is a block device * ?c | boolean | True if file1 is a character device * ?C | Time | Last change time for file1 * ?d | boolean | True if file1 exists and is a directory * ?e | boolean | True if file1 exists * ?f | boolean | True if file1 exists and is a regular file * ?g | boolean | True if file1 has the \CF{setgid} bit * | | set (false under NT) * ?G | boolean | True if file1 exists and has a group * | | ownership equal to the caller's group * ?k | boolean | True if file1 exists and has the sticky bit set * ?l | boolean | True if file1 exists and is a symbolic link * ?M | Time | Last modification time for file1 * ?o | boolean | True if file1 exists and is owned by * | | the caller's effective uid * ?O | boolean | True if file1 exists and is owned by * | | the caller's real uid * ?p | boolean | True if file1 exists and is a fifo * ?r | boolean | True if file1 is readable by the effective * | | uid/gid of the caller * ?R | boolean | True if file is readable by the real * | | uid/gid of the caller * ?s | int/nil | If file1 has nonzero size, return the size, * | | otherwise return nil * ?S | boolean | True if file1 exists and is a socket * ?u | boolean | True if file1 has the setuid bit set * ?w | boolean | True if file1 exists and is writable by * | | the effective uid/gid * ?W | boolean | True if file1 exists and is writable by * | | the real uid/gid * ?x | boolean | True if file1 exists and is executable by * | | the effective uid/gid * ?X | boolean | True if file1 exists and is executable by * | | the real uid/gid * ?z | boolean | True if file1 exists and has a zero length * * Tests that take two files: * * ?- | boolean | True if file1 and file2 are identical * ?= | boolean | True if the modification times of file1 * | | and file2 are equal * ?< | boolean | True if the modification time of file1 * | | is prior to that of file2 * ?> | boolean | True if the modification time of file1 * | | is after that of file2 */ static VALUE rb_f_test(argc, argv) int argc; VALUE *argv; { int cmd; if (argc == 0) rb_raise(rb_eArgError, "wrong number of arguments"); #if 0 /* 1.7 behavior? */ if (argc == 1) { return RTEST(argv[0]) ? Qtrue : Qfalse; } #endif cmd = NUM2CHR(argv[0]); if (cmd == 0) return Qfalse; if (strchr("bcdefgGkloOprRsSuwWxXz", cmd)) { CHECK(1); switch (cmd) { case 'b': return test_b(0, argv[1]); case 'c': return test_c(0, argv[1]); case 'd': return test_d(0, argv[1]); case 'a': case 'e': return test_e(0, argv[1]); case 'f': return test_f(0, argv[1]); case 'g': return test_sgid(0, argv[1]); case 'G': return test_grpowned(0, argv[1]); case 'k': return test_sticky(0, argv[1]); case 'l': return test_l(0, argv[1]); case 'o': return test_owned(0, argv[1]); case 'O': return test_rowned(0, argv[1]); case 'p': return test_p(0, argv[1]); case 'r': return test_r(0, argv[1]); case 'R': return test_R(0, argv[1]); case 's': return test_s(0, argv[1]); case 'S': return test_S(0, argv[1]); case 'u': return test_suid(0, argv[1]); case 'w': return test_w(0, argv[1]); case 'W': return test_W(0, argv[1]); case 'x': return test_x(0, argv[1]); case 'X': return test_X(0, argv[1]); case 'z': return test_z(0, argv[1]); } } if (strchr("MAC", cmd)) { struct stat st; CHECK(1); if (rb_stat(argv[1], &st) == -1) { rb_sys_fail(RSTRING(argv[1])->ptr); } switch (cmd) { case 'A': return rb_time_new(st.st_atime, 0); case 'M': return rb_time_new(st.st_mtime, 0); case 'C': return rb_time_new(st.st_ctime, 0); } } if (cmd == '-') { CHECK(2); return test_identical(0, argv[1], argv[2]); } if (strchr("=<>", cmd)) { struct stat st1, st2; CHECK(2); if (rb_stat(argv[1], &st1) < 0) return Qfalse; if (rb_stat(argv[2], &st2) < 0) return Qfalse; switch (cmd) { case '=': if (st1.st_mtime == st2.st_mtime) return Qtrue; return Qfalse; case '>': if (st1.st_mtime > st2.st_mtime) return Qtrue; return Qfalse; case '<': if (st1.st_mtime < st2.st_mtime) return Qtrue; return Qfalse; } } /* unknown command */ rb_raise(rb_eArgError, "unknown command ?%c", cmd); return Qnil; /* not reached */ }