ftree.c revision 1556
11556Srgrimes/*-
21556Srgrimes * Copyright (c) 1992 Keith Muller.
31556Srgrimes * Copyright (c) 1992, 1993
41556Srgrimes *	The Regents of the University of California.  All rights reserved.
51556Srgrimes *
61556Srgrimes * This code is derived from software contributed to Berkeley by
71556Srgrimes * Keith Muller of the University of California, San Diego.
81556Srgrimes *
91556Srgrimes * Redistribution and use in source and binary forms, with or without
101556Srgrimes * modification, are permitted provided that the following conditions
111556Srgrimes * are met:
121556Srgrimes * 1. Redistributions of source code must retain the above copyright
131556Srgrimes *    notice, this list of conditions and the following disclaimer.
141556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
151556Srgrimes *    notice, this list of conditions and the following disclaimer in the
161556Srgrimes *    documentation and/or other materials provided with the distribution.
171556Srgrimes * 3. All advertising materials mentioning features or use of this software
181556Srgrimes *    must display the following acknowledgement:
191556Srgrimes *	This product includes software developed by the University of
201556Srgrimes *	California, Berkeley and its contributors.
211556Srgrimes * 4. Neither the name of the University nor the names of its contributors
221556Srgrimes *    may be used to endorse or promote products derived from this software
231556Srgrimes *    without specific prior written permission.
241556Srgrimes *
251556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
261556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
271556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
281556Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
291556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
301556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
311556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
321556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
331556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
341556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
351556Srgrimes * SUCH DAMAGE.
361556Srgrimes */
371556Srgrimes
381556Srgrimes#ifndef lint
391556Srgrimesstatic char sccsid[] = "@(#)ftree.c	8.2 (Berkeley) 4/18/94";
401556Srgrimes#endif /* not lint */
411556Srgrimes
421556Srgrimes#include <sys/types.h>
431556Srgrimes#include <sys/time.h>
441556Srgrimes#include <sys/stat.h>
451556Srgrimes#include <sys/param.h>
461556Srgrimes#include <unistd.h>
471556Srgrimes#include <string.h>
481556Srgrimes#include <stdio.h>
491556Srgrimes#include <ctype.h>
501556Srgrimes#include <errno.h>
511556Srgrimes#include <stdlib.h>
521556Srgrimes#include <fts.h>
531556Srgrimes#include "pax.h"
541556Srgrimes#include "ftree.h"
551556Srgrimes#include "extern.h"
561556Srgrimes
571556Srgrimes/*
581556Srgrimes * routines to interface with the fts library function.
591556Srgrimes *
601556Srgrimes * file args supplied to pax are stored on a single linked list (of type FTREE)
611556Srgrimes * and given to fts to be processed one at a time. pax "selects" files from
621556Srgrimes * the expansion of each arg into the corresponding file tree (if the arg is a
631556Srgrimes * directory, otherwise the node itself is just passed to pax). The selection
641556Srgrimes * is modified by the -n and -u flags. The user is informed when a specific
651556Srgrimes * file arg does not generate any selected files. -n keeps expanding the file
661556Srgrimes * tree arg until one of its files is selected, then skips to the next file
671556Srgrimes * arg. when the user does not supply the file trees as command line args to
681556Srgrimes * pax, they are read from stdin
691556Srgrimes */
701556Srgrimes
711556Srgrimesstatic FTS *ftsp = NULL;		/* curent FTS handle */
721556Srgrimesstatic int ftsopts;			/* options to be used on fts_open */
731556Srgrimesstatic char *farray[2];			/* array for passing each arg to fts */
741556Srgrimesstatic FTREE *fthead = NULL;		/* head of linked list of file args */
751556Srgrimesstatic FTREE *fttail = NULL;		/* tail of linked list of file args */
761556Srgrimesstatic FTREE *ftcur = NULL;		/* current file arg being processed */
771556Srgrimesstatic FTSENT *ftent = NULL;		/* current file tree entry */
781556Srgrimesstatic int ftree_skip;			/* when set skip to next file arg */
791556Srgrimes
801556Srgrimesstatic int ftree_arg __P((void));
811556Srgrimes
821556Srgrimes/*
831556Srgrimes * ftree_start()
841556Srgrimes *	initialize the options passed to fts_open() during this run of pax
851556Srgrimes *	options are based on the selection of pax options by the user
861556Srgrimes *	fts_start() also calls fts_arg() to open the first valid file arg. We
871556Srgrimes *	also attempt to reset directory access times when -t (tflag) is set.
881556Srgrimes * Return:
891556Srgrimes *	0 if there is at least one valid file arg to process, -1 otherwise
901556Srgrimes */
911556Srgrimes
921556Srgrimes#if __STDC__
931556Srgrimesint
941556Srgrimesftree_start(void)
951556Srgrimes#else
961556Srgrimesint
971556Srgrimesftree_start()
981556Srgrimes#endif
991556Srgrimes{
1001556Srgrimes	/*
1011556Srgrimes	 * set up the operation mode of fts, open the first file arg. We must
1021556Srgrimes	 * use FTS_NOCHDIR, as the user may have to open multiple archives and
1031556Srgrimes	 * if fts did a chdir off into the boondocks, we may create an archive
1041556Srgrimes	 * volume in an place where the user did not expect to.
1051556Srgrimes	 */
1061556Srgrimes	ftsopts = FTS_NOCHDIR;
1071556Srgrimes
1081556Srgrimes	/*
1091556Srgrimes	 * optional user flags that effect file traversal
1101556Srgrimes	 * -H command line symlink follow only (half follow)
1111556Srgrimes	 * -L follow sylinks (logical)
1121556Srgrimes	 * -P do not follow sylinks (physical). This is the default.
1131556Srgrimes	 * -X do not cross over mount points
1141556Srgrimes	 * -t preserve access times on files read.
1151556Srgrimes	 * -n select only the first member of a file tree when a match is found
1161556Srgrimes	 * -d do not extract subtrees rooted at a directory arg.
1171556Srgrimes	 */
1181556Srgrimes	if (Lflag)
1191556Srgrimes		ftsopts |= FTS_LOGICAL;
1201556Srgrimes	else
1211556Srgrimes		ftsopts |= FTS_PHYSICAL;
1221556Srgrimes	if (Hflag)
1231556Srgrimes#	ifdef NET2_FTS
1241556Srgrimes		warn(0, "The -H flag is not supported on this version");
1251556Srgrimes#	else
1261556Srgrimes		ftsopts |= FTS_COMFOLLOW;
1271556Srgrimes#	endif
1281556Srgrimes	if (Xflag)
1291556Srgrimes		ftsopts |= FTS_XDEV;
1301556Srgrimes
1311556Srgrimes	if ((fthead == NULL) && ((farray[0] = malloc(PAXPATHLEN+2)) == NULL)) {
1321556Srgrimes		warn(1, "Unable to allocate memory for file name buffer");
1331556Srgrimes		return(-1);
1341556Srgrimes	}
1351556Srgrimes
1361556Srgrimes	if (ftree_arg() < 0)
1371556Srgrimes		return(-1);
1381556Srgrimes	if (tflag && (atdir_start() < 0))
1391556Srgrimes		return(-1);
1401556Srgrimes	return(0);
1411556Srgrimes}
1421556Srgrimes
1431556Srgrimes/*
1441556Srgrimes * ftree_add()
1451556Srgrimes *	add the arg to the linked list of files to process. Each will be
1461556Srgrimes *	processed by fts one at a time
1471556Srgrimes * Return:
1481556Srgrimes *	0 if added to the linked list, -1 if failed
1491556Srgrimes */
1501556Srgrimes
1511556Srgrimes#if __STDC__
1521556Srgrimesint
1531556Srgrimesftree_add(register char *str)
1541556Srgrimes#else
1551556Srgrimesint
1561556Srgrimesftree_add(str)
1571556Srgrimes	register char *str;
1581556Srgrimes#endif
1591556Srgrimes{
1601556Srgrimes	register FTREE *ft;
1611556Srgrimes	register int len;
1621556Srgrimes
1631556Srgrimes	/*
1641556Srgrimes	 * simple check for bad args
1651556Srgrimes	 */
1661556Srgrimes	if ((str == NULL) || (*str == '\0')) {
1671556Srgrimes		warn(0, "Invalid file name arguement");
1681556Srgrimes		return(-1);
1691556Srgrimes	}
1701556Srgrimes
1711556Srgrimes	/*
1721556Srgrimes	 * allocate FTREE node and add to the end of the linked list (args are
1731556Srgrimes	 * processed in the same order they were passed to pax). Get rid of any
1741556Srgrimes	 * trailing / the user may pass us. (watch out for / by itself).
1751556Srgrimes	 */
1761556Srgrimes	if ((ft = (FTREE *)malloc(sizeof(FTREE))) == NULL) {
1771556Srgrimes		warn(0, "Unable to allocate memory for filename");
1781556Srgrimes		return(-1);
1791556Srgrimes	}
1801556Srgrimes
1811556Srgrimes	if (((len = strlen(str) - 1) > 0) && (str[len] == '/'))
1821556Srgrimes		str[len] = '\0';
1831556Srgrimes	ft->fname = str;
1841556Srgrimes	ft->refcnt = 0;
1851556Srgrimes	ft->fow = NULL;
1861556Srgrimes	if (fthead == NULL) {
1871556Srgrimes		fttail = fthead = ft;
1881556Srgrimes		return(0);
1891556Srgrimes	}
1901556Srgrimes	fttail->fow = ft;
1911556Srgrimes	fttail = ft;
1921556Srgrimes	return(0);
1931556Srgrimes}
1941556Srgrimes
1951556Srgrimes/*
1961556Srgrimes * ftree_sel()
1971556Srgrimes *	this entry has been selected by pax. bump up reference count and handle
1981556Srgrimes *	-n and -d processing.
1991556Srgrimes */
2001556Srgrimes
2011556Srgrimes#if __STDC__
2021556Srgrimesvoid
2031556Srgrimesftree_sel(register ARCHD *arcn)
2041556Srgrimes#else
2051556Srgrimesvoid
2061556Srgrimesftree_sel(arcn)
2071556Srgrimes	register ARCHD *arcn;
2081556Srgrimes#endif
2091556Srgrimes{
2101556Srgrimes	/*
2111556Srgrimes	 * set reference bit for this pattern. This linked list is only used
2121556Srgrimes	 * when file trees are supplied pax as args. The list is not used when
2131556Srgrimes	 * the trees are read from stdin.
2141556Srgrimes	 */
2151556Srgrimes	if (ftcur != NULL)
2161556Srgrimes		ftcur->refcnt = 1;
2171556Srgrimes
2181556Srgrimes	/*
2191556Srgrimes	 * if -n we are done with this arg, force a skip to the next arg when
2201556Srgrimes	 * pax asks for the next file in next_file().
2211556Srgrimes	 * if -d we tell fts only to match the directory (if the arg is a dir)
2221556Srgrimes	 * and not the entire file tree rooted at that point.
2231556Srgrimes	 */
2241556Srgrimes	if (nflag)
2251556Srgrimes		ftree_skip = 1;
2261556Srgrimes
2271556Srgrimes	if (!dflag || (arcn->type != PAX_DIR))
2281556Srgrimes		return;
2291556Srgrimes
2301556Srgrimes	if (ftent != NULL)
2311556Srgrimes		(void)fts_set(ftsp, ftent, FTS_SKIP);
2321556Srgrimes}
2331556Srgrimes
2341556Srgrimes/*
2351556Srgrimes * ftree_chk()
2361556Srgrimes *	called at end on pax execution. Prints all those file args that did not
2371556Srgrimes *	have a selected member (reference count still 0)
2381556Srgrimes */
2391556Srgrimes
2401556Srgrimes#if __STDC__
2411556Srgrimesvoid
2421556Srgrimesftree_chk(void)
2431556Srgrimes#else
2441556Srgrimesvoid
2451556Srgrimesftree_chk()
2461556Srgrimes#endif
2471556Srgrimes{
2481556Srgrimes	register FTREE *ft;
2491556Srgrimes	register int wban = 0;
2501556Srgrimes
2511556Srgrimes	/*
2521556Srgrimes	 * make sure all dir access times were reset.
2531556Srgrimes	 */
2541556Srgrimes	if (tflag)
2551556Srgrimes		atdir_end();
2561556Srgrimes
2571556Srgrimes	/*
2581556Srgrimes	 * walk down list and check reference count. Print out those members
2591556Srgrimes	 * that never had a match
2601556Srgrimes	 */
2611556Srgrimes	for (ft = fthead; ft != NULL; ft = ft->fow) {
2621556Srgrimes		if (ft->refcnt > 0)
2631556Srgrimes			continue;
2641556Srgrimes		if (wban == 0) {
2651556Srgrimes			warn(1,"WARNING! These file names were not selected:");
2661556Srgrimes			++wban;
2671556Srgrimes		}
2681556Srgrimes		(void)fprintf(stderr, "%s\n", ft->fname);
2691556Srgrimes	}
2701556Srgrimes}
2711556Srgrimes
2721556Srgrimes/*
2731556Srgrimes * ftree_arg()
2741556Srgrimes *	Get the next file arg for fts to process. Can be from either the linked
2751556Srgrimes *	list or read from stdin when the user did not them as args to pax. Each
2761556Srgrimes *	arg is processed until the first successful fts_open().
2771556Srgrimes * Return:
2781556Srgrimes *	0 when the next arg is ready to go, -1 if out of file args (or EOF on
2791556Srgrimes *	stdin).
2801556Srgrimes */
2811556Srgrimes
2821556Srgrimes#if __STDC__
2831556Srgrimesstatic int
2841556Srgrimesftree_arg(void)
2851556Srgrimes#else
2861556Srgrimesstatic int
2871556Srgrimesftree_arg()
2881556Srgrimes#endif
2891556Srgrimes{
2901556Srgrimes	register char *pt;
2911556Srgrimes
2921556Srgrimes	/*
2931556Srgrimes	 * close off the current file tree
2941556Srgrimes	 */
2951556Srgrimes	if (ftsp != NULL) {
2961556Srgrimes		(void)fts_close(ftsp);
2971556Srgrimes		ftsp = NULL;
2981556Srgrimes	}
2991556Srgrimes
3001556Srgrimes	/*
3011556Srgrimes	 * keep looping until we get a valid file tree to process. Stop when we
3021556Srgrimes	 * reach the end of the list (or get an eof on stdin)
3031556Srgrimes	 */
3041556Srgrimes	for(;;) {
3051556Srgrimes		if (fthead == NULL) {
3061556Srgrimes			/*
3071556Srgrimes			 * the user didn't supply any args, get the file trees
3081556Srgrimes			 * to process from stdin;
3091556Srgrimes			 */
3101556Srgrimes			if (fgets(farray[0], PAXPATHLEN+1, stdin) == NULL)
3111556Srgrimes				return(-1);
3121556Srgrimes			if ((pt = strchr(farray[0], '\n')) != NULL)
3131556Srgrimes				*pt = '\0';
3141556Srgrimes		} else {
3151556Srgrimes			/*
3161556Srgrimes			 * the user supplied the file args as arguements to pax
3171556Srgrimes			 */
3181556Srgrimes			if (ftcur == NULL)
3191556Srgrimes				ftcur = fthead;
3201556Srgrimes			else if ((ftcur = ftcur->fow) == NULL)
3211556Srgrimes				return(-1);
3221556Srgrimes			farray[0] = ftcur->fname;
3231556Srgrimes		}
3241556Srgrimes
3251556Srgrimes		/*
3261556Srgrimes		 * watch it, fts wants the file arg stored in a array of char
3271556Srgrimes		 * ptrs, with the last one a null. we use a two element array
3281556Srgrimes		 * and set farray[0] to point at the buffer with the file name
3291556Srgrimes		 * in it. We cannnot pass all the file args to fts at one shot
3301556Srgrimes		 * as we need to keep a handle on which file arg generates what
3311556Srgrimes		 * files (the -n and -d flags need this). If the open is
3321556Srgrimes		 * successful, return a 0.
3331556Srgrimes		 */
3341556Srgrimes		if ((ftsp = fts_open(farray, ftsopts, NULL)) != NULL)
3351556Srgrimes			break;
3361556Srgrimes	}
3371556Srgrimes	return(0);
3381556Srgrimes}
3391556Srgrimes
3401556Srgrimes/*
3411556Srgrimes * next_file()
3421556Srgrimes *	supplies the next file to process in the supplied archd structure.
3431556Srgrimes * Return:
3441556Srgrimes *	0 when contents of arcn have been set with the next file, -1 when done.
3451556Srgrimes */
3461556Srgrimes
3471556Srgrimes#if __STDC__
3481556Srgrimesint
3491556Srgrimesnext_file(register ARCHD *arcn)
3501556Srgrimes#else
3511556Srgrimesint
3521556Srgrimesnext_file(arcn)
3531556Srgrimes	register ARCHD *arcn;
3541556Srgrimes#endif
3551556Srgrimes{
3561556Srgrimes	register int cnt;
3571556Srgrimes	time_t atime;
3581556Srgrimes	time_t mtime;
3591556Srgrimes
3601556Srgrimes	/*
3611556Srgrimes	 * ftree_sel() might have set the ftree_skip flag if the user has the
3621556Srgrimes	 * -n option and a file was selected from this file arg tree. (-n says
3631556Srgrimes	 * only one member is matched for each pattern) ftree_skip being 1
3641556Srgrimes	 * forces us to go to the next arg now.
3651556Srgrimes	 */
3661556Srgrimes	if (ftree_skip) {
3671556Srgrimes		/*
3681556Srgrimes		 * clear and go to next arg
3691556Srgrimes		 */
3701556Srgrimes		ftree_skip = 0;
3711556Srgrimes		if (ftree_arg() < 0)
3721556Srgrimes			return(-1);
3731556Srgrimes	}
3741556Srgrimes
3751556Srgrimes	/*
3761556Srgrimes	 * loop until we get a valid file to process
3771556Srgrimes	 */
3781556Srgrimes	for(;;) {
3791556Srgrimes		if ((ftent = fts_read(ftsp)) == NULL) {
3801556Srgrimes			/*
3811556Srgrimes			 * out of files in this tree, go to next arg, if none
3821556Srgrimes			 * we are done
3831556Srgrimes			 */
3841556Srgrimes			if (ftree_arg() < 0)
3851556Srgrimes				return(-1);
3861556Srgrimes			continue;
3871556Srgrimes		}
3881556Srgrimes
3891556Srgrimes		/*
3901556Srgrimes		 * handle each type of fts_read() flag
3911556Srgrimes		 */
3921556Srgrimes		switch(ftent->fts_info) {
3931556Srgrimes		case FTS_D:
3941556Srgrimes		case FTS_DEFAULT:
3951556Srgrimes		case FTS_F:
3961556Srgrimes		case FTS_SL:
3971556Srgrimes		case FTS_SLNONE:
3981556Srgrimes			/*
3991556Srgrimes			 * these are all ok
4001556Srgrimes			 */
4011556Srgrimes			break;
4021556Srgrimes		case FTS_DP:
4031556Srgrimes			/*
4041556Srgrimes			 * already saw this directory. If the user wants file
4051556Srgrimes			 * access times reset, we use this to restore the
4061556Srgrimes			 * access time for this directory since this is the
4071556Srgrimes			 * last time we will see it in this file subtree
4081556Srgrimes			 * remember to force the time (this is -t on a read
4091556Srgrimes			 * directory, not a created directory).
4101556Srgrimes			 */
4111556Srgrimes#			ifdef NET2_FTS
4121556Srgrimes			if (!tflag || (get_atdir(ftent->fts_statb.st_dev,
4131556Srgrimes			    ftent->fts_statb.st_ino, &mtime, &atime) < 0))
4141556Srgrimes#			else
4151556Srgrimes			if (!tflag || (get_atdir(ftent->fts_statp->st_dev,
4161556Srgrimes			    ftent->fts_statp->st_ino, &mtime, &atime) < 0))
4171556Srgrimes#			endif
4181556Srgrimes				continue;
4191556Srgrimes			set_ftime(ftent->fts_path, mtime, atime, 1);
4201556Srgrimes			continue;
4211556Srgrimes		case FTS_DC:
4221556Srgrimes			/*
4231556Srgrimes			 * fts claims a file system cycle
4241556Srgrimes			 */
4251556Srgrimes			warn(1,"File system cycle found at %s",ftent->fts_path);
4261556Srgrimes			continue;
4271556Srgrimes		case FTS_DNR:
4281556Srgrimes#			ifdef NET2_FTS
4291556Srgrimes			syswarn(1, errno,
4301556Srgrimes#			else
4311556Srgrimes			syswarn(1, ftent->fts_errno,
4321556Srgrimes#			endif
4331556Srgrimes			    "Unable to read directory %s", ftent->fts_path);
4341556Srgrimes			continue;
4351556Srgrimes		case FTS_ERR:
4361556Srgrimes#			ifdef NET2_FTS
4371556Srgrimes			syswarn(1, errno,
4381556Srgrimes#			else
4391556Srgrimes			syswarn(1, ftent->fts_errno,
4401556Srgrimes#			endif
4411556Srgrimes			    "File system traversal error");
4421556Srgrimes			continue;
4431556Srgrimes		case FTS_NS:
4441556Srgrimes		case FTS_NSOK:
4451556Srgrimes#			ifdef NET2_FTS
4461556Srgrimes			syswarn(1, errno,
4471556Srgrimes#			else
4481556Srgrimes			syswarn(1, ftent->fts_errno,
4491556Srgrimes#			endif
4501556Srgrimes			    "Unable to access %s", ftent->fts_path);
4511556Srgrimes			continue;
4521556Srgrimes		}
4531556Srgrimes
4541556Srgrimes		/*
4551556Srgrimes		 * ok got a file tree node to process. copy info into arcn
4561556Srgrimes		 * structure (initialize as required)
4571556Srgrimes		 */
4581556Srgrimes		arcn->skip = 0;
4591556Srgrimes		arcn->pad = 0;
4601556Srgrimes		arcn->ln_nlen = 0;
4611556Srgrimes		arcn->ln_name[0] = '\0';
4621556Srgrimes#		ifdef NET2_FTS
4631556Srgrimes		arcn->sb = ftent->fts_statb;
4641556Srgrimes#		else
4651556Srgrimes		arcn->sb = *(ftent->fts_statp);
4661556Srgrimes#		endif
4671556Srgrimes
4681556Srgrimes		/*
4691556Srgrimes		 * file type based set up and copy into the arcn struct
4701556Srgrimes		 * SIDE NOTE:
4711556Srgrimes		 * we try to reset the access time on all files and directories
4721556Srgrimes		 * we may read when the -t flag is specified. files are reset
4731556Srgrimes		 * when we close them after copying. we reset the directories
4741556Srgrimes		 * when we are done with their file tree (we also clean up at
4751556Srgrimes		 * end in case we cut short a file tree traversal). However
4761556Srgrimes		 * there is no way to reset access times on symlinks.
4771556Srgrimes		 */
4781556Srgrimes		switch(S_IFMT & arcn->sb.st_mode) {
4791556Srgrimes		case S_IFDIR:
4801556Srgrimes			arcn->type = PAX_DIR;
4811556Srgrimes			if (!tflag)
4821556Srgrimes				break;
4831556Srgrimes			add_atdir(ftent->fts_path, arcn->sb.st_dev,
4841556Srgrimes			    arcn->sb.st_ino, arcn->sb.st_mtime,
4851556Srgrimes			    arcn->sb.st_atime);
4861556Srgrimes			break;
4871556Srgrimes		case S_IFCHR:
4881556Srgrimes			arcn->type = PAX_CHR;
4891556Srgrimes			break;
4901556Srgrimes		case S_IFBLK:
4911556Srgrimes			arcn->type = PAX_BLK;
4921556Srgrimes			break;
4931556Srgrimes		case S_IFREG:
4941556Srgrimes			/*
4951556Srgrimes			 * only regular files with have data to store on the
4961556Srgrimes			 * archive. all others will store a zero length skip.
4971556Srgrimes			 * the skip field is used by pax for actual data it has
4981556Srgrimes			 * to read (or skip over).
4991556Srgrimes			 */
5001556Srgrimes			arcn->type = PAX_REG;
5011556Srgrimes			arcn->skip = arcn->sb.st_size;
5021556Srgrimes			break;
5031556Srgrimes		case S_IFLNK:
5041556Srgrimes			arcn->type = PAX_SLK;
5051556Srgrimes			/*
5061556Srgrimes			 * have to read the symlink path from the file
5071556Srgrimes			 */
5081556Srgrimes			if ((cnt = readlink(ftent->fts_path, arcn->ln_name,
5091556Srgrimes			    PAXPATHLEN)) < 0) {
5101556Srgrimes				syswarn(1, errno, "Unable to read symlink %s",
5111556Srgrimes				    ftent->fts_path);
5121556Srgrimes				continue;
5131556Srgrimes			}
5141556Srgrimes			/*
5151556Srgrimes			 * set link name length, watch out readlink does not
5161556Srgrimes			 * allways null terminate the link path
5171556Srgrimes			 */
5181556Srgrimes			arcn->ln_name[cnt] = '\0';
5191556Srgrimes			arcn->ln_nlen = cnt;
5201556Srgrimes			break;
5211556Srgrimes		case S_IFSOCK:
5221556Srgrimes			/*
5231556Srgrimes			 * under BSD storing a socket is senseless but we will
5241556Srgrimes			 * let the format specific write function make the
5251556Srgrimes			 * decision of what to do with it.
5261556Srgrimes			 */
5271556Srgrimes			arcn->type = PAX_SCK;
5281556Srgrimes			break;
5291556Srgrimes		case S_IFIFO:
5301556Srgrimes			arcn->type = PAX_FIF;
5311556Srgrimes			break;
5321556Srgrimes		}
5331556Srgrimes		break;
5341556Srgrimes	}
5351556Srgrimes
5361556Srgrimes	/*
5371556Srgrimes	 * copy file name, set file name length
5381556Srgrimes	 */
5391556Srgrimes	arcn->nlen = l_strncpy(arcn->name, ftent->fts_path, PAXPATHLEN+1);
5401556Srgrimes	arcn->name[arcn->nlen] = '\0';
5411556Srgrimes	arcn->org_name = ftent->fts_path;
5421556Srgrimes	return(0);
5431556Srgrimes}
544