]>
git.ipfire.org Git - thirdparty/bash.git/blob - examples/loadables/ln.c
874e9db886f8c717ee63bfeda3008f21eaad063c
3 /* See Makefile for compilation details. */
6 Copyright (C) 1999-2020 Free Software Foundation, Inc.
8 This file is part of GNU Bash.
9 Bash is free software: you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
14 Bash is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with Bash. If not, see <http://www.gnu.org/licenses/>.
25 #include "bashtypes.h"
27 #if defined (HAVE_UNISTD_H)
31 #include "posixstat.h"
38 #include "bashgetopt.h"
45 typedef int unix_link_syscall_t
PARAMS((const char *, const char *));
47 #define LN_SYMLINK 0x01
48 #define LN_UNLINK 0x02
49 #define LN_NOFOLLOW 0x04
51 static unix_link_syscall_t
*linkfn
;
64 reset_internal_getopt ();
65 while ((opt
= internal_getopt (list
, "fs")) != -1)
93 linkfn
= (flags
& LN_SYMLINK
) ? symlink
: link
;
95 if (list
->next
== 0) /* ln target, equivalent to ln target . */
96 return (dolink (list
->word
->word
, ".", flags
));
98 if (list
->next
->next
== 0) /* ln target source */
99 return (dolink (list
->word
->word
, list
->next
->word
->word
, flags
));
101 /* ln target1 target2 ... directory */
103 /* find last argument: target directory, and make sure it's an existing
105 for (l
= list
; l
->next
; l
= l
->next
)
107 sdir
= l
->word
->word
;
109 if (stat(sdir
, &sb
) < 0)
111 builtin_error ("%s", sdir
);
112 return (EXECUTION_FAILURE
);
115 if (S_ISDIR (sb
.st_mode
) == 0)
121 for (rval
= EXECUTION_SUCCESS
; list
!= l
; list
= list
->next
)
122 rval
+= dolink (list
->word
->word
, sdir
, flags
);
128 mkdirpath (dir
, file
)
135 flen
= strlen (file
);
137 ret
= xmalloc (2 + dlen
+ flen
);
140 if (ret
[dlen
- 1] != '/')
142 strcpy (ret
+ dlen
, file
);
146 #if defined (HAVE_LSTAT)
148 # define LSTAT_OR_STAT_IF(c, f, b) ((c) ? lstat((f), (b)) : stat((f), (b)))
151 # define LSTAT_OR_STAT_IF(c, f, b) (stat((f), (b)))
155 dolink (src
, dst
, flags
)
159 struct stat ssb
, dsb
;
163 /* If we're not doing symlinks, the source must exist and not be a
165 if ((flags
& LN_SYMLINK
) == 0)
167 if (stat (src
, &ssb
) != 0)
169 builtin_error ("%s: %s", src
, strerror (errno
));
170 return (EXECUTION_FAILURE
);
172 if (S_ISDIR (ssb
.st_mode
))
175 builtin_error ("%s: %s", src
, strerror (errno
));
176 return (EXECUTION_FAILURE
);
180 /* If the destination is a directory, create the final filename by appending
181 the basename of the source to the destination. */
183 if ((LSTAT_OR_STAT_IF((flags
& LN_NOFOLLOW
), dst
, &dsb
) == 0) && S_ISDIR (dsb
.st_mode
))
185 if ((p
= strrchr (src
, '/')) == 0)
190 dst_path
= mkdirpath (dst
, p
);
194 exists
= LSTAT (dst
, &dsb
) == 0;
196 /* If -f was specified, and the destination exists, unlink it. */
197 if ((flags
& LN_UNLINK
) && exists
&& unlink (dst
) != 0)
199 builtin_error ("%s: cannot unlink: %s", dst
, strerror (errno
));
201 return (EXECUTION_FAILURE
);
204 /* Perform the link. */
205 if ((*linkfn
) (src
, dst
) != 0)
207 builtin_error ("cannot link %s to %s: %s", dst
, src
, strerror (errno
));
209 return (EXECUTION_FAILURE
);
213 return (EXECUTION_SUCCESS
);
219 "Create a new directory entry with the same modes as the original",
220 "file. The -f option means to unlink any existing file, permitting",
221 "the link to occur. The -s option means to create a symbolic link.",
222 "By default, ln makes hard links. Specifying -n or its synonym -h",
223 "causes ln to not resolve symlinks in the target file or directory.",
227 /* The standard structure describing a builtin command. bash keeps an array
228 of these structures. */
229 struct builtin ln_struct
= {
230 "ln", /* builtin name */
231 ln_builtin
, /* function implementing the builtin */
232 BUILTIN_ENABLED
, /* initial flags for builtin */
233 ln_doc
, /* array of long documentation strings. */
234 "ln [-fhns] file1 [file2] OR ln [-fhns] file ... directory", /* usage synopsis; becomes short_doc */
235 0 /* reserved for internal use */