Changeset 2708 for trunk/src/kmk


Ignore:
Timestamp:
Nov 21, 2013, 11:26:40 AM (12 years ago)
Author:
bird
Message:

Optimized ftsfake.c for windows (similar things can be done for OS/2, if we care).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kmk/kmkbuiltin/fts.c

    r2546 r2708  
    127127static FTSENT   *fts_sort(FTS *, FTSENT *, size_t);
    128128static u_short   fts_stat(FTS *, FTSENT *, int);
     129#ifdef _MSC_VER
     130static u_short   fts_stat_dirent(FTS *sp, FTSENT *p, int follow, struct dirent *pDirEnt);
     131#endif
    129132static int       fts_safe_changedir(const FTS *, const FTSENT *, int,
    130133    const char *);
    131134
    132135#ifdef _MSC_VER
    133 #undef HAVE_STRUCT_DIRENT_D_NAMLEN
    134 #undef HAVE_FCHDIR
     136# undef HAVE_FCHDIR
    135137#endif
    136138
     
    387389                if (chdir(sp->fts_rdir))
    388390                        saved_errno =  errno;
    389         free(sp->fts_rdir);
     391                free(sp->fts_rdir);
    390392                sp->fts_rdir = NULL;
    391393#endif
     
    786788        else
    787789                oflag = DTF_HIDEW|DTF_NODUP|DTF_REWIND;
     790#elif defined(_MSC_VER)
     791# define __opendir2(path, flag) birdDirOpenExtraInfo(path)
    788792#else
    789793#define __opendir2(path, flag) opendir(path)
     
    941945                        } else
    942946                                p->fts_accpath = p->fts_name;
     947
    943948                        /* Stat it. */
     949#ifdef _MSC_VER
     950                        p->fts_info = fts_stat_dirent(sp, p, 0, dp);
     951#else
    944952                        p->fts_info = fts_stat(sp, p, 0);
     953#endif
    945954
    946955                        /* Decrement link count if applicable. */
     
    10121021}
    10131022
     1023#ifdef _MSC_VER
     1024/** Special version of fts_stat that takes the information from the directory
     1025 *  entry returned by readdir().
     1026 *
     1027 *  Directory listing returns all the stat information on systems likes
     1028 *  Windows and OS/2. */
    10141029static u_short
    1015 fts_stat(sp, p, follow)
    1016         FTS *sp;
    1017         FTSENT *p;
    1018         int follow;
     1030fts_stat_dirent(FTS *sp, FTSENT *p, int follow, struct dirent *pDirEnt)
    10191031{
    10201032        FTSENT *t;
     
    10301042        sbp = ISSET(FTS_NOSTAT) ? &sb : p->fts_statp;
    10311043
    1032 #ifdef FTS_WHITEOUT
    1033         /* check for whiteout */
    1034         if (p->fts_flags & FTS_ISW) {
    1035                 if (sbp != &sb) {
    1036                         memset(sbp, '\0', sizeof (*sbp));
    1037                         sbp->st_mode = S_IFWHT;
    1038                 }
    1039                 return (FTS_W);
    1040         }
    1041 #endif
     1044        /*
     1045         * Copy over the stat info from the direntry.
     1046         */
     1047        *sbp = pDirEnt->d_stat;
    10421048
    10431049        /*
    10441050         * If doing a logical walk, or application requested FTS_FOLLOW, do
    1045          * a stat(2).  If that fails, check for a non-existent symlink.  If
    1046          * fail, set the errno from the stat call.
    1047          */
    1048         if (ISSET(FTS_LOGICAL) || follow) {
     1051         * a stat(2) on symlinks.  If that fails, assume non-existent
     1052         * symlink and set the errno from the stat call.
     1053         */
     1054        if (S_ISLNK(sbp->st_mode) && (ISSET(FTS_LOGICAL) || follow)) {
    10491055                if (stat(p->fts_accpath, sbp)) {
    10501056                        saved_errno = errno;
    1051                         if (!lstat(p->fts_accpath, sbp)) {
    1052                                 errno = 0;
    1053                                 return (FTS_SLNONE);
    1054                         }
    1055                         p->fts_errno = saved_errno;
    1056                         goto err;
    1057                 }
    1058         } else if (lstat(p->fts_accpath, sbp)) {
    1059                 p->fts_errno = errno;
    1060 err:            memset(sbp, 0, sizeof(struct STAT));
    1061                 return (FTS_NS);
     1057                        errno = 0;
     1058                        return (FTS_SLNONE);
     1059                }
    10621060        }
    10631061
     
    10871085                if (ino && dev) /** @todo ino emulation on windows... */
    10881086#endif
     1087                    for (t = p->fts_parent;
     1088                        t->fts_level >= FTS_ROOTLEVEL; t = t->fts_parent)
     1089                            if (ino == t->fts_ino && dev == t->fts_dev) {
     1090                                    p->fts_cycle = t;
     1091                                    return (FTS_DC);
     1092                            }
     1093                return (FTS_D);
     1094        }
     1095        if (S_ISLNK(sbp->st_mode))
     1096                return (FTS_SL);
     1097        if (S_ISREG(sbp->st_mode))
     1098                return (FTS_F);
     1099        return (FTS_DEFAULT);
     1100}
     1101
     1102#endif /* fts_stat_dirent */
     1103
     1104static u_short
     1105fts_stat(sp, p, follow)
     1106        FTS *sp;
     1107        FTSENT *p;
     1108        int follow;
     1109{
     1110        FTSENT *t;
     1111        dev_t dev;
     1112        ino_t ino;
     1113        struct STAT *sbp, sb;
     1114        int saved_errno;
     1115
     1116        _DIAGASSERT(sp != NULL);
     1117        _DIAGASSERT(p != NULL);
     1118
     1119        /* If user needs stat info, stat buffer already allocated. */
     1120        sbp = ISSET(FTS_NOSTAT) ? &sb : p->fts_statp;
     1121
     1122#ifdef FTS_WHITEOUT
     1123        /* check for whiteout */
     1124        if (p->fts_flags & FTS_ISW) {
     1125                if (sbp != &sb) {
     1126                        memset(sbp, '\0', sizeof (*sbp));
     1127                        sbp->st_mode = S_IFWHT;
     1128                }
     1129                return (FTS_W);
     1130        }
     1131#endif
     1132
     1133        /*
     1134         * If doing a logical walk, or application requested FTS_FOLLOW, do
     1135         * a stat(2).  If that fails, check for a non-existent symlink.  If
     1136         * fail, set the errno from the stat call.
     1137         */
     1138        if (ISSET(FTS_LOGICAL) || follow) {
     1139                if (stat(p->fts_accpath, sbp)) {
     1140                        saved_errno = errno;
     1141                        if (!lstat(p->fts_accpath, sbp)) {
     1142                                errno = 0;
     1143                                return (FTS_SLNONE);
     1144                        }
     1145                        p->fts_errno = saved_errno;
     1146                        goto err;
     1147                }
     1148        } else if (lstat(p->fts_accpath, sbp)) {
     1149                p->fts_errno = errno;
     1150err:            memset(sbp, 0, sizeof(struct STAT));
     1151                return (FTS_NS);
     1152        }
     1153
     1154        if (S_ISDIR(sbp->st_mode)) {
     1155                /*
     1156                 * Set the device/inode.  Used to find cycles and check for
     1157                 * crossing mount points.  Also remember the link count, used
     1158                 * in fts_build to limit the number of stat calls.  It is
     1159                 * understood that these fields are only referenced if fts_info
     1160                 * is set to FTS_D.
     1161                 */
     1162                dev = p->fts_dev = sbp->st_dev;
     1163                ino = p->fts_ino = sbp->st_ino;
     1164                p->fts_nlink = sbp->st_nlink;
     1165
     1166                if (ISDOT(p->fts_name))
     1167                        return (FTS_DOT);
     1168
     1169                /*
     1170                 * Cycle detection is done by brute force when the directory
     1171                 * is first encountered.  If the tree gets deep enough or the
     1172                 * number of symbolic links to directories is high enough,
     1173                 * something faster might be worthwhile.
     1174                 */
     1175
     1176#ifdef _MSC_VER
     1177                if (ino && dev) /** @todo ino emulation on windows... */
     1178#endif
    10891179                for (t = p->fts_parent;
    10901180                    t->fts_level >= FTS_ROOTLEVEL; t = t->fts_parent)
Note: See TracChangeset for help on using the changeset viewer.