| 363 | } |
| 364 | |
| 365 | static bool |
| 366 | unary_operator (void) |
| 367 | { |
| 368 | struct stat stat_buf; |
| 369 | |
| 370 | switch (argv[pos][1]) |
| 371 | { |
| 372 | default: |
| 373 | test_syntax_error (_("%s: unary operator expected"), quote (argv[pos])); |
| 374 | |
| 375 | /* All of the following unary operators use unary_advance (), which |
| 376 | checks to make sure that there is an argument, and then advances |
| 377 | pos right past it. This means that pos - 1 is the location of the |
| 378 | argument. */ |
| 379 | |
| 380 | case 'e': /* file exists in the file system? */ |
| 381 | unary_advance (); |
| 382 | return stat (argv[pos - 1], &stat_buf) == 0; |
| 383 | |
| 384 | case 'r': /* file is readable? */ |
| 385 | unary_advance (); |
| 386 | return euidaccess (argv[pos - 1], R_OK) == 0; |
| 387 | |
| 388 | case 'w': /* File is writable? */ |
| 389 | unary_advance (); |
| 390 | return euidaccess (argv[pos - 1], W_OK) == 0; |
| 391 | |
| 392 | case 'x': /* File is executable? */ |
| 393 | unary_advance (); |
| 394 | return euidaccess (argv[pos - 1], X_OK) == 0; |
| 395 | |
| 396 | case 'N': /* File exists and has been modified since it was last read? */ |
| 397 | { |
| 398 | unary_advance (); |
| 399 | if (stat (argv[pos - 1], &stat_buf) != 0) |
| 400 | return false; |
| 401 | struct timespec atime = get_stat_atime (&stat_buf); |
| 402 | struct timespec mtime = get_stat_mtime (&stat_buf); |
| 403 | return (timespec_cmp (mtime, atime) > 0); |
| 404 | } |
| 405 | |
| 406 | case 'O': /* File is owned by you? */ |
| 407 | { |
| 408 | unary_advance (); |
| 409 | if (stat (argv[pos - 1], &stat_buf) != 0) |
| 410 | return false; |
| 411 | errno = 0; |
| 412 | uid_t euid = geteuid (); |
| 413 | uid_t NO_UID = -1; |
| 414 | return ! (euid == NO_UID && errno) && euid == stat_buf.st_uid; |
| 415 | } |
| 416 | |
| 417 | case 'G': /* File is owned by your group? */ |
| 418 | { |
| 419 | unary_advance (); |
| 420 | if (stat (argv[pos - 1], &stat_buf) != 0) |
| 421 | return false; |
| 422 | errno = 0; |
no test coverage detected