| 42 |
#else |
#else |
| 43 |
#include <sys/file.h> |
#include <sys/file.h> |
| 44 |
#endif |
#endif |
| 45 |
|
#include <openat.h> |
| 46 |
|
|
| 47 |
#include "../gnulib/lib/xalloc.h" |
#include "../gnulib/lib/xalloc.h" |
| 48 |
#include "../gnulib/lib/human.h" |
#include "../gnulib/lib/human.h" |
| 49 |
#include "../gnulib/lib/canonicalize.h" |
#include "../gnulib/lib/canonicalize.h" |
|
#include "closeout.h" |
|
| 50 |
#include <modetype.h> |
#include <modetype.h> |
| 51 |
|
|
| 52 |
|
#include "closeout.h" |
| 53 |
#include "savedirinfo.h" |
#include "savedirinfo.h" |
| 54 |
#include "buildcmd.h" |
#include "buildcmd.h" |
| 55 |
#include "dirname.h" |
#include "dirname.h" |
| 119 |
NON_FATAL_IF_SANITY_CHECK_FAILS |
NON_FATAL_IF_SANITY_CHECK_FAILS |
| 120 |
}; |
}; |
| 121 |
|
|
| 122 |
|
|
| 123 |
|
int get_current_dirfd(void) |
| 124 |
|
{ |
| 125 |
|
return AT_FDCWD; |
| 126 |
|
} |
| 127 |
|
|
| 128 |
|
|
| 129 |
int |
int |
| 130 |
main (int argc, char **argv) |
main (int argc, char **argv) |
| 159 |
fprintf (stderr, "cur_day_start = %s", ctime (&options.cur_day_start)); |
fprintf (stderr, "cur_day_start = %s", ctime (&options.cur_day_start)); |
| 160 |
#endif /* DEBUG */ |
#endif /* DEBUG */ |
| 161 |
|
|
| 162 |
|
/* state.cwd_dir_fd has to be initialised before we call build_expression_tree() |
| 163 |
|
* because command-line parsing may lead us to stat some files. |
| 164 |
|
*/ |
| 165 |
|
state.cwd_dir_fd = AT_FDCWD; |
| 166 |
|
|
| 167 |
/* We are now processing the part of the "find" command line |
/* We are now processing the part of the "find" command line |
| 168 |
* after the -H/-L options (if any). |
* after the -H/-L options (if any). |
| 169 |
*/ |
*/ |
| 188 |
} |
} |
| 189 |
|
|
| 190 |
|
|
| 191 |
starting_desc = open (".", O_RDONLY); |
starting_desc = open (".", O_RDONLY|O_LARGEFILE); |
| 192 |
if (0 <= starting_desc && fchdir (starting_desc) != 0) |
if (0 <= starting_desc && fchdir (starting_desc) != 0) |
| 193 |
{ |
{ |
| 194 |
close (starting_desc); |
close (starting_desc); |
| 195 |
starting_desc = -1; |
starting_desc = -1; |
| 196 |
} |
} |
| 197 |
|
assert(starting_desc >= 0); |
| 198 |
|
|
| 199 |
if (starting_desc < 0) |
if (starting_desc < 0) |
| 200 |
{ |
{ |
| 201 |
starting_dir = xgetcwd (); |
starting_dir = xgetcwd (); |
| 204 |
} |
} |
| 205 |
set_stat_placeholders(&starting_stat_buf); |
set_stat_placeholders(&starting_stat_buf); |
| 206 |
if ((*options.xstat) (".", &starting_stat_buf) != 0) |
if ((*options.xstat) (".", &starting_stat_buf) != 0) |
| 207 |
error (1, errno, _("cannot get current directory")); |
error (1, errno, _("cannot stat current directory")); |
| 208 |
|
|
| 209 |
/* If no paths are given, default to ".". */ |
/* If no paths are given, default to ".". */ |
| 210 |
for (i = end_of_leading_options; i < argc && !looks_like_expression(argv[i], true); i++) |
for (i = end_of_leading_options; i < argc && !looks_like_expression(argv[i], true); i++) |
| 233 |
return state.exit_status; |
return state.exit_status; |
| 234 |
} |
} |
| 235 |
|
|
| 236 |
boolean is_fts_enabled() |
boolean is_fts_enabled(int *ftsoptions) |
| 237 |
{ |
{ |
| 238 |
/* this version of find (i.e. this main()) does not use fts. */ |
/* this version of find (i.e. this main()) does not use fts. */ |
| 239 |
|
*ftsoptions = 0; |
| 240 |
return false; |
return false; |
| 241 |
} |
} |
| 242 |
|
|
| 549 |
SafeChdirFailStat, |
SafeChdirFailStat, |
| 550 |
SafeChdirFailWouldBeUnableToReturn, |
SafeChdirFailWouldBeUnableToReturn, |
| 551 |
SafeChdirFailChdirFailed, |
SafeChdirFailChdirFailed, |
| 552 |
SafeChdirFailNonexistent |
SafeChdirFailNonexistent, |
| 553 |
|
SafeChdirFailDestUnreadable |
| 554 |
}; |
}; |
| 555 |
|
|
| 556 |
/* Safely perform a change in directory. We do this by calling |
/* Safely perform a change in directory. We do this by calling |
| 577 |
|
|
| 578 |
saved_errno = errno = 0; |
saved_errno = errno = 0; |
| 579 |
|
|
| 580 |
dotfd = open(".", O_RDONLY); |
dotfd = open(".", O_RDONLY|O_LARGEFILE); |
| 581 |
|
|
| 582 |
/* We jump back to here if wd_sanity_check() |
/* We jump back to here if wd_sanity_check() |
| 583 |
* recoverably triggers an alert. |
* recoverably triggers an alert. |
| 697 |
goto fail; |
goto fail; |
| 698 |
} |
} |
| 699 |
} |
} |
| 700 |
|
|
| 701 |
close(dotfd); |
close(dotfd); |
| 702 |
return SafeChdirOK; |
return SafeChdirOK; |
| 703 |
} |
} |
| 811 |
} |
} |
| 812 |
|
|
| 813 |
errno = 0; |
errno = 0; |
| 814 |
fd = open(dest, O_RDONLY|extraflags); |
fd = open(dest, O_RDONLY|O_LARGEFILE|extraflags); |
| 815 |
if (fd < 0) |
if (fd < 0) |
| 816 |
{ |
{ |
| 817 |
switch (errno) |
switch (errno) |
| 821 |
case ENOENT: |
case ENOENT: |
| 822 |
return SafeChdirFailNonexistent; |
return SafeChdirFailNonexistent; |
| 823 |
default: |
default: |
| 824 |
return SafeChdirFailChdirFailed; |
return SafeChdirFailDestUnreadable; |
| 825 |
} |
} |
| 826 |
} |
} |
| 827 |
|
|
| 860 |
enum ChdirSymlinkHandling symlink_follow_option, |
enum ChdirSymlinkHandling symlink_follow_option, |
| 861 |
boolean *did_stat) |
boolean *did_stat) |
| 862 |
{ |
{ |
| 863 |
|
enum SafeChdirStatus result; |
| 864 |
|
|
| 865 |
/* We're about to leave a directory. If there are any -execdir |
/* We're about to leave a directory. If there are any -execdir |
| 866 |
* argument lists which have been built but have not yet been |
* argument lists which have been built but have not yet been |
| 867 |
* processed, do them now because they must be done in the same |
* processed, do them now because they must be done in the same |
| 868 |
* directory. |
* directory. |
| 869 |
*/ |
*/ |
| 870 |
complete_pending_execdirs(get_eval_tree()); |
complete_pending_execdirs(get_current_dirfd()); |
| 871 |
|
|
| 872 |
#if defined(O_NOFOLLOW) |
#if !defined(O_NOFOLLOW) |
| 873 |
if (options.open_nofollow_available) |
options.open_nofollow_available = false; |
|
return safely_chdir_nofollow(dest, direction, statbuf_dest, symlink_follow_option, did_stat); |
|
| 874 |
#endif |
#endif |
| 875 |
return safely_chdir_lstat(dest, direction, statbuf_dest, symlink_follow_option, did_stat); |
if (options.open_nofollow_available) |
| 876 |
|
result = safely_chdir_nofollow(dest, direction, statbuf_dest, symlink_follow_option, did_stat); |
| 877 |
|
else |
| 878 |
|
result = safely_chdir_lstat(dest, direction, statbuf_dest, symlink_follow_option, did_stat); |
| 879 |
|
return result; |
| 880 |
} |
} |
| 881 |
|
|
| 882 |
|
|
| 920 |
fprintf(stderr, "chdir_back(): chdir(<starting-point>)\n"); |
fprintf(stderr, "chdir_back(): chdir(<starting-point>)\n"); |
| 921 |
|
|
| 922 |
if (fchdir (starting_desc) != 0) |
if (fchdir (starting_desc) != 0) |
| 923 |
error (1, errno, "%s", starting_dir); |
{ |
| 924 |
|
error (1, errno, "%s", starting_dir); |
| 925 |
|
} |
| 926 |
} |
} |
| 927 |
} |
} |
| 928 |
|
|
| 1011 |
(void) pstat; |
(void) pstat; |
| 1012 |
|
|
| 1013 |
process_path (pathname, base, false, ".", mode); |
process_path (pathname, base, false, ".", mode); |
| 1014 |
complete_pending_execdirs(get_eval_tree()); |
complete_pending_execdirs(get_current_dirfd()); |
| 1015 |
} |
} |
| 1016 |
|
|
| 1017 |
static void do_process_predicate(char *pathname, |
static void do_process_predicate(char *pathname, |
| 1021 |
{ |
{ |
| 1022 |
(void) mode; |
(void) mode; |
| 1023 |
|
|
| 1024 |
state.rel_pathname = base; |
state.rel_pathname = base; /* cwd_dir_fd was already set by safely_chdir */ |
| 1025 |
apply_predicate (pathname, pstat, get_eval_tree()); |
apply_predicate (pathname, pstat, get_eval_tree()); |
| 1026 |
} |
} |
| 1027 |
|
|
| 1152 |
/* Now we really need to stat the directory, even if we know the |
/* Now we really need to stat the directory, even if we know the |
| 1153 |
* type, because we need information like struct stat.st_rdev. |
* type, because we need information like struct stat.st_rdev. |
| 1154 |
*/ |
*/ |
| 1155 |
if (get_statinfo(pathname, name, &stat_buf) != 0) |
if (0 == stat_buf.st_mode) |
| 1156 |
return 0; |
{ |
| 1157 |
|
/* This call was made conditional on Sat Apr 14 16:01:01 2007, |
| 1158 |
|
* and at that time the test suite passed without it. Omitting |
| 1159 |
|
* this stat call saves a lot of system calls. |
| 1160 |
|
*/ |
| 1161 |
|
if (get_statinfo(pathname, name, &stat_buf) != 0) |
| 1162 |
|
return 0; |
| 1163 |
|
|
| 1164 |
state.have_stat = true; |
state.have_stat = true; |
| 1165 |
|
} |
| 1166 |
mode = state.type = stat_buf.st_mode; /* use full info now that we have it. */ |
mode = state.type = stat_buf.st_mode; /* use full info now that we have it. */ |
| 1167 |
state.stop_at_current_level = |
state.stop_at_current_level = |
| 1168 |
options.maxdepth >= 0 |
options.maxdepth >= 0 |
| 1293 |
* yet been processed, do them now because they must be done in |
* yet been processed, do them now because they must be done in |
| 1294 |
* the same directory. |
* the same directory. |
| 1295 |
*/ |
*/ |
| 1296 |
complete_pending_execdirs(get_eval_tree()); |
complete_pending_execdirs(get_current_dirfd()); |
| 1297 |
|
|
| 1298 |
if (strcmp (name, ".")) |
if (strcmp (name, ".")) |
| 1299 |
{ |
{ |
| 1332 |
break; |
break; |
| 1333 |
|
|
| 1334 |
case SafeChdirFailNonexistent: |
case SafeChdirFailNonexistent: |
| 1335 |
|
case SafeChdirFailDestUnreadable: |
| 1336 |
case SafeChdirFailStat: |
case SafeChdirFailStat: |
| 1337 |
case SafeChdirFailNotDir: |
case SafeChdirFailNotDir: |
| 1338 |
case SafeChdirFailChdirFailed: |
case SafeChdirFailChdirFailed: |
| 1423 |
* yet been processed, do them now because they must be done in |
* yet been processed, do them now because they must be done in |
| 1424 |
* the same directory. |
* the same directory. |
| 1425 |
*/ |
*/ |
| 1426 |
complete_pending_execdirs(get_eval_tree()); |
complete_pending_execdirs(get_current_dirfd()); |
| 1427 |
|
|
| 1428 |
if (strcmp (name, ".")) |
if (strcmp (name, ".")) |
| 1429 |
{ |
{ |
| 1455 |
return; |
return; |
| 1456 |
|
|
| 1457 |
case SafeChdirFailNonexistent: |
case SafeChdirFailNonexistent: |
| 1458 |
|
case SafeChdirFailDestUnreadable: |
| 1459 |
case SafeChdirFailStat: |
case SafeChdirFailStat: |
| 1460 |
case SafeChdirFailSymlink: |
case SafeChdirFailSymlink: |
| 1461 |
case SafeChdirFailNotDir: |
case SafeChdirFailNotDir: |