ftree.c revision 46684
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 3936049Scharnier#if 0 4036049Scharnierstatic char sccsid[] = "@(#)ftree.c 8.2 (Berkeley) 4/18/94"; 4136049Scharnier#endif 4236049Scharnierstatic const char rcsid[] = 4346684Skris "$Id: ftree.c,v 1.11 1998/06/09 03:38:43 imp Exp $"; 441556Srgrimes#endif /* not lint */ 451556Srgrimes 461556Srgrimes#include <sys/types.h> 471556Srgrimes#include <sys/time.h> 481556Srgrimes#include <sys/stat.h> 491556Srgrimes#include <unistd.h> 501556Srgrimes#include <string.h> 511556Srgrimes#include <stdio.h> 521556Srgrimes#include <errno.h> 531556Srgrimes#include <stdlib.h> 541556Srgrimes#include <fts.h> 551556Srgrimes#include "pax.h" 561556Srgrimes#include "ftree.h" 571556Srgrimes#include "extern.h" 581556Srgrimes 591556Srgrimes/* 601556Srgrimes * routines to interface with the fts library function. 611556Srgrimes * 621556Srgrimes * file args supplied to pax are stored on a single linked list (of type FTREE) 631556Srgrimes * and given to fts to be processed one at a time. pax "selects" files from 641556Srgrimes * the expansion of each arg into the corresponding file tree (if the arg is a 651556Srgrimes * directory, otherwise the node itself is just passed to pax). The selection 661556Srgrimes * is modified by the -n and -u flags. The user is informed when a specific 671556Srgrimes * file arg does not generate any selected files. -n keeps expanding the file 681556Srgrimes * tree arg until one of its files is selected, then skips to the next file 691556Srgrimes * arg. when the user does not supply the file trees as command line args to 701556Srgrimes * pax, they are read from stdin 711556Srgrimes */ 721556Srgrimes 7346684Skrisstatic FTS *ftsp = NULL; /* current FTS handle */ 741556Srgrimesstatic int ftsopts; /* options to be used on fts_open */ 751556Srgrimesstatic char *farray[2]; /* array for passing each arg to fts */ 761556Srgrimesstatic FTREE *fthead = NULL; /* head of linked list of file args */ 771556Srgrimesstatic FTREE *fttail = NULL; /* tail of linked list of file args */ 781556Srgrimesstatic FTREE *ftcur = NULL; /* current file arg being processed */ 791556Srgrimesstatic FTSENT *ftent = NULL; /* current file tree entry */ 801556Srgrimesstatic int ftree_skip; /* when set skip to next file arg */ 811556Srgrimes 821556Srgrimesstatic int ftree_arg __P((void)); 831556Srgrimes 841556Srgrimes/* 851556Srgrimes * ftree_start() 861556Srgrimes * initialize the options passed to fts_open() during this run of pax 871556Srgrimes * options are based on the selection of pax options by the user 881556Srgrimes * fts_start() also calls fts_arg() to open the first valid file arg. We 891556Srgrimes * also attempt to reset directory access times when -t (tflag) is set. 901556Srgrimes * Return: 911556Srgrimes * 0 if there is at least one valid file arg to process, -1 otherwise 921556Srgrimes */ 931556Srgrimes 941556Srgrimes#if __STDC__ 951556Srgrimesint 961556Srgrimesftree_start(void) 971556Srgrimes#else 981556Srgrimesint 991556Srgrimesftree_start() 1001556Srgrimes#endif 1011556Srgrimes{ 1021556Srgrimes /* 1031556Srgrimes * set up the operation mode of fts, open the first file arg. We must 1041556Srgrimes * use FTS_NOCHDIR, as the user may have to open multiple archives and 1051556Srgrimes * if fts did a chdir off into the boondocks, we may create an archive 1061556Srgrimes * volume in an place where the user did not expect to. 1071556Srgrimes */ 1081556Srgrimes ftsopts = FTS_NOCHDIR; 1091556Srgrimes 1101556Srgrimes /* 1111556Srgrimes * optional user flags that effect file traversal 1121556Srgrimes * -H command line symlink follow only (half follow) 1131556Srgrimes * -L follow sylinks (logical) 1141556Srgrimes * -P do not follow sylinks (physical). This is the default. 1151556Srgrimes * -X do not cross over mount points 1161556Srgrimes * -t preserve access times on files read. 1171556Srgrimes * -n select only the first member of a file tree when a match is found 1181556Srgrimes * -d do not extract subtrees rooted at a directory arg. 1191556Srgrimes */ 1201556Srgrimes if (Lflag) 1211556Srgrimes ftsopts |= FTS_LOGICAL; 1221556Srgrimes else 1231556Srgrimes ftsopts |= FTS_PHYSICAL; 1241556Srgrimes if (Hflag) 1251556Srgrimes# ifdef NET2_FTS 12628904Ssos pax_warn(0, "The -H flag is not supported on this version"); 1271556Srgrimes# else 1281556Srgrimes ftsopts |= FTS_COMFOLLOW; 1291556Srgrimes# endif 1301556Srgrimes if (Xflag) 1311556Srgrimes ftsopts |= FTS_XDEV; 1321556Srgrimes 1331556Srgrimes if ((fthead == NULL) && ((farray[0] = malloc(PAXPATHLEN+2)) == NULL)) { 13428904Ssos pax_warn(1, "Unable to allocate memory for file name buffer"); 1351556Srgrimes return(-1); 1361556Srgrimes } 1371556Srgrimes 1381556Srgrimes if (ftree_arg() < 0) 1391556Srgrimes return(-1); 1401556Srgrimes if (tflag && (atdir_start() < 0)) 1411556Srgrimes return(-1); 1421556Srgrimes return(0); 1431556Srgrimes} 1441556Srgrimes 1451556Srgrimes/* 1461556Srgrimes * ftree_add() 1471556Srgrimes * add the arg to the linked list of files to process. Each will be 1481556Srgrimes * processed by fts one at a time 1491556Srgrimes * Return: 1501556Srgrimes * 0 if added to the linked list, -1 if failed 1511556Srgrimes */ 1521556Srgrimes 1531556Srgrimes#if __STDC__ 1541556Srgrimesint 1551556Srgrimesftree_add(register char *str) 1561556Srgrimes#else 1571556Srgrimesint 1581556Srgrimesftree_add(str) 1591556Srgrimes register char *str; 1601556Srgrimes#endif 1611556Srgrimes{ 1621556Srgrimes register FTREE *ft; 1631556Srgrimes register int len; 1641556Srgrimes 1651556Srgrimes /* 1661556Srgrimes * simple check for bad args 1671556Srgrimes */ 1681556Srgrimes if ((str == NULL) || (*str == '\0')) { 16928904Ssos pax_warn(0, "Invalid file name arguement"); 1701556Srgrimes return(-1); 1711556Srgrimes } 1721556Srgrimes 1731556Srgrimes /* 1741556Srgrimes * allocate FTREE node and add to the end of the linked list (args are 1751556Srgrimes * processed in the same order they were passed to pax). Get rid of any 1761556Srgrimes * trailing / the user may pass us. (watch out for / by itself). 1771556Srgrimes */ 1781556Srgrimes if ((ft = (FTREE *)malloc(sizeof(FTREE))) == NULL) { 17928904Ssos pax_warn(0, "Unable to allocate memory for filename"); 1801556Srgrimes return(-1); 1811556Srgrimes } 1821556Srgrimes 1831556Srgrimes if (((len = strlen(str) - 1) > 0) && (str[len] == '/')) 1841556Srgrimes str[len] = '\0'; 1851556Srgrimes ft->fname = str; 1861556Srgrimes ft->refcnt = 0; 1871556Srgrimes ft->fow = NULL; 1881556Srgrimes if (fthead == NULL) { 1891556Srgrimes fttail = fthead = ft; 1901556Srgrimes return(0); 1911556Srgrimes } 1921556Srgrimes fttail->fow = ft; 1931556Srgrimes fttail = ft; 1941556Srgrimes return(0); 1951556Srgrimes} 1961556Srgrimes 1971556Srgrimes/* 1981556Srgrimes * ftree_sel() 1991556Srgrimes * this entry has been selected by pax. bump up reference count and handle 2001556Srgrimes * -n and -d processing. 2011556Srgrimes */ 2021556Srgrimes 2031556Srgrimes#if __STDC__ 2041556Srgrimesvoid 2051556Srgrimesftree_sel(register ARCHD *arcn) 2061556Srgrimes#else 2071556Srgrimesvoid 2081556Srgrimesftree_sel(arcn) 2091556Srgrimes register ARCHD *arcn; 2101556Srgrimes#endif 2111556Srgrimes{ 2121556Srgrimes /* 2131556Srgrimes * set reference bit for this pattern. This linked list is only used 2141556Srgrimes * when file trees are supplied pax as args. The list is not used when 2151556Srgrimes * the trees are read from stdin. 2161556Srgrimes */ 2178855Srgrimes if (ftcur != NULL) 2181556Srgrimes ftcur->refcnt = 1; 2191556Srgrimes 2201556Srgrimes /* 2211556Srgrimes * if -n we are done with this arg, force a skip to the next arg when 2221556Srgrimes * pax asks for the next file in next_file(). 2231556Srgrimes * if -d we tell fts only to match the directory (if the arg is a dir) 2241556Srgrimes * and not the entire file tree rooted at that point. 2251556Srgrimes */ 2261556Srgrimes if (nflag) 2271556Srgrimes ftree_skip = 1; 2281556Srgrimes 2291556Srgrimes if (!dflag || (arcn->type != PAX_DIR)) 2301556Srgrimes return; 2311556Srgrimes 2321556Srgrimes if (ftent != NULL) 2331556Srgrimes (void)fts_set(ftsp, ftent, FTS_SKIP); 2341556Srgrimes} 2351556Srgrimes 2361556Srgrimes/* 2371556Srgrimes * ftree_chk() 2381556Srgrimes * called at end on pax execution. Prints all those file args that did not 2391556Srgrimes * have a selected member (reference count still 0) 2401556Srgrimes */ 2411556Srgrimes 2421556Srgrimes#if __STDC__ 2431556Srgrimesvoid 2441556Srgrimesftree_chk(void) 2451556Srgrimes#else 2461556Srgrimesvoid 2471556Srgrimesftree_chk() 2481556Srgrimes#endif 2491556Srgrimes{ 2501556Srgrimes register FTREE *ft; 2511556Srgrimes register int wban = 0; 2521556Srgrimes 2531556Srgrimes /* 2541556Srgrimes * make sure all dir access times were reset. 2551556Srgrimes */ 2561556Srgrimes if (tflag) 2571556Srgrimes atdir_end(); 2581556Srgrimes 2591556Srgrimes /* 2601556Srgrimes * walk down list and check reference count. Print out those members 2611556Srgrimes * that never had a match 2621556Srgrimes */ 2631556Srgrimes for (ft = fthead; ft != NULL; ft = ft->fow) { 2641556Srgrimes if (ft->refcnt > 0) 2651556Srgrimes continue; 2661556Srgrimes if (wban == 0) { 26728904Ssos pax_warn(1,"WARNING! These file names were not selected:"); 2681556Srgrimes ++wban; 2691556Srgrimes } 2701556Srgrimes (void)fprintf(stderr, "%s\n", ft->fname); 2711556Srgrimes } 2721556Srgrimes} 2731556Srgrimes 2741556Srgrimes/* 2751556Srgrimes * ftree_arg() 2761556Srgrimes * Get the next file arg for fts to process. Can be from either the linked 2771556Srgrimes * list or read from stdin when the user did not them as args to pax. Each 2781556Srgrimes * arg is processed until the first successful fts_open(). 2791556Srgrimes * Return: 2801556Srgrimes * 0 when the next arg is ready to go, -1 if out of file args (or EOF on 2811556Srgrimes * stdin). 2821556Srgrimes */ 2831556Srgrimes 2841556Srgrimes#if __STDC__ 2851556Srgrimesstatic int 2861556Srgrimesftree_arg(void) 2871556Srgrimes#else 2881556Srgrimesstatic int 2891556Srgrimesftree_arg() 2901556Srgrimes#endif 2911556Srgrimes{ 2921556Srgrimes register char *pt; 2931556Srgrimes 2941556Srgrimes /* 2951556Srgrimes * close off the current file tree 2961556Srgrimes */ 2971556Srgrimes if (ftsp != NULL) { 2981556Srgrimes (void)fts_close(ftsp); 2991556Srgrimes ftsp = NULL; 3001556Srgrimes } 3011556Srgrimes 3021556Srgrimes /* 3031556Srgrimes * keep looping until we get a valid file tree to process. Stop when we 3041556Srgrimes * reach the end of the list (or get an eof on stdin) 3051556Srgrimes */ 3061556Srgrimes for(;;) { 3071556Srgrimes if (fthead == NULL) { 3081556Srgrimes /* 3091556Srgrimes * the user didn't supply any args, get the file trees 3108855Srgrimes * to process from stdin; 3111556Srgrimes */ 3121556Srgrimes if (fgets(farray[0], PAXPATHLEN+1, stdin) == NULL) 3131556Srgrimes return(-1); 3141556Srgrimes if ((pt = strchr(farray[0], '\n')) != NULL) 3151556Srgrimes *pt = '\0'; 3161556Srgrimes } else { 3171556Srgrimes /* 3181556Srgrimes * the user supplied the file args as arguements to pax 3191556Srgrimes */ 3201556Srgrimes if (ftcur == NULL) 3211556Srgrimes ftcur = fthead; 3221556Srgrimes else if ((ftcur = ftcur->fow) == NULL) 3231556Srgrimes return(-1); 3241556Srgrimes farray[0] = ftcur->fname; 3251556Srgrimes } 3261556Srgrimes 3271556Srgrimes /* 3281556Srgrimes * watch it, fts wants the file arg stored in a array of char 3291556Srgrimes * ptrs, with the last one a null. we use a two element array 3301556Srgrimes * and set farray[0] to point at the buffer with the file name 33146684Skris * in it. We cannot pass all the file args to fts at one shot 3321556Srgrimes * as we need to keep a handle on which file arg generates what 3331556Srgrimes * files (the -n and -d flags need this). If the open is 3341556Srgrimes * successful, return a 0. 3351556Srgrimes */ 3361556Srgrimes if ((ftsp = fts_open(farray, ftsopts, NULL)) != NULL) 3371556Srgrimes break; 3381556Srgrimes } 3391556Srgrimes return(0); 3401556Srgrimes} 3411556Srgrimes 3421556Srgrimes/* 3431556Srgrimes * next_file() 3441556Srgrimes * supplies the next file to process in the supplied archd structure. 3451556Srgrimes * Return: 3461556Srgrimes * 0 when contents of arcn have been set with the next file, -1 when done. 3471556Srgrimes */ 3481556Srgrimes 3491556Srgrimes#if __STDC__ 3501556Srgrimesint 3511556Srgrimesnext_file(register ARCHD *arcn) 3521556Srgrimes#else 3531556Srgrimesint 3541556Srgrimesnext_file(arcn) 3551556Srgrimes register ARCHD *arcn; 3561556Srgrimes#endif 3571556Srgrimes{ 3581556Srgrimes register int cnt; 3591556Srgrimes time_t atime; 3601556Srgrimes time_t mtime; 3611556Srgrimes 3621556Srgrimes /* 3631556Srgrimes * ftree_sel() might have set the ftree_skip flag if the user has the 3641556Srgrimes * -n option and a file was selected from this file arg tree. (-n says 3658855Srgrimes * only one member is matched for each pattern) ftree_skip being 1 3661556Srgrimes * forces us to go to the next arg now. 3671556Srgrimes */ 3681556Srgrimes if (ftree_skip) { 3691556Srgrimes /* 3701556Srgrimes * clear and go to next arg 3711556Srgrimes */ 3721556Srgrimes ftree_skip = 0; 3731556Srgrimes if (ftree_arg() < 0) 3741556Srgrimes return(-1); 3751556Srgrimes } 3761556Srgrimes 3771556Srgrimes /* 3781556Srgrimes * loop until we get a valid file to process 3791556Srgrimes */ 3801556Srgrimes for(;;) { 3811556Srgrimes if ((ftent = fts_read(ftsp)) == NULL) { 3821556Srgrimes /* 3831556Srgrimes * out of files in this tree, go to next arg, if none 3841556Srgrimes * we are done 3851556Srgrimes */ 3861556Srgrimes if (ftree_arg() < 0) 3871556Srgrimes return(-1); 3881556Srgrimes continue; 3891556Srgrimes } 3901556Srgrimes 3911556Srgrimes /* 3921556Srgrimes * handle each type of fts_read() flag 3931556Srgrimes */ 3941556Srgrimes switch(ftent->fts_info) { 3951556Srgrimes case FTS_D: 3961556Srgrimes case FTS_DEFAULT: 3971556Srgrimes case FTS_F: 3981556Srgrimes case FTS_SL: 3991556Srgrimes case FTS_SLNONE: 4001556Srgrimes /* 4011556Srgrimes * these are all ok 4021556Srgrimes */ 4031556Srgrimes break; 4041556Srgrimes case FTS_DP: 4051556Srgrimes /* 4061556Srgrimes * already saw this directory. If the user wants file 4071556Srgrimes * access times reset, we use this to restore the 4081556Srgrimes * access time for this directory since this is the 4091556Srgrimes * last time we will see it in this file subtree 4101556Srgrimes * remember to force the time (this is -t on a read 4111556Srgrimes * directory, not a created directory). 4121556Srgrimes */ 4131556Srgrimes# ifdef NET2_FTS 4141556Srgrimes if (!tflag || (get_atdir(ftent->fts_statb.st_dev, 4151556Srgrimes ftent->fts_statb.st_ino, &mtime, &atime) < 0)) 4161556Srgrimes# else 4171556Srgrimes if (!tflag || (get_atdir(ftent->fts_statp->st_dev, 4181556Srgrimes ftent->fts_statp->st_ino, &mtime, &atime) < 0)) 4191556Srgrimes# endif 4201556Srgrimes continue; 4211556Srgrimes set_ftime(ftent->fts_path, mtime, atime, 1); 4221556Srgrimes continue; 4231556Srgrimes case FTS_DC: 4241556Srgrimes /* 4251556Srgrimes * fts claims a file system cycle 4261556Srgrimes */ 42728904Ssos pax_warn(1,"File system cycle found at %s",ftent->fts_path); 4281556Srgrimes continue; 4291556Srgrimes case FTS_DNR: 4301556Srgrimes# ifdef NET2_FTS 43128904Ssos sys_warn(1, errno, 4321556Srgrimes# else 43328904Ssos sys_warn(1, ftent->fts_errno, 4341556Srgrimes# endif 4351556Srgrimes "Unable to read directory %s", ftent->fts_path); 4361556Srgrimes continue; 4371556Srgrimes case FTS_ERR: 4381556Srgrimes# ifdef NET2_FTS 43928904Ssos sys_warn(1, errno, 4401556Srgrimes# else 44128904Ssos sys_warn(1, ftent->fts_errno, 4421556Srgrimes# endif 4431556Srgrimes "File system traversal error"); 4441556Srgrimes continue; 4451556Srgrimes case FTS_NS: 4461556Srgrimes case FTS_NSOK: 4471556Srgrimes# ifdef NET2_FTS 44828904Ssos sys_warn(1, errno, 4491556Srgrimes# else 45028904Ssos sys_warn(1, ftent->fts_errno, 4511556Srgrimes# endif 4521556Srgrimes "Unable to access %s", ftent->fts_path); 4531556Srgrimes continue; 4541556Srgrimes } 4551556Srgrimes 4561556Srgrimes /* 4571556Srgrimes * ok got a file tree node to process. copy info into arcn 4581556Srgrimes * structure (initialize as required) 4591556Srgrimes */ 4601556Srgrimes arcn->skip = 0; 4611556Srgrimes arcn->pad = 0; 4621556Srgrimes arcn->ln_nlen = 0; 4631556Srgrimes arcn->ln_name[0] = '\0'; 4641556Srgrimes# ifdef NET2_FTS 4651556Srgrimes arcn->sb = ftent->fts_statb; 4661556Srgrimes# else 4671556Srgrimes arcn->sb = *(ftent->fts_statp); 4681556Srgrimes# endif 4691556Srgrimes 4701556Srgrimes /* 4711556Srgrimes * file type based set up and copy into the arcn struct 4721556Srgrimes * SIDE NOTE: 4731556Srgrimes * we try to reset the access time on all files and directories 4741556Srgrimes * we may read when the -t flag is specified. files are reset 4751556Srgrimes * when we close them after copying. we reset the directories 4761556Srgrimes * when we are done with their file tree (we also clean up at 4771556Srgrimes * end in case we cut short a file tree traversal). However 4781556Srgrimes * there is no way to reset access times on symlinks. 4791556Srgrimes */ 4801556Srgrimes switch(S_IFMT & arcn->sb.st_mode) { 4811556Srgrimes case S_IFDIR: 4821556Srgrimes arcn->type = PAX_DIR; 4831556Srgrimes if (!tflag) 4841556Srgrimes break; 4851556Srgrimes add_atdir(ftent->fts_path, arcn->sb.st_dev, 4861556Srgrimes arcn->sb.st_ino, arcn->sb.st_mtime, 4871556Srgrimes arcn->sb.st_atime); 4881556Srgrimes break; 4891556Srgrimes case S_IFCHR: 4901556Srgrimes arcn->type = PAX_CHR; 4911556Srgrimes break; 4921556Srgrimes case S_IFBLK: 4931556Srgrimes arcn->type = PAX_BLK; 4941556Srgrimes break; 4951556Srgrimes case S_IFREG: 4961556Srgrimes /* 4971556Srgrimes * only regular files with have data to store on the 4981556Srgrimes * archive. all others will store a zero length skip. 4991556Srgrimes * the skip field is used by pax for actual data it has 5001556Srgrimes * to read (or skip over). 5011556Srgrimes */ 5021556Srgrimes arcn->type = PAX_REG; 5031556Srgrimes arcn->skip = arcn->sb.st_size; 5041556Srgrimes break; 5051556Srgrimes case S_IFLNK: 5061556Srgrimes arcn->type = PAX_SLK; 5071556Srgrimes /* 5081556Srgrimes * have to read the symlink path from the file 5091556Srgrimes */ 5101556Srgrimes if ((cnt = readlink(ftent->fts_path, arcn->ln_name, 51136784Simp PAXPATHLEN - 1)) < 0) { 51228904Ssos sys_warn(1, errno, "Unable to read symlink %s", 5131556Srgrimes ftent->fts_path); 5141556Srgrimes continue; 5151556Srgrimes } 5161556Srgrimes /* 5171556Srgrimes * set link name length, watch out readlink does not 51846684Skris * always NUL terminate the link path 5191556Srgrimes */ 5201556Srgrimes arcn->ln_name[cnt] = '\0'; 5211556Srgrimes arcn->ln_nlen = cnt; 5221556Srgrimes break; 5231556Srgrimes case S_IFSOCK: 5241556Srgrimes /* 5251556Srgrimes * under BSD storing a socket is senseless but we will 5261556Srgrimes * let the format specific write function make the 5271556Srgrimes * decision of what to do with it. 5281556Srgrimes */ 5291556Srgrimes arcn->type = PAX_SCK; 5301556Srgrimes break; 5311556Srgrimes case S_IFIFO: 5321556Srgrimes arcn->type = PAX_FIF; 5331556Srgrimes break; 5341556Srgrimes } 5351556Srgrimes break; 5361556Srgrimes } 5371556Srgrimes 5381556Srgrimes /* 5391556Srgrimes * copy file name, set file name length 5401556Srgrimes */ 5411556Srgrimes arcn->nlen = l_strncpy(arcn->name, ftent->fts_path, PAXPATHLEN+1); 5421556Srgrimes arcn->name[arcn->nlen] = '\0'; 5431556Srgrimes arcn->org_name = ftent->fts_path; 5441556Srgrimes return(0); 5451556Srgrimes} 546