[BACK]Return to walk.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / usr.sbin / makefs

Annotation of src/usr.sbin/makefs/walk.c, Revision 1.6

1.6     ! lukem       1: /*     $NetBSD: walk.c,v 1.5 2001/11/02 03:12:48 lukem Exp $   */
1.1       lukem       2:
                      3: /*
1.5       lukem       4:  * Copyright (c) 2001 Wasabi Systems, Inc.
1.1       lukem       5:  * All rights reserved.
                      6:  *
                      7:  * Written by Luke Mewburn for Wasabi Systems, Inc.
                      8:  *
                      9:  * Redistribution and use in source and binary forms, with or without
                     10:  * modification, are permitted provided that the following conditions
                     11:  * are met:
                     12:  * 1. Redistributions of source code must retain the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer.
                     14:  * 2. Redistributions in binary form must reproduce the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer in the
                     16:  *    documentation and/or other materials provided with the distribution.
                     17:  * 3. All advertising materials mentioning features or use of this software
                     18:  *    must display the following acknowledgement:
                     19:  *      This product includes software developed for the NetBSD Project by
                     20:  *      Wasabi Systems, Inc.
                     21:  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
                     22:  *    or promote products derived from this software without specific prior
                     23:  *    written permission.
                     24:  *
                     25:  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
                     26:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     27:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     28:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
                     29:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     30:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     31:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     32:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     33:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     34:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     35:  * POSSIBILITY OF SUCH DAMAGE.
                     36:  */
                     37:
                     38: /*
                     39:  * The function link_check() was inspired from NetBSD's usr.bin/du/du.c,
                     40:  * which has the following copyright notice:
                     41:  *
                     42:  *
                     43:  * Copyright (c) 1989, 1993, 1994
                     44:  *     The Regents of the University of California.  All rights reserved.
                     45:  *
                     46:  * This code is derived from software contributed to Berkeley by
                     47:  * Chris Newcomb.
                     48:  *
                     49:  * Redistribution and use in source and binary forms, with or without
                     50:  * modification, are permitted provided that the following conditions
                     51:  * are met:
                     52:  * 1. Redistributions of source code must retain the above copyright
                     53:  *    notice, this list of conditions and the following disclaimer.
                     54:  * 2. Redistributions in binary form must reproduce the above copyright
                     55:  *    notice, this list of conditions and the following disclaimer in the
                     56:  *    documentation and/or other materials provided with the distribution.
                     57:  * 3. All advertising materials mentioning features or use of this software
                     58:  *    must display the following acknowledgement:
                     59:  *     This product includes software developed by the University of
                     60:  *     California, Berkeley and its contributors.
                     61:  * 4. Neither the name of the University nor the names of its contributors
                     62:  *    may be used to endorse or promote products derived from this software
                     63:  *    without specific prior written permission.
                     64:  *
                     65:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     66:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     67:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     68:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     69:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     70:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     71:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     72:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     73:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     74:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     75:  * SUCH DAMAGE.
                     76:  */
1.2       lukem      77:
                     78: #include <sys/cdefs.h>
                     79: #ifndef __lint
1.6     ! lukem      80: __RCSID("$NetBSD: walk.c,v 1.5 2001/11/02 03:12:48 lukem Exp $");
1.2       lukem      81: #endif /* !__lint */
1.1       lukem      82:
                     83: #include <sys/param.h>
                     84:
                     85: #include <assert.h>
                     86: #include <err.h>
                     87: #include <errno.h>
                     88: #include <fcntl.h>
                     89: #include <stdio.h>
                     90: #include <dirent.h>
                     91: #include <stdlib.h>
                     92: #include <string.h>
                     93: #include <unistd.h>
                     94:
                     95: #include "makefs.h"
                     96: #include "mtree.h"
                     97:
                     98: static void     apply_specdir(const char *, NODE *, fsnode *);
                     99: static void     apply_specentry(const char *, NODE *, fsnode *);
                    100: static fsnode  *create_fsnode(const char *, struct stat *);
1.6     ! lukem     101: static fsinode *create_fsinode(struct stat *);
        !           102: static fsinode *link_check(fsinode *);
1.1       lukem     103:
                    104:
                    105: /*
                    106:  * walk_dir --
                    107:  *     build a tree of fsnodes from `dir', with a parent fsnode of `parent'
                    108:  *     (which may be NULL for the root of the tree).
                    109:  *     each "level" is a directory, with the "." entry guaranteed to be
                    110:  *     at the start of the list, and without ".." entries.
                    111:  */
                    112: fsnode *
                    113: walk_dir(const char *dir, fsnode *parent)
                    114: {
                    115:        fsnode          *first, *cur, *prev;
                    116:        DIR             *dirp;
                    117:        struct dirent   *dent;
                    118:        char            path[MAXPATHLEN + 1];
                    119:        struct stat     stbuf;
                    120:
                    121:        assert(dir != NULL);
                    122:
                    123:        if (debug & DEBUG_WALK_DIR)
                    124:                printf("walk_dir: %s %p\n", dir, parent);
                    125:        if ((dirp = opendir(dir)) == NULL)
                    126:                err(1, "Can't opendir `%s'", dir);
                    127:        first = prev = NULL;
                    128:        while ((dent = readdir(dirp)) != NULL) {
                    129:                if (strcmp(dent->d_name, "..") == 0)
                    130:                        continue;
                    131:                if (debug & DEBUG_WALK_DIR_NODE)
                    132:                        printf("scanning %s/%s\n", dir, dent->d_name);
                    133:                if (snprintf(path, sizeof(path), "%s/%s", dir, dent->d_name)
                    134:                    >= sizeof(path))
                    135:                        errx(1, "Pathname too long.");
                    136:                if (lstat(path, &stbuf) == -1)
                    137:                        err(1, "Can't lstat `%s'", path);
                    138:                if (S_ISSOCK(stbuf.st_mode & S_IFMT)) {
                    139:                        if (debug & DEBUG_WALK_DIR_NODE)
                    140:                                printf("  skipping socket %s\n", path);
                    141:                        continue;
                    142:                }
                    143:
                    144:                cur = create_fsnode(dent->d_name, &stbuf);
1.6     ! lukem     145:                cur->inode = create_fsinode(&stbuf);
1.1       lukem     146:                cur->parent = parent;
                    147:                if (strcmp(dent->d_name, ".") == 0) {
                    148:                                /* ensure "." is at the start of the list */
                    149:                        cur->next = first;
                    150:                        first = cur;
                    151:                        if (! prev)
                    152:                                prev = cur;
                    153:                } else {                        /* not "." */
                    154:                        if (prev)
                    155:                                prev->next = cur;
                    156:                        prev = cur;
                    157:                        if (!first)
                    158:                                first = cur;
                    159:                        if (S_ISDIR(cur->type)) {
                    160:                                cur->child = walk_dir(path, cur);
                    161:                                continue;
                    162:                        }
                    163:                }
1.6     ! lukem     164:                if (stbuf.st_nlink > 1) {
        !           165:                        fsinode *curino;
        !           166:
        !           167:                        curino = link_check(cur->inode);
        !           168:                        if (curino != NULL) {
        !           169:                                free(cur->inode);
        !           170:                                cur->inode = curino;
        !           171:                                cur->inode->nlink++;
        !           172:                        }
1.1       lukem     173:                }
                    174:                if (S_ISLNK(cur->type)) {
                    175:                        char    slink[PATH_MAX+1];
                    176:                        int     llen;
                    177:
                    178:                        llen = readlink(path, slink, PATH_MAX);
                    179:                        if (llen == -1)
                    180:                                err(1, "Readlink `%s'", path);
                    181:                        slink[llen] = '\0';
                    182:                        if ((cur->symlink = strdup(slink)) == NULL)
                    183:                                err(1, "Memory allocation error");
                    184:                }
                    185:        }
                    186:        for (cur = first; cur != NULL; cur = cur->next)
                    187:                cur->first = first;
                    188:        if (closedir(dirp) == -1)
                    189:                err(1, "Can't closedir `%s'", dir);
                    190:        return (first);
                    191: }
                    192:
                    193: static fsnode *
1.6     ! lukem     194: create_fsnode(const char *name, struct stat *stbuf)
1.1       lukem     195: {
                    196:        fsnode *cur;
                    197:
                    198:        if ((cur = calloc(1, sizeof(fsnode))) == NULL ||
                    199:            (cur->name = strdup(name)) == NULL)
                    200:                err(1, "Memory allocation error");
1.6     ! lukem     201:        cur->type = stbuf->st_mode & S_IFMT;
        !           202:        return (cur);
        !           203: }
        !           204:
        !           205: static fsinode *
        !           206: create_fsinode(struct stat *statbuf)
        !           207: {
        !           208:        fsinode *cur;
        !           209:
        !           210:        if ((cur = calloc(1, sizeof(fsinode))) == NULL)
        !           211:                err(1, "Memory allocation error");
1.1       lukem     212:        cur->nlink = 1;
1.6     ! lukem     213:        cur->st = *statbuf;
1.1       lukem     214:        return (cur);
                    215: }
                    216:
                    217: /*
                    218:  * apply_specfile --
                    219:  *     read in the mtree(8) specfile, and apply it to the tree
                    220:  *     at dir,parent. parameters in parent on equivalent types
                    221:  *     will be changed to those found in specfile, and missing
                    222:  *     entries will be added.
                    223:  */
                    224: void
                    225: apply_specfile(const char *specfile, const char *dir, fsnode *parent)
                    226: {
                    227:        struct timeval   start;
                    228:        FILE    *fp;
                    229:        NODE    *root;
                    230:
                    231:        assert(specfile != NULL);
                    232:        assert(parent != NULL);
                    233:
                    234:        if (debug & DEBUG_APPLY_SPECFILE)
                    235:                printf("apply_specfile: %s, %s %p\n", specfile, dir, parent);
                    236:
                    237:                                /* read in the specfile */
                    238:        if ((fp = fopen(specfile, "r")) == NULL)
                    239:                err(1, "Can't open `%s'", specfile);
                    240:        TIMER_START(start);
                    241:        root = spec(fp);
                    242:        TIMER_RESULTS(start, "spec");
                    243:        if (fclose(fp) == EOF)
                    244:                err(1, "Can't close `%s'", specfile);
                    245:
                    246:                                /* perform some sanity checks */
                    247:        if (root == NULL)
                    248:                errx(1, "Specfile `%s' did not contain a tree", specfile);
                    249:        assert(strcmp(root->name, ".") == 0);
                    250:        assert(root->type == F_DIR);
                    251:
                    252:                                /* merge in the changes */
                    253:        apply_specdir(dir, root, parent);
                    254: }
                    255:
                    256: static void
                    257: apply_specdir(const char *dir, NODE *specnode, fsnode *dirnode)
                    258: {
                    259:        char     path[MAXPATHLEN + 1];
                    260:        NODE    *curnode;
                    261:        fsnode  *curfsnode;
                    262:
                    263:        assert(specnode != NULL);
                    264:        assert(dirnode != NULL);
                    265:
                    266:        if (debug & DEBUG_APPLY_SPECFILE)
                    267:                printf("apply_specdir: %s %p %p\n", dir, specnode, dirnode);
                    268:
                    269:        if (specnode->type != F_DIR)
                    270:                errx(1, "Specfile node `%s/%s' is not a directory",
                    271:                    dir, specnode->name);
                    272:        if (dirnode->type != S_IFDIR)
                    273:                errx(1, "Directory node `%s/%s' is not a directory",
                    274:                    dir, dirnode->name);
                    275:
                    276:        apply_specentry(dir, specnode, dirnode);
                    277:
                    278:                        /* now walk specnode->child matching up with dirnode */
                    279:        for (curnode = specnode->child; curnode != NULL;
                    280:            curnode = curnode->next) {
                    281:                if (debug & DEBUG_APPLY_SPECENTRY)
                    282:                        printf("apply_specdir:  spec %s\n",
                    283:                            curnode->name);
                    284:                for (curfsnode = dirnode->next; curfsnode != NULL;
                    285:                    curfsnode = curfsnode->next) {
1.3       lukem     286: #if 0  /* too verbose for now */
1.1       lukem     287:                        if (debug & DEBUG_APPLY_SPECENTRY)
                    288:                                printf("apply_specdir:  dirent %s\n",
                    289:                                    curfsnode->name);
1.3       lukem     290: #endif
1.1       lukem     291:                        if (strcmp(curnode->name, curfsnode->name) == 0)
                    292:                                break;
                    293:                }
                    294:                if (curfsnode == NULL) {        /* need new entry */
                    295:                        struct stat     stbuf;
                    296:
                    297:                                        /* check that enough info is provided */
                    298: #define NODETEST(t, m)                                                 \
                    299:                        if (!(t))                                       \
                    300:                                errx(1, "`%s/%s': %s not provided",     \
                    301:                                    dir, curnode->name, m)
                    302:                        NODETEST(curnode->flags & F_TYPE, "type");
                    303:                        NODETEST(curnode->flags & F_MODE, "mode");
                    304:                                /* XXX: require F_TIME ? */
                    305:                        NODETEST(curnode->flags & F_GID ||
                    306:                            curnode->flags & F_GNAME, "group");
                    307:                        NODETEST(curnode->flags & F_UID ||
                    308:                            curnode->flags & F_UNAME, "user");
                    309:                        if (curnode->type == F_BLOCK || curnode->type == F_CHAR)
                    310:                                NODETEST(curnode->flags & F_DEV,
                    311:                                    "device number");
                    312: #undef NODETEST
                    313:
                    314:                        if (debug & DEBUG_APPLY_SPECFILE)
                    315:                                printf("apply_specdir: adding %s\n",
                    316:                                    curnode->name);
                    317:                                        /* build minimal fsnode */
                    318:                        memset(&stbuf, 0, sizeof(stbuf));
                    319:                        stbuf.st_mode = nodetoino(curnode->type);
1.6     ! lukem     320:                        stbuf.st_nlink = 1;
1.1       lukem     321:                        stbuf.st_mtime = stbuf.st_atime =
                    322:                            stbuf.st_ctime = start_time.tv_sec;
                    323:                        stbuf.st_mtimensec = stbuf.st_atimensec =
                    324:                            stbuf.st_ctimensec = start_time.tv_nsec;
                    325:                        curfsnode = create_fsnode(curnode->name, &stbuf);
                    326:                        curfsnode->parent = dirnode->parent;
                    327:                        curfsnode->first = dirnode;
                    328:                        curfsnode->next = dirnode->next;
                    329:                        dirnode->next = curfsnode;
                    330:                        if (curfsnode->type == S_IFDIR) {
                    331:                                        /* for dirs, make "." entry as well */
                    332:                                curfsnode->child = create_fsnode(".", &stbuf);
                    333:                                curfsnode->child->parent = curfsnode;
                    334:                                curfsnode->child->first = curfsnode->child;
                    335:                        }
                    336:                        if (curfsnode->type == S_IFLNK) {
1.3       lukem     337:                                assert(curnode->slink != NULL);
1.1       lukem     338:                                        /* for symlinks, copy the target */
                    339:                                if ((curfsnode->symlink =
                    340:                                    strdup(curnode->slink)) == NULL)
                    341:                                        err(1, "Memory allocation error");
                    342:                        }
                    343:                }
                    344:                apply_specentry(dir, curnode, curfsnode);
                    345:                if (curnode->type == F_DIR) {
                    346:                        if (curfsnode->type != S_IFDIR)
                    347:                                errx(1, "`%s/%s' is not a directory",
                    348:                                    dir, curfsnode->name);
                    349:                        assert (curfsnode->child != NULL);
                    350:                        if (snprintf(path, sizeof(path), "%s/%s",
                    351:                            dir, curnode->name) >= sizeof(path))
                    352:                                errx(1, "Pathname too long.");
                    353:                        apply_specdir(path, curnode, curfsnode->child);
                    354:                }
                    355:        }
                    356: }
                    357:
                    358: static void
                    359: apply_specentry(const char *dir, NODE *specnode, fsnode *dirnode)
                    360: {
                    361:
                    362:        assert(specnode != NULL);
                    363:        assert(dirnode != NULL);
                    364:
                    365:        if (nodetoino(specnode->type) != dirnode->type)
                    366:                errx(1, "`%s/%s' type mismatch: specfile %s, tree %s",
                    367:                    dir, specnode->name, inode_type(nodetoino(specnode->type)),
                    368:                    inode_type(dirnode->type));
                    369:
                    370:        if (debug & DEBUG_APPLY_SPECENTRY)
                    371:                printf("apply_specentry: %s/%s\n", dir, dirnode->name);
                    372:
                    373: #define ASEPRINT(t, b, o, n) \
                    374:                if (debug & DEBUG_APPLY_SPECENTRY) \
                    375:                        printf("\t\t\tchanging %s from " b " to " b "\n", \
                    376:                            t, o, n)
                    377:
                    378:        if (specnode->flags & (F_GID | F_GNAME)) {
                    379:                ASEPRINT("gid", "%d",
1.6     ! lukem     380:                    dirnode->inode->st.st_gid, specnode->st_gid);
        !           381:                dirnode->inode->st.st_gid = specnode->st_gid;
1.1       lukem     382:        }
                    383:        if (specnode->flags & F_MODE) {
                    384:                ASEPRINT("mode", "%#o",
1.6     ! lukem     385:                    dirnode->inode->st.st_mode & ALLPERMS, specnode->st_mode);
        !           386:                dirnode->inode->st.st_mode &= ~ALLPERMS;
        !           387:                dirnode->inode->st.st_mode |= (specnode->st_mode & ALLPERMS);
1.1       lukem     388:        }
                    389:                /* XXX: ignoring F_NLINK for now */
                    390:        if (specnode->flags & F_SIZE) {
                    391:                ASEPRINT("size", "%lld",
1.6     ! lukem     392:                    (long long)dirnode->inode->st.st_size,
1.1       lukem     393:                    (long long)specnode->st_size);
1.6     ! lukem     394:                dirnode->inode->st.st_size = specnode->st_size;
1.1       lukem     395:        }
                    396:        if (specnode->flags & F_SLINK) {
                    397:                assert(dirnode->symlink != NULL);
                    398:                assert(specnode->slink != NULL);
                    399:                ASEPRINT("symlink", "%s", dirnode->symlink, specnode->slink);
                    400:                free(dirnode->symlink);
                    401:                if ((dirnode->symlink = strdup(specnode->slink)) == NULL)
                    402:                        err(1, "Memory allocation error");
                    403:        }
                    404:        if (specnode->flags & F_TIME) {
                    405:                ASEPRINT("time", "%ld",
1.6     ! lukem     406:                    (long)dirnode->inode->st.st_mtime,
        !           407:                    (long)specnode->st_mtime);
        !           408:                dirnode->inode->st.st_mtime =           specnode->st_mtime;
        !           409:                dirnode->inode->st.st_mtimensec =       specnode->st_mtimensec;
        !           410:                dirnode->inode->st.st_atime =           specnode->st_mtime;
        !           411:                dirnode->inode->st.st_atimensec =       specnode->st_mtimensec;
        !           412:                dirnode->inode->st.st_ctime =           start_time.tv_sec;
        !           413:                dirnode->inode->st.st_ctimensec =       start_time.tv_nsec;
1.1       lukem     414:        }
                    415:        if (specnode->flags & (F_UID | F_UNAME)) {
                    416:                ASEPRINT("uid", "%d",
1.6     ! lukem     417:                    dirnode->inode->st.st_uid, specnode->st_uid);
        !           418:                dirnode->inode->st.st_uid = specnode->st_uid;
1.1       lukem     419:        }
                    420:        if (specnode->flags & F_FLAGS) {
                    421:                ASEPRINT("flags", "%#lX",
1.6     ! lukem     422:                    (ulong)dirnode->inode->st.st_flags,
        !           423:                    (ulong)specnode->st_flags);
        !           424:                dirnode->inode->st.st_flags = specnode->st_flags;
1.1       lukem     425:        }
                    426:        if (specnode->flags & F_DEV) {
                    427:                ASEPRINT("rdev", "%#x",
1.6     ! lukem     428:                    dirnode->inode->st.st_rdev, specnode->st_rdev);
        !           429:                dirnode->inode->st.st_rdev = specnode->st_rdev;
1.1       lukem     430:        }
                    431: #undef ASEPRINT
                    432: }
                    433:
                    434:
                    435: /*
                    436:  * dump_fsnodes --
                    437:  *     dump the fsnodes from `cur', based in the directory `dir'
                    438:  */
                    439: void
                    440: dump_fsnodes(const char *dir, fsnode *root)
                    441: {
                    442:        fsnode  *cur;
                    443:        char    path[MAXPATHLEN + 1];
                    444:
                    445:        assert (dir != NULL);
                    446:        printf("dump_fsnodes: %s %p\n", dir, root);
                    447:        for (cur = root; cur != NULL; cur = cur->next) {
                    448:                if (snprintf(path, sizeof(path), "%s/%s", dir, cur->name)
                    449:                    >= sizeof(path))
                    450:                        errx(1, "Pathname too long.");
                    451:
                    452:                if (debug & DEBUG_DUMP_FSNODES_VERBOSE)
                    453:                        printf("cur=%8p parent=%8p first=%8p ",
                    454:                            cur, cur->parent, cur->first);
                    455:                printf("%7s: %s", inode_type(cur->type), path);
                    456:                if (S_ISLNK(cur->type)) {
                    457:                        assert(cur->symlink != NULL);
                    458:                        printf(" -> %s", cur->symlink);
                    459:                } else {
                    460:                        assert (cur->symlink == NULL);
                    461:                }
1.6     ! lukem     462:                if (cur->inode->nlink > 1)
        !           463:                        printf(", nlinks=%d", cur->inode->nlink);
1.1       lukem     464:                putchar('\n');
                    465:
                    466:                if (cur->child) {
                    467:                        assert (cur->type == S_IFDIR);
                    468:                        dump_fsnodes(path, cur->child);
                    469:                }
                    470:        }
                    471:        printf("dump_fsnodes: finished %s\n", dir);
                    472: }
                    473:
                    474:
                    475: /*
                    476:  * inode_type --
                    477:  *     for a given inode type `mode', return a descriptive string.
                    478:  *     for most cases, uses inotype() from mtree/misc.c
                    479:  */
                    480: const char *
                    481: inode_type(mode_t mode)
                    482: {
                    483:
1.3       lukem     484:        if (S_ISLNK(mode))
1.1       lukem     485:                return ("symlink");     /* inotype() returns "link"...  */
                    486:        return (inotype(mode));
                    487: }
                    488:
                    489:
                    490: /*
                    491:  * link_check --
                    492:  *     return pointer to fsnode matching `entry's st_ino & st_dev if it exists,
                    493:  *     otherwise add `entry' to table and return NULL
                    494:  */
1.6     ! lukem     495: static fsinode *
        !           496: link_check(fsinode *entry)
1.1       lukem     497: {
1.6     ! lukem     498:        static  struct dupnode {
        !           499:                uint32_t        dev;
        !           500:                uint32_t        ino;
        !           501:                fsinode         *dup;
        !           502:        } *dups;
1.1       lukem     503:        static  int     ndups, maxdups;
                    504:
                    505:        int     i;
                    506:
                    507:        assert (entry != NULL);
                    508:
                    509:                /* XXX; maybe traverse in reverse for speed? */
                    510:        for (i = 0; i < ndups; i++) {
1.6     ! lukem     511:                if (dups[i].dev == entry->st.st_dev &&
        !           512:                    dups[i].ino == entry->st.st_ino) {
1.1       lukem     513:                        if (debug & DEBUG_WALK_DIR_LINKCHECK)
1.6     ! lukem     514:                                printf("link_check: found [%d,%d]\n",
        !           515:                                    entry->st.st_dev, entry->st.st_ino);
1.1       lukem     516:                        return (dups[i].dup);
                    517:                }
                    518:        }
                    519:
                    520:        if (debug & DEBUG_WALK_DIR_LINKCHECK)
1.6     ! lukem     521:                printf("link_check: no match for [%d, %d]\n",
        !           522:                    entry->st.st_dev, entry->st.st_ino);
1.1       lukem     523:        if (ndups == maxdups) {
                    524:                maxdups += 128;
1.6     ! lukem     525:                if ((dups = realloc(dups, sizeof(struct dupnode) * maxdups))
        !           526:                    == NULL)
1.1       lukem     527:                        err(1, "Memory allocation error");
                    528:        }
1.6     ! lukem     529:        dups[ndups].dev = entry->st.st_dev;
        !           530:        dups[ndups].ino = entry->st.st_ino;
1.1       lukem     531:        dups[ndups].dup = entry;
                    532:        ndups++;
                    533:
                    534:        return (NULL);
                    535: }

CVSweb <webmaster@jp.NetBSD.org>