public Method

Kernel.test(...)

test(int_cmd, file1 [, file2] )  obj

Uses the integer aCmd 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

Source Code

/*
*  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 */
}
Comments

Have your say
Please use Textile formatting (click here for a cheat sheet). Use <code/> and <pre/> for code samples.
Click here to login with OpenID to to post comments.