ln.c (1410B)
1 /* See LICENSE file for copyright and license details. */ 2 #include <errno.h> 3 #include <fcntl.h> 4 #include <libgen.h> 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <string.h> 8 #include <sys/stat.h> 9 #include <unistd.h> 10 11 #include "util.h" 12 13 static void 14 usage(void) 15 { 16 eprintf("usage: %1$s [-LPfs] target [linkname]\n" 17 " %1$s [-LPfs] target... directory\n", argv0); 18 } 19 20 int 21 main(int argc, char *argv[]) 22 { 23 char *fname, *to; 24 int sflag = 0; 25 int fflag = 0; 26 int hasto = 0; 27 int dirfd = AT_FDCWD; 28 int flags = AT_SYMLINK_FOLLOW; 29 struct stat st; 30 31 ARGBEGIN { 32 case 'f': 33 fflag = 1; 34 break; 35 case 's': 36 sflag = 1; 37 break; 38 case 'L': 39 flags |= AT_SYMLINK_FOLLOW; 40 break; 41 case 'P': 42 flags &= ~AT_SYMLINK_FOLLOW; 43 break; 44 default: 45 usage(); 46 } ARGEND; 47 48 if (argc == 0) 49 usage(); 50 51 fname = sflag ? "symlink" : "link"; 52 53 if (argc >= 2) { 54 if (stat(argv[argc - 1], &st) == 0 && S_ISDIR(st.st_mode)) { 55 if ((dirfd = open(argv[argc - 1], O_RDONLY)) < 0) 56 eprintf("open:"); 57 } else if (argc == 2) { 58 to = argv[1]; 59 hasto = 1; 60 } else { 61 eprintf("destination is not a directory\n"); 62 } 63 argc--; 64 } 65 66 for (; argc > 0; argc--, argv++) { 67 if (!hasto) 68 to = basename(argv[0]); 69 if (fflag) 70 remove(to); 71 if ((!sflag ? linkat(AT_FDCWD, argv[0], dirfd, to, flags) 72 : symlinkat(argv[0], dirfd, to)) < 0) { 73 eprintf("%s %s <- %s:", fname, argv[0], to); 74 } 75 } 76 77 return 0; 78 }