/* See LICENSE file for copyright and license details. */ #include #include #include #include #include "util.h" static void usage(void) { eprintf("usage: %s [-f] [-L | -P | -s] target [name]\n" " %s [-f] [-L | -P | -s] target ... directory\n", argv0, argv0); } int main(int argc, char *argv[]) { char *fname, *to; int sflag = 0; int fflag = 0; int hasto = 0; int dirfd = AT_FDCWD; int flags = AT_SYMLINK_FOLLOW; struct stat st; ARGBEGIN { case 'f': fflag = 1; break; case 's': sflag = 1; break; case 'L': flags |= AT_SYMLINK_FOLLOW; break; case 'P': flags &= ~AT_SYMLINK_FOLLOW; break; default: usage(); } ARGEND; if (argc == 0) usage(); fname = sflag ? "symlink" : "link"; if (argc >= 2) { if (stat(argv[argc - 1], &st) == 0 && S_ISDIR(st.st_mode)) { if ((dirfd = open(argv[argc - 1], O_RDONLY)) < 0) eprintf("open:"); } else if (argc == 2) { to = argv[1]; hasto = 1; } else { eprintf("destination is not a directory\n"); } argc--; } for (; argc > 0; argc--, argv++) { if (!hasto) to = basename(argv[0]); if (fflag) unlinkat(dirfd, to, 0); if ((!sflag ? linkat(AT_FDCWD, argv[0], dirfd, to, flags) : symlinkat(argv[0], dirfd, to)) < 0) { eprintf("%s %s <- %s:", fname, argv[0], to); } } return 0; }