blob: 6751e909384c0e447c50e00c023112480a995397 [file] [log] [blame]
Erik Andersene49d5ec2000-02-08 19:58:47 +00001/* vi: set sw=4 ts=4: */
Eric Andersenf6be9441999-10-13 21:12:06 +00002/*
3 * Mini ln implementation for busybox
4 *
Eric Andersenc7bda1c2004-03-15 08:29:22 +00005 * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
Eric Andersenf6be9441999-10-13 21:12:06 +00006 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 */
22
Manuel Novoa III cad53642003-03-19 09:13:01 +000023/* BB_AUDIT SUSv3 compliant */
Rob Landley3071e2f2005-04-29 22:13:04 +000024/* BB_AUDIT GNU options missing: -d, -F, -i, and -v. */
Manuel Novoa III cad53642003-03-19 09:13:01 +000025/* http://www.opengroup.org/onlinepubs/007904975/utilities/ln.html */
26
Rob Landley3071e2f2005-04-29 22:13:04 +000027#include <stdio.h>
Eric Andersened3ef502001-01-27 08:24:39 +000028#include <stdlib.h>
Eric Andersened3ef502001-01-27 08:24:39 +000029#include <unistd.h>
Rob Landley3071e2f2005-04-29 22:13:04 +000030#include <errno.h>
Eric Andersencbe31da2001-02-20 06:14:08 +000031#include "busybox.h"
Eric Andersencbe31da2001-02-20 06:14:08 +000032
Manuel Novoa III cad53642003-03-19 09:13:01 +000033#define LN_SYMLINK 1
34#define LN_FORCE 2
35#define LN_NODEREFERENCE 4
Rob Landley3071e2f2005-04-29 22:13:04 +000036#define LN_BACKUP 8
37#define LN_SUFFIX 16
Eric Andersenf6be9441999-10-13 21:12:06 +000038
39extern int ln_main(int argc, char **argv)
Eric Andersencc8ed391999-10-05 16:24:54 +000040{
Eric Andersen13241df2000-10-04 16:02:53 +000041 int status = EXIT_SUCCESS;
Manuel Novoa III cad53642003-03-19 09:13:01 +000042 int flag;
43 char *last;
44 char *src_name;
Glenn L McGrathcfc0ad42003-12-31 23:10:44 +000045 char *src;
Rob Landley3071e2f2005-04-29 22:13:04 +000046 char *suffix = "~";
Glenn L McGrathcfc0ad42003-12-31 23:10:44 +000047 struct stat statbuf;
Manuel Novoa III cad53642003-03-19 09:13:01 +000048 int (*link_func)(const char *, const char *);
49
Rob Landley3071e2f2005-04-29 22:13:04 +000050 flag = bb_getopt_ulflags(argc, argv, "sfnbS:", &suffix);
Manuel Novoa III cad53642003-03-19 09:13:01 +000051
52 if (argc == optind) {
53 bb_show_usage();
54 }
55
56 last = argv[argc - 1];
57 argv += optind;
58
59 if (argc == optind + 1) {
60 *--argv = last;
61 last = bb_get_last_path_component(bb_xstrdup(last));
62 }
63
64 do {
Glenn L McGrathcfc0ad42003-12-31 23:10:44 +000065 src_name = NULL;
Manuel Novoa III cad53642003-03-19 09:13:01 +000066 src = last;
67
68 if (is_directory(src,
69 (flag & LN_NODEREFERENCE) ^ LN_NODEREFERENCE,
70 NULL)) {
71 src_name = bb_xstrdup(*argv);
72 src = concat_path_file(src, bb_get_last_path_component(src_name));
73 free(src_name);
Glenn L McGrathcfc0ad42003-12-31 23:10:44 +000074 src_name = src;
75 }
Glenn L McGrath95f75a32004-01-08 10:51:09 +000076 if (!(flag & LN_SYMLINK) && stat(*argv, &statbuf)) {
"Vladimir N. Oleynik"39a841c2005-09-29 16:18:57 +000077 bb_perror_msg("%s", *argv);
Glenn L McGrathcfc0ad42003-12-31 23:10:44 +000078 status = EXIT_FAILURE;
79 free(src_name);
80 continue;
Eric Andersen815e9042000-06-06 16:15:23 +000081 }
Manuel Novoa III cad53642003-03-19 09:13:01 +000082
Rob Landley3071e2f2005-04-29 22:13:04 +000083 if (flag & LN_BACKUP) {
"Vladimir N. Oleynik"39a841c2005-09-29 16:18:57 +000084 char *backup;
85 backup = bb_xasprintf("%s%s", src, suffix);
Rob Landley3071e2f2005-04-29 22:13:04 +000086 if (rename(src, backup) < 0 && errno != ENOENT) {
"Vladimir N. Oleynik"39a841c2005-09-29 16:18:57 +000087 bb_perror_msg("%s", src);
Rob Landley3071e2f2005-04-29 22:13:04 +000088 status = EXIT_FAILURE;
89 free(backup);
90 continue;
91 }
92 free(backup);
93 /*
94 * When the source and dest are both hard links to the same
95 * inode, a rename may succeed even though nothing happened.
96 * Therefore, always unlink().
97 */
98 unlink(src);
99 } else if (flag & LN_FORCE) {
Manuel Novoa III cad53642003-03-19 09:13:01 +0000100 unlink(src);
101 }
102
103 link_func = link;
104 if (flag & LN_SYMLINK) {
105 link_func = symlink;
106 }
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000107
Manuel Novoa III cad53642003-03-19 09:13:01 +0000108 if (link_func(*argv, src) != 0) {
109 bb_perror_msg(src);
Glenn L McGrathcfc0ad42003-12-31 23:10:44 +0000110 status = EXIT_FAILURE;
Manuel Novoa III cad53642003-03-19 09:13:01 +0000111 }
112
113 free(src_name);
Eric Andersenc7bda1c2004-03-15 08:29:22 +0000114
Manuel Novoa III cad53642003-03-19 09:13:01 +0000115 } while ((++argv)[1]);
116
Eric Andersenfcffa2c2002-04-06 05:17:57 +0000117 return status;
Eric Andersencc8ed391999-10-05 16:24:54 +0000118}