| 1096 | } |
| 1097 | |
| 1098 | static u_short |
| 1099 | fts_stat(FTS* sp, FTSENT* p, int follow) |
| 1100 | { |
| 1101 | dev_t dev; |
| 1102 | ino_t ino; |
| 1103 | stat_struct *sbp, sb; |
| 1104 | int saved_errno; |
| 1105 | /* If user needs stat info, stat buffer already allocated. */ |
| 1106 | sbp = ISSET(FTS_NOSTAT) ? &sb : p->fts_statp; |
| 1107 | |
| 1108 | #ifdef FTS_WHITEOUT |
| 1109 | /* check for whiteout */ |
| 1110 | if (p->fts_flags & FTS_ISW) { |
| 1111 | if (sbp != &sb) { |
| 1112 | memset(sbp, '\0', sizeof(*sbp)); |
| 1113 | sbp->st_mode = S_IFWHT; |
| 1114 | } |
| 1115 | return (FTS_W); |
| 1116 | } |
| 1117 | #endif |
| 1118 | |
| 1119 | /* |
| 1120 | * If doing a logical walk, or application requested FTS_FOLLOW, do |
| 1121 | * a stat(2). If that fails, check for a non-existent symlink. If |
| 1122 | * fail, set the errno from the stat call. |
| 1123 | */ |
| 1124 | if (ISSET(FTS_LOGICAL) || follow) { |
| 1125 | if (STAT_FUNC(p->fts_accpath, sbp)) { |
| 1126 | saved_errno = errno; |
| 1127 | if (!lstat(p->fts_accpath, sbp)) { |
| 1128 | errno = 0; |
| 1129 | return (FTS_SLNONE); |
| 1130 | } |
| 1131 | p->fts_errno = saved_errno; |
| 1132 | memset(sbp, 0, sizeof(stat_struct)); |
| 1133 | return (FTS_NS); |
| 1134 | } |
| 1135 | } else if (lstat(p->fts_accpath, sbp)) { |
| 1136 | p->fts_errno = errno; |
| 1137 | memset(sbp, 0, sizeof(stat_struct)); |
| 1138 | return (FTS_NS); |
| 1139 | } |
| 1140 | |
| 1141 | if (S_ISDIR(sbp->st_mode)) { |
| 1142 | /* |
| 1143 | * Set the device/inode. Used to find cycles and check for |
| 1144 | * crossing mount points. Also remember the link count, used |
| 1145 | * in fts_build to limit the number of stat calls. It is |
| 1146 | * understood that these fields are only referenced if fts_info |
| 1147 | * is set to FTS_D. |
| 1148 | */ |
| 1149 | dev = p->fts_dev = sbp->st_dev; |
| 1150 | ino = p->fts_ino = sbp->st_ino; |
| 1151 | p->fts_nlink = sbp->st_nlink; |
| 1152 | |
| 1153 | const char* fts_name_x = p->fts_name; |
| 1154 | if (ISDOT(fts_name_x)) { |
| 1155 | return (FTS_DOT); |