xref: /illumos-gate/usr/src/ucbcmd/ln/ln.c (revision 8c0b080c)
1*cc6c5292Schin /*
2*cc6c5292Schin  * Copyright 1991 Sun Microsystems, Inc.  All rights reserved.
3*cc6c5292Schin  * Use is subject to license terms.
4*cc6c5292Schin  */
5*cc6c5292Schin 
67c478bd9Sstevel@tonic-gate /*	Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T	*/
77c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
87c478bd9Sstevel@tonic-gate 
97c478bd9Sstevel@tonic-gate /*
107c478bd9Sstevel@tonic-gate  * Copyright (c) 1980 Regents of the University of California.
117c478bd9Sstevel@tonic-gate  * All rights reserved. The Berkeley software License Agreement
127c478bd9Sstevel@tonic-gate  * specifies the terms and conditions for redistribution.
137c478bd9Sstevel@tonic-gate  */
147c478bd9Sstevel@tonic-gate 
157c478bd9Sstevel@tonic-gate /*
167c478bd9Sstevel@tonic-gate  * ln
177c478bd9Sstevel@tonic-gate  */
187c478bd9Sstevel@tonic-gate #include <stdio.h>
197c478bd9Sstevel@tonic-gate #include <sys/types.h>
207c478bd9Sstevel@tonic-gate #include <sys/param.h>
217c478bd9Sstevel@tonic-gate #include <sys/stat.h>
227c478bd9Sstevel@tonic-gate #include <errno.h>
23*cc6c5292Schin #include <unistd.h>
247c478bd9Sstevel@tonic-gate 
257c478bd9Sstevel@tonic-gate struct	stat stb;
267c478bd9Sstevel@tonic-gate int	fflag;		/* force flag set? */
277c478bd9Sstevel@tonic-gate int	sflag;
287c478bd9Sstevel@tonic-gate 
29*cc6c5292Schin int linkit(char *, char *);
30*cc6c5292Schin void Perror(char *);
31*cc6c5292Schin 
32*cc6c5292Schin int
main(int argc,char ** argv)33*cc6c5292Schin main(int argc, char **argv)
347c478bd9Sstevel@tonic-gate {
35*cc6c5292Schin 	int i, r;
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate 	argc--, argv++;
387c478bd9Sstevel@tonic-gate again:
397c478bd9Sstevel@tonic-gate 	if (argc && strcmp(argv[0], "-f") == 0) {
407c478bd9Sstevel@tonic-gate 		fflag++;
417c478bd9Sstevel@tonic-gate 		argv++;
427c478bd9Sstevel@tonic-gate 		argc--;
437c478bd9Sstevel@tonic-gate 	}
447c478bd9Sstevel@tonic-gate 	if (argc && strcmp(argv[0], "-s") == 0) {
457c478bd9Sstevel@tonic-gate 		sflag++;
467c478bd9Sstevel@tonic-gate 		argv++;
477c478bd9Sstevel@tonic-gate 		argc--;
487c478bd9Sstevel@tonic-gate 	}
497c478bd9Sstevel@tonic-gate 	if (argc == 0)
507c478bd9Sstevel@tonic-gate 		goto usage;
517c478bd9Sstevel@tonic-gate 	else if (argc == 1) {
527c478bd9Sstevel@tonic-gate 		argv[argc] = ".";
537c478bd9Sstevel@tonic-gate 		argc++;
547c478bd9Sstevel@tonic-gate 	}
557c478bd9Sstevel@tonic-gate 	if (argc > 2) {
567c478bd9Sstevel@tonic-gate 		if (stat(argv[argc-1], &stb) < 0)
577c478bd9Sstevel@tonic-gate 			goto usage;
587c478bd9Sstevel@tonic-gate 		if ((stb.st_mode&S_IFMT) != S_IFDIR)
597c478bd9Sstevel@tonic-gate 			goto usage;
607c478bd9Sstevel@tonic-gate 	}
617c478bd9Sstevel@tonic-gate 	r = 0;
627c478bd9Sstevel@tonic-gate 	for (i = 0; i < argc-1; i++)
637c478bd9Sstevel@tonic-gate 		r |= linkit(argv[i], argv[argc-1]);
647c478bd9Sstevel@tonic-gate 	exit(r);
657c478bd9Sstevel@tonic-gate usage:
667c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr,
677c478bd9Sstevel@tonic-gate 	    "Usage: ln [-f] [-s] f1\n\
687c478bd9Sstevel@tonic-gate        ln [-f] [-s] f1 f2\n\
697c478bd9Sstevel@tonic-gate        ln [-f] [-s] f1 ... fn d1\n");
70*cc6c5292Schin 	return (1);
717c478bd9Sstevel@tonic-gate }
727c478bd9Sstevel@tonic-gate 
73*cc6c5292Schin int
linkit(char * from,char * to)74*cc6c5292Schin linkit(char *from, char *to)
757c478bd9Sstevel@tonic-gate {
767c478bd9Sstevel@tonic-gate 	char destname[MAXPATHLEN + 1];
777c478bd9Sstevel@tonic-gate 	char *tail;
787c478bd9Sstevel@tonic-gate 	int (*linkf)() = sflag ? symlink : link;
797c478bd9Sstevel@tonic-gate 	char *strrchr();
807c478bd9Sstevel@tonic-gate 
817c478bd9Sstevel@tonic-gate 	/* is target a directory? */
82*cc6c5292Schin 	if (sflag == 0 && fflag == 0 && stat(from, &stb) >= 0 &&
83*cc6c5292Schin 	    (stb.st_mode&S_IFMT) == S_IFDIR) {
847c478bd9Sstevel@tonic-gate 		printf("%s is a directory\n", from);
857c478bd9Sstevel@tonic-gate 		return (1);
867c478bd9Sstevel@tonic-gate 	}
877c478bd9Sstevel@tonic-gate 	if (stat(to, &stb) >= 0 && (stb.st_mode&S_IFMT) == S_IFDIR) {
887c478bd9Sstevel@tonic-gate 		tail = strrchr(from, '/');
897c478bd9Sstevel@tonic-gate 		if (tail == 0)
907c478bd9Sstevel@tonic-gate 			tail = from;
917c478bd9Sstevel@tonic-gate 		else
927c478bd9Sstevel@tonic-gate 			tail++;
93*cc6c5292Schin 		if (strlen(to) + strlen(tail) >= sizeof (destname) - 1) {
947c478bd9Sstevel@tonic-gate 			(void) fprintf(stderr, "ln: %s/%s: Name too long\n",
957c478bd9Sstevel@tonic-gate 			    to, tail);
967c478bd9Sstevel@tonic-gate 			return (1);
977c478bd9Sstevel@tonic-gate 		}
987c478bd9Sstevel@tonic-gate 		(void) sprintf(destname, "%s/%s", to, tail);
997c478bd9Sstevel@tonic-gate 		to = destname;
1007c478bd9Sstevel@tonic-gate 	}
1017c478bd9Sstevel@tonic-gate 	if ((*linkf)(from, to) < 0) {
1027c478bd9Sstevel@tonic-gate 		if (errno == EEXIST || sflag)
1037c478bd9Sstevel@tonic-gate 			Perror(to);
1047c478bd9Sstevel@tonic-gate 		else if (access(from, 0) < 0)
1057c478bd9Sstevel@tonic-gate 			Perror(from);
1067c478bd9Sstevel@tonic-gate 		else
1077c478bd9Sstevel@tonic-gate 			Perror(to);
1087c478bd9Sstevel@tonic-gate 		return (1);
1097c478bd9Sstevel@tonic-gate 	}
1107c478bd9Sstevel@tonic-gate 	return (0);
1117c478bd9Sstevel@tonic-gate }
1127c478bd9Sstevel@tonic-gate 
113*cc6c5292Schin void
Perror(char * s)114*cc6c5292Schin Perror(char *s)
1157c478bd9Sstevel@tonic-gate {
1167c478bd9Sstevel@tonic-gate 	(void) fprintf(stderr, "ln: ");
1177c478bd9Sstevel@tonic-gate 	perror(s);
1187c478bd9Sstevel@tonic-gate }
119