@@ -360,7 +360,7 @@ static int la_mktemp(struct archive_write_disk *);
360360static void fsobj_error (int * , struct archive_string * , int , const char * ,
361361 const char * );
362362static int check_symlinks_fsobj (char * , int * , struct archive_string * ,
363- int );
363+ int , int );
364364static int check_symlinks (struct archive_write_disk * );
365365static int create_filesystem_object (struct archive_write_disk * );
366366static struct fixup_entry * current_fixup (struct archive_write_disk * ,
@@ -2263,7 +2263,7 @@ create_filesystem_object(struct archive_write_disk *a)
22632263 return (EPERM );
22642264 }
22652265 r = check_symlinks_fsobj (linkname_copy , & error_number ,
2266- & error_string , a -> flags );
2266+ & error_string , a -> flags , 1 );
22672267 if (r != ARCHIVE_OK ) {
22682268 archive_set_error (& a -> archive , error_number , "%s" ,
22692269 error_string .s );
@@ -2284,7 +2284,12 @@ create_filesystem_object(struct archive_write_disk *a)
22842284 */
22852285 if (a -> flags & ARCHIVE_EXTRACT_SAFE_WRITES )
22862286 unlink (a -> name );
2287+ #ifdef HAVE_LINKAT
2288+ r = linkat (AT_FDCWD , linkname , AT_FDCWD , a -> name ,
2289+ 0 ) ? errno : 0 ;
2290+ #else
22872291 r = link (linkname , a -> name ) ? errno : 0 ;
2292+ #endif
22882293 /*
22892294 * New cpio and pax formats allow hardlink entries
22902295 * to carry data, so we may have to open the file
@@ -2675,7 +2680,7 @@ fsobj_error(int *a_eno, struct archive_string *a_estr,
26752680 */
26762681static int
26772682check_symlinks_fsobj (char * path , int * a_eno , struct archive_string * a_estr ,
2678- int flags )
2683+ int flags , int extracting_hardlink )
26792684{
26802685#if !defined(HAVE_LSTAT ) && \
26812686 !(defined(HAVE_OPENAT ) && defined(HAVE_FSTATAT ) && defined(HAVE_UNLINKAT ))
@@ -2684,6 +2689,7 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
26842689 (void )error_number ; /* UNUSED */
26852690 (void )error_string ; /* UNUSED */
26862691 (void )flags ; /* UNUSED */
2692+ (void )extracting_hardlink ; /* UNUSED */
26872693 return (ARCHIVE_OK );
26882694#else
26892695 int res = ARCHIVE_OK ;
@@ -2805,6 +2811,28 @@ check_symlinks_fsobj(char *path, int *a_eno, struct archive_string *a_estr,
28052811 head = tail + 1 ;
28062812 }
28072813 } else if (S_ISLNK (st .st_mode )) {
2814+ if (last && extracting_hardlink ) {
2815+ #ifdef HAVE_LINKAT
2816+ /*
2817+ * Hardlinks to symlinks are safe to write
2818+ * if linkat() is supported as it does not
2819+ * follow symlinks.
2820+ */
2821+ res = ARCHIVE_OK ;
2822+ #else
2823+ /*
2824+ * We return ARCHIVE_FAILED here as we are
2825+ * not able to safely write hardlinks
2826+ * to symlinks.
2827+ */
2828+ tail [0 ] = c ;
2829+ fsobj_error (a_eno , a_estr , errno ,
2830+ "Cannot write hardlink to symlink " ,
2831+ path );
2832+ res = ARCHIVE_FAILED ;
2833+ #endif
2834+ break ;
2835+ } else
28082836 if (last ) {
28092837 /*
28102838 * Last element is symlink; remove it
@@ -2971,7 +2999,7 @@ check_symlinks(struct archive_write_disk *a)
29712999 int rc ;
29723000 archive_string_init (& error_string );
29733001 rc = check_symlinks_fsobj (a -> name , & error_number , & error_string ,
2974- a -> flags );
3002+ a -> flags , 0 );
29753003 if (rc != ARCHIVE_OK ) {
29763004 archive_set_error (& a -> archive , error_number , "%s" ,
29773005 error_string .s );
0 commit comments