Home | History | Annotate | Download | only in ln
      1 /*
      2  * Copyright 1991 Sun Microsystems, Inc.  All rights reserved.
      3  * Use is subject to license terms.
      4  */
      5 
      6 /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
      7 /*	  All Rights Reserved  	*/
      8 
      9 /*
     10  * Copyright (c) 1980 Regents of the University of California.
     11  * All rights reserved. The Berkeley software License Agreement
     12  * specifies the terms and conditions for redistribution.
     13  */
     14 
     15 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     16 
     17 /*
     18  * ln
     19  */
     20 #include <stdio.h>
     21 #include <sys/types.h>
     22 #include <sys/param.h>
     23 #include <sys/stat.h>
     24 #include <errno.h>
     25 #include <unistd.h>
     26 
     27 struct	stat stb;
     28 int	fflag;		/* force flag set? */
     29 int	sflag;
     30 
     31 int linkit(char *, char *);
     32 void Perror(char *);
     33 
     34 int
     35 main(int argc, char **argv)
     36 {
     37 	int i, r;
     38 
     39 	argc--, argv++;
     40 again:
     41 	if (argc && strcmp(argv[0], "-f") == 0) {
     42 		fflag++;
     43 		argv++;
     44 		argc--;
     45 	}
     46 	if (argc && strcmp(argv[0], "-s") == 0) {
     47 		sflag++;
     48 		argv++;
     49 		argc--;
     50 	}
     51 	if (argc == 0)
     52 		goto usage;
     53 	else if (argc == 1) {
     54 		argv[argc] = ".";
     55 		argc++;
     56 	}
     57 	if (argc > 2) {
     58 		if (stat(argv[argc-1], &stb) < 0)
     59 			goto usage;
     60 		if ((stb.st_mode&S_IFMT) != S_IFDIR)
     61 			goto usage;
     62 	}
     63 	r = 0;
     64 	for (i = 0; i < argc-1; i++)
     65 		r |= linkit(argv[i], argv[argc-1]);
     66 	exit(r);
     67 usage:
     68 	(void) fprintf(stderr,
     69 	    "Usage: ln [-f] [-s] f1\n\
     70        ln [-f] [-s] f1 f2\n\
     71        ln [-f] [-s] f1 ... fn d1\n");
     72 	return (1);
     73 }
     74 
     75 int
     76 linkit(char *from, char *to)
     77 {
     78 	char destname[MAXPATHLEN + 1];
     79 	char *tail;
     80 	int (*linkf)() = sflag ? symlink : link;
     81 	char *strrchr();
     82 
     83 	/* is target a directory? */
     84 	if (sflag == 0 && fflag == 0 && stat(from, &stb) >= 0 &&
     85 	    (stb.st_mode&S_IFMT) == S_IFDIR) {
     86 		printf("%s is a directory\n", from);
     87 		return (1);
     88 	}
     89 	if (stat(to, &stb) >= 0 && (stb.st_mode&S_IFMT) == S_IFDIR) {
     90 		tail = strrchr(from, '/');
     91 		if (tail == 0)
     92 			tail = from;
     93 		else
     94 			tail++;
     95 		if (strlen(to) + strlen(tail) >= sizeof (destname) - 1) {
     96 			(void) fprintf(stderr, "ln: %s/%s: Name too long\n",
     97 			    to, tail);
     98 			return (1);
     99 		}
    100 		(void) sprintf(destname, "%s/%s", to, tail);
    101 		to = destname;
    102 	}
    103 	if ((*linkf)(from, to) < 0) {
    104 		if (errno == EEXIST || sflag)
    105 			Perror(to);
    106 		else if (access(from, 0) < 0)
    107 			Perror(from);
    108 		else
    109 			Perror(to);
    110 		return (1);
    111 	}
    112 	return (0);
    113 }
    114 
    115 void
    116 Perror(char *s)
    117 {
    118 	(void) fprintf(stderr, "ln: ");
    119 	perror(s);
    120 }
    121