[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
--absolute and --relative option for ln(1).
From: |
Shigio Yamaguchi |
Subject: |
--absolute and --relative option for ln(1). |
Date: |
Fri, 29 Mar 2002 13:24:11 +0900 |
Hello,
I have implemented two options for ln(1).
[Problem]
The ln(1) makes a wrong symbolic link in some cases.
(It is not a bug but a spec of ln(1).)
For example:
% cd /usr
% ln -s src/bin /tmp/bin
% cd /tmp/bin
/tmp/bin: No such file or directory.
% ls -l /tmp/bin
lrwxrwxrwx 1 shigio wheel 7 Jan 10 22:10 /tmp/bin -> src/bin
~~~~~~~
It's wrong!
[Solution]
I have made a patch for ln(1) to make right symbolic links.
New ln(1) has additional two options:
-a(--absolute) If the -s option is specified, make absolute symbolic link.
-r(--relative) If the -s option is specified, make relative symbolic link.
The -a and -r options override each other; the last one specified
determines the method used.
New ln(1) with -r or -a option makes right symbolic link like this:
% cd /usr
% ln -sr src/bin /tmp/bin # relative symbolic link
% cd /tmp/bin
lrwxrwxrwx 1 shigio wheel 14 Jan 10 22:12 /tmp/bin -> ../usr/src/bin
~~~~~~~~~~~~~~
Right!
or
% cd /usr
% ln -sa src/bin /tmp/bin # absolute symbolic link
% cd /tmp/bin
lrwxrwxrwx 1 shigio wheel 12 Jan 10 22:13 /tmp/bin -> /usr/src/bin
~~~~~~~~~~~~
Right!
[Files]
Here is a patch for fileutils-4.1.7.
This patch calls two external functions: abs2rel() and rel2abs().
You can get the source code from http://www.tamacom.com/pathconvert/.
If you include this patch, abs2rel and rel2abs into fileutils,
I will transfer all of them to FSF and write a disclaimer paper for it.
Thanks!
/*
* This file is placed into the public domain by the author,
* Shigio Yamaguchi <address@hidden>
*/
diff -c -r -N fileutils-4.1.7-/man/ln.1 fileutils-4.1.7/man/ln.1
*** fileutils-4.1.7-/man/ln.1 Fri Mar 29 12:49:23 2002
--- fileutils-4.1.7/man/ln.1 Fri Mar 29 12:56:18 2002
***************
*** 20,28 ****
--- 20,32 ----
than one TARGET, the last argument must be a directory; create links
in DIRECTORY to each TARGET. Create hard links by default, symbolic
links with \fB\-\-symbolic\fR. When creating hard links, each TARGET must
exist.
+ The \fB\-\-absolute\fR and \fB\-\-relative\fR options override each other;
the last one specified determines
.PP
Mandatory arguments to long options are mandatory for short options too.
.TP
+ \fB\-a\fR, \fB\-\-absolute\fR
+ If \fB\-\-symbolic\fR option is specified, make absolute symbolic link.
+ .TP
\fB\-\-backup\fR[=\fICONTROL\fR]
make a backup of each existing destination file
.TP
***************
*** 41,46 ****
--- 45,53 ----
.TP
\fB\-i\fR, \fB\-\-interactive\fR
prompt whether to remove destinations
+ .TP
+ \fB\-r\fR, \fB\-\-relative\fR
+ If \fB\-\-symbolic\fR option is specified, make relative symbolic link.
.TP
\fB\-s\fR, \fB\-\-symbolic\fR
make symbolic links instead of hard links
diff -c -r -N fileutils-4.1.7-/src/ln.c fileutils-4.1.7/src/ln.c
*** fileutils-4.1.7-/src/ln.c Fri Mar 29 12:49:21 2002
--- fileutils-4.1.7/src/ln.c Fri Mar 29 12:24:48 2002
***************
*** 119,131 ****
--- 119,139 ----
symlink-to-dir before creating the new link. */
static int dereference_dest_dir_symlinks = 1;
+ /* If nonzero, make absolute symbolic links. */
+ static int absolute = 0;
+
+ /* If nonzero, make relative symbolic links. */
+ static int relative = 0;
+
static struct option const long_options[] =
{
+ {"absolute", no_argument, NULL, 'a'},
{"backup", optional_argument, NULL, 'b'},
{"directory", no_argument, NULL, 'F'},
{"no-dereference", no_argument, NULL, 'n'},
{"force", no_argument, NULL, 'f'},
{"interactive", no_argument, NULL, 'i'},
+ {"relative", no_argument, NULL, 'r'},
{"suffix", required_argument, NULL, 'S'},
{"target-directory", required_argument, NULL, TARGET_DIRECTORY_OPTION},
{"symbolic", no_argument, NULL, 's'},
***************
*** 149,154 ****
--- 157,165 ----
char *dest_backup = NULL;
int lstat_status;
int backup_succeeded = 0;
+ char base[PATH_MAX];
+ char abssource[PATH_MAX];
+ char relsource[PATH_MAX];
/* Use stat here instead of lstat.
On SVR4, link does not follow symlinks, so this check disallows
***************
*** 212,217 ****
--- 223,264 ----
}
}
+ /* If -a or -r option specified, do path conversion. */
+ if (symbolic_link && (absolute || relative))
+ {
+ /* convert source directory into absolute name */
+ if (*source != '/') {
+ if (getcwd(base, PATH_MAX) == NULL)
+ error(1, errno, "couldn't get current directory.");
+ if (rel2abs(source, base, abssource, PATH_MAX) == NULL)
+ error(1, errno, "couldn't convert path");
+ source = abssource;
+ }
+ /* convert source directory into relative name */
+ if (relative) {
+ char path[PATH_MAX];
+ const char *p;
+
+ if (!S_ISDIR (dest_stats.st_mode)) {
+ if ((p = strrchr(dest, '/')) != NULL) {
+ int col = p - dest + 1;
+ strncpy(path, dest, col);
+ path[col] = 0;
+ } else {
+ path[0] = '.';
+ path[1] = 0;
+ }
+ p = path;
+ } else
+ p = dest;
+ if (realpath(p, base) == NULL)
+ error(1, errno, p);
+ if (abs2rel(source, base, relsource, PATH_MAX) == NULL)
+ error(1, errno, "couldn't convert path");
+ source = relsource;
+ }
+ }
+
/* If --force (-f) has been specified without --backup, then before
making a link ln must remove the destination file if it exists.
(with --backup, it just renames any existing destination file)
***************
*** 355,360 ****
--- 402,408 ----
Mandatory arguments to long options are mandatory for short options too.\n\
"), stdout);
fputs (_("\
+ -a, --absolute make absolute symbolic link\n\
--backup[=CONTROL] make a backup of each existing destination
file\n\
-b like --backup but does not accept an argument\n\
-d, -F, --directory hard link directories (super-user only)\n\
***************
*** 363,368 ****
--- 411,417 ----
fputs (_("\
-n, --no-dereference treat destination that is a symlink to a\n\
directory as if it were a normal file\n\
+ -r, --relative make relative symbolic link\n\
-i, --interactive prompt whether to remove destinations\n\
-s, --symbolic make symbolic links instead of hard links\n\
"), stdout);
***************
*** 421,427 ****
= hard_dir_link = 0;
errors = 0;
! while ((c = getopt_long (argc, argv, "bdfinsvFS:V:", long_options, NULL))
!= -1)
{
switch (c)
--- 470,476 ----
= hard_dir_link = 0;
errors = 0;
! while ((c = getopt_long (argc, argv, "abdfinrsvFS:V:", long_options, NULL))
!= -1)
{
switch (c)
***************
*** 436,441 ****
--- 485,493 ----
), optarg);
/* Fall through. */
+ case 'a':
+ absolute = 1;
+ break;
case 'b':
make_backups = 1;
if (optarg)
***************
*** 455,460 ****
--- 507,515 ----
break;
case 'n':
dereference_dest_dir_symlinks = 0;
+ break;
+ case 'r':
+ relative = 1;
break;
case 's':
#ifdef S_ISLNK
--
Shigio Yamaguchi - Tama Communications Corporation
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- --absolute and --relative option for ln(1).,
Shigio Yamaguchi <=