Allow hardlinks to symlinks.
Reviewed by: Bill Studenmund, Klaus Klein
This commit is contained in:
parent
2425433ff6
commit
abda8d9447
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: ln.c,v 1.15 1998/07/28 05:31:25 mycroft Exp $ */
|
||||
/* $NetBSD: ln.c,v 1.16 1999/09/05 23:34:40 hubertf Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1987, 1993, 1994
|
||||
@ -43,7 +43,7 @@ __COPYRIGHT("@(#) Copyright (c) 1987, 1993, 1994\n\
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)ln.c 8.2 (Berkeley) 3/31/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: ln.c,v 1.15 1998/07/28 05:31:25 mycroft Exp $");
|
||||
__RCSID("$NetBSD: ln.c,v 1.16 1999/09/05 23:34:40 hubertf Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
@ -137,7 +137,7 @@ linkit(target, source, isdir)
|
||||
|
||||
if (!sflag) {
|
||||
/* If target doesn't exist, quit now. */
|
||||
if (stat(target, &sb)) {
|
||||
if (lstat(target, &sb)) {
|
||||
warn("%s", target);
|
||||
return (1);
|
||||
}
|
||||
|
@ -876,6 +876,68 @@ process_copy_in ()
|
||||
#ifdef CP_IFLNK
|
||||
case CP_IFLNK:
|
||||
{
|
||||
/* Can the current symlink be linked to a previously copied
|
||||
file? */
|
||||
if (file_hdr.c_nlink > 1 && (archive_format == arf_newascii
|
||||
|| archive_format == arf_crcascii) )
|
||||
{
|
||||
int link_res;
|
||||
if (file_hdr.c_filesize == 0)
|
||||
{
|
||||
/* See CP_IFREG case for how links are handled */
|
||||
defer_copyin (&file_hdr);
|
||||
toss_input (in_file_des, file_hdr.c_filesize);
|
||||
skip_padding (in_file_des, file_hdr.c_filesize);
|
||||
break;
|
||||
}
|
||||
/* If the file has data (filesize != 0), then presumably
|
||||
any other links have already been defer_copyin'ed(),
|
||||
but GNU cpio version 2.0-2.2 didn't do that, so we
|
||||
still have to check for links here (and also in case
|
||||
the archive was created and later appeneded to). */
|
||||
link_res = link_to_maj_min_ino (file_hdr.c_name,
|
||||
file_hdr.c_dev_maj, file_hdr.c_dev_maj,
|
||||
file_hdr.c_ino);
|
||||
if (link_res == 0)
|
||||
{
|
||||
toss_input (in_file_des, file_hdr.c_filesize);
|
||||
skip_padding (in_file_des, file_hdr.c_filesize);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (file_hdr.c_nlink > 1 && archive_format != arf_tar
|
||||
&& archive_format != arf_ustar)
|
||||
{
|
||||
int link_res;
|
||||
link_res = link_to_maj_min_ino (file_hdr.c_name,
|
||||
file_hdr.c_dev_maj, file_hdr.c_dev_maj,
|
||||
file_hdr.c_ino);
|
||||
if (link_res == 0)
|
||||
{
|
||||
toss_input (in_file_des, file_hdr.c_filesize);
|
||||
skip_padding (in_file_des, file_hdr.c_filesize);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if ((archive_format == arf_tar || archive_format == arf_ustar)
|
||||
&& file_hdr.c_tar_linkname &&
|
||||
file_hdr.c_tar_linkname[0] != '\0')
|
||||
{
|
||||
int link_res;
|
||||
link_res = link_to_maj_min_ino (file_hdr.c_tar_linkname,
|
||||
file_hdr.c_dev_maj, file_hdr.c_dev_maj,
|
||||
file_hdr.c_ino);
|
||||
if (link_res == 0)
|
||||
{
|
||||
toss_input (in_file_des, file_hdr.c_filesize);
|
||||
skip_padding (in_file_des, file_hdr.c_filesize);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* If not linked, copy the contents of the file. */
|
||||
if (link_name == NULL)
|
||||
{
|
||||
if (archive_format != arf_tar && archive_format != arf_ustar)
|
||||
{
|
||||
link_name = (char *) xmalloc ((unsigned int) file_hdr.c_filesize + 1);
|
||||
@ -911,6 +973,7 @@ process_copy_in ()
|
||||
error (0, errno, "%s", file_hdr.c_name);
|
||||
free (link_name);
|
||||
link_name = NULL;
|
||||
}
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
@ -450,8 +450,9 @@ process_copy_out ()
|
||||
#ifdef CP_IFLNK
|
||||
case CP_IFLNK:
|
||||
{
|
||||
char *link_name = (char *) xmalloc (file_stat.st_size + 1);
|
||||
char *link_name;
|
||||
|
||||
link_name = (char *) xmalloc (file_stat.st_size + 1);
|
||||
if (readlink (input_name.ds_string, link_name,
|
||||
file_stat.st_size) < 0)
|
||||
{
|
||||
@ -459,6 +460,36 @@ process_copy_out ()
|
||||
free (link_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
#ifndef __MSDOS__
|
||||
if (archive_format == arf_tar || archive_format == arf_ustar)
|
||||
{
|
||||
char *otherfile;
|
||||
if ((otherfile = find_inode_file (file_hdr.c_ino,
|
||||
file_hdr.c_dev_maj,
|
||||
file_hdr.c_dev_min)))
|
||||
{
|
||||
file_hdr.c_mode = CP_IFREG; /* XXX hardlink! */
|
||||
file_hdr.c_tar_linkname = otherfile;
|
||||
write_out_header (&file_hdr, out_file_des);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( (archive_format == arf_newascii || archive_format == arf_crcascii)
|
||||
&& (file_hdr.c_nlink > 1) )
|
||||
{
|
||||
if (last_link (&file_hdr) )
|
||||
{
|
||||
writeout_other_defers (&file_hdr, out_file_des);
|
||||
}
|
||||
else
|
||||
{
|
||||
add_link_defer (&file_hdr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (archive_format == arf_tar || archive_format == arf_ustar)
|
||||
{
|
||||
if (file_stat.st_size + 1 > 100)
|
||||
@ -479,6 +510,12 @@ process_copy_out ()
|
||||
copy_buf_out (link_name, out_file_des, file_stat.st_size);
|
||||
pad_output (out_file_des, file_hdr.c_filesize);
|
||||
}
|
||||
#ifndef __MSDOS__
|
||||
if (archive_format == arf_tar || archive_format == arf_ustar)
|
||||
add_inode (file_hdr.c_ino, input_name.ds_string, file_hdr.c_dev_maj,
|
||||
file_hdr.c_dev_min);
|
||||
#endif
|
||||
|
||||
free (link_name);
|
||||
}
|
||||
break;
|
||||
|
@ -332,6 +332,24 @@ process_copy_pass ()
|
||||
}
|
||||
link_name[in_file_stat.st_size] = '\0';
|
||||
|
||||
/* Can the current symlink be linked to a another file?
|
||||
Set link_name to the original file name. */
|
||||
if (link_flag)
|
||||
/* User said to link it if possible. Try and link to
|
||||
the original copy. If that fails we'll still try
|
||||
and link to a copy we've already made. */
|
||||
link_res = link_to_name (output_name.ds_string,
|
||||
input_name.ds_string);
|
||||
if ( (link_res < 0) && (in_file_stat.st_nlink > 1) )
|
||||
link_res = link_to_maj_min_ino (output_name.ds_string,
|
||||
major (in_file_stat.st_dev),
|
||||
minor (in_file_stat.st_dev),
|
||||
in_file_stat.st_ino);
|
||||
|
||||
/* If the link was not (hard)linked, make a softlink. */
|
||||
if (link_res < 0)
|
||||
{
|
||||
|
||||
res = UMASKED_SYMLINK (link_name, output_name.ds_string,
|
||||
in_file_stat.st_mode);
|
||||
if (res < 0 && create_dir_flag)
|
||||
@ -355,6 +373,7 @@ process_copy_pass ()
|
||||
&& errno != EPERM)
|
||||
error (0, errno, "%s", output_name.ds_string);
|
||||
free (link_name);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
else
|
||||
|
@ -18,7 +18,7 @@ along with GNU Tar; see the file COPYING. If not, write to
|
||||
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
|
||||
|
||||
#ifndef lint
|
||||
static char rcsid[] = "$Id: create.c,v 1.7 1998/06/07 02:30:12 enami Exp $";
|
||||
static char rcsid[] = "$Id: create.c,v 1.8 1999/09/05 23:34:40 hubertf Exp $";
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
@ -292,6 +292,9 @@ dump_file (p, curdev, toplevel)
|
||||
#endif
|
||||
#ifdef S_ISFIFO
|
||||
|| S_ISFIFO (hstat.st_mode)
|
||||
#endif
|
||||
#ifdef S_ISLNK
|
||||
|| S_ISLNK (hstat.st_mode)
|
||||
#endif
|
||||
))
|
||||
{
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: vfs_syscalls.c,v 1.146 1999/07/31 03:18:43 christos Exp $ */
|
||||
/* $NetBSD: vfs_syscalls.c,v 1.147 1999/09/05 23:34:39 hubertf Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
@ -1391,7 +1391,7 @@ sys_link(p, v, retval)
|
||||
struct nameidata nd;
|
||||
int error;
|
||||
|
||||
NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
|
||||
NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
|
||||
if ((error = namei(&nd)) != 0)
|
||||
return (error);
|
||||
vp = nd.ni_vp;
|
||||
|
Loading…
Reference in New Issue
Block a user