diff options
Diffstat (limited to 'toys/posix/ln.c')
-rw-r--r-- | toys/posix/ln.c | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/toys/posix/ln.c b/toys/posix/ln.c new file mode 100644 index 00000000..6f55971a --- /dev/null +++ b/toys/posix/ln.c @@ -0,0 +1,70 @@ +/* vi: set sw=4 ts=4: + * + * ln.c - Create filesystem links + * + * Copyright 2012 Andre Renaud <andre@bluewatersys.com> + * + * See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/ln.html + +USE_LN(NEWTOY(ln, "<1nfs", TOYFLAG_BIN)) + +config LN + bool "ln" + default y + help + usage: ln [-sf] [FROM...] TO + + Create a link between FROM and TO. + With only one argument, create link in current directory. + + -s Create a symbolic link + -f Force the creation of the link, even if TO already exists + -n Symlink at destination treated as file +*/ + +#include "toys.h" + +#define FLAG_s 1 +#define FLAG_f 2 +#define FLAG_n 4 + +void ln_main(void) +{ + char *dest = toys.optargs[--toys.optc], *new; + struct stat buf; + int i; + + // With one argument, create link in current directory. + if (!toys.optc) { + toys.optc++; + dest="."; + } + + // Is destination a directory? + if (((toys.optflags&FLAG_n) ? lstat : stat)(dest, &buf) + || !S_ISDIR(buf.st_mode)) + { + if (toys.optc>1) error_exit("'%s' not a directory"); + buf.st_mode = 0; + } + + for (i=0; i<toys.optc; i++) { + int rc; + char *try = toys.optargs[i]; + + if (S_ISDIR(buf.st_mode)) { + new = strrchr(try, '/'); + if (!new) new = try; + new = xmsprintf("%s/%s", dest, new); + } else new = dest; + /* Silently unlink the existing target. If it doesn't exist, + * then we just move on */ + if (toys.optflags & FLAG_f) unlink(new); + + rc = (toys.optflags & FLAG_s) ? symlink(try, new) : link(try, new); + if (rc) + perror_exit("cannot create %s link from '%s' to '%s'", + (toys.optflags & FLAG_s) ? "symbolic" : "hard", try, new); + if (new != dest) free(new); + } +} |