~ubuntu-branches/ubuntu/gutsy/findutils/gutsy-proposed

« back to all changes in this revision

Viewing changes to find/pred.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Metzler
  • Date: 2005-07-04 11:37:37 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20050704113737-ll89ui8be35r0pir
Tags: 4.2.22-2
* Remove locatedb on purge. (Closes: #315343)
* revert regex-syntax back to emacs-re. (Closes: #315136) Future versions
  will allow to select this by commandline parameter.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/* pred.c -- execute the expression tree.
2
 
   Copyright (C) 1990, 91, 92, 93, 94, 2000, 2003 Free Software Foundation, Inc.
 
2
   Copyright (C) 1990, 1991, 1992, 1993, 1994, 2000, 2003, 
 
3
                 2004, 2005 Free Software Foundation, Inc.
3
4
 
4
5
   This program is free software; you can redistribute it and/or modify
5
6
   it under the terms of the GNU General Public License as published by
13
14
 
14
15
   You should have received a copy of the GNU General Public License
15
16
   along with this program; if not, write to the Free Software
16
 
   Foundation, Inc., 9 Temple Place - Suite 330, Boston, MA 02111-1307,
 
17
   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
17
18
   USA.
18
19
*/
19
20
 
20
 
#define _GNU_SOURCE
21
21
#include "defs.h"
22
22
 
23
23
#include <fnmatch.h>
24
24
#include <signal.h>
25
25
#include <pwd.h>
26
26
#include <grp.h>
 
27
#include <sys/types.h>
 
28
#include <sys/stat.h>
 
29
#include <assert.h>
 
30
#include <fcntl.h>
 
31
#include "xalloc.h"
27
32
#include "dirname.h"
28
33
#include "human.h"
29
34
#include "modetype.h"
 
35
#include "filemode.h"
30
36
#include "wait.h"
 
37
#include "printquoted.h"
 
38
#include "buildcmd.h"
 
39
#include "yesno.h"
31
40
 
32
41
#if ENABLE_NLS
33
42
# include <libintl.h>
38
47
#ifdef gettext_noop
39
48
# define N_(String) gettext_noop (String)
40
49
#else
41
 
# define N_(String) (String)
 
50
/* See locate.c for explanation as to why not use (String) */
 
51
# define N_(String) String
42
52
#endif
43
53
 
44
54
#if !defined(SIGCHLD) && defined(SIGCLD)
45
55
#define SIGCHLD SIGCLD
46
56
#endif
47
57
 
 
58
 
 
59
 
48
60
#if HAVE_DIRENT_H
49
61
# include <dirent.h>
50
62
# define NAMLEN(dirent) strlen((dirent)->d_name)
69
81
#define CLOSEDIR(d) closedir (d)
70
82
#endif
71
83
 
72
 
extern int yesno ();
 
84
 
73
85
 
74
86
 
75
87
/* Get or fake the disk device blocksize.
133
145
# define ST_NBLOCKSIZE 512
134
146
#endif
135
147
 
 
148
 
136
149
#undef MAX
137
150
#define MAX(a, b) ((a) > (b) ? (a) : (b))
138
151
 
139
152
static boolean insert_lname PARAMS((char *pathname, struct stat *stat_buf, struct predicate *pred_ptr, boolean ignore_case));
140
 
static boolean launch PARAMS((struct predicate *pred_ptr));
 
153
 
141
154
static char *format_date PARAMS((time_t when, int kind));
142
155
static char *ctime_format PARAMS((time_t when));
143
156
 
159
172
  {pred_cnewer, "cnewer  "},
160
173
  {pred_comma, ",       "},
161
174
  {pred_ctime, "ctime   "},
 
175
  {pred_delete, "delete  "},
162
176
  {pred_empty, "empty   "},
163
177
  {pred_exec, "exec    "},
 
178
  {pred_execdir, "execdir "},
164
179
  {pred_false, "false   "},
165
180
  {pred_fprint, "fprint  "},
166
181
  {pred_fprint0, "fprint0 "},
183
198
  {pred_nogroup, "nogroup "},
184
199
  {pred_nouser, "nouser  "},
185
200
  {pred_ok, "ok      "},
 
201
  {pred_okdir, "okdir   "},
186
202
  {pred_open, "(       "},
187
203
  {pred_or, "or      "},
188
204
  {pred_path, "path    "},
191
207
  {pred_print0, "print0  "},
192
208
  {pred_prune, "prune   "},
193
209
  {pred_regex, "regex   "},
 
210
  {pred_samefile,"samefile "},
194
211
  {pred_size, "size    "},
195
212
  {pred_true, "true    "},
196
213
  {pred_type, "type    "},
244
261
 
245
262
   Return true if the file passes this predicate, false if not. */
246
263
 
 
264
 
 
265
/* pred_timewindow
 
266
 *
 
267
 * Returns true if THE_TIME is 
 
268
 * COMP_GT: after the specified time
 
269
 * COMP_LT: before the specified time
 
270
 * COMP_EQ: less than WINDOW seconds after the specified time.
 
271
 */
 
272
static boolean
 
273
pred_timewindow(time_t the_time, struct predicate const *pred_ptr, int window)
 
274
{
 
275
  switch (pred_ptr->args.info.kind)
 
276
    {
 
277
    case COMP_GT:
 
278
      if (the_time > (time_t) pred_ptr->args.info.l_val)
 
279
        return true;
 
280
      break;
 
281
    case COMP_LT:
 
282
      if (the_time < (time_t) pred_ptr->args.info.l_val)
 
283
        return true;
 
284
      break;
 
285
    case COMP_EQ:
 
286
      if ((the_time >= (time_t) pred_ptr->args.info.l_val)
 
287
          && (the_time < (time_t) pred_ptr->args.info.l_val + window))
 
288
        return true;
 
289
      break;
 
290
    }
 
291
  return false;
 
292
}
 
293
 
 
294
 
247
295
boolean
248
296
pred_amin (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
249
297
{
250
 
  switch (pred_ptr->args.info.kind)
251
 
    {
252
 
    case COMP_GT:
253
 
      if (stat_buf->st_atime > (time_t) pred_ptr->args.info.l_val)
254
 
        return (true);
255
 
      break;
256
 
    case COMP_LT:
257
 
      if (stat_buf->st_atime < (time_t) pred_ptr->args.info.l_val)
258
 
        return (true);
259
 
      break;
260
 
    case COMP_EQ:
261
 
      if ((stat_buf->st_atime >= (time_t) pred_ptr->args.info.l_val)
262
 
          && (stat_buf->st_atime < (time_t) pred_ptr->args.info.l_val + 60))
263
 
        return (true);
264
 
      break;
265
 
    }
266
 
  return (false);
 
298
  (void) &pathname;
 
299
  return pred_timewindow(stat_buf->st_atime, pred_ptr, 60);
267
300
}
268
301
 
269
302
boolean
274
307
                                            pred_ptr->pred_left))
275
308
    {
276
309
      /* Check whether we need a stat here. */
277
 
      if (pred_ptr->need_stat)
278
 
        {
279
 
          if (!have_stat && (*xstat) (rel_pathname, stat_buf) != 0)
280
 
            {
281
 
              error (0, errno, "%s", pathname);
282
 
              exit_status = 1;
283
 
              return (false);
284
 
            }
285
 
          have_stat = true;
286
 
        }
287
 
      return ((*pred_ptr->pred_right->pred_func) (pathname, stat_buf,
 
310
      if (get_info(pathname, state.rel_pathname, stat_buf, pred_ptr) != 0)
 
311
            return false;
 
312
      return ((*pred_ptr->pred_right->pred_func) (pathname, stat_buf,  
288
313
                                                  pred_ptr->pred_right));
289
314
    }
290
315
  else
294
319
boolean
295
320
pred_anewer (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
296
321
{
 
322
  (void) &pathname;
 
323
  
297
324
  if (stat_buf->st_atime > pred_ptr->args.time)
298
325
    return (true);
299
326
  return (false);
302
329
boolean
303
330
pred_atime (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
304
331
{
305
 
  switch (pred_ptr->args.info.kind)
306
 
    {
307
 
    case COMP_GT:
308
 
      if (stat_buf->st_atime > (time_t) pred_ptr->args.info.l_val)
309
 
        return (true);
310
 
      break;
311
 
    case COMP_LT:
312
 
      if (stat_buf->st_atime < (time_t) pred_ptr->args.info.l_val)
313
 
        return (true);
314
 
      break;
315
 
    case COMP_EQ:
316
 
      if ((stat_buf->st_atime >= (time_t) pred_ptr->args.info.l_val)
317
 
          && (stat_buf->st_atime < (time_t) pred_ptr->args.info.l_val
318
 
              + DAYSECS))
319
 
        return (true);
320
 
      break;
321
 
    }
322
 
  return (false);
 
332
  (void) &pathname;
 
333
  return pred_timewindow(stat_buf->st_atime, pred_ptr, DAYSECS);
323
334
}
324
335
 
325
336
boolean
326
337
pred_close (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
327
338
{
328
 
  return (true);
 
339
  (void) &pathname;
 
340
  (void) &stat_buf;
 
341
  (void) &pred_ptr;
 
342
  
 
343
  return true;
329
344
}
330
345
 
331
346
boolean
332
347
pred_cmin (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
333
348
{
334
 
  switch (pred_ptr->args.info.kind)
335
 
    {
336
 
    case COMP_GT:
337
 
      if (stat_buf->st_ctime > (time_t) pred_ptr->args.info.l_val)
338
 
        return (true);
339
 
      break;
340
 
    case COMP_LT:
341
 
      if (stat_buf->st_ctime < (time_t) pred_ptr->args.info.l_val)
342
 
        return (true);
343
 
      break;
344
 
    case COMP_EQ:
345
 
      if ((stat_buf->st_ctime >= (time_t) pred_ptr->args.info.l_val)
346
 
          && (stat_buf->st_ctime < (time_t) pred_ptr->args.info.l_val + 60))
347
 
        return (true);
348
 
      break;
349
 
    }
350
 
  return (false);
 
349
  (void) pathname;
 
350
  return pred_timewindow(stat_buf->st_ctime, pred_ptr, 60);
351
351
}
352
352
 
353
353
boolean
354
354
pred_cnewer (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
355
355
{
 
356
  (void) pathname;
 
357
  
356
358
  if (stat_buf->st_ctime > pred_ptr->args.time)
357
 
    return (true);
358
 
  return (false);
 
359
    return true;
 
360
  else
 
361
    return false;
359
362
}
360
363
 
361
364
boolean
365
368
    (*pred_ptr->pred_left->pred_func) (pathname, stat_buf,
366
369
                                       pred_ptr->pred_left);
367
370
  /* Check whether we need a stat here. */
368
 
  if (pred_ptr->need_stat)
369
 
    {
370
 
      if (!have_stat && (*xstat) (rel_pathname, stat_buf) != 0)
371
 
        {
372
 
          error (0, errno, "%s", pathname);
373
 
          exit_status = 1;
374
 
          return (false);
375
 
        }
376
 
      have_stat = true;
377
 
    }
 
371
  /* TODO: what about need_type? */
 
372
  if (get_info(pathname, state.rel_pathname, stat_buf, pred_ptr) != 0)
 
373
    return false;
378
374
  return ((*pred_ptr->pred_right->pred_func) (pathname, stat_buf,
379
375
                                              pred_ptr->pred_right));
380
376
}
382
378
boolean
383
379
pred_ctime (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
384
380
{
385
 
  switch (pred_ptr->args.info.kind)
 
381
  (void) &pathname;
 
382
  return pred_timewindow(stat_buf->st_ctime, pred_ptr, DAYSECS);
 
383
}
 
384
 
 
385
boolean
 
386
pred_delete (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
 
387
{
 
388
  (void) pred_ptr;
 
389
  (void) stat_buf;
 
390
  if (strcmp (state.rel_pathname, "."))
386
391
    {
387
 
    case COMP_GT:
388
 
      if (stat_buf->st_ctime > (time_t) pred_ptr->args.info.l_val)
389
 
        return (true);
390
 
      break;
391
 
    case COMP_LT:
392
 
      if (stat_buf->st_ctime < (time_t) pred_ptr->args.info.l_val)
393
 
        return (true);
394
 
      break;
395
 
    case COMP_EQ:
396
 
      if ((stat_buf->st_ctime >= (time_t) pred_ptr->args.info.l_val)
397
 
          && (stat_buf->st_ctime < (time_t) pred_ptr->args.info.l_val
398
 
              + DAYSECS))
399
 
        return (true);
400
 
      break;
 
392
      if (0 != remove (state.rel_pathname))
 
393
        {
 
394
          error (0, errno, "cannot delete %s", pathname);
 
395
          return false;
 
396
        }
 
397
      else
 
398
        {
 
399
          return true;
 
400
        }
401
401
    }
402
 
  return (false);
 
402
  
 
403
  /* nothing to do. */
 
404
  return true;
403
405
}
404
406
 
405
407
boolean
406
408
pred_empty (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
407
409
{
 
410
  (void) pathname;
 
411
  (void) pred_ptr;
 
412
  
408
413
  if (S_ISDIR (stat_buf->st_mode))
409
414
    {
410
415
      DIR *d;
412
417
      boolean empty = true;
413
418
 
414
419
      errno = 0;
415
 
      d = opendir (rel_pathname);
 
420
      d = opendir (state.rel_pathname);
416
421
      if (d == NULL)
417
422
        {
418
423
          error (0, errno, "%s", pathname);
419
 
          exit_status = 1;
420
 
          return (false);
 
424
          state.exit_status = 1;
 
425
          return false;
421
426
        }
422
427
      for (dp = readdir (d); dp; dp = readdir (d))
423
428
        {
432
437
      if (CLOSEDIR (d))
433
438
        {
434
439
          error (0, errno, "%s", pathname);
435
 
          exit_status = 1;
436
 
          return (false);
 
440
          state.exit_status = 1;
 
441
          return false;
437
442
        }
438
443
      return (empty);
439
444
    }
443
448
    return (false);
444
449
}
445
450
 
 
451
static boolean
 
452
new_impl_pred_exec (const char *pathname, struct stat *stat_buf,
 
453
                    struct predicate *pred_ptr,
 
454
                    const char *prefix, size_t pfxlen)
 
455
{
 
456
  struct exec_val *execp = &pred_ptr->args.exec_vec;
 
457
  size_t len = strlen(pathname);
 
458
 
 
459
  (void) stat_buf;
 
460
  
 
461
  if (execp->multiple)
 
462
    {
 
463
      /* Push the argument onto the current list. 
 
464
       * The command may or may not be run at this point, 
 
465
       * depending on the command line length limits.
 
466
       */
 
467
      bc_push_arg(&execp->ctl,
 
468
                  &execp->state,
 
469
                  pathname, len+1,
 
470
                  prefix, pfxlen,
 
471
                  0);
 
472
      
 
473
      /* POSIX: If the primary expression is punctuated by a plus
 
474
       * sign, the primary shall always evaluate as true
 
475
       */
 
476
      return true;
 
477
    }
 
478
  else
 
479
    {
 
480
      int i;
 
481
 
 
482
      for (i=0; i<execp->num_args; ++i)
 
483
        {
 
484
          bc_do_insert(&execp->ctl,
 
485
                       &execp->state,
 
486
                       execp->replace_vec[i],
 
487
                       strlen(execp->replace_vec[i]),
 
488
                       prefix, pfxlen,
 
489
                       pathname, len,
 
490
                       0);
 
491
        }
 
492
 
 
493
      /* Actually invoke the command. */
 
494
      return  execp->ctl.exec_callback(&execp->ctl,
 
495
                                        &execp->state);
 
496
    }
 
497
}
 
498
 
 
499
 
446
500
boolean
447
501
pred_exec (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
448
502
{
449
 
  int i;
450
 
  int path_pos;
451
 
  struct exec_val *execp;       /* Pointer for efficiency. */
452
 
 
453
 
  execp = &pred_ptr->args.exec_vec;
454
 
 
455
 
  /* Replace "{}" with the real path in each affected arg. */
456
 
  for (path_pos = 0; execp->paths[path_pos].offset >= 0; path_pos++)
457
 
    {
458
 
      register char *from, *to;
459
 
 
460
 
      i = execp->paths[path_pos].offset;
461
 
      execp->vec[i] =
462
 
        xmalloc (strlen (execp->paths[path_pos].origarg) + 1
463
 
                 + (strlen (pathname) - 2) * execp->paths[path_pos].count);
464
 
      for (from = execp->paths[path_pos].origarg, to = execp->vec[i]; *from; )
465
 
        if (from[0] == '{' && from[1] == '}')
466
 
          {
467
 
            to = stpcpy (to, pathname);
468
 
            from += 2;
469
 
          }
470
 
        else
471
 
          *to++ = *from++;
472
 
      *to = *from;              /* Copy null. */
473
 
    }
474
 
 
475
 
  i = launch (pred_ptr);
476
 
 
477
 
  /* Free the temporary args. */
478
 
  for (path_pos = 0; execp->paths[path_pos].offset >= 0; path_pos++)
479
 
    free (execp->vec[execp->paths[path_pos].offset]);
480
 
 
481
 
  return (i);
 
503
  return new_impl_pred_exec(pathname, stat_buf, pred_ptr, NULL, 0);
 
504
}
 
505
 
 
506
boolean
 
507
pred_execdir (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
 
508
{
 
509
   const char *prefix = (state.rel_pathname[0] == '/') ? NULL : "./";
 
510
   (void) &pathname;
 
511
   return new_impl_pred_exec (state.rel_pathname, stat_buf, pred_ptr,
 
512
                              prefix, (prefix ? 2 : 0));
482
513
}
483
514
 
484
515
boolean
485
516
pred_false (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
486
517
{
 
518
  (void) &pathname;
 
519
  (void) &stat_buf;
 
520
  (void) &pred_ptr;
 
521
 
 
522
  
487
523
  return (false);
488
524
}
489
525
 
490
526
boolean
491
527
pred_fls (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
492
528
{
493
 
  list_file (pathname, rel_pathname, stat_buf, start_time,
494
 
             output_block_size, pred_ptr->args.stream);
 
529
  list_file (pathname, state.rel_pathname, stat_buf, options.start_time,
 
530
             options.output_block_size, pred_ptr->args.stream);
495
531
  return (true);
496
532
}
497
533
 
498
534
boolean
499
535
pred_fprint (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
500
536
{
501
 
  fputs (pathname, pred_ptr->args.stream);
502
 
  putc ('\n', pred_ptr->args.stream);
503
 
  return (true);
 
537
  (void) &pathname;
 
538
  (void) &stat_buf;
 
539
  
 
540
  print_quoted(pred_ptr->args.printf_vec.stream,
 
541
               pred_ptr->args.printf_vec.quote_opts,
 
542
               pred_ptr->args.printf_vec.dest_is_tty,
 
543
               "%s\n",
 
544
               pathname);
 
545
  return true;
504
546
}
505
547
 
506
548
boolean
507
549
pred_fprint0 (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
508
550
{
 
551
  (void) &pathname;
 
552
  (void) &stat_buf;
 
553
  
509
554
  fputs (pathname, pred_ptr->args.stream);
510
555
  putc (0, pred_ptr->args.stream);
511
556
  return (true);
512
557
}
513
558
 
 
559
 
 
560
 
 
561
 
 
562
 
514
563
boolean
515
564
pred_fprintf (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
516
565
{
517
566
  FILE *fp = pred_ptr->args.printf_vec.stream;
 
567
  const struct quoting_options *qopts = pred_ptr->args.printf_vec.quote_opts;
 
568
  boolean ttyflag = pred_ptr->args.printf_vec.dest_is_tty;
518
569
  struct segment *segment;
519
570
  char *cp;
520
571
  char hbuf[LONGEST_HUMAN_READABLE + 1];
540
591
            default:
541
592
              abort ();
542
593
            }
 
594
          /* We trust the output of format_date not to contain 
 
595
           * nasty characters, though the value of the date
 
596
           * is itself untrusted data.
 
597
           */
 
598
          /* trusted */
543
599
          fprintf (fp, segment->text,
544
600
                   format_date (t, (segment->kind >> 8) & 0xff));
545
601
          continue;
548
604
      switch (segment->kind)
549
605
        {
550
606
        case KIND_PLAIN:        /* Plain text string (no % conversion). */
 
607
          /* trusted */
551
608
          fwrite (segment->text, 1, segment->text_len, fp);
552
609
          break;
553
610
        case KIND_STOP:         /* Terminate argument and flush output. */
 
611
          /* trusted */
554
612
          fwrite (segment->text, 1, segment->text_len, fp);
555
613
          fflush (fp);
556
614
          return (true);
557
615
        case 'a':               /* atime in `ctime' format. */
 
616
          /* UNTRUSTED, probably unexploitable */
558
617
          fprintf (fp, segment->text, ctime_format (stat_buf->st_atime));
559
618
          break;
560
619
        case 'b':               /* size in 512-byte blocks */
 
620
          /* UNTRUSTED, probably unexploitable */
561
621
          fprintf (fp, segment->text,
562
622
                   human_readable ((uintmax_t) ST_NBLOCKS (*stat_buf),
563
 
                                   hbuf, ST_NBLOCKSIZE, 512));
 
623
                                   hbuf, human_ceiling,
 
624
                                   ST_NBLOCKSIZE, 512));
564
625
          break;
565
626
        case 'c':               /* ctime in `ctime' format */
 
627
          /* UNTRUSTED, probably unexploitable */
566
628
          fprintf (fp, segment->text, ctime_format (stat_buf->st_ctime));
567
629
          break;
568
630
        case 'd':               /* depth in search tree */
569
 
          fprintf (fp, segment->text, curdepth);
570
 
          break;
571
 
        case 'f':               /* basename of path */
572
 
          fprintf (fp, segment->text, base_name (pathname));
 
631
          /* UNTRUSTED, probably unexploitable */
 
632
          fprintf (fp, segment->text, state.curdepth);
 
633
          break;
 
634
        case 'D':               /* Device on which file exists (stat.st_dev) */
 
635
          /* trusted */
 
636
          fprintf (fp, segment->text, 
 
637
                   human_readable ((uintmax_t) stat_buf->st_dev, hbuf,
 
638
                                   human_ceiling, 1, 1));
 
639
          break;
 
640
        case 'f':               /* base name of path */
 
641
          /* sanitised */
 
642
          print_quoted (fp, qopts, ttyflag, segment->text, base_name (pathname));
573
643
          break;
574
644
        case 'F':               /* filesystem type */
575
 
          fprintf (fp, segment->text,
576
 
                   filesystem_type (pathname, rel_pathname, stat_buf));
 
645
          /* trusted */
 
646
          print_quoted (fp, qopts, ttyflag, segment->text, filesystem_type (stat_buf));
577
647
          break;
578
648
        case 'g':               /* group name */
 
649
          /* trusted */
 
650
          /* (well, the actual group is selected by the user but
 
651
           * its name was selected by the system administrator)
 
652
           */
579
653
          {
580
654
            struct group *g;
581
655
 
589
663
            /* else fallthru */
590
664
          }
591
665
        case 'G':               /* GID number */
 
666
          /* UNTRUSTED, probably unexploitable */
592
667
          fprintf (fp, segment->text,
593
 
                   human_readable ((uintmax_t) stat_buf->st_gid, hbuf, 1, 1));
 
668
                   human_readable ((uintmax_t) stat_buf->st_gid, hbuf,
 
669
                                   human_ceiling, 1, 1));
594
670
          break;
595
671
        case 'h':               /* leading directories part of path */
 
672
          /* sanitised */
596
673
          {
597
674
            char cc;
598
 
 
 
675
            
599
676
            cp = strrchr (pathname, '/');
600
677
            if (cp == NULL)     /* No leading directories. */
601
 
              break;
602
 
            cc = *cp;
603
 
            *cp = '\0';
604
 
            fprintf (fp, segment->text, pathname);
605
 
            *cp = cc;
 
678
              {
 
679
                /* If there is no slash in the pathname, we still
 
680
                 * print the string because it contains characters
 
681
                 * other than just '%s'.  The %h expands to ".".
 
682
                 */
 
683
                print_quoted (fp, qopts, ttyflag, segment->text, ".");
 
684
              }
 
685
            else
 
686
              {
 
687
                cc = *cp;
 
688
                *cp = '\0';
 
689
                print_quoted (fp, qopts, ttyflag, segment->text, pathname);
 
690
                *cp = cc;
 
691
              }
606
692
            break;
607
693
          }
608
694
        case 'H':               /* ARGV element file was found under */
 
695
          /* trusted */
609
696
          {
610
 
            char cc = pathname[path_length];
 
697
            char cc = pathname[state.path_length];
611
698
 
612
 
            pathname[path_length] = '\0';
 
699
            pathname[state.path_length] = '\0';
613
700
            fprintf (fp, segment->text, pathname);
614
 
            pathname[path_length] = cc;
 
701
            pathname[state.path_length] = cc;
615
702
            break;
616
703
          }
617
704
        case 'i':               /* inode number */
 
705
          /* UNTRUSTED, but not exploitable I think */
618
706
          fprintf (fp, segment->text,
619
 
                   human_readable ((uintmax_t) stat_buf->st_ino, hbuf, 1, 1));
 
707
                        human_readable ((uintmax_t) stat_buf->st_ino, hbuf,
 
708
                                        human_ceiling,
 
709
                                        1, 1));
620
710
          break;
621
711
        case 'k':               /* size in 1K blocks */
 
712
          /* UNTRUSTED, but not exploitable I think */
622
713
          fprintf (fp, segment->text,
623
714
                   human_readable ((uintmax_t) ST_NBLOCKS (*stat_buf),
624
 
                                   hbuf, ST_NBLOCKSIZE, 1024));
 
715
                                   hbuf, human_ceiling,
 
716
                                   ST_NBLOCKSIZE, 1024)); 
625
717
          break;
626
718
        case 'l':               /* object of symlink */
 
719
          /* sanitised */
627
720
#ifdef S_ISLNK
628
721
          {
629
722
            char *linkname = 0;
630
723
 
631
724
            if (S_ISLNK (stat_buf->st_mode))
632
725
              {
633
 
                linkname = get_link_name (pathname, rel_pathname);
 
726
                linkname = get_link_name (pathname, state.rel_pathname);
634
727
                if (linkname == 0)
635
 
                  exit_status = 1;
 
728
                  state.exit_status = 1;
636
729
              }
637
730
            if (linkname)
638
731
              {
639
 
                fprintf (fp, segment->text, linkname);
 
732
                print_quoted (fp, qopts, ttyflag, segment->text, linkname);
640
733
                free (linkname);
641
734
              }
642
735
            else
643
 
              fprintf (fp, segment->text, "");
 
736
              print_quoted (fp, qopts, ttyflag, segment->text, "");
644
737
          }
645
738
#endif                          /* S_ISLNK */
646
739
          break;
 
740
          
 
741
        case 'M':               /* mode as 10 chars (eg., "-rwxr-x--x" */
 
742
          /* UNTRUSTED, probably unexploitable */
 
743
          {
 
744
            char modestring[16] ;
 
745
            mode_string (stat_buf->st_mode, modestring);
 
746
            modestring[10] = '\0';
 
747
            fprintf (fp, segment->text, modestring);
 
748
          }
 
749
          break;
 
750
          
647
751
        case 'm':               /* mode as octal number (perms only) */
 
752
          /* UNTRUSTED, probably unexploitable */
648
753
          {
649
754
            /* Output the mode portably using the traditional numbers,
650
755
               even if the host unwisely uses some other numbering
673
778
                         | (m & S_IXOTH ? 00001 : 0))));
674
779
          }
675
780
          break;
 
781
          
676
782
        case 'n':               /* number of links */
 
783
          /* UNTRUSTED, probably unexploitable */
677
784
          fprintf (fp, segment->text,
678
785
                   human_readable ((uintmax_t) stat_buf->st_nlink,
679
 
                                   hbuf, 1, 1));
 
786
                                   hbuf,
 
787
                                   human_ceiling,
 
788
                                   1, 1));
680
789
          break;
681
790
        case 'p':               /* pathname */
682
 
          fprintf (fp, segment->text, pathname);
 
791
          /* sanitised */
 
792
          print_quoted (fp, qopts, ttyflag, segment->text, pathname);
683
793
          break;
684
794
        case 'P':               /* pathname with ARGV element stripped */
685
 
          if (curdepth)
 
795
          /* sanitised */
 
796
          if (state.curdepth > 0)
686
797
            {
687
 
              cp = pathname + path_length;
 
798
              cp = pathname + state.path_length;
688
799
              if (*cp == '/')
689
800
                /* Move past the slash between the ARGV element
690
801
                   and the rest of the pathname.  But if the ARGV element
694
805
            }
695
806
          else
696
807
            cp = "";
697
 
          fprintf (fp, segment->text, cp);
 
808
          print_quoted (fp, qopts, ttyflag, segment->text, cp);
698
809
          break;
699
810
        case 's':               /* size in bytes */
 
811
          /* UNTRUSTED, probably unexploitable */
700
812
          fprintf (fp, segment->text,
701
813
                   human_readable ((uintmax_t) stat_buf->st_size,
702
 
                                   hbuf, 1, 1));
 
814
                                   hbuf, human_ceiling, 1, 1));
703
815
          break;
704
816
        case 't':               /* mtime in `ctime' format */
 
817
          /* UNTRUSTED, probably unexploitable */
705
818
          fprintf (fp, segment->text, ctime_format (stat_buf->st_mtime));
706
819
          break;
707
820
        case 'u':               /* user name */
 
821
          /* trusted */
 
822
          /* (well, the actual user is selected by the user on systems
 
823
           * where chown is not restricted, but the user name was
 
824
           * selected by the system administrator)
 
825
           */
708
826
          {
709
827
            struct passwd *p;
710
828
 
717
835
              }
718
836
            /* else fallthru */
719
837
          }
 
838
          
720
839
        case 'U':               /* UID number */
 
840
          /* UNTRUSTED, probably unexploitable */
721
841
          fprintf (fp, segment->text,
722
 
                   human_readable ((uintmax_t) stat_buf->st_uid, hbuf, 1, 1));
 
842
                   human_readable ((uintmax_t) stat_buf->st_uid, hbuf,
 
843
                                   human_ceiling, 1, 1));
 
844
          break;
 
845
 
 
846
        /* type of filesystem entry like `ls -l`: (d,-,l,s,p,b,c,n) n=nonexistent(symlink) */
 
847
        case 'Y':               /* in case of symlink */
 
848
          /* trusted */
 
849
          {
 
850
#ifdef S_ISLNK
 
851
          if (S_ISLNK (stat_buf->st_mode))
 
852
            {
 
853
              struct stat sbuf;
 
854
              /* If we would normally follow links, do not do so.
 
855
               * If we would normally not follow links, do so.
 
856
               */
 
857
              if ((following_links() ? lstat : stat)
 
858
                  (state.rel_pathname, &sbuf) != 0)
 
859
              {
 
860
                if ( errno == ENOENT ) {
 
861
                  fprintf (fp, segment->text, "N");
 
862
                  break;
 
863
                };
 
864
                if ( errno == ELOOP ) {
 
865
                  fprintf (fp, segment->text, "L");
 
866
                  break;
 
867
                };
 
868
                error (0, errno, "%s", pathname);
 
869
                /* exit_status = 1;
 
870
                return (false); */
 
871
              }
 
872
              stat_buf->st_mode = sbuf.st_mode;
 
873
            }
 
874
#endif /* S_ISLNK */
 
875
          }
 
876
          /* FALLTHROUGH */
 
877
        case 'y':
 
878
          /* trusted */
 
879
          {
 
880
            mode_t m = stat_buf->st_mode & S_IFMT;
 
881
 
 
882
            fprintf (fp, segment->text,
 
883
                ( m == S_IFSOCK ? "s" :
 
884
                  m == S_IFLNK  ? "l" :
 
885
                  m == S_IFREG  ? "f" :
 
886
                  m == S_IFBLK  ? "b" :
 
887
                  m == S_IFDIR  ? "d" :
 
888
                  m == S_IFCHR  ? "c" :
 
889
#ifdef S_IFDOOR
 
890
                  m == S_IFDOOR ? "D" :
 
891
#endif
 
892
                  m == S_IFIFO  ? "p" : "U" ) );
 
893
 
 
894
          }
723
895
          break;
724
896
        }
725
897
    }
729
901
boolean
730
902
pred_fstype (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
731
903
{
732
 
  if (strcmp (filesystem_type (pathname, rel_pathname, stat_buf),
733
 
              pred_ptr->args.str) == 0)
734
 
    return (true);
735
 
  return (false);
 
904
  (void) pathname;
 
905
  
 
906
  if (strcmp (filesystem_type (stat_buf), pred_ptr->args.str) == 0)
 
907
    return true;
 
908
  else
 
909
    return false;
736
910
}
737
911
 
738
912
boolean
739
913
pred_gid (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
740
914
{
 
915
  (void) pathname;
 
916
  
741
917
  switch (pred_ptr->args.info.kind)
742
918
    {
743
919
    case COMP_GT:
759
935
boolean
760
936
pred_group (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
761
937
{
 
938
  (void) pathname;
 
939
  
762
940
  if (pred_ptr->args.gid == stat_buf->st_gid)
763
941
    return (true);
764
942
  else
776
954
{
777
955
  const char *base;
778
956
 
 
957
  (void) stat_buf;
 
958
 
 
959
  /* FNM_PERIOD is not used here because POSIX requires that it not be.
 
960
   * See http://standards.ieee.org/reading/ieee/interp/1003-2-92_int/pasc-1003.2-126.html
 
961
   */
779
962
  base = base_name (pathname);
780
 
  if (fnmatch (pred_ptr->args.str, base, FNM_PERIOD | FNM_CASEFOLD) == 0)
 
963
  if (fnmatch (pred_ptr->args.str, base, FNM_CASEFOLD) == 0)
781
964
    return (true);
782
965
  return (false);
783
966
}
785
968
boolean
786
969
pred_inum (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
787
970
{
 
971
  (void) pathname;
 
972
  
788
973
  switch (pred_ptr->args.info.kind)
789
974
    {
790
975
    case COMP_GT:
806
991
boolean
807
992
pred_ipath (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
808
993
{
 
994
  (void) stat_buf;
 
995
  
809
996
  if (fnmatch (pred_ptr->args.str, pathname, FNM_CASEFOLD) == 0)
810
997
    return (true);
811
998
  return (false);
814
1001
boolean
815
1002
pred_links (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
816
1003
{
 
1004
  (void) pathname;
 
1005
  
817
1006
  switch (pred_ptr->args.info.kind)
818
1007
    {
819
1008
    case COMP_GT:
845
1034
#ifdef S_ISLNK
846
1035
  if (S_ISLNK (stat_buf->st_mode))
847
1036
    {
848
 
      char *linkname = get_link_name (pathname, rel_pathname);
 
1037
      char *linkname = get_link_name (pathname, state.rel_pathname);
849
1038
      if (linkname)
850
1039
        {
851
1040
          if (fnmatch (pred_ptr->args.str, linkname,
861
1050
boolean
862
1051
pred_ls (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
863
1052
{
864
 
  list_file (pathname, rel_pathname, stat_buf, start_time,
865
 
             output_block_size, stdout);
 
1053
  (void) pred_ptr;
 
1054
  
 
1055
  list_file (pathname, state.rel_pathname, stat_buf, options.start_time,
 
1056
             options.output_block_size, stdout);
866
1057
  return (true);
867
1058
}
868
1059
 
869
1060
boolean
870
1061
pred_mmin (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
871
1062
{
872
 
  switch (pred_ptr->args.info.kind)
873
 
    {
874
 
    case COMP_GT:
875
 
      if (stat_buf->st_mtime > (time_t) pred_ptr->args.info.l_val)
876
 
        return (true);
877
 
      break;
878
 
    case COMP_LT:
879
 
      if (stat_buf->st_mtime < (time_t) pred_ptr->args.info.l_val)
880
 
        return (true);
881
 
      break;
882
 
    case COMP_EQ:
883
 
      if ((stat_buf->st_mtime >= (time_t) pred_ptr->args.info.l_val)
884
 
          && (stat_buf->st_mtime < (time_t) pred_ptr->args.info.l_val + 60))
885
 
        return (true);
886
 
      break;
887
 
    }
888
 
  return (false);
 
1063
  (void) &pathname;
 
1064
  return pred_timewindow(stat_buf->st_mtime, pred_ptr, 60);
889
1065
}
890
1066
 
891
1067
boolean
892
1068
pred_mtime (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
893
1069
{
894
 
  switch (pred_ptr->args.info.kind)
895
 
    {
896
 
    case COMP_GT:
897
 
      if (stat_buf->st_mtime > (time_t) pred_ptr->args.info.l_val)
898
 
        return (true);
899
 
      break;
900
 
    case COMP_LT:
901
 
      if (stat_buf->st_mtime < (time_t) pred_ptr->args.info.l_val)
902
 
        return (true);
903
 
      break;
904
 
    case COMP_EQ:
905
 
      if ((stat_buf->st_mtime >= (time_t) pred_ptr->args.info.l_val)
906
 
          && (stat_buf->st_mtime < (time_t) pred_ptr->args.info.l_val
907
 
              + DAYSECS))
908
 
        return (true);
909
 
      break;
910
 
    }
911
 
  return (false);
 
1070
  (void) pathname;
 
1071
  return pred_timewindow(stat_buf->st_mtime, pred_ptr, DAYSECS);
912
1072
}
913
1073
 
914
1074
boolean
916
1076
{
917
1077
  const char *base;
918
1078
 
 
1079
  (void) stat_buf;
919
1080
  base = base_name (pathname);
920
 
  if (fnmatch (pred_ptr->args.str, base, FNM_PERIOD) == 0)
 
1081
 
 
1082
  /* FNM_PERIOD is not used here because POSIX requires that it not be.
 
1083
   * See http://standards.ieee.org/reading/ieee/interp/1003-2-92_int/pasc-1003.2-126.html
 
1084
   */
 
1085
  if (fnmatch (pred_ptr->args.str, base, 0) == 0)
921
1086
    return (true);
922
1087
  return (false);
923
1088
}
926
1091
pred_negate (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
927
1092
{
928
1093
  /* Check whether we need a stat here. */
929
 
  if (pred_ptr->need_stat)
930
 
    {
931
 
      if (!have_stat && (*xstat) (rel_pathname, stat_buf) != 0)
932
 
        {
933
 
          error (0, errno, "%s", pathname);
934
 
          exit_status = 1;
935
 
          return (false);
936
 
        }
937
 
      have_stat = true;
938
 
    }
 
1094
  /* TODO: what about need_type? */
 
1095
  if (get_info(pathname, state.rel_pathname, stat_buf, pred_ptr) != 0)
 
1096
    return false;
939
1097
  return (!(*pred_ptr->pred_right->pred_func) (pathname, stat_buf,
940
1098
                                              pred_ptr->pred_right));
941
1099
}
943
1101
boolean
944
1102
pred_newer (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
945
1103
{
 
1104
  (void) pathname;
 
1105
  
946
1106
  if (stat_buf->st_mtime > pred_ptr->args.time)
947
1107
    return (true);
948
1108
  return (false);
951
1111
boolean
952
1112
pred_nogroup (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
953
1113
{
 
1114
  (void) pathname;
 
1115
  (void) pred_ptr;
 
1116
  
954
1117
#ifdef CACHE_IDS
955
1118
  extern char *gid_unused;
956
1119
 
965
1128
{
966
1129
#ifdef CACHE_IDS
967
1130
  extern char *uid_unused;
968
 
 
 
1131
#endif
 
1132
  
 
1133
  (void) pathname;
 
1134
  (void) pred_ptr;
 
1135
  
 
1136
#ifdef CACHE_IDS
969
1137
  return uid_unused[(unsigned) stat_buf->st_uid];
970
1138
#else
971
1139
  return getpwuid (stat_buf->st_uid) == NULL;
972
1140
#endif
973
1141
}
974
1142
 
975
 
boolean
976
 
pred_ok (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
 
1143
 
 
1144
static boolean
 
1145
is_ok(const char *program, const char *arg)
977
1146
{
978
1147
  fflush (stdout);
979
1148
  /* The draft open standard requires that, in the POSIX locale,
981
1150
     The exact format is not specified.
982
1151
     This standard does not have requirements for locales other than POSIX
983
1152
  */
984
 
  fprintf (stderr, _("< %s ... %s > ? "),
985
 
           pred_ptr->args.exec_vec.vec[0], pathname);
 
1153
  /* XXX: printing UNTRUSTED data here. */
 
1154
  fprintf (stderr, _("< %s ... %s > ? "), program, arg);
986
1155
  fflush (stderr);
987
 
  if (yesno ())
988
 
    return pred_exec (pathname, stat_buf, pred_ptr);
989
 
  else
990
 
    return (false);
 
1156
  return yesno();
 
1157
}
 
1158
 
 
1159
boolean
 
1160
pred_ok (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
 
1161
{
 
1162
  if (is_ok(pred_ptr->args.exec_vec.replace_vec[0], pathname))
 
1163
    return new_impl_pred_exec (pathname, stat_buf, pred_ptr, NULL, 0);
 
1164
  else
 
1165
    return false;
 
1166
}
 
1167
 
 
1168
boolean
 
1169
pred_okdir (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
 
1170
{
 
1171
  const char *prefix = (state.rel_pathname[0] == '/') ? NULL : "./";
 
1172
  if (is_ok(pred_ptr->args.exec_vec.replace_vec[0], pathname))
 
1173
    return new_impl_pred_exec (state.rel_pathname, stat_buf, pred_ptr, 
 
1174
                               prefix, (prefix ? 2 : 0));
 
1175
  else
 
1176
    return false;
991
1177
}
992
1178
 
993
1179
boolean
994
1180
pred_open (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
995
1181
{
996
 
  return (true);
 
1182
  (void) pathname;
 
1183
  (void) stat_buf;
 
1184
  (void) pred_ptr;
 
1185
  return true;
997
1186
}
998
1187
 
999
1188
boolean
1003
1192
      || !(*pred_ptr->pred_left->pred_func) (pathname, stat_buf,
1004
1193
                                             pred_ptr->pred_left))
1005
1194
    {
1006
 
      /* Check whether we need a stat here. */
1007
 
      if (pred_ptr->need_stat)
1008
 
        {
1009
 
          if (!have_stat && (*xstat) (rel_pathname, stat_buf) != 0)
1010
 
            {
1011
 
              error (0, errno, "%s", pathname);
1012
 
              exit_status = 1;
1013
 
              return (false);
1014
 
            }
1015
 
          have_stat = true;
1016
 
        }
 
1195
      if (get_info(pathname, state.rel_pathname, stat_buf, pred_ptr) != 0)
 
1196
        return false;
1017
1197
      return ((*pred_ptr->pred_right->pred_func) (pathname, stat_buf,
1018
1198
                                                  pred_ptr->pred_right));
1019
1199
    }
1020
1200
  else
1021
 
    return (true);
 
1201
    return true;
1022
1202
}
1023
1203
 
1024
1204
boolean
1025
1205
pred_path (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1026
1206
{
 
1207
  (void) stat_buf;
1027
1208
  if (fnmatch (pred_ptr->args.str, pathname, 0) == 0)
1028
1209
    return (true);
1029
1210
  return (false);
1032
1213
boolean
1033
1214
pred_perm (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1034
1215
{
 
1216
  (void) pathname;
1035
1217
  switch (pred_ptr->args.perm.kind)
1036
1218
    {
1037
1219
    case PERM_AT_LEAST:
1055
1237
boolean
1056
1238
pred_print (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1057
1239
{
1058
 
  puts (pathname);
1059
 
  return (true);
 
1240
  (void) stat_buf;
 
1241
  (void) pred_ptr;
 
1242
  /* puts (pathname); */
 
1243
  print_quoted(pred_ptr->args.printf_vec.stream,
 
1244
               pred_ptr->args.printf_vec.quote_opts,
 
1245
               pred_ptr->args.printf_vec.dest_is_tty,
 
1246
               "%s\n", pathname);
 
1247
  return true;
1060
1248
}
1061
1249
 
1062
1250
boolean
1063
1251
pred_print0 (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1064
1252
{
 
1253
  (void) stat_buf;
 
1254
  (void) pred_ptr;
1065
1255
  fputs (pathname, stdout);
1066
1256
  putc (0, stdout);
1067
1257
  return (true);
1070
1260
boolean
1071
1261
pred_prune (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1072
1262
{
1073
 
  stop_at_current_level = true;
1074
 
  return (do_dir_first);        /* This is what SunOS find seems to do. */
 
1263
  (void) pathname;
 
1264
  (void) stat_buf;
 
1265
  (void) pred_ptr;
 
1266
  state.stop_at_current_level = true;
 
1267
  return (options.do_dir_first); /* This is what SunOS find seems to do. */
 
1268
}
 
1269
 
 
1270
boolean
 
1271
pred_quit (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
 
1272
{
 
1273
  (void) pathname;
 
1274
  (void) stat_buf;
 
1275
  (void) pred_ptr;
 
1276
 
 
1277
  /* Run any cleanups.  This includes executing any command lines 
 
1278
   * we have partly built but not executed.
 
1279
   */
 
1280
  cleanup();
 
1281
  
 
1282
  /* Since -exec and friends don't leave child processes running in the 
 
1283
   * background, there is no need to wait for them here.
 
1284
   */
 
1285
  exit(state.exit_status);      /* 0 for success, etc. */
1075
1286
}
1076
1287
 
1077
1288
boolean
1078
1289
pred_regex (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1079
1290
{
1080
1291
  int len = strlen (pathname);
 
1292
(void) stat_buf;
1081
1293
  if (re_match (pred_ptr->args.regex, pathname, len, 0,
1082
1294
                (struct re_registers *) NULL) == len)
1083
1295
    return (true);
1089
1301
{
1090
1302
  uintmax_t f_val;
1091
1303
 
 
1304
  (void) pathname;
1092
1305
  f_val = ((stat_buf->st_size / pred_ptr->args.size.blocksize)
1093
1306
           + (stat_buf->st_size % pred_ptr->args.size.blocksize != 0));
1094
1307
  switch (pred_ptr->args.size.kind)
1110
1323
}
1111
1324
 
1112
1325
boolean
 
1326
pred_samefile (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
 
1327
{
 
1328
  /* Potential optimisation: because of the loop protection, we always
 
1329
   * know the device of the current directory, hence the device number
 
1330
   * of the file we're currently considering.  If -L is not in effect,
 
1331
   * and the device number of the file we're looking for is not the
 
1332
   * same as the device number of the current directory, this
 
1333
   * predicate cannot return true.  Hence there would be no need to
 
1334
   * stat the file we're lookingn at.
 
1335
   */
 
1336
  (void) pathname;
 
1337
  
 
1338
  return stat_buf->st_ino == pred_ptr->args.fileid.ino
 
1339
    &&   stat_buf->st_dev == pred_ptr->args.fileid.dev;
 
1340
}
 
1341
 
 
1342
boolean
1113
1343
pred_true (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1114
1344
{
1115
 
  return (true);
 
1345
  (void) pathname;
 
1346
  (void) stat_buf;
 
1347
  (void) pred_ptr;
 
1348
  return true;
1116
1349
}
1117
1350
 
1118
1351
boolean
1119
1352
pred_type (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1120
1353
{
1121
 
  mode_t mode = stat_buf->st_mode;
 
1354
  mode_t mode;
1122
1355
  mode_t type = pred_ptr->args.type;
1123
1356
 
 
1357
  assert(state.have_type);
 
1358
  assert(state.type != 0);
 
1359
  
 
1360
  (void) pathname;
 
1361
 
 
1362
  if (state.have_stat)
 
1363
     mode = stat_buf->st_mode;
 
1364
  else
 
1365
     mode = state.type;
 
1366
 
1124
1367
#ifndef S_IFMT
1125
1368
  /* POSIX system; check `mode' the slow way. */
1126
1369
  if ((S_ISBLK (mode) && type == S_IFBLK)
1152
1395
boolean
1153
1396
pred_uid (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1154
1397
{
 
1398
  (void) pathname;
1155
1399
  switch (pred_ptr->args.info.kind)
1156
1400
    {
1157
1401
    case COMP_GT:
1175
1419
{
1176
1420
  time_t delta;
1177
1421
 
 
1422
  (void) pathname;
1178
1423
  delta = stat_buf->st_atime - stat_buf->st_ctime; /* Use difftime? */
1179
 
  switch (pred_ptr->args.info.kind)
1180
 
    {
1181
 
    case COMP_GT:
1182
 
      if (delta > (time_t) pred_ptr->args.info.l_val)
1183
 
        return (true);
1184
 
      break;
1185
 
    case COMP_LT:
1186
 
      if (delta < (time_t) pred_ptr->args.info.l_val)
1187
 
        return (true);
1188
 
      break;
1189
 
    case COMP_EQ:
1190
 
      if ((delta >= (time_t) pred_ptr->args.info.l_val)
1191
 
          && (delta < (time_t) pred_ptr->args.info.l_val + DAYSECS))
1192
 
        return (true);
1193
 
      break;
1194
 
    }
1195
 
  return (false);
 
1424
  return pred_timewindow(delta, pred_ptr, DAYSECS);
1196
1425
}
1197
1426
 
1198
1427
boolean
1199
1428
pred_user (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1200
1429
{
 
1430
  (void) pathname;
1201
1431
  if (pred_ptr->args.uid == stat_buf->st_uid)
1202
1432
    return (true);
1203
1433
  else
1207
1437
boolean
1208
1438
pred_xtype (char *pathname, struct stat *stat_buf, struct predicate *pred_ptr)
1209
1439
{
1210
 
  struct stat sbuf;
1211
 
  int (*ystat) ();
 
1440
  struct stat sbuf;             /* local copy, not stat_buf because we're using a different stat method */
 
1441
  int (*ystat) (const char*, struct stat *p);
1212
1442
 
1213
 
  ystat = xstat == lstat ? stat : lstat;
1214
 
  if ((*ystat) (rel_pathname, &sbuf) != 0)
 
1443
  /* If we would normally stat the link itself, stat the target instead.
 
1444
   * If we would normally follow the link, stat the link itself instead. 
 
1445
   */
 
1446
  if (following_links())
 
1447
    ystat = optionp_stat;
 
1448
  else
 
1449
    ystat = optionl_stat;
 
1450
  
 
1451
  if ((*ystat) (state.rel_pathname, &sbuf) != 0)
1215
1452
    {
1216
 
      if (ystat == stat && errno == ENOENT)
1217
 
        /* Mimic behavior of ls -lL. */
1218
 
        return (pred_type (pathname, stat_buf, pred_ptr));
1219
 
      error (0, errno, "%s", pathname);
1220
 
      exit_status = 1;
1221
 
      return (false);
 
1453
      if (following_links() && errno == ENOENT)
 
1454
        {
 
1455
          /* If we failed to follow the symlink,
 
1456
           * fall back on looking at the symlink itself. 
 
1457
           */
 
1458
          /* Mimic behavior of ls -lL. */
 
1459
          return (pred_type (pathname, stat_buf, pred_ptr));
 
1460
        }
 
1461
      else
 
1462
        {
 
1463
          error (0, errno, "%s", pathname);
 
1464
          state.exit_status = 1;
 
1465
        }
 
1466
      return false;
1222
1467
    }
 
1468
  /* Now that we have our stat() information, query it in the same 
 
1469
   * way that -type does.
 
1470
   */
1223
1471
  return (pred_type (pathname, &sbuf, pred_ptr));
1224
1472
}
1225
1473
 
1241
1489
    zero, and the exit arg (status high) is 0.
1242
1490
    Otherwise return false, possibly printing an error message. */
1243
1491
 
1244
 
static boolean
1245
 
launch (struct predicate *pred_ptr)
1246
 
{
1247
 
  int status;
 
1492
 
 
1493
static void
 
1494
prep_child_for_exec (void)
 
1495
{
 
1496
  const char inputfile[] = "/dev/null";
 
1497
  /* fprintf(stderr, "attaching stdin to /dev/null\n"); */
 
1498
  
 
1499
  close(0);
 
1500
  if (open(inputfile, O_RDONLY) < 0)
 
1501
    {
 
1502
      /* This is not entirely fatal, since 
 
1503
       * executing the child with a closed
 
1504
       * stdin is almost as good as executing it
 
1505
       * with its stdin attached to /dev/null.
 
1506
       */
 
1507
      error (0, errno, "%s", inputfile);
 
1508
    }
 
1509
}
 
1510
 
 
1511
 
 
1512
 
 
1513
int
 
1514
launch (const struct buildcmd_control *ctl,
 
1515
        struct buildcmd_state *buildstate)
 
1516
{
 
1517
  int wait_status;
1248
1518
  pid_t child_pid;
1249
 
  struct exec_val *execp;       /* Pointer for efficiency. */
1250
1519
  static int first_time = 1;
1251
 
 
1252
 
  execp = &pred_ptr->args.exec_vec;
1253
 
 
 
1520
  const struct exec_val *execp = buildstate->usercontext;
 
1521
  
 
1522
  /* Null terminate the arg list.  */
 
1523
  bc_push_arg (ctl, buildstate, (char *) NULL, 0, NULL, 0, false); 
 
1524
  
1254
1525
  /* Make sure output of command doesn't get mixed with find output. */
1255
1526
  fflush (stdout);
1256
1527
  fflush (stderr);
1257
 
 
 
1528
  
1258
1529
  /* Make sure to listen for the kids.  */
1259
1530
  if (first_time)
1260
1531
    {
1268
1539
  if (child_pid == 0)
1269
1540
    {
1270
1541
      /* We be the child. */
1271
 
      if (starting_desc < 0
1272
 
          ? chdir (starting_dir) != 0
1273
 
          : fchdir (starting_desc) != 0)
 
1542
      prep_child_for_exec();
 
1543
 
 
1544
      /* For -exec and -ok, change directory back to the starting directory.
 
1545
       * for -execdir and -okdir, stay in the directory we are searching
 
1546
       * (the latter is more secure).
 
1547
       */
 
1548
      if (!execp->use_current_dir)
1274
1549
        {
1275
 
          error (0, errno, "%s", starting_dir);
1276
 
          _exit (1);
 
1550
          /* Even if DEBUG_STAT is set, don't announce our change of 
 
1551
           * directory, since we're not going to emit a subsequent 
 
1552
           * announcement of a call to stat() anyway, as we're about 
 
1553
           * to exec something. 
 
1554
           */
 
1555
          if (starting_desc < 0
 
1556
              ? chdir (starting_dir) != 0
 
1557
              : fchdir (starting_desc) != 0)
 
1558
            {
 
1559
              error (0, errno, "%s", starting_dir);
 
1560
              _exit (1);
 
1561
            }
1277
1562
        }
1278
 
      execvp (execp->vec[0], execp->vec);
1279
 
      error (0, errno, "%s", execp->vec[0]);
 
1563
      
 
1564
      execvp (buildstate->cmd_argv[0], buildstate->cmd_argv);
 
1565
      error (0, errno, "%s", buildstate->cmd_argv[0]);
1280
1566
      _exit (1);
1281
1567
    }
1282
1568
 
1283
 
  
1284
 
  while (waitpid (child_pid, &status, 0) == (pid_t) -1)
1285
 
    if (errno != EINTR)
1286
 
      {
1287
 
        error (0, errno, _("error waiting for %s"), execp->vec[0]);
1288
 
        exit_status = 1;
1289
 
        return false;
1290
 
      }
1291
 
  if (WIFSIGNALED (status))
 
1569
 
 
1570
  /* In parent; set up for next time. */
 
1571
  bc_clear_args(ctl, buildstate);
 
1572
 
 
1573
  
 
1574
  while (waitpid (child_pid, &wait_status, 0) == (pid_t) -1)
 
1575
    {
 
1576
      if (errno != EINTR)
 
1577
        {
 
1578
          error (0, errno, _("error waiting for %s"), buildstate->cmd_argv[0]);
 
1579
          state.exit_status = 1;
 
1580
          return 0;             /* FAIL */
 
1581
        }
 
1582
    }
 
1583
  
 
1584
  if (WIFSIGNALED (wait_status))
1292
1585
    {
1293
1586
      error (0, 0, _("%s terminated by signal %d"),
1294
 
             execp->vec[0], WTERMSIG (status));
1295
 
      exit_status = 1;
1296
 
      return (false);
1297
 
    }
1298
 
  return (!WEXITSTATUS (status));
 
1587
             buildstate->cmd_argv[0], WTERMSIG (wait_status));
 
1588
      
 
1589
      if (execp->multiple)
 
1590
        {
 
1591
          /* -exec   \; just returns false if the invoked command fails. 
 
1592
           * -exec {} + returns true if the invoked command fails, but
 
1593
           *            sets the program exit status.
 
1594
           */
 
1595
          state.exit_status = 1;
 
1596
        }
 
1597
      
 
1598
      return 1;                 /* OK */
 
1599
    }
 
1600
 
 
1601
  if (0 == WEXITSTATUS (wait_status))
 
1602
    {
 
1603
      return 1;                 /* OK */
 
1604
    }
 
1605
  else
 
1606
    {
 
1607
      if (execp->multiple)
 
1608
        {
 
1609
          /* -exec   \; just returns false if the invoked command fails. 
 
1610
           * -exec {} + returns true if the invoked command fails, but
 
1611
           *            sets the program exit status.
 
1612
           */
 
1613
          state.exit_status = 1;
 
1614
        }
 
1615
      return 0;                 /* FAIL */
 
1616
    }
 
1617
  
1299
1618
}
1300
1619
 
 
1620
 
1301
1621
/* Return a static string formatting the time WHEN according to the
1302
1622
   strftime format character KIND.  */
1303
1623
 
1306
1626
{
1307
1627
  static char buf[MAX (LONGEST_HUMAN_READABLE + 2, 64)];
1308
1628
  struct tm *tm;
1309
 
  char fmt[3];
 
1629
  char fmt[6];
1310
1630
 
1311
1631
  fmt[0] = '%';
1312
1632
  fmt[1] = kind;
1313
1633
  fmt[2] = '\0';
 
1634
  if (kind == '+')
 
1635
    strcpy (fmt, "%F+%T");
1314
1636
 
1315
1637
  if (kind != '@'
1316
1638
      && (tm = localtime (&when))
1319
1641
  else
1320
1642
    {
1321
1643
      uintmax_t w = when;
1322
 
      char *p = human_readable (when < 0 ? -w : w, buf + 1, 1, 1);
 
1644
      char *p = human_readable (when < 0 ? -w : w, buf + 1,
 
1645
                                human_ceiling, 1, 1);
1323
1646
      if (when < 0)
1324
1647
        *--p = '-';
1325
1648
      return p;
1327
1650
}
1328
1651
 
1329
1652
static char *
1330
 
ctime_format (when)
1331
 
     time_t when;
 
1653
ctime_format (time_t when)
1332
1654
{
1333
1655
  char *r = ctime (&when);
1334
1656
  if (!r)
1390
1712
   INDENT is the number of levels to indent the left margin. */
1391
1713
 
1392
1714
void
1393
 
print_tree (node, indent)
1394
 
     struct predicate *node;
1395
 
     int indent;
 
1715
print_tree (FILE *fp, struct predicate *node, int indent)
1396
1716
{
1397
1717
  int i;
1398
1718
 
1399
1719
  if (node == NULL)
1400
1720
    return;
1401
1721
  for (i = 0; i < indent; i++)
1402
 
    printf ("    ");
1403
 
  printf ("pred = %s type = %s prec = %s addr = %x\n",
 
1722
    fprintf (fp, "    ");
 
1723
  fprintf (fp, "pred = %s type = %s prec = %s addr = %p\n",
1404
1724
          find_pred_name (node->pred_func),
1405
1725
          type_name (node->p_type), prec_name (node->p_prec), node);
1406
 
  for (i = 0; i < indent; i++)
1407
 
    printf ("    ");
1408
 
  printf (_("left:\n"));
1409
 
  print_tree (node->pred_left, indent + 1);
1410
 
  for (i = 0; i < indent; i++)
1411
 
    printf ("    ");
1412
 
  printf (_("right:\n"));
1413
 
  print_tree (node->pred_right, indent + 1);
 
1726
  if (node->need_stat || node->need_type)
 
1727
    {
 
1728
      int comma = 0;
 
1729
      
 
1730
      for (i = 0; i < indent; i++)
 
1731
        fprintf (fp, "    ");
 
1732
      
 
1733
      fprintf (fp, "Needs ");
 
1734
      if (node->need_stat)
 
1735
        {
 
1736
          fprintf (fp, "stat");
 
1737
          comma = 1;
 
1738
        }
 
1739
      if (node->need_type)
 
1740
        {
 
1741
          fprintf (fp, "%stype", comma ? "," : "");
 
1742
        }
 
1743
      fprintf (fp, "\n");
 
1744
    }
 
1745
  
 
1746
  for (i = 0; i < indent; i++)
 
1747
    fprintf (fp, "    ");
 
1748
  fprintf (fp, "left:\n");
 
1749
  print_tree (fp, node->pred_left, indent + 1);
 
1750
  for (i = 0; i < indent; i++)
 
1751
    fprintf (fp, "    ");
 
1752
  fprintf (fp, "right:\n");
 
1753
  print_tree (fp, node->pred_right, indent + 1);
1414
1754
}
1415
1755
 
1416
1756
/* Copy STR into BUF and trim blanks from the end of BUF.
1436
1776
/* Print out the predicate list starting at NODE. */
1437
1777
 
1438
1778
void
1439
 
print_list (node)
1440
 
     struct predicate *node;
 
1779
print_list (FILE *fp, struct predicate *node)
1441
1780
{
1442
1781
  struct predicate *cur;
1443
1782
  char name[256];
1445
1784
  cur = node;
1446
1785
  while (cur != NULL)
1447
1786
    {
1448
 
      printf ("%s ", blank_rtrim (find_pred_name (cur->pred_func), name));
 
1787
      fprintf (fp, "%s ", blank_rtrim (find_pred_name (cur->pred_func), name));
1449
1788
      cur = cur->pred_next;
1450
1789
    }
1451
 
  printf ("\n");
1452
 
}
 
1790
  fprintf (fp, "\n");
 
1791
}
 
1792
 
 
1793
 
 
1794
/* Print out the predicate list starting at NODE. */
 
1795
 
 
1796
 
 
1797
static void
 
1798
print_parenthesised(FILE *fp, struct predicate *node)
 
1799
{
 
1800
  int parens = 0;
 
1801
 
 
1802
  if (node)
 
1803
    {
 
1804
      if ( ( (node->pred_func == pred_or)
 
1805
             || (node->pred_func == pred_and) )
 
1806
          && node->pred_left == NULL)
 
1807
        {
 
1808
          /* We print "<nothing> or  X" as just "X"
 
1809
           * We print "<nothing> and X" as just "X"
 
1810
           */
 
1811
          print_parenthesised(fp, node->pred_right);
 
1812
        }
 
1813
      else
 
1814
        {
 
1815
          if (node->pred_left || node->pred_right)
 
1816
            parens = 1;
 
1817
 
 
1818
          if (parens)
 
1819
            fprintf(fp, "%s", " ( ");
 
1820
          print_optlist(fp, node);
 
1821
          if (parens)
 
1822
            fprintf(fp, "%s", " ) ");
 
1823
        }
 
1824
    }
 
1825
}
 
1826
 
 
1827
void
 
1828
print_optlist (FILE *fp, struct predicate *p)
 
1829
{
 
1830
  char name[256];
 
1831
 
 
1832
  if (p)
 
1833
    {
 
1834
      print_parenthesised(fp, p->pred_left);
 
1835
      fprintf (fp,
 
1836
               "%s%s%s ",
 
1837
               p->need_stat ? "[stat called here] " : "",
 
1838
               p->need_type ? "[type needed here] " : "",
 
1839
               blank_rtrim (find_pred_name (p->pred_func), name));
 
1840
      print_parenthesised(fp, p->pred_right);
 
1841
    }
 
1842
}
 
1843
 
1453
1844
#endif  /* DEBUG */