usr/src/lib/libc/port/gen/nftw.c
author Jon Tibble <meths@btinternet.com>
Thu, 09 Dec 2010 22:32:39 +0100
changeset 13255 4afa820d78b9
parent 6812 febeba71273d
permissions -rw-r--r--
298 SPARC build fails in smt_pause.o 478 Build needs fixing for pkgdepend flag day Reviewed by: [email protected] Reviewed by: [email protected] Reviewed by: [email protected] Approved by: [email protected]
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     1
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     2
 * CDDL HEADER START
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     3
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     4
 * The contents of this file are subject to the terms of the
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
     5
 * Common Development and Distribution License (the "License").
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
     6
 * You may not use this file except in compliance with the License.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     7
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     8
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     9
 * or http://www.opensolaris.org/os/licensing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    10
 * See the License for the specific language governing permissions
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    11
 * and limitations under the License.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    12
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    13
 * When distributing Covered Code, include this CDDL HEADER in each
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    14
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    15
 * If applicable, add the following below this CDDL HEADER, with the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    16
 * fields enclosed by brackets "[]" replaced with your own identifying
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    17
 * information: Portions Copyright [yyyy] [name of copyright owner]
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    18
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    19
 * CDDL HEADER END
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    20
 */
1219
f89f56c2d9ac 6362982 namespace pollution/protection in libc
raf
parents: 0
diff changeset
    21
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    22
/*
6812
febeba71273d PSARC 2008/309 expunge synonyms.h
raf
parents: 5302
diff changeset
    23
 * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    24
 * Use is subject to license terms.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    25
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    26
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    27
/*	Copyright (c) 1988 AT&T	*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    28
/*	  All Rights Reserved  	*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    29
6812
febeba71273d PSARC 2008/309 expunge synonyms.h
raf
parents: 5302
diff changeset
    30
#pragma ident	"%Z%%M%	%I%	%E% SMI"
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    31
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    32
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    33
 *	nftw - new file tree walk
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    34
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    35
 *	int nftw(char *path, int (*fn)(), int depth, int flags);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    36
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    37
 *	Derived from System V ftw() by David Korn
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    38
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    39
 *	nftw visits each file and directory in the tree starting at
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    40
 *	path. It uses the generic directory reading library so it works
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    41
 *	for any file system type.  The flags field is used to specify:
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
    42
 *		FTW_PHYS  Physical walk, does not follow symbolic links
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    43
 *			  Otherwise, nftw will follow links but will not
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    44
 *			  walk down any path the crosses itself.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    45
 *		FTW_MOUNT The walk will not cross a mount point.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    46
 *		FTW_DEPTH All subdirectories will be visited before the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    47
 *			  directory itself.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    48
 *		FTW_CHDIR The walk will change to each directory before
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    49
 *			  reading it.  This is faster but core dumps
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    50
 *			  may not get generated.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    51
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    52
 *	The following flags are private, and are used by the find
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    53
 *	utility:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    54
 *		FTW_ANYERR Call the callback function and return
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    55
 *			   FTW_NS on any stat failure, not just
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    56
 *			   lack of permission.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    57
 *		FTW_HOPTION Use stat the first time the walk
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    58
 *			    function is called, regardless of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    59
 *			    whether or not FTW_PHYS is specified.
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
    60
 *		FTW_NOLOOP Allow find utility to detect infinite loops created
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
    61
 *			   by both symbolic and hard linked directories.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    62
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    63
 *	fn is called with four arguments at each file and directory.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    64
 *	The first argument is the pathname of the object, the second
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    65
 *	is a pointer to the stat buffer and the third is an integer
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    66
 *	giving additional information as follows:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    67
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    68
 *		FTW_F	The object is a file.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    69
 *		FTW_D	The object is a directory.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    70
 *		FTW_DP	The object is a directory and subdirectories
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    71
 *			have been visited.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    72
 *		FTW_SL	The object is a symbolic link.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    73
 *		FTW_SLN The object is a symbolic link pointing at a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    74
 *		        non-existing file.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    75
 *		FTW_DNR	The object is a directory that cannot be read.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    76
 *			fn will not be called for any of its descendants.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    77
 *		FTW_NS	Stat failed on the object because of lack of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    78
 *			appropriate permission. The stat buffer passed to fn
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    79
 *			is undefined.  Stat failure for any reason is
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    80
 *			considered an error and nftw will return -1.
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
    81
 *	The following value is private, and is used by the find utility:
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
    82
 *		FTW_DL	An infinite loop has been detected.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    83
 *	The fourth argument is a struct FTW* which contains the depth
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    84
 *	and the offset into pathname to the base name.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    85
 *	If fn returns nonzero, nftw returns this value to its caller.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    86
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    87
 *	depth limits the number of open directories that ftw uses
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    88
 *	before it starts recycling file descriptors.  In general,
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
    89
 *	a file descriptor is used for each level.  When FTW_CHDIR isn't set,
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
    90
 *	in order to descend to arbitrary depths, nftw requires 2 file
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
    91
 *	descriptors to be open during the call to openat(), therefore if
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
    92
 *	the depth argument is less than 2 nftw will not use openat(), and
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
    93
 *	it will fail with ENAMETOOLONG if it descends to a directory that
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
    94
 *	exceeds PATH_MAX.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    95
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    96
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    97
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    98
#include "lint.h"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    99
#include <mtlib.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   100
#include <sys/types.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   101
#include <sys/stat.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   102
#include <dirent.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   103
#include <errno.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   104
#include <limits.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   105
#include <ftw.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   106
#include <stdlib.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   107
#include <string.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   108
#include <unistd.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   109
#include <thread.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   110
#include <synch.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   111
#include <stdio.h>
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   112
#include <strings.h>
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   113
#include <fcntl.h>
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   114
6812
febeba71273d PSARC 2008/309 expunge synonyms.h
raf
parents: 5302
diff changeset
   115
#if !defined(_LP64) && _FILE_OFFSET_BITS == 64
febeba71273d PSARC 2008/309 expunge synonyms.h
raf
parents: 5302
diff changeset
   116
#define	nftw	nftw64
febeba71273d PSARC 2008/309 expunge synonyms.h
raf
parents: 5302
diff changeset
   117
#define	stat	stat64
febeba71273d PSARC 2008/309 expunge synonyms.h
raf
parents: 5302
diff changeset
   118
#define	fstat	fstat64
febeba71273d PSARC 2008/309 expunge synonyms.h
raf
parents: 5302
diff changeset
   119
#define	fstatat	fstatat64
febeba71273d PSARC 2008/309 expunge synonyms.h
raf
parents: 5302
diff changeset
   120
#pragma weak _nftw64 = nftw64
febeba71273d PSARC 2008/309 expunge synonyms.h
raf
parents: 5302
diff changeset
   121
#else
febeba71273d PSARC 2008/309 expunge synonyms.h
raf
parents: 5302
diff changeset
   122
#pragma weak _nftw = nftw
febeba71273d PSARC 2008/309 expunge synonyms.h
raf
parents: 5302
diff changeset
   123
#endif /* !_LP64 && _FILE_OFFSET_BITS == 64 */
febeba71273d PSARC 2008/309 expunge synonyms.h
raf
parents: 5302
diff changeset
   124
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   125
#ifndef PATH_MAX
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   126
#define	PATH_MAX	1023
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   127
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   128
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   129
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   130
 * Local variables (used to be static local).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   131
 * Putting them into a structure that is passed
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   132
 * around makes nftw() MT-safe with no locking required.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   133
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   134
struct Save {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   135
	struct Save *last;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   136
	DIR	*fd;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   137
	char	*comp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   138
	long	here;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   139
	dev_t	dev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   140
	ino_t	inode;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   141
};
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   142
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   143
struct Var {
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   144
	char	*home;
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   145
	size_t	len;
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   146
	char	*fullpath;
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   147
	char	*tmppath;
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   148
	int	curflags;
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   149
	dev_t	cur_mount;
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   150
	struct FTW state;
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   151
	int	walklevel;
5302
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   152
	int	(*statf)(const char *, struct stat *, struct Save *, int flags);
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   153
	int	(*savedstatf)(const char *, struct stat *, struct Save *,
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   154
	    int flags);
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   155
	DIR	*(*opendirf)(const char *);
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   156
};
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   157
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   158
static int oldclose(struct Save *);
5302
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   159
static int cdlstat(const char *, struct stat *, struct Save *, int flags);
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   160
static int cdstat(const char *, struct stat *, struct Save *, int flags);
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   161
static int nocdlstat(const char *, struct stat *, struct Save *, int flags);
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   162
static int nocdstat(const char *, struct stat *, struct Save *, int flags);
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   163
static DIR *cdopendir(const char *);
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   164
static DIR *nocdopendir(const char *);
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   165
static const char *get_unrooted(const char *);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   166
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   167
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   168
 * This is the recursive walker.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   169
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   170
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   171
walk(char *component,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   172
    int (*fn)(const char *, const struct stat *, int, struct FTW *),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   173
    int depth, struct Save *last, struct Var *vp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   174
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   175
	struct stat statb;
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   176
	char *p, *tmp;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   177
	int type;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   178
	char *comp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   179
	struct dirent *dir;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   180
	char *q;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   181
	int rc = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   182
	int val = -1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   183
	int cdval = -1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   184
	int oldbase;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   185
	int skip;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   186
	struct Save this;
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   187
	size_t base_comp, base_component, base_this_comp, base_last_comp;
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   188
	size_t base_fullpath, base_tmppath;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   189
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   190
	this.last = last;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   191
	this.fd = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   192
	if ((vp->curflags & FTW_CHDIR) && last)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   193
		comp = last->comp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   194
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   195
		comp = vp->tmppath;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   196
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   197
	if (vp->savedstatf == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   198
		vp->savedstatf = vp->statf;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   199
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   200
	if ((vp->walklevel++ == 0) && (vp->curflags & FTW_HOPTION)) {
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   201
		if (((vp->curflags & FTW_CHDIR) == 0) && (depth >= 2)) {
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   202
			vp->statf = nocdstat;
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   203
		} else {
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   204
			vp->statf = cdstat;
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   205
		}
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   206
	} else {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   207
		vp->statf = vp->savedstatf;
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   208
	}
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   209
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   210
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   211
	 * Determine the type of the component.
5302
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   212
	 *
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   213
	 * Note that if the component is a trigger mount, this
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   214
	 * will cause it to load.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   215
	 */
5302
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   216
	if ((*vp->statf)(comp, &statb, last, _AT_TRIGGER) >= 0) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   217
		if ((statb.st_mode & S_IFMT) == S_IFDIR) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   218
			type = FTW_D;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   219
			if (depth <= 1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   220
				(void) oldclose(last);
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   221
			if ((this.fd = (*vp->opendirf)(comp)) == 0) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   222
				if (errno == EMFILE && oldclose(last) &&
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   223
				    (this.fd = (*vp->opendirf)(comp)) != 0) {
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   224
					/*
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   225
					 * If opendirf fails because there
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   226
					 * are OPEN_MAX fd in the calling
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   227
					 * process, and we close the oldest
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   228
					 * fd, and another opendirf doesn't
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   229
					 * fail, depth is set to 1.
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   230
					 */
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   231
					depth = 1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   232
				} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   233
					type = FTW_DNR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   234
					goto fail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   235
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   236
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   237
		} else if ((statb.st_mode & S_IFMT) == S_IFLNK) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   238
			type = FTW_SL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   239
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   240
			type = FTW_F;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   241
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   242
	} else if ((vp->curflags & FTW_ANYERR) && errno != ENOENT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   243
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   244
		 * If FTW_ANYERR is specified, then a stat error
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   245
		 * other than ENOENT automatically results in
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   246
		 * failure.  This allows the callback function
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   247
		 * to properly handle ENAMETOOLONG and ELOOP and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   248
		 * things of that nature, that would be masked
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   249
		 * by calling lstat before failing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   250
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   251
		type = FTW_NS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   252
		goto fail;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   253
	} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   254
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   255
		 * Statf has failed. If stat was used instead of lstat,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   256
		 * try using lstat. If lstat doesn't fail, "comp"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   257
		 * must be a symbolic link pointing to a non-existent
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   258
		 * file. Such a symbolic link should be ignored.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   259
		 * Also check the file type, if possible, for symbolic
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   260
		 * link.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   261
		 */
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   262
		if (((vp->statf == cdstat) &&
5302
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   263
		    (cdlstat(comp, &statb, last, 0) >= 0) &&
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   264
		    ((statb.st_mode & S_IFMT) == S_IFLNK)) ||
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   265
		    ((vp->statf == nocdstat) &&
5302
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   266
		    (nocdlstat(comp, &statb, last, 0) >= 0) &&
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   267
		    ((statb.st_mode & S_IFMT) == S_IFLNK))) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   268
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   269
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   270
			 * Ignore bad symbolic link, let "fn"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   271
			 * report it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   272
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   273
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   274
			errno = ENOENT;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   275
			type = FTW_SLN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   276
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   277
			type = FTW_NS;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   278
	fail:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   279
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   280
			 * if FTW_ANYERR is set in flags, we call
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   281
			 * the user function with FTW_NS set, regardless
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   282
			 * of the reason stat failed.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   283
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   284
			if (!(vp->curflags & FTW_ANYERR))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   285
				if (errno != EACCES)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   286
					return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   287
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   288
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   289
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   290
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   291
	 * If the walk is not supposed to cross a mount point,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   292
	 * and it did, get ready to return.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   293
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   294
	if ((vp->curflags & FTW_MOUNT) && type != FTW_NS &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   295
	    statb.st_dev != vp->cur_mount)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   296
		goto quit;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   297
	vp->state.quit = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   298
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   299
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   300
	 * If current component is not a directory, call user
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   301
	 * specified function and get ready to return.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   302
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   303
	if (type != FTW_D || (vp->curflags & FTW_DEPTH) == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   304
		rc = (*fn)(vp->tmppath, &statb, type, &vp->state);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   305
	if (rc > 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   306
		val = rc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   307
	skip = (vp->state.quit & FTW_SKD);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   308
	if (rc != 0 || type != FTW_D || (vp->state.quit & FTW_PRUNE))
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   309
		goto quit;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   310
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   311
	if (vp->tmppath[0] != '\0' && component[-1] != '/')
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   312
		*component++ = '/';
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   313
	*component = 0;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   314
	if (vp->curflags & FTW_CHDIR) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   315
		struct stat statb2;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   316
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   317
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   318
		 * Security check (there is a window between
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   319
		 * (*vp->statf)() and opendir() above).
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   320
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   321
		if ((vp->curflags & FTW_PHYS) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   322
		    (fstat(this.fd->dd_fd, &statb2) < 0 ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   323
		    statb2.st_ino != statb.st_ino ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   324
		    statb2.st_dev != statb.st_dev)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   325
			errno = EAGAIN;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   326
			rc = -1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   327
			goto quit;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   328
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   329
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   330
		if ((cdval = fchdir(this.fd->dd_fd)) >= 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   331
			this.comp = component;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   332
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   333
			type = FTW_DNR;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   334
			rc = (*fn)(vp->tmppath, &statb, type, &vp->state);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   335
			goto quit;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   336
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   337
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   338
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   339
	/*
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   340
	 * If the walk has followed a symbolic link (FTW_PHYS is not set),
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   341
	 * traverse the walk back to make sure there is not a loop.
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   342
	 * The find utility (FTW_NOLOOP is set) detects infinite loops
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   343
	 * in both symbolic and hard linked directories.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   344
	 */
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   345
	if ((vp->curflags & FTW_NOLOOP) ||
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   346
	    ((vp->curflags & FTW_PHYS) == 0)) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   347
		struct Save *sp = last;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   348
		while (sp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   349
			/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   350
			 * If the same node has already been visited, there
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   351
			 * is a loop. Get ready to return.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   352
			 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   353
			if (sp->dev == statb.st_dev &&
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   354
			    sp->inode == statb.st_ino) {
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   355
				if (vp->curflags & FTW_NOLOOP) {
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   356
					/* private interface for find util */
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   357
					type = FTW_DL;
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   358
					goto fail;
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   359
				}
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   360
				goto quit;
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   361
			}
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   362
			sp = sp->last;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   363
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   364
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   365
	this.dev = statb.st_dev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   366
	this.inode = statb.st_ino;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   367
	oldbase = vp->state.base;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   368
	vp->state.base = (int)(component - vp->tmppath);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   369
	while (dir = readdir(this.fd)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   370
		if (dir->d_ino == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   371
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   372
		q = dir->d_name;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   373
		if (*q == '.') {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   374
			if (q[1] == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   375
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   376
			else if (q[1] == '.' && q[2] == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   377
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   378
		}
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   379
		if (last != NULL && last->comp != NULL) {
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   380
			base_last_comp = last->comp - vp->home;
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   381
		}
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   382
		base_comp = comp - vp->home;
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   383
		base_component = component - vp->home;
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   384
		if ((strlen(q) + strlen(vp->home) + 1) > vp->len) {
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   385
			/*
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   386
			 * When the space needed for vp->home has
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   387
			 * exceeded the amount of space that has
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   388
			 * been allocated, realloc() more space
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   389
			 * and adjust pointers to point to the
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   390
			 * (possibly moved) new block for vp->home
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   391
			 */
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   392
			base_this_comp = this.comp - vp->home;
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   393
			base_fullpath = vp->fullpath - vp->home;
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   394
			base_tmppath = vp->tmppath - vp->home;
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   395
			vp->len *= 2;
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   396
			tmp = (char *)realloc(vp->home, vp->len);
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   397
			if (tmp == NULL) {
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   398
				rc = -1;
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   399
				goto quit;
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   400
			}
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   401
			vp->home = tmp;
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   402
			comp = vp->home + base_comp;
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   403
			component = vp->home + base_component;
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   404
			this.comp = vp->home + base_this_comp;
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   405
			vp->fullpath = vp->home + base_fullpath;
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   406
			vp->tmppath = vp->home + base_tmppath;
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   407
			if (last != NULL && last->comp != NULL) {
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   408
				last->comp = vp->home + base_last_comp;
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   409
			}
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   410
		}
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   411
		p = component;
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   412
		while (*q != '\0')
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   413
			*p++ = *q++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   414
		*p = '\0';
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   415
		vp->state.level++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   416
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   417
		/* Call walk() recursively.  */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   418
		rc = walk(p, fn, depth-1, &this, vp);
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   419
		if (last != NULL && last->comp != NULL) {
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   420
			last->comp = vp->home + base_last_comp;
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   421
		}
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   422
		comp = vp->home + base_comp;
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   423
		component = vp->home + base_component;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   424
		vp->state.level--;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   425
		if (this.fd == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   426
			*component = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   427
			if (vp->curflags & FTW_CHDIR) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   428
				this.fd = opendir(".");
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   429
			} else {
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   430
				this.fd = (*vp->opendirf)(comp);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   431
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   432
			if (this.fd == 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   433
				rc = -1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   434
				goto quit;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   435
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   436
			seekdir(this.fd, this.here);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   437
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   438
		if (rc != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   439
			if (errno == ENOENT) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   440
				(void) fprintf(stderr, "cannot open %s: %s\n",
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   441
				    vp->tmppath, strerror(errno));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   442
				val = rc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   443
				continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   444
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   445
			goto quit;	/* this seems extreme */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   446
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   447
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   448
	vp->state.base = oldbase;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   449
	*--component = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   450
	type = FTW_DP;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   451
	if ((vp->tmppath[0] != '\0') && (vp->curflags & FTW_DEPTH) && !skip)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   452
		rc = (*fn)(vp->tmppath, &statb, type, &vp->state);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   453
quit:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   454
	if (cdval >= 0 && last) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   455
		/* try to change back to previous directory */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   456
		if (last->fd != NULL) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   457
			if (fchdir(last->fd->dd_fd) < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   458
				rc = -1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   459
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   460
		} else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   461
			if ((cdval = chdir("..")) >= 0) {
5302
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   462
				if ((*vp->statf)(".", &statb, last, 0) < 0 ||
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   463
				    statb.st_ino != last->inode ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   464
				    statb.st_dev != last->dev)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   465
					cdval = -1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   466
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   467
			*comp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   468
			if (cdval < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   469
				if (chdir(vp->fullpath) < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   470
					rc = -1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   471
				} else {
5302
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   472
					/* Security check */
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   473
					if ((vp->curflags & FTW_PHYS) &&
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   474
					    ((*vp->statf)(".", &statb,
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   475
					    last, 0) < 0 ||
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   476
					    statb.st_ino != last->inode ||
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   477
					    statb.st_dev != last->dev)) {
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   478
						errno = EAGAIN;
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   479
						rc = -1;
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   480
					}
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   481
				}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   482
			}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   483
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   484
	}
5302
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   485
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   486
	if (this.fd)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   487
		(void) closedir(this.fd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   488
	if (val > rc)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   489
		return (val);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   490
	else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   491
		return (rc);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   492
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   493
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   494
int
6812
febeba71273d PSARC 2008/309 expunge synonyms.h
raf
parents: 5302
diff changeset
   495
nftw(const char *path,
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   496
    int (*fn)(const char *, const struct stat *, int, struct FTW *),
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   497
    int depth, int flags)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   498
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   499
	struct Var var;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   500
	struct stat statb;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   501
	int rc = -1;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   502
	char *dp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   503
	char *base;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   504
	char *endhome;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   505
	const char *savepath = path;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   506
	int save_errno;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   507
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   508
	var.walklevel = 0;
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   509
	var.len = 2*(PATH_MAX+1);
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   510
	var.home = (char *)malloc(var.len);
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   511
	if (var.home == NULL)
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   512
		return (-1);
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   513
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   514
	var.home[0] = 0;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   515
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   516
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   517
	 * If the walk is going to change directory before
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   518
	 * reading it, save current working directory.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   519
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   520
	if (flags & FTW_CHDIR) {
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   521
		if (getcwd(var.home, PATH_MAX+1) == 0) {
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   522
			free(var.home);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   523
			return (-1);
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   524
		}
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   525
	}
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   526
	endhome = dp = var.home + strlen(var.home);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   527
	if (*path == '/')
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   528
		var.fullpath = dp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   529
	else {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   530
		*dp++ = '/';
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   531
		var.fullpath = var.home;
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   532
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   533
	var.tmppath =  dp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   534
	base = dp-1;
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   535
	while (*path) {
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   536
		*dp = *path;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   537
		if (*dp == '/')
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   538
			base = dp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   539
		dp++, path++;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   540
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   541
	*dp = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   542
	var.state.base = (int)(base + 1 - var.tmppath);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   543
	if (*path) {
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   544
		free(var.home);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   545
		errno = ENAMETOOLONG;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   546
		return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   547
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   548
	var.curflags = flags;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   549
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   550
	/*
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   551
	 * If doing chdir()'s, set var.opendirf to cdopendir.
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   552
	 * If not doing chdir()'s and if nftw()'s depth arg >= 2,
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   553
	 * set var.opendirf to nocdopendir.  In order to
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   554
	 * descend to arbitrary depths without doing chdir()'s, nftw()
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   555
	 * requires a depth arg >= 2 so that nocdopendir() can use openat()
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   556
	 * to traverse the directories.  So when not doing
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   557
	 * chdir()'s if nftw()'s depth arg <= 1, set var.opendirf to
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   558
	 * cdopendir.
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   559
	 * If doing a physical walk (not following symbolic link), set
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   560
	 * var.statf to cdlstat() or nocdlstat(). Otherwise, set var.statf
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   561
	 * to cdstat() or nocdstat().
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   562
	 */
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   563
	if (((flags & FTW_CHDIR) == 0) && (depth >= 2)) {
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   564
		var.opendirf = nocdopendir;
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   565
		if (flags & FTW_PHYS)
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   566
			var.statf = nocdlstat;
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   567
		else
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   568
			var.statf = nocdstat;
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   569
	} else {
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   570
		var.opendirf = cdopendir;
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   571
		if (flags & FTW_PHYS)
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   572
			var.statf = cdlstat;
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   573
		else
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   574
			var.statf = cdstat;
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   575
	}
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   576
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   577
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   578
	 * If walk is not going to cross a mount point,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   579
	 * save the current mount point.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   580
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   581
	if (flags & FTW_MOUNT) {
5302
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   582
		if ((*var.statf)(savepath, &statb, NULL, 0) >= 0)
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   583
			var.cur_mount = statb.st_dev;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   584
		else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   585
			goto done;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   586
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   587
	var.state.level = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   588
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   589
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   590
	 * Call walk() which does most of the work.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   591
	 * walk() uses errno in a rather obtuse way
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   592
	 * so we shield any incoming errno.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   593
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   594
	save_errno = errno;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   595
	errno = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   596
	var.savedstatf = NULL;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   597
	rc = walk(dp, fn, depth, (struct Save *)0, &var);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   598
	if (errno == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   599
		errno = save_errno;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   600
done:
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   601
	*endhome = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   602
	if (flags & FTW_CHDIR)
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   603
		(void) chdir(var.home);
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   604
	free(var.home);
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   605
	return (rc);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   606
}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   607
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   608
/*
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   609
 * Get stat info on path when FTW_CHDIR is set.
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   610
 */
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   611
/*ARGSUSED1*/
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   612
static int
5302
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   613
cdstat(const char *path, struct stat *statp, struct Save *lp, int flags)
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   614
{
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   615
	return (fstatat(AT_FDCWD, path, statp, flags));
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   616
}
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   617
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   618
/*
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   619
 * Get lstat info on path when FTW_CHDIR is set.
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   620
 */
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   621
/*ARGSUSED1*/
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   622
static int
5302
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   623
cdlstat(const char *path, struct stat *statp, struct Save *lp, int flags)
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   624
{
5302
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   625
	return (fstatat(AT_FDCWD, path, statp,
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   626
	    flags | AT_SYMLINK_NOFOLLOW));
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   627
}
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   628
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   629
/*
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   630
 * Get stat info on path when FTW_CHDIR is not set.
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   631
 */
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   632
static int
5302
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   633
nocdstat(const char *path, struct stat *statp, struct Save *lp, int flags)
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   634
{
5302
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   635
	int		fd;
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   636
	const char	*basepath;
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   637
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   638
	if (lp && lp->fd) {
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   639
		/* get basename of path */
5302
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   640
		basepath = get_unrooted(path);
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   641
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   642
		fd = lp->fd->dd_fd;
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   643
	} else {
5302
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   644
		basepath = path;
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   645
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   646
		fd = AT_FDCWD;
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   647
	}
5302
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   648
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   649
	return (fstatat(fd, basepath, statp, flags));
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   650
}
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   651
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   652
/*
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   653
 * Get lstat info on path when FTW_CHDIR is not set.
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   654
 */
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   655
static int
5302
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   656
nocdlstat(const char *path, struct stat *statp, struct Save *lp, int flags)
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   657
{
5302
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   658
	int		fd;
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   659
	const char	*basepath;
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   660
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   661
	if (lp && lp->fd) {
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   662
		/* get basename of path */
5302
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   663
		basepath = get_unrooted(path);
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   664
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   665
		fd = lp->fd->dd_fd;
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   666
	} else {
5302
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   667
		basepath = path;
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   668
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   669
		fd = AT_FDCWD;
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   670
	}
5302
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   671
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   672
	return (fstatat(fd, basepath, statp, flags | AT_SYMLINK_NOFOLLOW));
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   673
}
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   674
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   675
/*
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   676
 * Open path directory when FTW_CHDIR is set.
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   677
 *
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   678
 */
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   679
static DIR *
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   680
cdopendir(const char *path)
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   681
{
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   682
	return (opendir(path));
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   683
}
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   684
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   685
/*
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   686
 * Open path directory when FTW_CHDIR is not set.
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   687
 */
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   688
static DIR *
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   689
nocdopendir(const char *path)
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   690
{
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   691
	int fd, cfd;
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   692
	DIR *fdd;
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   693
	char *dirp, *token, *ptr;
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   694
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   695
	if (((fdd = opendir(path)) == NULL) && (errno == ENAMETOOLONG)) {
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   696
		if ((dirp = strdup(path)) == NULL) {
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   697
			errno = ENAMETOOLONG;
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   698
			return (NULL);
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   699
		}
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   700
		if ((token = strtok_r(dirp, "/", &ptr)) != NULL) {
5302
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   701
			if ((fd = openat(AT_FDCWD, dirp, O_RDONLY)) < 0) {
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   702
				(void) free(dirp);
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   703
				errno = ENAMETOOLONG;
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   704
				return (NULL);
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   705
			}
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   706
			while ((token = strtok_r(NULL, "/", &ptr)) != NULL) {
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   707
				if ((cfd = openat(fd, token, O_RDONLY)) < 0) {
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   708
					(void) close(fd);
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   709
					(void) free(dirp);
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   710
					errno = ENAMETOOLONG;
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   711
					return (NULL);
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   712
				}
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   713
				(void) close(fd);
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   714
				fd = cfd;
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   715
			}
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   716
			(void) free(dirp);
5302
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   717
			return (fdopendir(fd));
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   718
		}
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   719
		(void) free(dirp);
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   720
		errno = ENAMETOOLONG;
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   721
	}
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   722
	return (fdd);
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   723
}
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   724
5302
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   725
/*
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   726
 * return pointer basename of path, which may contain trailing slashes
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   727
 *
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   728
 * We do this when we do not chdir() on the input.
eec6aeacde6e PSARC 2007/416 NFSv4 Mirror-mounts
th199096
parents: 3523
diff changeset
   729
 */
3523
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   730
static const char *
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   731
get_unrooted(const char *path)
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   732
{
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   733
	const char *ptr;
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   734
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   735
	if (!path || !*path)
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   736
		return (NULL);
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   737
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   738
	ptr = path + strlen(path);
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   739
	/* find last char in path before any trailing slashes */
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   740
	while (ptr != path && *--ptr == '/')
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   741
		;
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   742
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   743
	if (ptr == path)	/* all slashes */
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   744
		return (ptr);
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   745
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   746
	while (ptr != path)
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   747
		if (*--ptr == '/')
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   748
			return (++ptr);
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   749
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   750
	return (ptr);
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   751
}
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   752
b9f12aa2fb57 PSARC/2006/403 Add two new private interfaces to nftw() for 'find' command
cf46844
parents: 1219
diff changeset
   753
/*
0
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   754
 * close the oldest directory.  It saves the seek offset.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   755
 * return value is 0 unless it was unable to close any descriptor
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   756
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   757
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   758
static int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   759
oldclose(struct Save *sp)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   760
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   761
	struct Save *spnext;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   762
	while (sp) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   763
		spnext = sp->last;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   764
		if (spnext == 0 || spnext->fd == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   765
			break;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   766
		sp = spnext;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   767
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   768
	if (sp == 0 || sp->fd == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   769
		return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   770
	sp->here = telldir(sp->fd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   771
	(void) closedir(sp->fd);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   772
	sp->fd = 0;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   773
	return (1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   774
}