fts-compat.c (128946) | fts-compat.c (129052) |
---|---|
1/*- 2 * Copyright (c) 1990, 1993, 1994 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 23 unchanged lines hidden (view full) --- 32 * 33 * $OpenBSD: fts.c,v 1.22 1999/10/03 19:22:22 millert Exp $ 34 */ 35 36#if defined(LIBC_SCCS) && !defined(lint) 37static char sccsid[] = "@(#)fts.c 8.6 (Berkeley) 8/14/94"; 38#endif /* LIBC_SCCS and not lint */ 39#include <sys/cdefs.h> | 1/*- 2 * Copyright (c) 1990, 1993, 1994 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 23 unchanged lines hidden (view full) --- 32 * 33 * $OpenBSD: fts.c,v 1.22 1999/10/03 19:22:22 millert Exp $ 34 */ 35 36#if defined(LIBC_SCCS) && !defined(lint) 37static char sccsid[] = "@(#)fts.c 8.6 (Berkeley) 8/14/94"; 38#endif /* LIBC_SCCS and not lint */ 39#include <sys/cdefs.h> |
40__FBSDID("$FreeBSD: head/lib/libc/gen/fts-compat.c 128946 2004-05-05 06:33:00Z kientzle $"); | 40__FBSDID("$FreeBSD: head/lib/libc/gen/fts-compat.c 129052 2004-05-08 15:09:02Z peadar $"); |
41 42#include "namespace.h" 43#include <sys/types.h> 44#include <sys/param.h> 45#include <sys/stat.h> | 41 42#include "namespace.h" 43#include <sys/types.h> 44#include <sys/param.h> 45#include <sys/stat.h> |
46#include <sys/mount.h> |
|
46 47#include <dirent.h> 48#include <errno.h> 49#include <fcntl.h> 50#include <fts.h> 51#include <stdlib.h> 52#include <string.h> 53#include <unistd.h> --- 4 unchanged lines hidden (view full) --- 58static void fts_lfree(FTSENT *); 59static void fts_load(FTS *, FTSENT *); 60static size_t fts_maxarglen(char * const *); 61static void fts_padjust(FTS *, FTSENT *); 62static int fts_palloc(FTS *, size_t); 63static FTSENT *fts_sort(FTS *, FTSENT *, int); 64static u_short fts_stat(FTS *, FTSENT *, int); 65static int fts_safe_changedir(FTS *, FTSENT *, int, char *); | 47 48#include <dirent.h> 49#include <errno.h> 50#include <fcntl.h> 51#include <fts.h> 52#include <stdlib.h> 53#include <string.h> 54#include <unistd.h> --- 4 unchanged lines hidden (view full) --- 59static void fts_lfree(FTSENT *); 60static void fts_load(FTS *, FTSENT *); 61static size_t fts_maxarglen(char * const *); 62static void fts_padjust(FTS *, FTSENT *); 63static int fts_palloc(FTS *, size_t); 64static FTSENT *fts_sort(FTS *, FTSENT *, int); 65static u_short fts_stat(FTS *, FTSENT *, int); 66static int fts_safe_changedir(FTS *, FTSENT *, int, char *); |
67static int fts_ufslinks(FTS *sp, const FTSENT *ent); |
|
66 67#define ISDOT(a) (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2]))) 68 69#define CLR(opt) (sp->fts_options &= ~(opt)) 70#define ISSET(opt) (sp->fts_options & (opt)) 71#define SET(opt) (sp->fts_options |= (opt)) 72 73#define FCHDIR(sp, fd) (!ISSET(FTS_NOCHDIR) && fchdir(fd)) 74 75/* fts_build flags */ 76#define BCHILD 1 /* fts_children */ 77#define BNAMES 2 /* fts_children, names only */ 78#define BREAD 3 /* fts_read */ 79 | 68 69#define ISDOT(a) (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2]))) 70 71#define CLR(opt) (sp->fts_options &= ~(opt)) 72#define ISSET(opt) (sp->fts_options & (opt)) 73#define SET(opt) (sp->fts_options |= (opt)) 74 75#define FCHDIR(sp, fd) (!ISSET(FTS_NOCHDIR) && fchdir(fd)) 76 77/* fts_build flags */ 78#define BCHILD 1 /* fts_children */ 79#define BNAMES 2 /* fts_children, names only */ 80#define BREAD 3 /* fts_read */ 81 |
82/* 83 * Internal representation of FTS, including extra implementation details. 84 * The FTS returned from fts_open is ftsp_fts from this structure, and it's 85 * fts_priv in turn points back to this internal version. i.e. for a given 86 * fts_private *priv: &priv->fts_fts == (FTS *)f == priv->fts_fts.fts_priv 87 */ 88struct _fts_private { 89 FTS ftsp_fts; 90 struct statfs ftsp_statfs; 91 dev_t ftsp_dev; 92 int ftsp_linksreliable; 93}; 94 95/* 96 * The "FTS_NOSTAT" option can avoid a lot of calls to stat(2) if it knows 97 * that a directory could not possibly have subdirectories. This is decided 98 * by looking at the link count: A subdirectory would increment its parent's 99 * link count by virtue of its own ".." entry. 100 * This assumption only holds for UFS-like filesystems that implement links 101 * and directories this way, so we must punt for others. 102 */ 103 104static const char *ufslike_filesystems[] = { 105 "ufs", 106 "nfs", 107 "nfs4", 108 "ext2fs", 109 0 110}; 111 |
|
80FTS * 81fts_open(argv, options, compar) 82 char * const *argv; 83 int options; 84 int (*compar)(const FTSENT * const *, const FTSENT * const *); 85{ | 112FTS * 113fts_open(argv, options, compar) 114 char * const *argv; 115 int options; 116 int (*compar)(const FTSENT * const *, const FTSENT * const *); 117{ |
118 struct _fts_private *priv; |
|
86 FTS *sp; 87 FTSENT *p, *root; 88 int nitems; 89 FTSENT *parent, *tmp; 90 int len; 91 92 /* Options check. */ 93 if (options & ~FTS_OPTIONMASK) { 94 errno = EINVAL; 95 return (NULL); 96 } 97 98 /* Allocate/initialize the stream */ | 119 FTS *sp; 120 FTSENT *p, *root; 121 int nitems; 122 FTSENT *parent, *tmp; 123 int len; 124 125 /* Options check. */ 126 if (options & ~FTS_OPTIONMASK) { 127 errno = EINVAL; 128 return (NULL); 129 } 130 131 /* Allocate/initialize the stream */ |
99 if ((sp = malloc(sizeof(FTS))) == NULL) | 132 if ((priv = malloc(sizeof(struct _fts_private))) == NULL) |
100 return (NULL); | 133 return (NULL); |
101 memset(sp, 0, sizeof(FTS)); | 134 memset(priv, 0, sizeof(struct _fts_private)); 135 sp = &priv->ftsp_fts; |
102 sp->fts_compar = compar; 103 sp->fts_options = options; | 136 sp->fts_compar = compar; 137 sp->fts_options = options; |
138 sp->fts_priv = priv; |
|
104 105 /* Shush, GCC. */ 106 tmp = NULL; 107 108 /* Logical walks turn on NOCHDIR; symbolic links are too hard. */ 109 if (ISSET(FTS_LOGICAL)) 110 SET(FTS_NOCHDIR); 111 --- 520 unchanged lines hidden (view full) --- 632 * directory if we're cheating on stat calls, 0 if we're not doing 633 * any stat calls at all, -1 if we're doing stats on everything. 634 */ 635 if (type == BNAMES) { 636 nlinks = 0; 637 /* Be quiet about nostat, GCC. */ 638 nostat = 0; 639 } else if (ISSET(FTS_NOSTAT) && ISSET(FTS_PHYSICAL)) { | 139 140 /* Shush, GCC. */ 141 tmp = NULL; 142 143 /* Logical walks turn on NOCHDIR; symbolic links are too hard. */ 144 if (ISSET(FTS_LOGICAL)) 145 SET(FTS_NOCHDIR); 146 --- 520 unchanged lines hidden (view full) --- 667 * directory if we're cheating on stat calls, 0 if we're not doing 668 * any stat calls at all, -1 if we're doing stats on everything. 669 */ 670 if (type == BNAMES) { 671 nlinks = 0; 672 /* Be quiet about nostat, GCC. */ 673 nostat = 0; 674 } else if (ISSET(FTS_NOSTAT) && ISSET(FTS_PHYSICAL)) { |
640 nlinks = cur->fts_nlink - (ISSET(FTS_SEEDOT) ? 0 : 2); | 675 if (fts_ufslinks(sp, cur)) 676 nlinks = cur->fts_nlink - (ISSET(FTS_SEEDOT) ? 0 : 2); 677 else 678 nlinks = -1; |
641 nostat = 1; 642 } else { 643 nlinks = -1; 644 nostat = 0; 645 } 646 647#ifdef notdef 648 (void)printf("nlinks == %d (cur: %d)\n", nlinks, cur->fts_nlink); --- 500 unchanged lines hidden (view full) --- 1149 ret = fchdir(newfd); 1150bail: 1151 oerrno = errno; 1152 if (fd < 0) 1153 (void)_close(newfd); 1154 errno = oerrno; 1155 return (ret); 1156} | 679 nostat = 1; 680 } else { 681 nlinks = -1; 682 nostat = 0; 683 } 684 685#ifdef notdef 686 (void)printf("nlinks == %d (cur: %d)\n", nlinks, cur->fts_nlink); --- 500 unchanged lines hidden (view full) --- 1187 ret = fchdir(newfd); 1188bail: 1189 oerrno = errno; 1190 if (fd < 0) 1191 (void)_close(newfd); 1192 errno = oerrno; 1193 return (ret); 1194} |
1195 1196/* 1197 * Check if the filesystem for "ent" has UFS-style links. 1198 */ 1199static int 1200fts_ufslinks(FTS *sp, const FTSENT *ent) 1201{ 1202 struct _fts_private *priv; 1203 const char **cpp; 1204 1205 priv = sp->fts_priv; 1206 /* 1207 * If this node's device is different from the previous, grab 1208 * the filesystem information, and decide on the reliability 1209 * of the link information from this filesystem for stat(2) 1210 * avoidance. 1211 */ 1212 if (priv->ftsp_dev != ent->fts_dev) { 1213 if (statfs(ent->fts_path, &priv->ftsp_statfs) != -1) { 1214 priv->ftsp_dev = ent->fts_dev; 1215 priv->ftsp_linksreliable = 0; 1216 for (cpp = ufslike_filesystems; *cpp; cpp++) { 1217 if (strcmp(priv->ftsp_statfs.f_fstypename, 1218 *cpp) == 0) { 1219 priv->ftsp_linksreliable = 1; 1220 break; 1221 } 1222 } 1223 } else { 1224 priv->ftsp_linksreliable = 0; 1225 } 1226 } 1227 return priv->ftsp_linksreliable; 1228} |
|