[BACK]Return to lndir.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / lndir

Annotation of src/usr.bin/lndir/lndir.c, Revision 1.1

1.1     ! downsj      1: /*     $OpenBSD$       */
        !             2: /* $XConsortium: lndir.c /main/15 1995/08/30 10:56:18 gildea $ */
        !             3: /* Create shadow link tree (after X11R4 script of the same name)
        !             4:    Mark Reinhold (mbr@lcs.mit.edu)/3 January 1990 */
        !             5:
        !             6: /*
        !             7: Copyright (c) 1990,  X Consortium
        !             8:
        !             9: Permission is hereby granted, free of charge, to any person obtaining a copy
        !            10: of this software and associated documentation files (the "Software"), to deal
        !            11: in the Software without restriction, including without limitation the rights
        !            12: to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        !            13: copies of the Software, and to permit persons to whom the Software is
        !            14: furnished to do so, subject to the following conditions:
        !            15:
        !            16: The above copyright notice and this permission notice shall be included in
        !            17: all copies or substantial portions of the Software.
        !            18:
        !            19: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        !            20: IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        !            21: FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
        !            22: X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
        !            23: AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
        !            24: CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
        !            25:
        !            26: Except as contained in this notice, the name of the X Consortium shall not be
        !            27: used in advertising or otherwise to promote the sale, use or other dealings
        !            28: in this Software without prior written authorization from the X Consortium.
        !            29:
        !            30: */
        !            31:
        !            32: /* From the original /bin/sh script:
        !            33:
        !            34:   Used to create a copy of the a directory tree that has links for all
        !            35:   non-directories (except those named RCS, SCCS or CVS.adm).  If you are
        !            36:   building the distribution on more than one machine, you should use
        !            37:   this technique.
        !            38:
        !            39:   If your master sources are located in /usr/local/src/X and you would like
        !            40:   your link tree to be in /usr/local/src/new-X, do the following:
        !            41:
        !            42:        %  mkdir /usr/local/src/new-X
        !            43:        %  cd /usr/local/src/new-X
        !            44:        %  lndir ../X
        !            45: */
        !            46:
        !            47: #include <stdio.h>
        !            48: #include <sys/types.h>
        !            49: #include <sys/stat.h>
        !            50: #include <sys/param.h>
        !            51: #include <errno.h>
        !            52: #include <dirent.h>
        !            53: #include <stdarg.h>
        !            54: #include <string.h>
        !            55:
        !            56: int silent = 0;                        /* -silent */
        !            57: int ignore_links = 0;          /* -ignorelinks */
        !            58:
        !            59: char *rcurdir;
        !            60: char *curdir;
        !            61:
        !            62: struct except {
        !            63:        char *name;
        !            64:
        !            65:        struct except *next;
        !            66: };
        !            67: struct except *exceptions = (struct except *)NULL;
        !            68:
        !            69: void
        !            70: quit (int code, char * fmt, ...)
        !            71: {
        !            72:     va_list args;
        !            73:     va_start(args, fmt);
        !            74:     vfprintf (stderr, fmt, args);
        !            75:     va_end(args);
        !            76:     putc ('\n', stderr);
        !            77:     exit (code);
        !            78: }
        !            79:
        !            80: void
        !            81: quiterr (code, s)
        !            82:     char *s;
        !            83: {
        !            84:     perror (s);
        !            85:     exit (code);
        !            86: }
        !            87:
        !            88: void
        !            89: msg (char * fmt, ...)
        !            90: {
        !            91:     va_list args;
        !            92:     if (curdir) {
        !            93:        fprintf (stderr, "%s:\n", curdir);
        !            94:        curdir = 0;
        !            95:     }
        !            96:     va_start(args, fmt);
        !            97:     vfprintf (stderr, fmt, args);
        !            98:     va_end(args);
        !            99:     putc ('\n', stderr);
        !           100: }
        !           101:
        !           102: void
        !           103: mperror (s)
        !           104:     char *s;
        !           105: {
        !           106:     if (curdir) {
        !           107:        fprintf (stderr, "%s:\n", curdir);
        !           108:        curdir = 0;
        !           109:     }
        !           110:     perror (s);
        !           111: }
        !           112:
        !           113:
        !           114: int equivalent(lname, rname)
        !           115:     char *lname;
        !           116:     char *rname;
        !           117: {
        !           118:     char *s;
        !           119:
        !           120:     if (!strcmp(lname, rname))
        !           121:        return 1;
        !           122:     for (s = lname; *s && (s = strchr(s, '/')); s++) {
        !           123:        while (s[1] == '/')
        !           124:            strcpy(s+1, s+2);
        !           125:     }
        !           126:     return !strcmp(lname, rname);
        !           127: }
        !           128:
        !           129:
        !           130: addexcept(name)
        !           131:     char *name;
        !           132: {
        !           133:     struct except *new;
        !           134:
        !           135:     new = (struct except *)malloc(sizeof(struct except));
        !           136:     if (new == (struct except *)NULL)
        !           137:         quiterr(1, "addexcept");
        !           138:     new->name = strdup(name);
        !           139:     if (new->name == (char *)NULL)
        !           140:         quiterr(1, "addexcept");
        !           141:
        !           142:     new->next = exceptions;
        !           143:     exceptions = new;
        !           144: }
        !           145:
        !           146:
        !           147: /* Recursively create symbolic links from the current directory to the "from"
        !           148:    directory.  Assumes that files described by fs and ts are directories. */
        !           149:
        !           150: dodir (fn, fs, ts, rel)
        !           151: char *fn;                      /* name of "from" directory, either absolute or
        !           152:                                   relative to cwd */
        !           153: struct stat *fs, *ts;          /* stats for the "from" directory and cwd */
        !           154: int rel;                       /* if true, prepend "../" to fn before using */
        !           155: {
        !           156:     DIR *df;
        !           157:     struct dirent *dp;
        !           158:     char buf[MAXPATHLEN + 1], *p;
        !           159:     char symbuf[MAXPATHLEN + 1];
        !           160:     char basesym[MAXPATHLEN + 1];
        !           161:     struct stat sb, sc;
        !           162:     int n_dirs;
        !           163:     int symlen;
        !           164:     int basesymlen = -1;
        !           165:     char *ocurdir;
        !           166:     struct except *cur;
        !           167:
        !           168:     if ((fs->st_dev == ts->st_dev) && (fs->st_ino == ts->st_ino)) {
        !           169:        msg ("%s: From and to directories are identical!", fn);
        !           170:        return 1;
        !           171:     }
        !           172:
        !           173:     if (rel)
        !           174:        strcpy (buf, "../");
        !           175:     else
        !           176:        buf[0] = '\0';
        !           177:     strcat (buf, fn);
        !           178:
        !           179:     if (!(df = opendir (buf))) {
        !           180:        msg ("%s: Cannot opendir", buf);
        !           181:        return 1;
        !           182:     }
        !           183:
        !           184:     p = buf + strlen (buf);
        !           185:     *p++ = '/';
        !           186:     n_dirs = fs->st_nlink;
        !           187:     while (dp = readdir (df)) {
        !           188:        if (dp->d_name[strlen(dp->d_name) - 1] == '~')
        !           189:            continue;
        !           190:        strcpy (p, dp->d_name);
        !           191:
        !           192:        if (n_dirs > 0) {
        !           193:            if (stat (buf, &sb) < 0) {
        !           194:                mperror (buf);
        !           195:                continue;
        !           196:            }
        !           197:
        !           198:            if(S_ISDIR(sb.st_mode)) {
        !           199:                /* directory */
        !           200:                n_dirs--;
        !           201:                if (dp->d_name[0] == '.' &&
        !           202:                    (dp->d_name[1] == '\0' || (dp->d_name[1] == '.' &&
        !           203:                                               dp->d_name[2] == '\0')))
        !           204:                    continue;
        !           205:                for (cur = exceptions; cur != (struct except *)NULL;
        !           206:                     cur = cur->next) {
        !           207:                    if (!strcmp (dp->d_name, cur->name))
        !           208:                        goto next;      /* can't continue */
        !           209:                }
        !           210:                if (!strcmp (dp->d_name, "RCS"))
        !           211:                    continue;
        !           212:                if (!strcmp (dp->d_name, "SCCS"))
        !           213:                    continue;
        !           214:                if (!strcmp (dp->d_name, "CVS"))
        !           215:                    continue;
        !           216:                if (!strcmp (dp->d_name, "CVS.adm"))
        !           217:                    continue;
        !           218:                ocurdir = rcurdir;
        !           219:                rcurdir = buf;
        !           220:                curdir = silent ? buf : (char *)0;
        !           221:                if (!silent)
        !           222:                    printf ("%s:\n", buf);
        !           223:                if ((stat (dp->d_name, &sc) < 0) && (errno == ENOENT)) {
        !           224:                    if (mkdir (dp->d_name, 0777) < 0 ||
        !           225:                        stat (dp->d_name, &sc) < 0) {
        !           226:                        mperror (dp->d_name);
        !           227:                        curdir = rcurdir = ocurdir;
        !           228:                        continue;
        !           229:                    }
        !           230:                }
        !           231:                if (readlink (dp->d_name, symbuf, sizeof(symbuf) - 1) >= 0) {
        !           232:                    msg ("%s: is a link instead of a directory", dp->d_name);
        !           233:                    curdir = rcurdir = ocurdir;
        !           234:                    continue;
        !           235:                }
        !           236:                if (chdir (dp->d_name) < 0) {
        !           237:                    mperror (dp->d_name);
        !           238:                    curdir = rcurdir = ocurdir;
        !           239:                    continue;
        !           240:                }
        !           241:                dodir (buf, &sb, &sc, (buf[0] != '/'));
        !           242:                if (chdir ("..") < 0)
        !           243:                    quiterr (1, "..");
        !           244:                curdir = rcurdir = ocurdir;
        !           245:                continue;
        !           246:            }
        !           247:        }
        !           248:
        !           249:        /* non-directory */
        !           250:        symlen = readlink (dp->d_name, symbuf, sizeof(symbuf) - 1);
        !           251:        if (symlen >= 0)
        !           252:            symbuf[symlen] = '\0';
        !           253:
        !           254:        /* The option to ignore links exists mostly because
        !           255:           checking for them slows us down by 10-20%.
        !           256:           But it is off by default because this really is a useful check. */
        !           257:        if (!ignore_links) {
        !           258:            /* see if the file in the base tree was a symlink */
        !           259:            basesymlen = readlink(buf, basesym, sizeof(basesym) - 1);
        !           260:            if (basesymlen >= 0)
        !           261:                basesym[basesymlen] = '\0';
        !           262:        }
        !           263:
        !           264:        if (symlen >= 0) {
        !           265:            /* Link exists in new tree.  Print message if it doesn't match. */
        !           266:            if (!equivalent (basesymlen>=0 ? basesym : buf, symbuf))
        !           267:                msg ("%s: %s", dp->d_name, symbuf);
        !           268:        } else {
        !           269:            if (symlink (basesymlen>=0 ? basesym : buf, dp->d_name) < 0)
        !           270:                mperror (dp->d_name);
        !           271:        }
        !           272: next:
        !           273:     }
        !           274:
        !           275:     closedir (df);
        !           276:     return 0;
        !           277: }
        !           278:
        !           279:
        !           280: main (ac, av)
        !           281: int ac;
        !           282: char **av;
        !           283: {
        !           284:     char *prog_name = av[0];
        !           285:     char *fn, *tn;
        !           286:     struct stat fs, ts;
        !           287:
        !           288:     while (++av, --ac) {
        !           289:        if ((strcmp(*av, "-silent") == 0) || (strcmp(*av, "-s") == 0))
        !           290:            silent = 1;
        !           291:        else if ((strcmp(*av, "-ignorelinks") == 0) || (strcmp(*av, "-i") == 0))
        !           292:            ignore_links = 1;
        !           293:        else if (strcmp(*av, "-e") == 0) {
        !           294:            ++av, --ac;
        !           295:
        !           296:            if (ac < 2)
        !           297:                quit (1, "usage: %s [-e except] [-s] [-i] fromdir [todir]",
        !           298:                      prog_name);
        !           299:            addexcept(*av);
        !           300:        }
        !           301:        else if (strcmp(*av, "--") == 0) {
        !           302:            ++av, --ac;
        !           303:            break;
        !           304:        }
        !           305:        else
        !           306:            break;
        !           307:     }
        !           308:
        !           309:     if (ac < 1 || ac > 2)
        !           310:        quit (1, "usage: %s [-e except] [-s] [-i] fromdir [todir]",
        !           311:              prog_name);
        !           312:
        !           313:     fn = av[0];
        !           314:     if (ac == 2)
        !           315:        tn = av[1];
        !           316:     else
        !           317:        tn = ".";
        !           318:
        !           319:     /* to directory */
        !           320:     if (stat (tn, &ts) < 0)
        !           321:        quiterr (1, tn);
        !           322: #ifdef S_ISDIR
        !           323:     if (!(S_ISDIR(ts.st_mode)))
        !           324: #else
        !           325:     if (!(ts.st_mode & S_IFDIR))
        !           326: #endif
        !           327:        quit (2, "%s: Not a directory", tn);
        !           328:     if (chdir (tn) < 0)
        !           329:        quiterr (1, tn);
        !           330:
        !           331:     /* from directory */
        !           332:     if (stat (fn, &fs) < 0)
        !           333:        quiterr (1, fn);
        !           334: #ifdef S_ISDIR
        !           335:     if (!(S_ISDIR(fs.st_mode)))
        !           336: #else
        !           337:     if (!(fs.st_mode & S_IFDIR))
        !           338: #endif
        !           339:        quit (2, "%s: Not a directory", fn);
        !           340:
        !           341:     exit (dodir (fn, &fs, &ts, 0));
        !           342: }