Annotation of coherent/d/bin/ln.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * ln.c
                      3:  * Make a link.
                      4:  */
                      5: 
                      6: #include <stdio.h>
                      7: #include <sys/stat.h>
                      8: #include <errno.h>
                      9: 
                     10: #define        VERSION "2.2"
                     11: #define        USAGE   "Usage:\t%s [-f] oldfile newfile\n\t%s [-f] file ... directory\n"
                     12: 
                     13: /* Externals. */
                     14: extern int     errno;
                     15: extern char *  rindex();
                     16: extern         char *  strcpy();
                     17: extern int     strlen();
                     18: 
                     19: /* Globals. */
                     20: char           *argv0;
                     21: int            fflag;
                     22: char           namebuf[200];
                     23: 
                     24: /* Functions. */
                     25: char * basename();
                     26: int    ln();
                     27: void   usage();
                     28: 
                     29: main(argc, argv) int argc; char *argv[];
                     30: {
                     31:        register int i, estat;
                     32:        struct  stat    sb;
                     33:        char *lname, *s;
                     34: 
                     35:        argv0 = *argv;
                     36:        if (argc > 1 && argv[1][0]=='-') {
                     37:                for (s = &argv[1][1]; *s; s++) {
                     38:                        switch (*s) {
                     39:                        case 'V':
                     40:                                fprintf(stderr, "%s: V%s\n", argv0, VERSION);
                     41:                                break;
                     42:                        case 'f':
                     43:                                ++fflag;
                     44:                                break;
                     45:                        default:
                     46:                                usage();
                     47:                        }
                     48:                        --argc;
                     49:                        ++argv;
                     50:                }
                     51:        }
                     52:        if (argc < 3)
                     53:                usage();
                     54: 
                     55:        lname = argv[argc-1];
                     56:        if (stat(lname, &sb)>=0 && (sb.st_mode&S_IFMT)==S_IFDIR) {
                     57:                /* The last arg is a directory. */
                     58:                strcpy(namebuf, lname);
                     59:                s = &namebuf[strlen(namebuf)];
                     60:                *s++ = '/';
                     61:                for (estat = 0, i=1; i<argc-1; i++) {
                     62:                        strcpy(s, basename(argv[i]));
                     63:                        estat |= ln(argv[i], namebuf);
                     64:                }
                     65:                exit(estat);
                     66:        } else if (argc > 3)
                     67:                usage();
                     68:        else
                     69:                exit(ln(argv[1], argv[2]));
                     70: }
                     71: 
                     72: /*
                     73:  * Do the link and check for errors.
                     74:  * Try to force the link if the '-f' is specified.
                     75:  * Return 0 on success, 1 on failure.
                     76:  */
                     77: int
                     78: ln(n1, n2) char *n1, *n2;
                     79: {
                     80:        if (link(n1, n2) == 0)
                     81:                return 0;
                     82:        if (fflag && errno==EEXIST && force(n1, n2) == 0)
                     83:                return 0;
                     84:        perror(argv0);
                     85:        return 1;
                     86: }
                     87: 
                     88: /*
                     89:  * The link failed, try to force it while avoiding:
                     90:  *     directory unlink
                     91:  *     unlinking source == destination
                     92:  *     unlinking destination when different device
                     93:  * Return 0 on success, -1 on failure.
                     94:  */
                     95: int
                     96: force(n1, n2) char *n1, *n2;
                     97: {
                     98:        struct stat sb1, sb2;
                     99: 
                    100:        if (stat(n2, &sb2) < 0)
                    101:                return -1;              /* e.g. n2 in nonexistent directory */
                    102:        if ((sb2.st_mode&S_IFMT) == S_IFDIR) {
                    103:                errno = EISDIR;
                    104:                return -1;              /* n2 is a directory */
                    105:        } else if (stat(n1, &sb1) >= 0) {
                    106:                if (sb1.st_dev != sb2.st_dev) {
                    107:                        errno = EXDEV;
                    108:                        return -1;      /* cross device link */
                    109:                }
                    110:                if (sb1.st_ino == sb2.st_ino)
                    111:                        return 0;       /* n1 and n2 are already linked, ok */
                    112:        }
                    113:        if (unlink(n2) < 0)
                    114:                return -1;              /* cannot unlink */
                    115:        return link(n1, n2);
                    116: }
                    117: 
                    118: /*
                    119:  * Find the part of a name past the last '/'.
                    120:  */
                    121: char *
                    122: basename(n) register char *n;
                    123: {
                    124:        register char *s;
                    125: 
                    126:        if ((s = rindex(n, '/')) == NULL)
                    127:                return n;
                    128:        return ++s;
                    129: }
                    130: 
                    131: void
                    132: usage()
                    133: {
                    134:        fprintf(stderr, USAGE, argv0, argv0);
                    135:        exit(1);
                    136: }
                    137: 
                    138: /* end of ln.c */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.