[prev in list] [next in list] [prev in thread] [next in thread]
List: busybox
Subject: Re: Patch to add "-r" option (create relative symlinks) to coreutils/ln
From: Ross Thomas <halfacanuck () gmail ! com>
Date: 2016-06-19 7:57:05
Message-ID: CAJzZAcuk2PWjxDmFfw3snQmOCcGC806=L+O-L+R+qLJa71+23g () mail ! gmail ! com
[Download RAW message or body]
[Attachment #2 (multipart/alternative)]
Thanks for the tip!
Here's the updated patch.
On Sat, Jun 18, 2016 at 12:41 PM, Tito <farmatito@tiscali.it> wrote:
>
>
> On 06/18/2016 05:24 PM, Ross Thomas wrote:
> > I recently had a need for the "-r" option to ln while using Busybox, and
> > it turned out to be easy enough to add, so here's a patch against
> v1.24.2.
> >
> > This is the first time I've poked at the BB source so it's possible I
> > overlooked something helpful in libbb, or am not using approved style,
> > or whatever. Suggestions welcome!
> >
> > Thanks,
> >
> > R
> >
>
> Hi,
> i think you could use something like:
>
> opt_complementary = "-1:r?s"; /* min one arg */
>
> so to raise an error if -r is used without -s like real ln does:
>
>
> ln: cannot do --relative without --symbolic
>
> from libb/getopt32
>
> "a?b" A "?" between an option and a group of options means that
> at least one of them is required to occur if the first option
> occurs in preceding command line arguments.
>
> For example from "id" applet:
>
> // Don't allow -n -r -rn -ug -rug -nug -rnug
> opt_complementary = "r?ug:n?ug:u--g:g--u";
> flags = getopt32(argv, "rnug");
>
> This example allowed only:
> $ id; id -u; id -g; id -ru; id -nu; id -rg; id -ng; id -rnu; id
> -rng
>
> This is just a untested hint.
>
> Ciao,
> Tito
> _______________________________________________
> busybox mailing list
> busybox@busybox.net
> http://lists.busybox.net/mailman/listinfo/busybox
>
[Attachment #5 (text/html)]
<div dir="ltr"><div>Thanks for the tip!<br><br></div>Here's the updated \
patch.<br><div><div><br><div class="gmail_extra"><br><div class="gmail_quote">On Sat, \
Jun 18, 2016 at 12:41 PM, Tito <span dir="ltr"><<a \
href="mailto:farmatito@tiscali.it" \
target="_blank">farmatito@tiscali.it</a>></span> wrote:<br><blockquote \
class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc \
solid;padding-left:1ex"><div class="HOEnZb"><div class="h5"><br> <br>
On 06/18/2016 05:24 PM, Ross Thomas wrote:<br>
> I recently had a need for the "-r" option to ln while using Busybox, \
and<br> > it turned out to be easy enough to add, so here's a patch against \
v1.24.2.<br> ><br>
> This is the first time I've poked at the BB source so it's possible \
I<br> > overlooked something helpful in libbb, or am not using approved style,<br>
> or whatever. Suggestions welcome!<br>
><br>
> Thanks,<br>
><br>
> R<br>
><br>
<br>
</div></div>Hi,<br>
i think you could use something like:<br>
<br>
opt_complementary = "-1:r?s"; /* min one arg */<br>
<br>
so to raise an error if -r is used without -s like real ln does:<br>
<br>
<br>
ln: cannot do --relative without --symbolic<br>
<br>
from libb/getopt32<br>
<br>
"a?b" A "?" between an option and a group of options means \
that<br>
at least one of them is required to occur if the first option<br>
occurs in preceding command line arguments.<br>
<br>
For example from "id" applet:<br>
<br>
// Don't allow -n -r -rn -ug -rug -nug -rnug<br>
opt_complementary = "r?ug:n?ug:u--g:g--u";<br>
flags = getopt32(argv, "rnug");<br>
<br>
This example allowed only:<br>
$ id; id -u; id -g; id -ru; id -nu; id -rg; id -ng; id -rnu; id -rng<br>
<br>
This is just a untested hint.<br>
<br>
Ciao,<br>
Tito<br>
_______________________________________________<br>
busybox mailing list<br>
<a href="mailto:busybox@busybox.net">busybox@busybox.net</a><br>
<a href="http://lists.busybox.net/mailman/listinfo/busybox" rel="noreferrer" \
target="_blank">http://lists.busybox.net/mailman/listinfo/busybox</a><br> \
</blockquote></div><br></div></div></div></div>
["ln-r.patch" (text/x-diff)]
--- busybox-1.24.2/coreutils/ln.c.orig 2016-02-11 03:50:37.000000000 -0800
+++ busybox-1.24.2/coreutils/ln.c 2016-06-19 00:22:58.720032674 -0700
@@ -18,6 +18,7 @@
//usage: "\n -s Make symlinks instead of hardlinks"
//usage: "\n -f Remove existing destinations"
//usage: "\n -n Don't dereference symlinks - treat like normal file"
+//usage: "\n -r Create symlinks relative to link location (with -s)"
//usage: "\n -b Make a backup of the target (if exists) before link operation"
//usage: "\n -S suf Use suffix instead of ~ when making backup files"
//usage: "\n -T 2nd arg must be a DIR"
@@ -40,6 +41,74 @@
#define LN_SUFFIX (1 << 4)
#define LN_VERBOSE (1 << 5)
#define LN_LINKFILE (1 << 6)
+#define LN_RELATIVE (1 << 7)
+
+
+static int common_prefix_length(const char *path1, const char *path2)
+{
+ const char *start1 = path1;
+
+ /* NB: Function assumes absolute paths */
+
+ /* Find common string prefix */
+
+ while (*path1 && *path2 && *path1 == *path2) {
+ path1++;
+ path2++;
+ }
+
+ /* Search backwards to common path-component prefix */
+
+ while (path1 > start1 && *path1 != '/') {
+ path1--;
+ }
+
+ return (path1 + 1) - start1;
+}
+
+static char *xmalloc_relativized_target(const char *target, const char *src)
+{
+ const char *target_abs, *src_abs, *src_last, *sp;
+ char *out, *op;
+ int out_len, common_len;
+
+ /* Absolutize both inputs */
+
+ target_abs = bb_simplify_path(target);
+ src_abs = bb_simplify_path(src);
+
+ /* Output can't be longer than twice the longest absolutized input */
+
+ out_len = 1 + 2 * MAX(strlen(target_abs), strlen(src_abs));
+ out = op = xmalloc(out_len);
+
+ /* Skip common leading components */
+
+ common_len = common_prefix_length(target_abs, src_abs);
+ sp = src_abs + common_len;
+
+ /* Output "../" for each non-tail component remaining in src */
+
+ src_last = bb_get_last_path_component_nostrip(src_abs);
+ while (sp < src_last) {
+ if ('/' == *sp) {
+ *op++ = '.';
+ *op++ = '.';
+ *op++ = '/';
+ }
+ sp++;
+ }
+
+ /* Append target postfix */
+
+ strcpy(op, target_abs + common_len);
+
+ free((char *)target_abs);
+ free((char *)src_abs);
+
+ return out;
+}
+
int ln_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int ln_main(int argc, char **argv)
@@ -49,12 +118,13 @@
char *last;
char *src_name;
char *src;
+ char *target;
char *suffix = (char*)"~";
struct stat statbuf;
int (*link_func)(const char *, const char *);
- opt_complementary = "-1"; /* min one arg */
- opts = getopt32(argv, "sfnbS:vT", &suffix);
+ opt_complementary = "-1r?s"; /* min one arg; cannot use -r without -s */
+ opts = getopt32(argv, "sfnbS:vTr", &suffix);
last = argv[argc - 1];
argv += optind;
@@ -120,19 +190,28 @@
}
link_func = link;
+ target = *argv;
if (opts & LN_SYMLINK) {
link_func = symlink;
+ if (opts & LN_RELATIVE) {
+ target = xmalloc_relativized_target(*argv, src);
+ }
}
if (opts & LN_VERBOSE) {
- printf("'%s' -> '%s'\n", src, *argv);
+ printf("'%s' -> '%s'\n", src, target);
}
- if (link_func(*argv, src) != 0) {
+ if (link_func(target, src) != 0) {
bb_simple_perror_msg(src);
status = EXIT_FAILURE;
}
+ if (target != *argv) {
+ free(target);
+ target = NULL;
+ }
+
free(src_name);
} while ((++argv)[1]);
_______________________________________________
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic