usr/src/lib/libc/port/gen/_xftw.c
author stevel@tonic-gate
Tue, 14 Jun 2005 00:00:00 -0700
changeset 0 68f95e015346
child 3523 b9f12aa2fb57
permissions -rw-r--r--
OpenSolaris Launch
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
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     5
 * Common Development and Distribution License, Version 1.0 only
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     6
 * (the "License").  You may not use this file except in compliance
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     7
 * with the License.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     8
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
     9
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    10
 * or http://www.opensolaris.org/os/licensing.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    11
 * See the License for the specific language governing permissions
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    12
 * and limitations under the License.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    13
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    14
 * When distributing Covered Code, include this CDDL HEADER in each
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    15
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    16
 * If applicable, add the following below this CDDL HEADER, with the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    17
 * fields enclosed by brackets "[]" replaced with your own identifying
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    18
 * information: Portions Copyright [yyyy] [name of copyright owner]
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    19
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    20
 * CDDL HEADER END
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    21
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    22
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    23
 * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
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
#pragma ident	"%Z%%M%	%I%	%E% SMI"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    28
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    29
/*	Copyright (c) 1988 AT&T	*/
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    30
/*	  All Rights Reserved  	*/
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
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    34
 *	_xftw - file tree walk the uses expanded stat structure
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    35
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    36
 *	int _xftw(path, fn, depth)  char *path; int (*fn)(); int depth;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    37
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    38
 *	Given a path name, _xftw starts from the file given by that path
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    39
 *	name and visits each file and directory in the tree beneath
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    40
 *	that file.  If a single file has multiple links within the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    41
 *	structure, it will be visited once for each such link.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    42
 *	For each object visited, fn is called with three arguments.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    43
 *		(*fn) (pathname, statp, ftwflag)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    44
 *	The first contains the path name of the object, the second
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    45
 *	contains a pointer to a stat buffer which will usually hold
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    46
 *	appropriate information for the object and the third will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    47
 *	contain an integer value giving additional information about
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    48
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    49
 *		FTW_F	The object is a file for which stat was
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    50
 *			successful.  It does not guarantee that the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    51
 *			file can actually be read.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    52
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    53
 *		FTW_D	The object is a directory for which stat and
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    54
 *			open for read were both successful.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    55
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    56
 *		FTW_DNR	The object is a directory for which stat
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    57
 *			succeeded, but which cannot be read.  Because
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    58
 *			the directory cannot be read, fn will not be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    59
 *			called for any descendants of this directory.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    60
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    61
 *		FTW_NS	Stat failed on the object because of lack of
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    62
 *			appropriate permission.  This indication will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    63
 *			be given for example for each file in a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    64
 *			directory with read but no execute permission.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    65
 *			Because stat failed, it is not possible to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    66
 *			determine whether this object is a file or a
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    67
 *			directory.  The stat buffer passed to fn will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    68
 *			contain garbage.  Stat failure for any reason
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    69
 *			other than lack of permission will be
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    70
 *			considered an error and will cause _xftw to stop
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    71
 *			and return -1 to its caller.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    72
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    73
 *	If fn returns nonzero, _xftw stops and returns the same value
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    74
 *	to its caller.  If _xftw gets into other trouble along the way,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    75
 *	it returns -1 and leaves an indication of the cause in errno.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    76
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    77
 *	The third argument to _xftw does not limit the depth to which
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    78
 *	_xftw will go.  Rather, it limits the depth to which _xftw will
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    79
 *	go before it starts recycling file descriptors.  In general,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    80
 *	it is necessary to use a file descriptor for each level of the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    81
 *	tree, but they can be recycled for deep trees by saving the
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    82
 *	position, closing, re-opening, and seeking.  It is possible
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    83
 *	to start recycling file descriptors by sensing when we have
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    84
 *	run out, but in general this will not be terribly useful if
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    85
 *	fn expects to be able to open files.  We could also figure out
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    86
 *	how many file descriptors are available and guarantee a certain
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    87
 *	number to fn, but we would not know how many to guarantee,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    88
 *	and we do not want to impose the extra overhead on a caller who
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    89
 *	knows how many are available without having to figure it out.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    90
 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    91
 *	It is possible for _xftw to die with a memory fault in the event
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    92
 *	of a file system so deeply nested that the stack overflows.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    93
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    94
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    95
/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    96
 * this interface uses the expanded stat structure and therefore
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    97
 * must have EFT enabled.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    98
 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
    99
#ifdef _STYPES
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   100
#undef _STYPES
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   101
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   102
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   103
#include <sys/feature_tests.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   104
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   105
#if !defined(_LP64) && _FILE_OFFSET_BITS == 64
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   106
#define	lstat64		_lstat64
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   107
#define	readdir64	_readdir64
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   108
#define	stat64		_stat64
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   109
#else
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   110
#define	lstat		_lstat
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   111
#define	readdir		_readdir
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   112
#define	stat		_stat
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   113
#endif /* !_LP64 && _FILE_OFFSET_BITS == 64 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   114
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   115
#define	closedir	_closedir
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   116
#define	opendir		_opendir
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   117
#define	seekdir		_seekdir
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   118
#define	telldir		_telldir
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   119
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   120
#include "lint.h"
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   121
#include <sys/types.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   122
#include <sys/stat.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   123
#include <sys/param.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   124
#include <dirent.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   125
#include <errno.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   126
#include <ftw.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   127
#include <string.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   128
#include <stdlib.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   129
#include <alloca.h>
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   130
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   131
int
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   132
_xftw(int ver, const char *path,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   133
	int (*fn)(const char *, const struct stat *, int), int depth)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   134
{
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   135
	size_t	n;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   136
	int rc;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   137
	int save_errno;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   138
	DIR *dirp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   139
	char *subpath;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   140
	struct stat sb;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   141
	struct dirent *direntp;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   142
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   143
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   144
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   145
	 * Try to get file status.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   146
	 * If unsuccessful, errno will say why.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   147
	 * It's ok to have a symbolic link that points to
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   148
	 * non-existing file. In this case, pass FTW_NS
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   149
	 * to a function instead of aborting _xftw() right away.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   150
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   151
	if (stat(path, &sb) < 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   152
#ifdef S_IFLNK
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   153
		save_errno = errno;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   154
		if ((lstat(path, &sb) != -1) &&
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   155
				((sb.st_mode & S_IFMT) == S_IFLNK)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   156
			errno = save_errno;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   157
			return (*fn)(path, &sb, FTW_NS);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   158
		} else  {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   159
			errno = save_errno;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   160
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   161
#endif
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   162
		return (errno == EACCES? (*fn)(path, &sb, FTW_NS): -1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   163
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   164
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   165
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   166
	 *	The stat succeeded, so we know the object exists.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   167
	 *	If not a directory, call the user function and return.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   168
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   169
	if ((sb.st_mode & S_IFMT) != S_IFDIR)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   170
		return ((*fn)(path, &sb, FTW_F));
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   171
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   172
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   173
	 *	The object was a directory.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   174
	 *
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   175
	 *	Open a file to read the directory
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   176
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   177
	dirp = opendir(path);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   178
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   179
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   180
	 *	Call the user function, telling it whether
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   181
	 *	the directory can be read.  If it can't be read
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   182
	 *	call the user function or indicate an error,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   183
	 *	depending on the reason it couldn't be read.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   184
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   185
	if (dirp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   186
		return (errno == EACCES? (*fn)(path, &sb, FTW_DNR): -1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   187
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   188
	/* We could read the directory.  Call user function. */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   189
	rc = (*fn)(path, &sb, FTW_D);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   190
	if (rc != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   191
		(void) closedir(dirp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   192
		return (rc);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   193
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   194
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   195
	/* Create a prefix to which we will append component names */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   196
	n = strlen(path);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   197
	subpath = alloca(n + MAXNAMELEN + 2);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   198
	(void) strcpy(subpath, path);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   199
	if (subpath[0] != '\0' && subpath[n-1] != '/')
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   200
		subpath[n++] = '/';
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   201
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   202
	/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   203
	 *	Read the directory one component at a time.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   204
	 *	We must ignore "." and "..", but other than that,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   205
	 *	just create a path name and call self to check it out.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   206
	 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   207
	while (direntp = readdir(dirp)) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   208
		long here;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   209
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   210
		if (strcmp(direntp->d_name, ".") == 0 ||
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   211
		    strcmp(direntp->d_name, "..") == 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   212
			continue;
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   213
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   214
		/* Append component name to the working path */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   215
		(void) strlcpy(&subpath[n], direntp->d_name, MAXNAMELEN);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   216
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   217
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   218
		 *	If we are about to exceed our depth,
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   219
		 *	remember where we are and close a file.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   220
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   221
		if (depth <= 1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   222
			here = telldir(dirp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   223
			if (closedir(dirp) < 0)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   224
				return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   225
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   226
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   227
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   228
		 *	Do a recursive call to process the file.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   229
		 *	(watch this, sports fans)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   230
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   231
		rc = _xftw(ver, subpath, fn, depth-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   232
		if (rc != 0) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   233
			if (depth > 1)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   234
				(void) closedir(dirp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   235
			return (rc);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   236
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   237
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   238
		/*
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   239
		 *	If we closed the file, try to reopen it.
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   240
		 */
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   241
		if (depth <= 1) {
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   242
			dirp = opendir(path);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   243
			if (dirp == NULL)
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   244
				return (-1);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   245
			seekdir(dirp, here);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   246
		}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   247
	}
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   248
	(void) closedir(dirp);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   249
	return (0);
68f95e015346 OpenSolaris Launch
stevel@tonic-gate
parents:
diff changeset
   250
}