link: new applet
No binary (build failed)
—
(log yok)
| @@ -127,8 +127,9 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle) | |
| if (hard_link) { | |
| res = link(hard_link, dst_name); | |
| if (res != 0 && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET)) { | |
| + | /* shared message */ |
| bb_perror_msg("can't create %slink " | |
| - | "from %s to %s", "hard", |
| + | "%s to %s", "hard", |
| dst_name, | |
| hard_link); | |
| } | |
| @@ -181,8 +182,9 @@ void FAST_FUNC data_extract_all(archive_handle_t *archive_handle) | |
| if (res != 0 | |
| && !(archive_handle->ah_flags & ARCHIVE_EXTRACT_QUIET) | |
| ) { | |
| + | /* shared message */ |
| bb_perror_msg("can't create %slink " | |
| - | "from %s to %s", "sym", |
| + | "%s to %s", "sym", |
| dst_name, | |
| file_header->link_target); | |
| } | |
| @@ -0,0 +1,41 @@ | |
| + | /* |
| + | * link implementation for busybox |
| + | * |
| + | * Copyright (C) 2017 Denys Vlasenko <[email protected]> |
| + | * |
| + | * Licensed under GPLv2, see file LICENSE in this source tree. |
| + | */ |
| + | //config:config LINK |
| + | //config: bool "link" |
| + | //config: default y |
| + | //config: help |
| + | //config: link creates hard links between files. |
| + | |
| + | //applet:IF_LINK(APPLET_NOFORK(link, link, BB_DIR_BIN, BB_SUID_DROP, link)) |
| + | |
| + | //kbuild:lib-$(CONFIG_LINK) += link.o |
| + | |
| + | //usage:#define link_trivial_usage |
| + | //usage: "FILE LINK" |
| + | //usage:#define link_full_usage "\n\n" |
| + | //usage: "Create hard LINK to FILE" |
| + | |
| + | #include "libbb.h" |
| + | |
| + | /* This is a NOFORK applet. Be very careful! */ |
| + | |
| + | int link_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
| + | int link_main(int argc UNUSED_PARAM, char **argv) |
| + | { |
| + | opt_complementary = "=2"; /* exactly 2 params */ |
| + | getopt32(argv, ""); |
| + | argv += optind; |
| + | if (link(argv[0], argv[1]) != 0) { |
| + | /* shared message */ |
| + | bb_perror_msg_and_die("can't create %slink " |
| + | "%s to %s", "hard", |
| + | argv[1], argv[0] |
| + | ); |
| + | } |
| + | return EXIT_SUCCESS; |
| + | } |
| @@ -33,6 +33,7 @@ roughly are: | |
| * do not expect shared global variables/buffers to be in their | |
| "initialized" state. Examples: xfunc_error_retval can be != 1, | |
| bb_common_bufsiz1 can be scribbled over, ... | |
| + | (although usually xfunc_error_retval's state is not a problem). |
| * do not expect that stdio wasn't used before. Calling set[v]buf() | |
| can be disastrous. | |
| * ... | |
| @@ -81,18 +82,37 @@ are probably not worth the effort. | |
| Any NOFORK applet is also a NOEXEC applet. | |
| + | Calling NOFORK applets |
| + | |
| + | API to call NOFORK applets is two functions: |
| + | |
| + | run_nofork_applet(appno, argv) |
| + | spawn_and_wait(argv) // only if FEATURE_PREFER_APPLETS=y |
| + | |
| + | First one is directly used by shells if FEATURE_SH_NOFORK=y. |
| + | Second one is used by many applets, but main users are xargs and find. |
| + | It itself calls run_nofork_applet(), if argv[0] turned out to be a name |
| + | of a NOFORK applet. |
| + | |
| + | run_nofork_applet() saves/inits/restores option parsing, xfunc_error_retval, |
| + | applet_name. Thus, for example, caller does not need to worry about |
| + | option_mask32 getting trashed. |
| + | |
| + | |
| Relevant CONFIG options | |
| FEATURE_PREFER_APPLETS | |
| BB_EXECVP(cmd, argv) will try to exec /proc/self/exe | |
| - | if command's name matches some applet name |
| - | applet tables will contain NOFORK/NOEXEC bits |
| + | if command's name matches some applet name; |
| spawn_and_wait(argv) will do NOFORK/NOEXEC tricks | |
| - | FEATURE_SH_STANDALONE (needs FEATURE_PREFER_APPLETS=y) |
| + | //TODO: the above two things probably should have separate options? |
| + | |
| + | FEATURE_SH_STANDALONE |
| shells will try to exec /proc/self/exe if command's name matches | |
| - | some applet name |
| - | shells will do NOEXEC trick on NOEXEC applets |
| + | some applet name; shells will do NOEXEC trick on NOEXEC applets |
| + | |
| + | //TODO: split (same as for PREFER_APPLETS) |
| - | FEATURE_SH_NOFORK (needs FEATURE_PREFER_APPLETS=y) |
| + | FEATURE_SH_NOFORK |
| shells will do NOFORK trick on NOFORK applets | |