(root)/
findutils-4.9.0/
find/
pred.c
       1  /* pred.c -- execute the expression tree.
       2     Copyright (C) 1990-2022 Free Software Foundation, Inc.
       3  
       4     This program is free software: you can redistribute it and/or modify
       5     it under the terms of the GNU General Public License as published by
       6     the Free Software Foundation, either version 3 of the License, or
       7     (at your option) any later version.
       8  
       9     This program is distributed in the hope that it will be useful,
      10     but WITHOUT ANY WARRANTY; without even the implied warranty of
      11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12     GNU General Public License for more details.
      13  
      14     You should have received a copy of the GNU General Public License
      15     along with this program.  If not, see <https://www.gnu.org/licenses/>.
      16  */
      17  
      18  /* config.h always comes first. */
      19  #include <config.h>
      20  
      21  /* system headers. */
      22  #include <assert.h>
      23  #include <ctype.h>
      24  #include <dirent.h>
      25  #include <errno.h>
      26  #include <fcntl.h>
      27  #include <grp.h>
      28  #include <math.h>
      29  #include <pwd.h>
      30  #include <selinux/selinux.h>
      31  #include <stdarg.h>
      32  #include <sys/stat.h>
      33  #include <sys/types.h>
      34  #include <sys/wait.h>
      35  #include <unistd.h> /* for unlinkat() */
      36  
      37  /* gnulib headers. */
      38  #include "areadlink.h"
      39  #include "dirname.h"
      40  #include "error.h"
      41  #include "fcntl--.h"
      42  #include "fnmatch.h"
      43  #include "stat-size.h"
      44  #include "stat-time.h"
      45  #include "yesno.h"
      46  
      47  /* find headers. */
      48  #include "defs.h"
      49  #include "die.h"
      50  #include "dircallback.h"
      51  #include "listfile.h"
      52  #include "printquoted.h"
      53  #include "system.h"
      54  
      55  
      56  
      57  #ifdef CLOSEDIR_VOID
      58  /* Fake a return value. */
      59  # define CLOSEDIR(d) (closedir (d), 0)
      60  #else
      61  # define CLOSEDIR(d) closedir (d)
      62  #endif
      63  
      64  static bool match_lname (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr, bool ignore_case);
      65  
      66  /* Returns ts1 - ts2 */
      67  static double ts_difference (struct timespec ts1,
      68  			     struct timespec ts2)
      69  {
      70    double d =  difftime (ts1.tv_sec, ts2.tv_sec)
      71      + (1.0e-9 * (ts1.tv_nsec - ts2.tv_nsec));
      72    return d;
      73  }
      74  
      75  
      76  static int
      77  compare_ts (struct timespec ts1,
      78  	    struct timespec ts2)
      79  {
      80    if ((ts1.tv_sec == ts2.tv_sec) &&
      81        (ts1.tv_nsec == ts2.tv_nsec))
      82      {
      83        return 0;
      84      }
      85    else
      86      {
      87        double diff = ts_difference (ts1, ts2);
      88        return diff < 0.0 ? -1 : +1;
      89      }
      90  }
      91  
      92  /* Predicate processing routines.
      93  
      94     PATHNAME is the full pathname of the file being checked.
      95     *STAT_BUF contains information about PATHNAME.
      96     *PRED_PTR contains information for applying the predicate.
      97  
      98     Return true if the file passes this predicate, false if not. */
      99  
     100  
     101  /* pred_timewindow
     102   *
     103   * Returns true if THE_TIME is
     104   * COMP_GT: after the specified time
     105   * COMP_LT: before the specified time
     106   * COMP_EQ: after the specified time but by not more than WINDOW seconds.
     107   */
     108  static bool
     109  pred_timewindow (struct timespec ts, struct predicate const *pred_ptr, int window)
     110  {
     111    switch (pred_ptr->args.reftime.kind)
     112      {
     113      case COMP_GT:
     114        return compare_ts (ts, pred_ptr->args.reftime.ts) > 0;
     115  
     116      case COMP_LT:
     117        return compare_ts (ts, pred_ptr->args.reftime.ts) < 0;
     118  
     119      case COMP_EQ:
     120        {
     121  	/* consider "find . -mtime 0".
     122  	 *
     123  	 * Here, the origin is exactly 86400 seconds before the start
     124  	 * of the program (since -daystart was not specified).   This
     125  	 * function will be called with window=86400 and
     126  	 * pred_ptr->args.reftime.ts as the origin.  Hence a file
     127  	 * created the instant the program starts will show a time
     128  	 * difference (value of delta) of 86400.   Similarly, a file
     129  	 * created exactly 24h ago would be the newest file which was
     130  	 * _not_ created today.   So, if delta is 0.0, the file
     131  	 * was not created today.  If the delta is 86400, the file
     132  	 * was created this instant.
     133  	 */
     134  	double delta = ts_difference (ts, pred_ptr->args.reftime.ts);
     135  	return (delta > 0.0 && delta <= window);
     136        }
     137      }
     138    assert (0);
     139    abort ();
     140  }
     141  
     142  
     143  bool
     144  pred_amin (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     145  {
     146    (void) &pathname;
     147    return pred_timewindow (get_stat_atime(stat_buf), pred_ptr, 60);
     148  }
     149  
     150  bool
     151  pred_and (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     152  {
     153    if (pred_ptr->pred_left == NULL
     154        || apply_predicate (pathname, stat_buf, pred_ptr->pred_left))
     155      {
     156        return apply_predicate (pathname, stat_buf, pred_ptr->pred_right);
     157      }
     158    else
     159      return false;
     160  }
     161  
     162  bool
     163  pred_anewer (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     164  {
     165    (void) &pathname;
     166    assert (COMP_GT == pred_ptr->args.reftime.kind);
     167    return compare_ts (get_stat_atime(stat_buf), pred_ptr->args.reftime.ts) > 0;
     168  }
     169  
     170  bool
     171  pred_atime (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     172  {
     173    (void) &pathname;
     174    return pred_timewindow (get_stat_atime(stat_buf), pred_ptr, DAYSECS);
     175  }
     176  
     177  bool
     178  pred_closeparen (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     179  {
     180    (void) &pathname;
     181    (void) &stat_buf;
     182    (void) &pred_ptr;
     183  
     184    return true;
     185  }
     186  
     187  bool
     188  pred_cmin (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     189  {
     190    (void) pathname;
     191    return pred_timewindow (get_stat_ctime(stat_buf), pred_ptr, 60);
     192  }
     193  
     194  bool
     195  pred_cnewer (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     196  {
     197    (void) pathname;
     198  
     199    assert (COMP_GT == pred_ptr->args.reftime.kind);
     200    return compare_ts (get_stat_ctime(stat_buf), pred_ptr->args.reftime.ts) > 0;
     201  }
     202  
     203  bool
     204  pred_comma (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     205  {
     206    if (pred_ptr->pred_left != NULL)
     207      {
     208        apply_predicate (pathname, stat_buf,pred_ptr->pred_left);
     209      }
     210    return apply_predicate (pathname, stat_buf, pred_ptr->pred_right);
     211  }
     212  
     213  bool
     214  pred_ctime (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     215  {
     216    (void) &pathname;
     217    return pred_timewindow (get_stat_ctime(stat_buf), pred_ptr, DAYSECS);
     218  }
     219  
     220  static bool
     221  perform_delete (int flags)
     222  {
     223    return 0 == unlinkat (state.cwd_dir_fd, state.rel_pathname, flags);
     224  }
     225  
     226  
     227  bool
     228  pred_delete (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     229  {
     230    (void) pred_ptr;
     231    (void) stat_buf;
     232    if (strcmp (state.rel_pathname, "."))
     233      {
     234        int flags=0;
     235        if (state.have_stat && S_ISDIR(stat_buf->st_mode))
     236  	flags |= AT_REMOVEDIR;
     237        if (perform_delete (flags))
     238  	{
     239  	  return true;
     240  	}
     241        else
     242  	{
     243  	  if (ENOENT == errno && options.ignore_readdir_race)
     244  	    {
     245  	      /* Ignore unlink() error for vanished files.  */
     246  	      errno = 0;
     247  	      return true;
     248  	    }
     249  	  if (EISDIR == errno)
     250  	    {
     251  	      if ((flags & AT_REMOVEDIR) == 0)
     252  		{
     253  		  /* unlink() operation failed because we should have done rmdir(). */
     254  		  flags |= AT_REMOVEDIR;
     255  		  if (perform_delete (flags))
     256  		    return true;
     257  		}
     258  	    }
     259  	}
     260        error (0, errno, _("cannot delete %s"),
     261  	     safely_quote_err_filename (0, pathname));
     262        /* Previously I had believed that having the -delete action
     263         * return false provided the user with control over whether an
     264         * error message is issued.  While this is true, the policy of
     265         * not affecting the exit status is contrary to the POSIX
     266         * requirement that diagnostic messages are accompanied by a
     267         * nonzero exit status.  While -delete is not a POSIX option and
     268         * we can therefore opt not to follow POSIX in this case, that
     269         * seems somewhat arbitrary and confusing.  So, as of
     270         * findutils-4.3.11, we also set the exit status in this case.
     271         */
     272        state.exit_status = EXIT_FAILURE;
     273        return false;
     274      }
     275    else
     276      {
     277        /* nothing to do. */
     278        return true;
     279      }
     280  }
     281  
     282  bool
     283  pred_empty (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     284  {
     285    (void) pathname;
     286    (void) pred_ptr;
     287  
     288    if (S_ISDIR (stat_buf->st_mode))
     289      {
     290        int fd;
     291        DIR *d;
     292        struct dirent *dp;
     293        bool empty = true;
     294  
     295        errno = 0;
     296        if ((fd = openat (state.cwd_dir_fd, state.rel_pathname, O_RDONLY
     297  #if defined O_LARGEFILE
     298  			| O_LARGEFILE
     299  #endif
     300  			| O_CLOEXEC | O_DIRECTORY | O_NOCTTY | O_NONBLOCK)) < 0)
     301  	{
     302  	  error (0, errno, "%s", safely_quote_err_filename (0, pathname));
     303  	  state.exit_status = EXIT_FAILURE;
     304  	  return false;
     305  	}
     306        d = fdopendir (fd);
     307        if (d == NULL)
     308  	{
     309  	  error (0, errno, "%s", safely_quote_err_filename (0, pathname));
     310  	  state.exit_status = EXIT_FAILURE;
     311  	  close (fd);
     312  	  return false;
     313  	}
     314        /* errno is not touched in the loop body, so initializing it here
     315         * once before the loop is enough to detect readdir(3) errors.  */
     316        errno = 0;
     317        for (dp = readdir (d); dp; dp = readdir (d))
     318  	{
     319  	  if (dp->d_name[0] != '.'
     320  	      || (dp->d_name[1] != '\0'
     321  		  && (dp->d_name[1] != '.' || dp->d_name[2] != '\0')))
     322  	    {
     323  	      empty = false;
     324  	      break;
     325  	    }
     326  	}
     327        if (errno)
     328  	{
     329  	  /* Handle errors from readdir(3). */
     330  	  error (0, errno, "%s", safely_quote_err_filename (0, pathname));
     331  	  state.exit_status = EXIT_FAILURE;
     332  	  CLOSEDIR (d);
     333  	  return false;
     334  	}
     335        if (CLOSEDIR (d))
     336  	{
     337  	  error (0, errno, "%s", safely_quote_err_filename (0, pathname));
     338  	  state.exit_status = EXIT_FAILURE;
     339  	  return false;
     340  	}
     341        return (empty);
     342      }
     343    else if (S_ISREG (stat_buf->st_mode))
     344      return (stat_buf->st_size == 0);
     345    else
     346      return (false);
     347  }
     348  
     349  
     350  bool
     351  pred_exec (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     352  {
     353    return impl_pred_exec (pathname, stat_buf, pred_ptr);
     354  }
     355  
     356  bool
     357  pred_execdir (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     358  {
     359     (void) &pathname;
     360     return impl_pred_exec (state.rel_pathname, stat_buf, pred_ptr);
     361  }
     362  
     363  bool
     364  pred_false (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     365  {
     366    (void) &pathname;
     367    (void) &stat_buf;
     368    (void) &pred_ptr;
     369  
     370  
     371    return (false);
     372  }
     373  
     374  bool
     375  pred_fls (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     376  {
     377    FILE * stream = pred_ptr->args.printf_vec.stream;
     378    list_file (pathname, state.cwd_dir_fd, state.rel_pathname, stat_buf,
     379  	     options.start_time.tv_sec,
     380  	     options.output_block_size,
     381  	     pred_ptr->literal_control_chars, stream);
     382    return true;
     383  }
     384  
     385  bool
     386  pred_fprint (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     387  {
     388    (void) &pathname;
     389    (void) &stat_buf;
     390  
     391    print_quoted (pred_ptr->args.printf_vec.stream,
     392  		pred_ptr->args.printf_vec.quote_opts,
     393  		pred_ptr->args.printf_vec.dest_is_tty,
     394  		"%s\n",
     395  		pathname);
     396    return true;
     397  }
     398  
     399  bool
     400  pred_fprint0 (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     401  {
     402    FILE * fp = pred_ptr->args.printf_vec.stream;
     403  
     404    (void) &stat_buf;
     405  
     406    fputs (pathname, fp);
     407    putc (0, fp);
     408    return true;
     409  }
     410  
     411  
     412  
     413  bool
     414  pred_fstype (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     415  {
     416    (void) pathname;
     417  
     418    if (strcmp (filesystem_type (stat_buf, pathname), pred_ptr->args.str) == 0)
     419      return true;
     420    else
     421      return false;
     422  }
     423  
     424  bool
     425  pred_gid (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     426  {
     427    (void) pathname;
     428  
     429    switch (pred_ptr->args.numinfo.kind)
     430      {
     431      case COMP_GT:
     432        if (stat_buf->st_gid > pred_ptr->args.numinfo.l_val)
     433  	return (true);
     434        break;
     435      case COMP_LT:
     436        if (stat_buf->st_gid < pred_ptr->args.numinfo.l_val)
     437  	return (true);
     438        break;
     439      case COMP_EQ:
     440        if (stat_buf->st_gid == pred_ptr->args.numinfo.l_val)
     441  	return (true);
     442        break;
     443      }
     444    return (false);
     445  }
     446  
     447  bool
     448  pred_group (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     449  {
     450    (void) pathname;
     451  
     452    if (pred_ptr->args.gid == stat_buf->st_gid)
     453      return (true);
     454    else
     455      return (false);
     456  }
     457  
     458  bool
     459  pred_ilname (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     460  {
     461    return match_lname (pathname, stat_buf, pred_ptr, true);
     462  }
     463  
     464  /* Common code between -name, -iname.  PATHNAME is being visited, STR
     465     is name to compare basename against, and FLAGS are passed to
     466     fnmatch.  Recall that 'find / -name /' is one of the few times where a '/'
     467     in the -name must actually find something. */
     468  static bool
     469  pred_name_common (const char *pathname, const char *str, int flags)
     470  {
     471    bool b;
     472    /* We used to use last_component() here, but that would not allow us to modify the
     473     * input string, which is const.   We could optimise by duplicating the string only
     474     * if we need to modify it, and I'll do that if there is a measurable
     475     * performance difference on a machine built after 1990...
     476     */
     477    char *base = base_name (pathname);
     478    /* remove trailing slashes, but leave  "/" or "//foo" unchanged. */
     479    strip_trailing_slashes (base);
     480  
     481    /* FNM_PERIOD is not used here because POSIX requires that it not be.
     482     * See https://standards.ieee.org/reading/ieee/interp/1003-2-92_int/pasc-1003.2-126.html
     483     */
     484    b = fnmatch (str, base, flags) == 0;
     485    free (base);
     486    return b;
     487  }
     488  
     489  bool
     490  pred_iname (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     491  {
     492    (void) stat_buf;
     493    return pred_name_common (pathname, pred_ptr->args.str, FNM_CASEFOLD);
     494  }
     495  
     496  bool
     497  pred_inum (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     498  {
     499    (void) pathname;
     500  
     501    switch (pred_ptr->args.numinfo.kind)
     502      {
     503      case COMP_GT:
     504        if (stat_buf->st_ino > pred_ptr->args.numinfo.l_val)
     505  	return (true);
     506        break;
     507      case COMP_LT:
     508        if (stat_buf->st_ino < pred_ptr->args.numinfo.l_val)
     509  	return (true);
     510        break;
     511      case COMP_EQ:
     512        if (stat_buf->st_ino == pred_ptr->args.numinfo.l_val)
     513  	return (true);
     514        break;
     515      }
     516    return (false);
     517  }
     518  
     519  bool
     520  pred_ipath (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     521  {
     522    (void) stat_buf;
     523  
     524    if (fnmatch (pred_ptr->args.str, pathname, FNM_CASEFOLD) == 0)
     525      return (true);
     526    return (false);
     527  }
     528  
     529  bool
     530  pred_links (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     531  {
     532    (void) pathname;
     533  
     534    switch (pred_ptr->args.numinfo.kind)
     535      {
     536      case COMP_GT:
     537        if (stat_buf->st_nlink > pred_ptr->args.numinfo.l_val)
     538  	return (true);
     539        break;
     540      case COMP_LT:
     541        if (stat_buf->st_nlink < pred_ptr->args.numinfo.l_val)
     542  	return (true);
     543        break;
     544      case COMP_EQ:
     545        if (stat_buf->st_nlink == pred_ptr->args.numinfo.l_val)
     546  	return (true);
     547        break;
     548      }
     549    return (false);
     550  }
     551  
     552  bool
     553  pred_lname (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     554  {
     555    return match_lname (pathname, stat_buf, pred_ptr, false);
     556  }
     557  
     558  static bool
     559  match_lname (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr, bool ignore_case)
     560  {
     561    bool ret = false;
     562  #ifdef S_ISLNK
     563    if (S_ISLNK (stat_buf->st_mode))
     564      {
     565        char *linkname = areadlinkat (state.cwd_dir_fd, state.rel_pathname);
     566        if (linkname)
     567  	{
     568  	  if (fnmatch (pred_ptr->args.str, linkname,
     569  		       ignore_case ? FNM_CASEFOLD : 0) == 0)
     570  	    ret = true;
     571  	}
     572        else
     573  	{
     574  	  nonfatal_target_file_error (errno, pathname);
     575  	  state.exit_status = EXIT_FAILURE;
     576  	}
     577        free (linkname);
     578      }
     579  #endif /* S_ISLNK */
     580    return ret;
     581  }
     582  
     583  bool
     584  pred_ls (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     585  {
     586    return pred_fls (pathname, stat_buf, pred_ptr);
     587  }
     588  
     589  bool
     590  pred_mmin (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     591  {
     592    (void) &pathname;
     593    return pred_timewindow (get_stat_mtime(stat_buf), pred_ptr, 60);
     594  }
     595  
     596  bool
     597  pred_mtime (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     598  {
     599    (void) pathname;
     600    return pred_timewindow (get_stat_mtime(stat_buf), pred_ptr, DAYSECS);
     601  }
     602  
     603  bool
     604  pred_name (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     605  {
     606    (void) stat_buf;
     607    return pred_name_common (pathname, pred_ptr->args.str, 0);
     608  }
     609  
     610  bool
     611  pred_negate (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     612  {
     613    return !apply_predicate (pathname, stat_buf, pred_ptr->pred_right);
     614  }
     615  
     616  bool
     617  pred_newer (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     618  {
     619    (void) pathname;
     620  
     621    assert (COMP_GT == pred_ptr->args.reftime.kind);
     622    return compare_ts (get_stat_mtime(stat_buf), pred_ptr->args.reftime.ts) > 0;
     623  }
     624  
     625  bool
     626  pred_newerXY (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     627  {
     628    struct timespec ts;
     629    bool collected = false;
     630  
     631    assert (COMP_GT == pred_ptr->args.reftime.kind);
     632  
     633    switch (pred_ptr->args.reftime.xval)
     634      {
     635      case XVAL_TIME:
     636        assert (pred_ptr->args.reftime.xval != XVAL_TIME);
     637        return false;
     638  
     639      case XVAL_ATIME:
     640        ts = get_stat_atime (stat_buf);
     641        collected = true;
     642        break;
     643  
     644      case XVAL_BIRTHTIME:
     645        ts = get_stat_birthtime (stat_buf);
     646        collected = true;
     647        if (ts.tv_nsec < 0)
     648  	{
     649  	  /* XXX: Cannot determine birth time.  Warn once. */
     650  	  error (0, 0, _("WARNING: cannot determine birth time of file %s"),
     651  		 safely_quote_err_filename (0, pathname));
     652  	  return false;
     653  	}
     654        break;
     655  
     656      case XVAL_CTIME:
     657        ts = get_stat_ctime (stat_buf);
     658        collected = true;
     659        break;
     660  
     661      case XVAL_MTIME:
     662        ts = get_stat_mtime (stat_buf);
     663        collected = true;
     664        break;
     665      }
     666  
     667    assert (collected);
     668    return compare_ts (ts, pred_ptr->args.reftime.ts) > 0;
     669  }
     670  
     671  bool
     672  pred_nogroup (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     673  {
     674    (void) pathname;
     675    (void) pred_ptr;
     676    return getgrgid (stat_buf->st_gid) == NULL;
     677  }
     678  
     679  bool
     680  pred_nouser (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     681  {
     682    (void) pathname;
     683    (void) pred_ptr;
     684    return getpwuid (stat_buf->st_uid) == NULL;
     685  }
     686  
     687  
     688  static bool
     689  is_ok (const char *program, const char *arg)
     690  {
     691    fflush (stdout);
     692    /* The draft open standard requires that, in the POSIX locale,
     693       the last non-blank character of this prompt be '?'.
     694       The exact format is not specified.
     695       This standard does not have requirements for locales other than POSIX
     696    */
     697    /* XXX: printing UNTRUSTED data here. */
     698    if (fprintf (stderr, _("< %s ... %s > ? "), program, arg) < 0)
     699      {
     700        die (EXIT_FAILURE, errno, _("Failed to write prompt for -ok"));
     701      }
     702    fflush (stderr);
     703    return yesno ();
     704  }
     705  
     706  bool
     707  pred_ok (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     708  {
     709    if (is_ok (pred_ptr->args.exec_vec.replace_vec[0], pathname))
     710      return impl_pred_exec (pathname, stat_buf, pred_ptr);
     711    else
     712      return false;
     713  }
     714  
     715  bool
     716  pred_okdir (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     717  {
     718    if (is_ok (pred_ptr->args.exec_vec.replace_vec[0], pathname))
     719      return impl_pred_exec (state.rel_pathname, stat_buf, pred_ptr);
     720    else
     721      return false;
     722  }
     723  
     724  bool
     725  pred_openparen (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     726  {
     727    (void) pathname;
     728    (void) stat_buf;
     729    (void) pred_ptr;
     730    return true;
     731  }
     732  
     733  bool
     734  pred_or (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     735  {
     736    if (pred_ptr->pred_left == NULL
     737        || !apply_predicate (pathname, stat_buf, pred_ptr->pred_left))
     738      {
     739        return apply_predicate (pathname, stat_buf, pred_ptr->pred_right);
     740      }
     741    else
     742      return true;
     743  }
     744  
     745  bool
     746  pred_path (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     747  {
     748    (void) stat_buf;
     749    if (fnmatch (pred_ptr->args.str, pathname, 0) == 0)
     750      return (true);
     751    return (false);
     752  }
     753  
     754  bool
     755  pred_perm (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     756  {
     757    mode_t mode = stat_buf->st_mode;
     758    mode_t perm_val = pred_ptr->args.perm.val[S_ISDIR (mode) != 0];
     759    (void) pathname;
     760    switch (pred_ptr->args.perm.kind)
     761      {
     762      case PERM_AT_LEAST:
     763        return (mode & perm_val) == perm_val;
     764        break;
     765  
     766      case PERM_ANY:
     767        /* True if any of the bits set in the mask are also set in the file's mode.
     768         *
     769         *
     770         * Otherwise, if onum is prefixed by a hyphen, the primary shall
     771         * evaluate as true if at least all of the bits specified in
     772         * onum that are also set in the octal mask 07777 are set.
     773         *
     774         * Eric Blake's interpretation is that the mode argument is zero,
     775  
     776         */
     777        if (0 == perm_val)
     778  	return true;		/* Savannah bug 14748; we used to return false */
     779        else
     780  	return (mode & perm_val) != 0;
     781        break;
     782  
     783      case PERM_EXACT:
     784        return (mode & MODE_ALL) == perm_val;
     785        break;
     786  
     787      default:
     788        abort ();
     789        break;
     790      }
     791  }
     792  
     793  
     794  bool
     795  pred_executable (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     796  {
     797    (void) pathname;
     798    (void) stat_buf;
     799    (void) pred_ptr;
     800  
     801    /* As for access, the check is performed with the real user id. */
     802    return 0 == faccessat (state.cwd_dir_fd, state.rel_pathname, X_OK, 0);
     803  }
     804  
     805  bool
     806  pred_readable (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     807  {
     808    (void) pathname;
     809    (void) stat_buf;
     810    (void) pred_ptr;
     811  
     812    /* As for access, the check is performed with the real user id. */
     813    return 0 == faccessat (state.cwd_dir_fd, state.rel_pathname, R_OK, 0);
     814  }
     815  
     816  bool
     817  pred_writable (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     818  {
     819    (void) pathname;
     820    (void) stat_buf;
     821    (void) pred_ptr;
     822  
     823    /* As for access, the check is performed with the real user id. */
     824    return 0 == faccessat (state.cwd_dir_fd, state.rel_pathname, W_OK, 0);
     825  }
     826  
     827  bool
     828  pred_print (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     829  {
     830    (void) stat_buf;
     831    (void) pred_ptr;
     832  
     833    print_quoted (pred_ptr->args.printf_vec.stream,
     834  		pred_ptr->args.printf_vec.quote_opts,
     835  		pred_ptr->args.printf_vec.dest_is_tty,
     836  		"%s\n", pathname);
     837    return true;
     838  }
     839  
     840  bool
     841  pred_print0 (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     842  {
     843    return pred_fprint0(pathname, stat_buf, pred_ptr);
     844  }
     845  
     846  bool
     847  pred_prune (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     848  {
     849    (void) pathname;
     850    (void) pred_ptr;
     851  
     852    if (options.do_dir_first == true) { /* no effect with -depth */
     853      assert (state.have_stat);
     854      if (stat_buf != NULL &&
     855  	S_ISDIR(stat_buf->st_mode))
     856        state.stop_at_current_level = true;
     857    }
     858  
     859    /* findutils used to return options.do_dir_first here, so that -prune
     860     * returns true only if -depth is not in effect.   But POSIX requires
     861     * that -prune always evaluate as true.
     862     */
     863    return true;
     864  }
     865  
     866  bool
     867  pred_quit (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     868  {
     869    (void) pathname;
     870    (void) stat_buf;
     871    (void) pred_ptr;
     872  
     873    /* Run any cleanups.  This includes executing any command lines
     874     * we have partly built but not executed.
     875     */
     876    cleanup ();
     877  
     878    /* Since -exec and friends don't leave child processes running in the
     879     * background, there is no need to wait for them here.
     880     */
     881    exit (state.exit_status);	/* 0 for success, etc. */
     882  }
     883  
     884  bool
     885  pred_regex (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     886  {
     887    int len = strlen (pathname);
     888  (void) stat_buf;
     889    if (re_match (pred_ptr->args.regex, pathname, len, 0,
     890  		(struct re_registers *) NULL) == len)
     891      return (true);
     892    return (false);
     893  }
     894  
     895  bool
     896  pred_size (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     897  {
     898    uintmax_t f_val;
     899  
     900    (void) pathname;
     901    f_val = ((stat_buf->st_size / pred_ptr->args.size.blocksize)
     902  	   + (stat_buf->st_size % pred_ptr->args.size.blocksize != 0));
     903    switch (pred_ptr->args.size.kind)
     904      {
     905      case COMP_GT:
     906        if (f_val > pred_ptr->args.size.size)
     907  	return (true);
     908        break;
     909      case COMP_LT:
     910        if (f_val < pred_ptr->args.size.size)
     911  	return (true);
     912        break;
     913      case COMP_EQ:
     914        if (f_val == pred_ptr->args.size.size)
     915  	return (true);
     916        break;
     917      }
     918    return (false);
     919  }
     920  
     921  bool
     922  pred_samefile (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     923  {
     924    /* Potential optimisation: because of the loop protection, we always
     925     * know the device of the current directory, hence the device number
     926     * of the file we're currently considering.  If -L is not in effect,
     927     * and the device number of the file we're looking for is not the
     928     * same as the device number of the current directory, this
     929     * predicate cannot return true.  Hence there would be no need to
     930     * stat the file we're looking at.
     931     *
     932     * For the moment, we simply compare inode numbers, which should cut
     933     * down greatly on the number of calls to stat.  Some of the
     934     * remainder will be unnecessary, but the additional complexity
     935     * probably isn't worthwhile.
     936     */
     937    (void) pathname;
     938  
     939    /* We will often still have an fd open on the file under consideration,
     940     * but that's just to ensure inode number stability by maintaining
     941     * a reference to it; we don't need the file for anything else.
     942     */
     943    if (stat_buf->st_ino)
     944      {
     945        if (stat_buf->st_ino != pred_ptr->args.samefileid.ino)
     946  	return false;
     947      }
     948    /* Now stat the file to check the device number. */
     949    if (0 == get_statinfo (pathname, state.rel_pathname, stat_buf))
     950      {
     951        /* the repeated test here is necessary in case stat_buf.st_ino had been zero. */
     952        return stat_buf->st_ino == pred_ptr->args.samefileid.ino
     953  	&& stat_buf->st_dev == pred_ptr->args.samefileid.dev;
     954      }
     955    else
     956      {
     957        /* get_statinfo will already have emitted an error message. */
     958        return false;
     959      }
     960  }
     961  
     962  bool
     963  pred_true (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     964  {
     965    (void) pathname;
     966    (void) stat_buf;
     967    (void) pred_ptr;
     968    return true;
     969  }
     970  
     971  bool
     972  pred_type (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
     973  {
     974    mode_t mode;
     975    enum file_type type = FTYPE_COUNT;
     976  
     977    assert (state.have_type);
     978  
     979    if (0 == state.type)
     980      {
     981        /* This can sometimes happen with broken NFS servers.
     982         * See Savannah bug #16378.
     983         */
     984        return false;
     985      }
     986  
     987    (void) pathname;
     988  
     989    if (state.have_stat)
     990       mode = stat_buf->st_mode;
     991    else
     992       mode = state.type;
     993  
     994  #ifndef S_IFMT
     995    /* POSIX system; check `mode' the slow way.
     996     * Search in the order of probability (f,d,l,b,c,s,p,D).
     997     */
     998    if (S_ISREG (mode))
     999       type = FTYPE_REG;
    1000    else if (S_ISDIR (mode))
    1001       type = FTYPE_DIR;
    1002  # ifdef S_IFLNK
    1003    else if (S_ISLNK (mode))
    1004       type = FTYPE_LNK;
    1005  # endif
    1006    else if (S_ISBLK (mode))
    1007       type = FTYPE_BLK;
    1008    else if (S_ISCHR (mode))
    1009       type = FTYPE_CHR;
    1010  # ifdef S_IFSOCK
    1011    else if (S_ISSOCK (mode))
    1012       type = FTYPE_SOCK;
    1013  # endif
    1014  # ifdef S_IFIFO
    1015    else if (S_ISFIFO (mode))
    1016       type = FTYPE_FIFO;
    1017  # endif
    1018  # ifdef S_IFDOOR
    1019    else if (S_ISDOOR (mode))
    1020      type = FTYPE_DOOR;
    1021  # endif
    1022  #else /* S_IFMT */
    1023    /* Unix system; check `mode' the fast way. */
    1024    switch (mode & S_IFMT)
    1025      {
    1026      case S_IFREG:
    1027        type = FTYPE_REG;
    1028        break;
    1029      case S_IFDIR:
    1030        type = FTYPE_DIR;
    1031        break;
    1032  # ifdef S_IFLNK
    1033      case S_IFLNK:
    1034        type = FTYPE_LNK;
    1035        break;
    1036  # endif
    1037      case S_IFBLK:
    1038        type = FTYPE_BLK;
    1039        break;
    1040      case S_IFCHR:
    1041        type = FTYPE_CHR;
    1042        break;
    1043  # ifdef S_IFSOCK
    1044      case S_IFSOCK:
    1045        type = FTYPE_SOCK;
    1046        break;
    1047  # endif
    1048  # ifdef S_IFIFO
    1049      case S_IFIFO:
    1050        type = FTYPE_FIFO;
    1051        break;
    1052  # endif
    1053  # ifdef S_IFDOOR
    1054      case S_IFDOOR:
    1055        type = FTYPE_DOOR;
    1056        break;
    1057  # endif
    1058      }
    1059  #endif /* S_IFMT */
    1060  
    1061    if ((type != FTYPE_COUNT) && pred_ptr->args.types[type])
    1062      return true;
    1063    else
    1064      return false;
    1065  }
    1066  
    1067  bool
    1068  pred_uid (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
    1069  {
    1070    (void) pathname;
    1071    switch (pred_ptr->args.numinfo.kind)
    1072      {
    1073      case COMP_GT:
    1074        if (stat_buf->st_uid > pred_ptr->args.numinfo.l_val)
    1075  	return (true);
    1076        break;
    1077      case COMP_LT:
    1078        if (stat_buf->st_uid < pred_ptr->args.numinfo.l_val)
    1079  	return (true);
    1080        break;
    1081      case COMP_EQ:
    1082        if (stat_buf->st_uid == pred_ptr->args.numinfo.l_val)
    1083  	return (true);
    1084        break;
    1085      }
    1086    return (false);
    1087  }
    1088  
    1089  bool
    1090  pred_used (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
    1091  {
    1092    struct timespec delta, at, ct;
    1093  
    1094    (void) pathname;
    1095  
    1096    at = get_stat_atime (stat_buf);
    1097    ct = get_stat_ctime (stat_buf);
    1098  
    1099    /* Always evaluate to false if atime < ctime.  */
    1100    if (compare_ts (at, ct) < 0)
    1101      return false;
    1102  
    1103    delta.tv_sec  = ct.tv_sec  - at.tv_sec;
    1104    delta.tv_nsec = ct.tv_nsec - at.tv_nsec;
    1105    if (delta.tv_nsec < 0)
    1106      {
    1107        delta.tv_nsec += 1000000000;
    1108        delta.tv_sec  -=          1;
    1109      }
    1110    return pred_timewindow (delta, pred_ptr, DAYSECS);
    1111  }
    1112  
    1113  bool
    1114  pred_user (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
    1115  {
    1116    (void) pathname;
    1117    if (pred_ptr->args.uid == stat_buf->st_uid)
    1118      return (true);
    1119    else
    1120      return (false);
    1121  }
    1122  
    1123  bool
    1124  pred_xtype (const char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
    1125  {
    1126    struct stat sbuf;		/* local copy, not stat_buf because we're using a different stat method */
    1127    int (*ystat) (const char*, struct stat *p);
    1128  
    1129    /* If we would normally stat the link itself, stat the target instead.
    1130     * If we would normally follow the link, stat the link itself instead.
    1131     */
    1132    if (following_links ())
    1133      ystat = optionp_stat;
    1134    else
    1135      ystat = optionl_stat;
    1136  
    1137    set_stat_placeholders (&sbuf);
    1138    if ((*ystat) (state.rel_pathname, &sbuf) != 0)
    1139      {
    1140        if (following_links () && errno == ENOENT)
    1141  	{
    1142  	  /* If we failed to follow the symlink,
    1143  	   * fall back on looking at the symlink itself.
    1144  	   */
    1145  	  /* Mimic behavior of ls -lL. */
    1146  	  return (pred_type (pathname, stat_buf, pred_ptr));
    1147  	}
    1148        else
    1149  	{
    1150  	  error (0, errno, "%s", safely_quote_err_filename (0, pathname));
    1151  	  state.exit_status = EXIT_FAILURE;
    1152  	}
    1153        return false;
    1154      }
    1155    /* Now that we have our stat() information, query it in the same
    1156     * way that -type does.
    1157     */
    1158    return (pred_type (pathname, &sbuf, pred_ptr));
    1159  }
    1160  
    1161  
    1162  bool
    1163  pred_context (const char *pathname, struct stat *stat_buf,
    1164  	      struct predicate *pred_ptr)
    1165  {
    1166    char *scontext;
    1167    int rv = (*options.x_getfilecon) (state.cwd_dir_fd, state.rel_pathname,
    1168  				    &scontext);
    1169    (void) stat_buf;
    1170  
    1171    if (rv < 0)
    1172      {
    1173        error (0, errno, _("getfilecon failed: %s"),
    1174  	     safely_quote_err_filename (0, pathname));
    1175        return false;
    1176      }
    1177  
    1178    rv = (fnmatch (pred_ptr->args.scontext, scontext, 0) == 0);
    1179    freecon (scontext);
    1180    return rv;
    1181  }
    1182  
    1183  /* Copy STR into BUF and trim blanks from the end of BUF.
    1184     Return BUF. */
    1185  
    1186  static char *
    1187  blank_rtrim (const char *str, char *buf)
    1188  {
    1189    int i;
    1190  
    1191    if (str == NULL)
    1192      return (NULL);
    1193    strcpy (buf, str);
    1194    i = strlen (buf) - 1;
    1195    while ((i >= 0) && ((buf[i] == ' ') || buf[i] == '\t'))
    1196      i--;
    1197    buf[++i] = '\0';
    1198    return buf;
    1199  }
    1200  
    1201  /* Print out the predicate list starting at NODE. */
    1202  void
    1203  print_list (FILE *fp, struct predicate *node)
    1204  {
    1205    struct predicate *cur;
    1206    char name[256];
    1207  
    1208    cur = node;
    1209    while (cur != NULL)
    1210      {
    1211        fprintf (fp, "[%s] ", blank_rtrim (cur->p_name, name));
    1212        cur = cur->pred_next;
    1213      }
    1214    fprintf (fp, "\n");
    1215  }
    1216  
    1217  /* Print out the predicate list starting at NODE. */
    1218  static void
    1219  print_parenthesised (FILE *fp, struct predicate *node)
    1220  {
    1221    int parens = 0;
    1222  
    1223    if (node)
    1224      {
    1225        if ((pred_is (node, pred_or) || pred_is (node, pred_and))
    1226  	  && node->pred_left == NULL)
    1227  	{
    1228  	  /* We print "<nothing> or  X" as just "X"
    1229  	   * We print "<nothing> and X" as just "X"
    1230  	   */
    1231  	  print_parenthesised(fp, node->pred_right);
    1232  	}
    1233        else
    1234  	{
    1235  	  if (node->pred_left || node->pred_right)
    1236  	    parens = 1;
    1237  
    1238  	  if (parens)
    1239  	    fprintf (fp, "%s", " ( ");
    1240  	  print_optlist (fp, node);
    1241  	  if (parens)
    1242  	    fprintf (fp, "%s", " ) ");
    1243  	}
    1244      }
    1245  }
    1246  
    1247  void
    1248  print_optlist (FILE *fp, const struct predicate *p)
    1249  {
    1250    if (p)
    1251      {
    1252        print_parenthesised (fp, p->pred_left);
    1253        fprintf (fp,
    1254                 "%s%s%s",
    1255                 p->need_stat ? "[call stat] " : "",
    1256                 p->need_type ? "[need type] " : "",
    1257                 p->need_inum ? "[need inum] " : "");
    1258        print_predicate (fp, p);
    1259        fprintf (fp, " [est success rate %.4g] ", p->est_success_rate);
    1260        if (options.debug_options & DebugSuccessRates)
    1261          {
    1262            fprintf (fp, "[real success rate %lu/%lu", p->perf.successes, p->perf.visits);
    1263            if (p->perf.visits)
    1264              {
    1265                double real_rate = (double)p->perf.successes / (double)p->perf.visits;
    1266                fprintf (fp, "=%.4g] ", real_rate);
    1267              }
    1268            else
    1269              {
    1270                fprintf (fp, "=_] ");
    1271              }
    1272          }
    1273        print_parenthesised (fp, p->pred_right);
    1274      }
    1275  }
    1276  
    1277  void show_success_rates (const struct predicate *p)
    1278  {
    1279    if (options.debug_options & DebugSuccessRates)
    1280      {
    1281        fprintf (stderr, "Predicate success rates after completion:\n");
    1282        print_optlist (stderr, p);
    1283        fprintf (stderr, "\n");
    1284      }
    1285  }
    1286  
    1287  
    1288  
    1289  
    1290  #ifdef _NDEBUG
    1291  /* If _NDEBUG is defined, the assertions will do nothing.   Hence
    1292   * there is no point in having a function body for pred_sanity_check()
    1293   * if that preprocessor macro is defined.
    1294   */
    1295  void
    1296  pred_sanity_check (const struct predicate *predicates)
    1297  {
    1298    /* Do nothing, since assert is a no-op with _NDEBUG set */
    1299    return;
    1300  }
    1301  #else
    1302  void
    1303  pred_sanity_check (const struct predicate *predicates)
    1304  {
    1305    const struct predicate *p;
    1306  
    1307    for (p=predicates; p != NULL; p=p->pred_next)
    1308      {
    1309        /* All predicates must do something. */
    1310        assert (p->pred_func != NULL);
    1311  
    1312        /* All predicates must have a parser table entry. */
    1313        assert (p->parser_entry != NULL);
    1314  
    1315        /* If the parser table tells us that just one predicate function is
    1316         * possible, verify that that is still the one that is in effect.
    1317         * If the parser has NULL for the predicate function, that means that
    1318         * the parse_xxx function fills it in, so we can't check it.
    1319         */
    1320        if (p->parser_entry->pred_func)
    1321  	{
    1322  	  assert (p->parser_entry->pred_func == p->pred_func);
    1323  	}
    1324  
    1325        switch (p->parser_entry->type)
    1326  	{
    1327  	  /* Options all take effect during parsing, so there should
    1328  	   * be no predicate entries corresponding to them.  Hence we
    1329  	   * should not see any ARG_OPTION or ARG_POSITIONAL_OPTION
    1330  	   * items.
    1331  	   *
    1332  	   * This is a silly way of coding this test, but it prevents
    1333  	   * a compiler warning (i.e. otherwise it would think that
    1334  	   * there would be case statements missing).
    1335  	   */
    1336  	case ARG_OPTION:
    1337  	case ARG_POSITIONAL_OPTION:
    1338  	  assert (p->parser_entry->type != ARG_OPTION);
    1339  	  assert (p->parser_entry->type != ARG_POSITIONAL_OPTION);
    1340  	  break;
    1341  
    1342  	case ARG_ACTION:
    1343  	  assert (p->side_effects); /* actions have side effects. */
    1344  	  if (!pred_is (p, pred_prune) && !pred_is(p, pred_quit))
    1345  	    {
    1346  	      /* actions other than -prune and -quit should
    1347  	       * inhibit the default -print
    1348  	       */
    1349  	      assert (p->no_default_print);
    1350  	    }
    1351  	  break;
    1352  
    1353  	/* We happen to know that the only user of ARG_SPECIAL_PARSE
    1354  	 * is a test, so handle it like ARG_TEST.
    1355  	 */
    1356  	case ARG_SPECIAL_PARSE:
    1357  	case ARG_TEST:
    1358  	case ARG_PUNCTUATION:
    1359  	case ARG_NOOP:
    1360  	  /* Punctuation and tests should have no side
    1361  	   * effects and not inhibit default print.
    1362  	   */
    1363  	  assert (!p->no_default_print);
    1364  	  assert (!p->side_effects);
    1365  	  break;
    1366  	}
    1367      }
    1368  }
    1369  #endif