Method: Kernel#test

Defined in:
file.c

#test(cmd, file1[, file2]) ⇒ Object

Uses the character cmd to perform various tests on file1 (first table below) or on file1 and file2 (second table).

File tests on a single file:

Cmd    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

Returns:



5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
5317
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418
5419
5420
5421
5422
5423
5424
5425
5426
5427
5428
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
# File 'file.c', line 5296

static VALUE
rb_f_test(int argc, VALUE *argv, VALUE _)
{
    int cmd;

    if (argc == 0) rb_check_arity(argc, 2, 3);
    cmd = NUM2CHR(argv[0]);
    if (cmd == 0) {
        goto unknown;
    }
    if (strchr("bcdefgGkloOprRsSuwWxXz", cmd)) {
	CHECK(1);
	switch (cmd) {
	  case 'b':
	    return rb_file_blockdev_p(0, argv[1]);

	  case 'c':
	    return rb_file_chardev_p(0, argv[1]);

	  case 'd':
	    return rb_file_directory_p(0, argv[1]);

	  case 'e':
	    return rb_file_exist_p(0, argv[1]);

	  case 'f':
	    return rb_file_file_p(0, argv[1]);

	  case 'g':
	    return rb_file_sgid_p(0, argv[1]);

	  case 'G':
	    return rb_file_grpowned_p(0, argv[1]);

	  case 'k':
	    return rb_file_sticky_p(0, argv[1]);

	  case 'l':
	    return rb_file_symlink_p(0, argv[1]);

	  case 'o':
	    return rb_file_owned_p(0, argv[1]);

	  case 'O':
	    return rb_file_rowned_p(0, argv[1]);

	  case 'p':
	    return rb_file_pipe_p(0, argv[1]);

	  case 'r':
	    return rb_file_readable_p(0, argv[1]);

	  case 'R':
	    return rb_file_readable_real_p(0, argv[1]);

	  case 's':
	    return rb_file_size_p(0, argv[1]);

	  case 'S':
	    return rb_file_socket_p(0, argv[1]);

	  case 'u':
	    return rb_file_suid_p(0, argv[1]);

	  case 'w':
	    return rb_file_writable_p(0, argv[1]);

	  case 'W':
	    return rb_file_writable_real_p(0, argv[1]);

	  case 'x':
	    return rb_file_executable_p(0, argv[1]);

	  case 'X':
	    return rb_file_executable_real_p(0, argv[1]);

	  case 'z':
	    return rb_file_zero_p(0, argv[1]);
	}
    }

    if (strchr("MAC", cmd)) {
	struct stat st;
	VALUE fname = argv[1];

	CHECK(1);
	if (rb_stat(fname, &st) == -1) {
	    int e = errno;
	    FilePathValue(fname);
	    rb_syserr_fail_path(e, fname);
	}

	switch (cmd) {
	  case 'A':
	    return stat_atime(&st);
	  case 'M':
	    return stat_mtime(&st);
	  case 'C':
	    return stat_ctime(&st);
	}
    }

    if (cmd == '-') {
	CHECK(2);
	return rb_file_identical_p(0, argv[1], argv[2]);
    }

    if (strchr("=<>", cmd)) {
	struct stat st1, st2;
        struct timespec t1, t2;

	CHECK(2);
	if (rb_stat(argv[1], &st1) < 0) return Qfalse;
	if (rb_stat(argv[2], &st2) < 0) return Qfalse;

        t1 = stat_mtimespec(&st1);
        t2 = stat_mtimespec(&st2);

	switch (cmd) {
	  case '=':
	    if (t1.tv_sec == t2.tv_sec && t1.tv_nsec == t2.tv_nsec) return Qtrue;
	    return Qfalse;

	  case '>':
	    if (t1.tv_sec > t2.tv_sec) return Qtrue;
	    if (t1.tv_sec == t2.tv_sec && t1.tv_nsec > t2.tv_nsec) return Qtrue;
	    return Qfalse;

	  case '<':
	    if (t1.tv_sec < t2.tv_sec) return Qtrue;
	    if (t1.tv_sec == t2.tv_sec && t1.tv_nsec < t2.tv_nsec) return Qtrue;
	    return Qfalse;
	}
    }
  unknown:
    /* unknown command */
    if (ISPRINT(cmd)) {
        rb_raise(rb_eArgError, "unknown command '%s%c'", cmd == '\'' || cmd == '\\' ? "\\" : "", cmd);
    }
    else {
        rb_raise(rb_eArgError, "unknown command \"\\x%02X\"", cmd);
    }
    UNREACHABLE_RETURN(Qundef);
}