2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar/*
65451a03349bdb7f4bf79a8f29d4065772e01caeReza Sabdar * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar/*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * BSD 3 Clause License
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar *
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Copyright (c) 2007, The Storage Networking Industry Association.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar *
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Redistribution and use in source and binary forms, with or without
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * modification, are permitted provided that the following conditions
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * are met:
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * - Redistributions of source code must retain the above copyright
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * notice, this list of conditions and the following disclaimer.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar *
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * - Redistributions in binary form must reproduce the above copyright
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * notice, this list of conditions and the following disclaimer in
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * the documentation and/or other materials provided with the
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * distribution.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar *
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * - Neither the name of The Storage Networking Industry Association (SNIA)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * nor the names of its contributors may be used to endorse or promote
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * products derived from this software without specific prior written
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * permission.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar *
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * POSSIBILITY OF SUCH DAMAGE.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar/*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * This file implemets the post-order, pre-order and level-order
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * traversing of the file system. The related macros and constants
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * are defined in traverse.h.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar#include <sys/stat.h>
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar#include <sys/types.h>
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar#include <sys/param.h>
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar#include <assert.h>
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar#include <cstack.h>
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar#include <dirent.h>
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar#include <errno.h>
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar#include <traverse.h>
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar#include <limits.h>
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar#include <stdarg.h>
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar#include <stdio.h>
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar#include <stdlib.h>
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar#include <string.h>
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar#include <syslog.h>
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar#include <fcntl.h>
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar#include <unistd.h>
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar#include <tlm.h>
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar#include "tlm_proto.h"
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar/*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Check if it's "." or ".."
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdarboolean_t
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdarrootfs_dot_or_dotdot(char *name)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar{
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (*name != '.')
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (FALSE);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if ((name[1] == 0) || (name[1] == '.' && name[2] == 0))
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (TRUE);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (FALSE);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar}
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar/*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Macros on fs_traverse flags.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar#define STOP_ONERR(f) ((f)->ft_flags & FST_STOP_ONERR)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar#define STOP_ONLONG(f) ((f)->ft_flags & FST_STOP_ONLONG)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar#define VERBOSE(f) ((f)->ft_flags & FST_VERBOSE)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar#define CALLBACK(pp, ep) \
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar (*(ftp)->ft_callbk)((ftp)->ft_arg, pp, ep)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar#define NEGATE(rv) ((rv) = -(rv))
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar/*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * The traversing state that is pushed onto the stack.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * This include:
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * - The end of the path of the current directory.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * - The position of the last component on it.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * - The read position in the directory.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * - The file handle of the directory.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * - The stat of the directory.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdartypedef struct traverse_state {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar char *ts_end;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar char *ts_ent;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar long ts_dpos; /* position in the directory when reading its entries */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar fs_fhandle_t ts_fh;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar struct stat64 ts_st;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar} traverse_state_t;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar/*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Statistics gathering structure.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdartypedef struct traverse_statistics {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar ulong_t fss_newdirs;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar ulong_t fss_readdir_err;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar ulong_t fss_longpath_err;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar ulong_t fss_lookup_err;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar ulong_t fss_nondir_calls;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar ulong_t fss_dir_calls;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar ulong_t fss_nondir_skipped;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar ulong_t fss_dir_skipped;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar ulong_t fss_pushes;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar ulong_t fss_pops;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar ulong_t fss_stack_residue;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar} traverse_statistics_t;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar/*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Global instance of statistics variable.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdartraverse_statistics_t traverse_stats;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar#define MAX_DENT_BUF_SIZE (8 * 1024)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdartypedef struct {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar struct stat64 fd_attr;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar fs_fhandle_t fd_fh;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar short fd_len;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar char fd_name[1];
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar} fs_dent_info_t;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdartypedef struct dent_arg {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar char *da_buf;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar int da_end;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar int da_size;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar} dent_arg_t;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdarstatic int traverse_level_nondir(struct fs_traverse *ftp,
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar traverse_state_t *tsp, struct fst_node *pnp,
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar dent_arg_t *darg);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar/*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Gather some directory entry information and return them
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdarstatic int
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdarfs_populate_dents(void *arg, int namelen,
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar char *name, long *countp, struct stat64 *attr,
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar fs_fhandle_t *fh)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar{
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar dent_arg_t *darg = (dent_arg_t *)arg;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar int reclen = sizeof (fs_dent_info_t) + namelen;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar fs_dent_info_t *dent;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if ((darg->da_end + reclen) > darg->da_size)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (-1);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar /* LINTED improper alignment */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar dent = (fs_dent_info_t *)(darg->da_buf + darg->da_end);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar dent->fd_attr = *attr;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar dent->fd_fh = *fh;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar (void) strcpy(dent->fd_name, name);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar dent->fd_len = reclen;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar darg->da_end += reclen;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (countp)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar (*countp)++;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (0);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar}
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar/*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Creates a new traversing state based on the path passed to it.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdarstatic traverse_state_t *
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdarnew_tsp(char *path)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar{
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar traverse_state_t *tsp;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar tsp = ndmp_malloc(sizeof (traverse_state_t));
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (!tsp)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (NULL);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar tsp->ts_end = strchr(path, '\0');
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (*(tsp->ts_end-1) == '/')
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar *--tsp->ts_end = '\0';
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar tsp->ts_ent = NULL;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar tsp->ts_dpos = 0;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (tsp);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar}
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar/*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Create a file handle and get stats for the given path
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdarint
84bf06e9e5fd6d61897cc8c298a0f3e807b27094Reza Sabdarfs_getstat(char *path, fs_fhandle_t *fh, struct stat64 *st)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar{
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (lstat64(path, st) == -1)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (errno);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar fh->fh_fid = st->st_ino;
c211fc479225fa54805cf480633bf6689ca9a2dbReza Sabdar
84bf06e9e5fd6d61897cc8c298a0f3e807b27094Reza Sabdar if (!S_ISDIR(st->st_mode))
c211fc479225fa54805cf480633bf6689ca9a2dbReza Sabdar fh->fh_fpath = NULL;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar else
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar fh->fh_fpath = strdup(path);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (0);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar}
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar/*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Get directory entries info and return in the buffer. Cookie
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * will keep the state of each call
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdarstatic int
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdarfs_getdents(int fildes, struct dirent *buf, size_t *nbyte,
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar char *pn_path, long *dpos, longlong_t *cookie,
84bf06e9e5fd6d61897cc8c298a0f3e807b27094Reza Sabdar long *n_entries, dent_arg_t *darg)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar{
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar struct dirent *ptr;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar char file_path[PATH_MAX + 1];
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar fs_fhandle_t fh;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar struct stat64 st;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar char *p;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar int len;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar int rv;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (*nbyte == 0) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar (void) memset((char *)buf, 0, MAX_DENT_BUF_SIZE);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar *nbyte = rv = getdents(fildes, buf, darg->da_size);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar *cookie = 0LL;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (rv <= 0)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (rv);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar p = (char *)buf + *cookie;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar len = *nbyte;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar do {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar /* LINTED improper alignment */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar ptr = (struct dirent *)p;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar *dpos = ptr->d_off;
84bf06e9e5fd6d61897cc8c298a0f3e807b27094Reza Sabdar
84bf06e9e5fd6d61897cc8c298a0f3e807b27094Reza Sabdar if (rootfs_dot_or_dotdot(ptr->d_name))
84bf06e9e5fd6d61897cc8c298a0f3e807b27094Reza Sabdar goto skip_entry;
84bf06e9e5fd6d61897cc8c298a0f3e807b27094Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar (void) snprintf(file_path, PATH_MAX, "%s/", pn_path);
65451a03349bdb7f4bf79a8f29d4065772e01caeReza Sabdar (void) strlcat(file_path, ptr->d_name, PATH_MAX + 1);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar (void) memset(&fh, 0, sizeof (fs_fhandle_t));
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
5a3c8170a75e81911cf43e0eb9ad5cdabb5f1e39Reza Sabdar if (lstat64(file_path, &st) != 0) {
5a3c8170a75e81911cf43e0eb9ad5cdabb5f1e39Reza Sabdar rv = -1;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar break;
5a3c8170a75e81911cf43e0eb9ad5cdabb5f1e39Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
84bf06e9e5fd6d61897cc8c298a0f3e807b27094Reza Sabdar fh.fh_fid = st.st_ino;
84bf06e9e5fd6d61897cc8c298a0f3e807b27094Reza Sabdar
84bf06e9e5fd6d61897cc8c298a0f3e807b27094Reza Sabdar if (S_ISDIR(st.st_mode))
84bf06e9e5fd6d61897cc8c298a0f3e807b27094Reza Sabdar goto skip_entry;
84bf06e9e5fd6d61897cc8c298a0f3e807b27094Reza Sabdar
5a3c8170a75e81911cf43e0eb9ad5cdabb5f1e39Reza Sabdar if (fs_populate_dents(darg, strlen(ptr->d_name),
5a3c8170a75e81911cf43e0eb9ad5cdabb5f1e39Reza Sabdar (char *)ptr->d_name, n_entries, &st, &fh) != 0)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar break;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
84bf06e9e5fd6d61897cc8c298a0f3e807b27094Reza Sabdarskip_entry:
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar p = p + ptr->d_reclen;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar len -= ptr->d_reclen;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar } while (len);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar *cookie = (longlong_t)(p - (char *)buf);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar *nbyte = len;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (rv);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar}
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar/*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Read the directory entries and return the information about
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * each entry
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdarint
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdarfs_readdir(fs_fhandle_t *ts_fh, char *path, long *dpos,
84bf06e9e5fd6d61897cc8c298a0f3e807b27094Reza Sabdar char *nm, int *el, fs_fhandle_t *efh, struct stat64 *est)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar{
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar struct dirent *dp;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar char file_path[PATH_MAX + 1];
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar DIR *dirp;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar int rv;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if ((dirp = opendir(ts_fh->fh_fpath)) == NULL)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (errno);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar seekdir(dirp, *dpos);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if ((dp = readdir(dirp)) == NULL) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar rv = 0; /* skip this dir */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar *el = 0;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar } else {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar (void) snprintf(file_path, PATH_MAX, "%s/", path);
65451a03349bdb7f4bf79a8f29d4065772e01caeReza Sabdar (void) strlcat(file_path, dp->d_name, PATH_MAX + 1);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
84bf06e9e5fd6d61897cc8c298a0f3e807b27094Reza Sabdar rv = fs_getstat(file_path, efh, est);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (rv == 0) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar *dpos = telldir(dirp);
65451a03349bdb7f4bf79a8f29d4065772e01caeReza Sabdar (void) strlcpy(nm, dp->d_name, NAME_MAX + 1);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar *el = strlen(dp->d_name);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar } else {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar *el = 0;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar (void) closedir(dirp);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (rv);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar}
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar/*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Traverse the file system in the post-order way. The description
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * and example is in the header file.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar *
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * The callback function should return 0, on success and non-zero on
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * failure. If the callback function returns non-zero return value,
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * the traversing stops.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdarint
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdartraverse_post(struct fs_traverse *ftp)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar{
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar char path[PATH_MAX + 1]; /* full path name of the current dir */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar char nm[NAME_MAX + 1]; /* directory entry name */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar char *lp; /* last position on the path */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar int next_dir, rv;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar int pl, el; /* path and directory entry length */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar cstack_t *sp;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar fs_fhandle_t pfh, efh;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar struct stat64 pst, est;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar traverse_state_t *tsp;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar struct fst_node pn, en; /* parent and entry nodes */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (!ftp || !ftp->ft_path || !*ftp->ft_path || !ftp->ft_callbk) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar NDMP_LOG(LOG_DEBUG, "Invalid argument");
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar errno = EINVAL;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (-1);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar /* set the default log function if it's not already set */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (!ftp->ft_logfp) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar ftp->ft_logfp = (ft_log_t)syslog;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar NDMP_LOG(LOG_DEBUG, "Log to system log \"%s\"", ftp->ft_path);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar /* set the logical path to physical path if it's not already set */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (!ftp->ft_lpath) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar NDMP_LOG(LOG_DEBUG,
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar "report the same paths: \"%s\"", ftp->ft_path);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar ftp->ft_lpath = ftp->ft_path;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar pl = strlen(ftp->ft_lpath);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (pl + 1 > PATH_MAX) { /* +1 for the '/' */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar NDMP_LOG(LOG_DEBUG, "lpath too long \"%s\"", ftp->ft_path);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar errno = ENAMETOOLONG;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (-1);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar (void) strcpy(path, ftp->ft_lpath);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar (void) memset(&pfh, 0, sizeof (pfh));
84bf06e9e5fd6d61897cc8c298a0f3e807b27094Reza Sabdar rv = fs_getstat(ftp->ft_lpath, &pfh, &pst);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (rv != 0) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar NDMP_LOG(LOG_DEBUG,
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar "Error %d on fs_getstat(%s)", rv, ftp->ft_path);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (rv);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (!S_ISDIR(pst.st_mode)) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar pn.tn_path = ftp->ft_lpath;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar pn.tn_fh = &pfh;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar pn.tn_st = &pst;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar en.tn_path = NULL;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar en.tn_fh = NULL;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar en.tn_st = NULL;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar rv = CALLBACK(&pn, &en);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (VERBOSE(ftp))
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar NDMP_LOG(LOG_DEBUG, "CALLBACK(%s): %d", pn.tn_path, rv);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar free(pfh.fh_fpath);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (rv);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar sp = cstack_new();
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (!sp) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar errno = ENOMEM;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar free(pfh.fh_fpath);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (-1);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar tsp = new_tsp(path);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (!tsp) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar cstack_delete(sp);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar errno = ENOMEM;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar free(pfh.fh_fpath);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (-1);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar tsp->ts_ent = tsp->ts_end;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar tsp->ts_fh = pfh;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar tsp->ts_st = pst;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar pn.tn_path = path;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar pn.tn_fh = &tsp->ts_fh;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar pn.tn_st = &tsp->ts_st;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar rv = 0;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar next_dir = 1;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar do {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (next_dir) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar traverse_stats.fss_newdirs++;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar *tsp->ts_end = '\0';
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (VERBOSE(ftp))
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar NDMP_LOG(LOG_DEBUG, "pl %d \"%s\"", pl, path);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar next_dir = 0;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar do {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar el = NAME_MAX;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar rv = fs_readdir(&tsp->ts_fh, pn.tn_path,
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar &tsp->ts_dpos, nm, &el,
84bf06e9e5fd6d61897cc8c298a0f3e807b27094Reza Sabdar &efh, &est);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (rv != 0) {
84bf06e9e5fd6d61897cc8c298a0f3e807b27094Reza Sabdar free(efh.fh_fpath);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar traverse_stats.fss_readdir_err++;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar NDMP_LOG(LOG_DEBUG,
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar "Error %d on readdir(%s) pos %d",
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar rv, path, tsp->ts_dpos);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (STOP_ONERR(ftp))
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar break;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar rv = SKIP_ENTRY;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar continue;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar /* done with this directory */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (el == 0) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (VERBOSE(ftp))
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar NDMP_LOG(LOG_DEBUG,
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar "Done(%s)", pn.tn_path);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar break;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar nm[el] = '\0';
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (rootfs_dot_or_dotdot(nm)) {
84bf06e9e5fd6d61897cc8c298a0f3e807b27094Reza Sabdar free(efh.fh_fpath);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar continue;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (VERBOSE(ftp))
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar NDMP_LOG(LOG_DEBUG, "%u dname: \"%s\"",
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar tsp->ts_dpos, nm);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (pl + 1 + el > PATH_MAX) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar traverse_stats.fss_longpath_err++;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar NDMP_LOG(LOG_ERR, "Path %s/%s is too long.",
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar path, nm);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (STOP_ONLONG(ftp))
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar rv = ENAMETOOLONG;
84bf06e9e5fd6d61897cc8c298a0f3e807b27094Reza Sabdar free(efh.fh_fpath);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar continue;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar /*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Push the current directory on to the stack and
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * dive into the entry found.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (S_ISDIR(est.st_mode)) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar assert(tsp != NULL);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (cstack_push(sp, tsp, 0)) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar rv = ENOMEM;
84bf06e9e5fd6d61897cc8c298a0f3e807b27094Reza Sabdar free(efh.fh_fpath);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar break;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar traverse_stats.fss_pushes++;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar /*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Concatenate the current entry with the
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * current path. This will be the path of
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * the new directory to be scanned.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar *
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Note:
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * sprintf(tsp->ts_end, "/%s", de->d_name);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * could be used here, but concatenating
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * strings like this might be faster.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * The length of the new path has been
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * checked above. So strcpy() can be
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * safe and should not lead to a buffer
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * over-run.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar lp = tsp->ts_end;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar *tsp->ts_end = '/';
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar (void) strcpy(tsp->ts_end + 1, nm);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar tsp = new_tsp(path);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (!tsp) {
84bf06e9e5fd6d61897cc8c298a0f3e807b27094Reza Sabdar free(efh.fh_fpath);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar rv = ENOMEM;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar } else {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar next_dir = 1;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar pl += el;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar tsp->ts_fh = efh;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar tsp->ts_st = est;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar tsp->ts_ent = lp;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar pn.tn_fh = &tsp->ts_fh;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar pn.tn_st = &tsp->ts_st;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar break;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar } else {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar /*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * The entry is not a directory so the
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * callback function must be called.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar traverse_stats.fss_nondir_calls++;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar en.tn_path = nm;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar en.tn_fh = &efh;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar en.tn_st = &est;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar rv = CALLBACK(&pn, &en);
84bf06e9e5fd6d61897cc8c298a0f3e807b27094Reza Sabdar free(efh.fh_fpath);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (VERBOSE(ftp))
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar NDMP_LOG(LOG_DEBUG,
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar "CALLBACK(%s/%s): %d",
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar pn.tn_path, en.tn_path, rv);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (rv != 0)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar break;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar } while (rv == 0);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar /*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * A new directory must be processed, go to the start of
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * the loop, open it and process it.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (next_dir)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar continue;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (rv == SKIP_ENTRY)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar rv = 0; /* We should skip the current directory */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (rv == 0) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar /*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Remove the ent from the end of path and send it
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * as an entry of the path.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar lp = tsp->ts_ent;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar *lp = '\0';
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar efh = tsp->ts_fh;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar est = tsp->ts_st;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar free(tsp);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (cstack_pop(sp, (void **)&tsp, (int *)NULL))
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar break;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar assert(tsp != NULL);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar pl = tsp->ts_end - path;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (VERBOSE(ftp))
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar NDMP_LOG(LOG_DEBUG, "poped pl %d 0x%p \"%s\"",
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar pl, tsp, path);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar traverse_stats.fss_pops++;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar traverse_stats.fss_dir_calls++;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar pn.tn_fh = &tsp->ts_fh;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar pn.tn_st = &tsp->ts_st;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar en.tn_path = lp + 1;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar en.tn_fh = &efh;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar en.tn_st = &est;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar rv = CALLBACK(&pn, &en);
84bf06e9e5fd6d61897cc8c298a0f3e807b27094Reza Sabdar free(efh.fh_fpath);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (VERBOSE(ftp))
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar NDMP_LOG(LOG_DEBUG, "CALLBACK(%s/%s): %d",
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar pn.tn_path, en.tn_path, rv);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar /*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Does not need to free tsp here. It will be released
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * later.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
84bf06e9e5fd6d61897cc8c298a0f3e807b27094Reza Sabdar if (rv != 0 && tsp) {
84bf06e9e5fd6d61897cc8c298a0f3e807b27094Reza Sabdar free(tsp->ts_fh.fh_fpath);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar free(tsp);
84bf06e9e5fd6d61897cc8c298a0f3e807b27094Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar } while (rv == 0);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar /*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * For the 'ftp->ft_path' directory itself.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (rv == 0) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar traverse_stats.fss_dir_calls++;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar pn.tn_fh = &efh;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar pn.tn_st = &est;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar en.tn_path = NULL;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar en.tn_fh = NULL;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar en.tn_st = NULL;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar rv = CALLBACK(&pn, &en);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (VERBOSE(ftp))
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar NDMP_LOG(LOG_DEBUG, "CALLBACK(%s): %d", pn.tn_path, rv);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar /*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Pop and free all the remaining entries on the stack.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar while (!cstack_pop(sp, (void **)&tsp, (int *)NULL)) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar traverse_stats.fss_stack_residue++;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
84bf06e9e5fd6d61897cc8c298a0f3e807b27094Reza Sabdar free(tsp->ts_fh.fh_fpath);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar free(tsp);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar cstack_delete(sp);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (rv);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar}
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar/*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * In one pass, read all the directory entries of the specified
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * directory and call the callback function for non-directory
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * entries.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar *
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * On return:
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * 0: Lets the directory to be scanned for directory entries.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * < 0: Completely stops traversing.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * FST_SKIP: stops further scanning of the directory. Traversing
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * will continue with the next directory in the hierarchy.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * SKIP_ENTRY: Failed to get the directory entries, so the caller
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * should skip this entry.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdarstatic int
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdartraverse_level_nondir(struct fs_traverse *ftp,
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar traverse_state_t *tsp, struct fst_node *pnp, dent_arg_t *darg)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar{
84bf06e9e5fd6d61897cc8c298a0f3e807b27094Reza Sabdar int pl; /* path length */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar int rv;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar struct fst_node en; /* entry node */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar longlong_t cookie_verf;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar fs_dent_info_t *dent;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar struct dirent *buf;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar size_t len = 0;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar int fd;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar rv = 0;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar pl = strlen(pnp->tn_path);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar buf = ndmp_malloc(MAX_DENT_BUF_SIZE);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (buf == NULL)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (errno);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar fd = open(tsp->ts_fh.fh_fpath, O_RDONLY);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (fd == -1) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar free(buf);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (errno);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar while (rv == 0) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar long i, n_entries;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar darg->da_end = 0;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar n_entries = 0;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar rv = fs_getdents(fd, buf, &len, pnp->tn_path, &tsp->ts_dpos,
84bf06e9e5fd6d61897cc8c298a0f3e807b27094Reza Sabdar &cookie_verf, &n_entries, darg);
5a3c8170a75e81911cf43e0eb9ad5cdabb5f1e39Reza Sabdar if (rv < 0) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar traverse_stats.fss_readdir_err++;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar NDMP_LOG(LOG_DEBUG, "Error %d on readdir(%s) pos %d",
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar rv, pnp->tn_path, tsp->ts_dpos);
65451a03349bdb7f4bf79a8f29d4065772e01caeReza Sabdar if (STOP_ONERR(ftp))
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar break;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar /*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * We cannot read the directory entry, we should
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * skip to the next directory.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar rv = SKIP_ENTRY;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar continue;
5a3c8170a75e81911cf43e0eb9ad5cdabb5f1e39Reza Sabdar } else {
5a3c8170a75e81911cf43e0eb9ad5cdabb5f1e39Reza Sabdar /* Break at the end of directory */
5a3c8170a75e81911cf43e0eb9ad5cdabb5f1e39Reza Sabdar if (rv > 0)
5a3c8170a75e81911cf43e0eb9ad5cdabb5f1e39Reza Sabdar rv = 0;
5a3c8170a75e81911cf43e0eb9ad5cdabb5f1e39Reza Sabdar else
5a3c8170a75e81911cf43e0eb9ad5cdabb5f1e39Reza Sabdar break;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar /* LINTED imporper alignment */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar dent = (fs_dent_info_t *)darg->da_buf;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar /* LINTED imporper alignment */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar for (i = 0; i < n_entries; i++, dent = (fs_dent_info_t *)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar ((char *)dent + dent->fd_len)) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (VERBOSE(ftp))
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar NDMP_LOG(LOG_DEBUG, "i %u dname: \"%s\"",
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar dent->fd_fh.fh_fid, dent->fd_name);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if ((pl + strlen(dent->fd_name)) > PATH_MAX) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar traverse_stats.fss_longpath_err++;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar NDMP_LOG(LOG_ERR, "Path %s/%s is too long.",
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar pnp->tn_path, dent->fd_name);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (STOP_ONLONG(ftp))
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar rv = -ENAMETOOLONG;
84bf06e9e5fd6d61897cc8c298a0f3e807b27094Reza Sabdar free(dent->fd_fh.fh_fpath);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar continue;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar /*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * The entry is not a directory so the callback
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * function must be called.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (!S_ISDIR(dent->fd_attr.st_mode)) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar traverse_stats.fss_nondir_calls++;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar en.tn_path = dent->fd_name;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar en.tn_fh = &dent->fd_fh;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar en.tn_st = &dent->fd_attr;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar rv = CALLBACK(pnp, &en);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar dent->fd_fh.fh_fpath = NULL;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (rv < 0)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar break;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (rv == FST_SKIP) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar traverse_stats.fss_nondir_skipped++;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar break;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar free(buf);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar (void) close(fd);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (rv);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar}
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar/*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Traverse the file system in the level-order way. The description
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * and example is in the header file.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdarint
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdartraverse_level(struct fs_traverse *ftp)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar{
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar char path[PATH_MAX + 1]; /* full path name of the current dir */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar char nm[NAME_MAX + 1]; /* directory entry name */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar char *lp; /* last position on the path */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar int next_dir, rv;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar int pl, el; /* path and directory entry length */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar cstack_t *sp;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar fs_fhandle_t pfh, efh;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar struct stat64 pst, est;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar traverse_state_t *tsp;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar struct fst_node pn, en; /* parent and entry nodes */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar dent_arg_t darg;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (!ftp || !ftp->ft_path || !*ftp->ft_path || !ftp->ft_callbk) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar NDMP_LOG(LOG_DEBUG, "Invalid argument");
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar errno = EINVAL;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (-1);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar /* set the default log function if it's not already set */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (!ftp->ft_logfp) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar ftp->ft_logfp = (ft_log_t)syslog;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar NDMP_LOG(LOG_DEBUG, "Log to system log \"%s\"", ftp->ft_path);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (!ftp->ft_lpath) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar NDMP_LOG(LOG_DEBUG,
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar "report the same paths \"%s\"", ftp->ft_path);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar ftp->ft_lpath = ftp->ft_path;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar pl = strlen(ftp->ft_lpath);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (pl + 1 > PATH_MAX) { /* +1 for the '/' */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar NDMP_LOG(LOG_DEBUG, "lpath too long \"%s\"", ftp->ft_path);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar errno = ENAMETOOLONG;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (-1);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar (void) strcpy(path, ftp->ft_lpath);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar (void) memset(&pfh, 0, sizeof (pfh));
84bf06e9e5fd6d61897cc8c298a0f3e807b27094Reza Sabdar rv = fs_getstat(ftp->ft_lpath, &pfh, &pst);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (rv != 0) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar NDMP_LOG(LOG_DEBUG,
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar "Error %d on fs_getstat(%s)", rv, ftp->ft_path);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (-1);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar en.tn_path = NULL;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar en.tn_fh = NULL;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar en.tn_st = NULL;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (!S_ISDIR(pst.st_mode)) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar pn.tn_path = ftp->ft_lpath;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar pn.tn_fh = &pfh;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar pn.tn_st = &pst;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar rv = CALLBACK(&pn, &en);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (VERBOSE(ftp))
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar NDMP_LOG(LOG_DEBUG, "CALLBACK(%s): %d", pn.tn_path, rv);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar free(pfh.fh_fpath);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (rv);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar sp = cstack_new();
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (!sp) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar free(pfh.fh_fpath);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar errno = ENOMEM;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (-1);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar tsp = new_tsp(path);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (!tsp) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar cstack_delete(sp);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar free(pfh.fh_fpath);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar errno = ENOMEM;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (-1);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar darg.da_buf = ndmp_malloc(MAX_DENT_BUF_SIZE);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (!darg.da_buf) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar cstack_delete(sp);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar free(pfh.fh_fpath);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar free(tsp);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar errno = ENOMEM;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (-1);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar darg.da_size = MAX_DENT_BUF_SIZE;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar tsp->ts_ent = tsp->ts_end;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar tsp->ts_fh = pfh;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar tsp->ts_st = pst;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar pn.tn_path = path;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar pn.tn_fh = &tsp->ts_fh;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar pn.tn_st = &tsp->ts_st;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar /* call the callback function on the path itself */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar traverse_stats.fss_dir_calls++;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar rv = CALLBACK(&pn, &en);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (rv < 0) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar free(tsp);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar goto end;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (rv == FST_SKIP) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar traverse_stats.fss_dir_skipped++;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar free(tsp);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar rv = 0;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar goto end;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar rv = 0;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar next_dir = 1;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar do {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (next_dir) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar traverse_stats.fss_newdirs++;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar *tsp->ts_end = '\0';
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (VERBOSE(ftp))
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar NDMP_LOG(LOG_DEBUG, "pl %d \"%s\"", pl, path);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar rv = traverse_level_nondir(ftp, tsp, &pn, &darg);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (rv < 0) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar NEGATE(rv);
84bf06e9e5fd6d61897cc8c298a0f3e807b27094Reza Sabdar free(tsp->ts_fh.fh_fpath);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar free(tsp);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar break;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar /*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * If skipped by the callback function or
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * error happened reading the information
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (rv == FST_SKIP || rv == SKIP_ENTRY) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar /*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * N.B. next_dir should be set to 0 as
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * well. This prevents the infinite loop.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * If it's not set the same directory will
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * be poped from the stack and will be
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * scanned again.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar next_dir = 0;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar rv = 0;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar goto skip_dir;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar /* re-start reading entries of the directory */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar tsp->ts_dpos = 0;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar next_dir = 0;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar do {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar el = NAME_MAX;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar rv = fs_readdir(&tsp->ts_fh, pn.tn_path,
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar &tsp->ts_dpos, nm, &el, &efh,
84bf06e9e5fd6d61897cc8c298a0f3e807b27094Reza Sabdar &est);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (rv != 0) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar traverse_stats.fss_readdir_err++;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar NDMP_LOG(LOG_DEBUG,
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar "Error %d on readdir(%s) pos %d",
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar rv, path, tsp->ts_dpos);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (STOP_ONERR(ftp))
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar break;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar rv = SKIP_ENTRY;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar continue;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar /* done with this directory */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (el == 0)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar break;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar nm[el] = '\0';
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (rootfs_dot_or_dotdot(nm)) {
84bf06e9e5fd6d61897cc8c298a0f3e807b27094Reza Sabdar free(efh.fh_fpath);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar continue;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (VERBOSE(ftp))
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar NDMP_LOG(LOG_DEBUG, "%u dname: \"%s\"",
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar tsp->ts_dpos, nm);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (pl + 1 + el > PATH_MAX) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar /*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * The long paths were already encountered
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * when processing non-dir entries in.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * traverse_level_nondir.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * We don't increase fss_longpath_err
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * counter for them again here.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar NDMP_LOG(LOG_ERR, "Path %s/%s is too long.",
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar path, nm);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (STOP_ONLONG(ftp))
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar rv = ENAMETOOLONG;
84bf06e9e5fd6d61897cc8c298a0f3e807b27094Reza Sabdar free(efh.fh_fpath);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar continue;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
84bf06e9e5fd6d61897cc8c298a0f3e807b27094Reza Sabdar if (!S_ISDIR(est.st_mode))
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar continue;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar /*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Call the callback function for the new
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * directory found, then push the current
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * directory on to the stack. Then dive
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * into the entry found.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar traverse_stats.fss_dir_calls++;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar en.tn_path = nm;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar en.tn_fh = &efh;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar en.tn_st = &est;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar rv = CALLBACK(&pn, &en);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (rv < 0) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar NEGATE(rv);
84bf06e9e5fd6d61897cc8c298a0f3e807b27094Reza Sabdar free(efh.fh_fpath);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar break;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (rv == FST_SKIP) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar traverse_stats.fss_dir_skipped++;
84bf06e9e5fd6d61897cc8c298a0f3e807b27094Reza Sabdar free(efh.fh_fpath);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar rv = 0;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar continue;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar /*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Push the current directory on to the stack and
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * dive into the entry found.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
84bf06e9e5fd6d61897cc8c298a0f3e807b27094Reza Sabdar if (cstack_push(sp, tsp, 0)) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar rv = ENOMEM;
84bf06e9e5fd6d61897cc8c298a0f3e807b27094Reza Sabdar } else {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar traverse_stats.fss_pushes++;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar lp = tsp->ts_end;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar *tsp->ts_end = '/';
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar (void) strcpy(tsp->ts_end + 1, nm);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar tsp = new_tsp(path);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (!tsp)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar rv = ENOMEM;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar else {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar next_dir = 1;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar pl += el + 1;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar tsp->ts_fh = efh;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar tsp->ts_st = est;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar tsp->ts_ent = lp;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar pn.tn_fh = &tsp->ts_fh;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar pn.tn_st = &tsp->ts_st;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar break;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar } while (rv == 0);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar /*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * A new directory must be processed, go to the start of
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * the loop, open it and process it.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (next_dir)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar continue;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdarskip_dir:
84bf06e9e5fd6d61897cc8c298a0f3e807b27094Reza Sabdar if (tsp) {
84bf06e9e5fd6d61897cc8c298a0f3e807b27094Reza Sabdar free(tsp->ts_fh.fh_fpath);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar free(tsp);
84bf06e9e5fd6d61897cc8c298a0f3e807b27094Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (rv == SKIP_ENTRY)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar rv = 0;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (rv == 0) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (cstack_pop(sp, (void **)&tsp, (int *)NULL))
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar break;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar traverse_stats.fss_pops++;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (VERBOSE(ftp))
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar NDMP_LOG(LOG_DEBUG,
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar "Poped pl %d \"%s\"", pl, path);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar *tsp->ts_end = '\0';
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar pl = tsp->ts_end - path;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar pn.tn_fh = &tsp->ts_fh;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar pn.tn_st = &tsp->ts_st;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar } while (rv == 0);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar /*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Pop and free all the remaining entries on the stack.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar while (!cstack_pop(sp, (void **)&tsp, (int *)NULL)) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar traverse_stats.fss_stack_residue++;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
84bf06e9e5fd6d61897cc8c298a0f3e807b27094Reza Sabdar free(tsp->ts_fh.fh_fpath);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar free(tsp);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdarend:
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar free(darg.da_buf);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar cstack_delete(sp);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (rv);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar}
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar/*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * filecopy - Copy a file
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar *
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Parameters:
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * char *dest - Destination path
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * char *src - Source path
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar *
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Returns:
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * 0 - No errors
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * #0 - Error occured
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * -4 - read/write error
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * -5 - source modified during copy
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar *
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Simplified version for Solaris
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar#define BUFSIZE 32768
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdarint
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdarfilecopy(char *dest, char *src)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar{
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar FILE *src_fh = 0;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar FILE *dst_fh = 0;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar struct stat64 src_attr;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar struct stat64 dst_attr;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar char *buf = 0;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar u_longlong_t bytes_to_copy;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar size_t nbytes;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar int file_copied = 0;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar buf = ndmp_malloc(BUFSIZE);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (!buf)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (-1);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar src_fh = fopen(src, "r");
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (src_fh == 0) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar free(buf);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (-2);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar dst_fh = fopen(dest, "w");
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (dst_fh == NULL) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar free(buf);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar (void) fclose(src_fh);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (-3);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (stat64(src, &src_attr) < 0) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar free(buf);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar (void) fclose(src_fh);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar (void) fclose(dst_fh);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (-2);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar bytes_to_copy = src_attr.st_size;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar while (bytes_to_copy) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (bytes_to_copy > BUFSIZE)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar nbytes = BUFSIZE;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar else
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar nbytes = bytes_to_copy;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if ((fread(buf, nbytes, 1, src_fh) != 1) ||
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar (fwrite(buf, nbytes, 1, dst_fh) != 1))
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar break;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar bytes_to_copy -= nbytes;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar (void) fclose(src_fh);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar (void) fclose(dst_fh);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (bytes_to_copy > 0) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar free(buf);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar /* short read/write, remove the partial file */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (-4);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (stat64(src, &dst_attr) < 0) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar free(buf);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (-2);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar free(buf);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (!file_copied)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (-5); /* source modified during copy */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar else
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (0);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar}