Home | History | Annotate | Line # | Download | only in util
      1 /*	$NetBSD: sane_link.c,v 1.2 2022/10/08 16:12:50 christos Exp $	*/
      2 
      3 /*++
      4 /* NAME
      5 /*	sane_link 3
      6 /* SUMMARY
      7 /*	sanitize link() error returns
      8 /* SYNOPSIS
      9 /*	#include <sane_fsops.h>
     10 /*
     11 /*	int	sane_link(from, to)
     12 /*	const char *from;
     13 /*	const char *to;
     14 /* DESCRIPTION
     15 /*	sane_link() implements the link(2) system call, and works
     16 /*	around some errors that are possible with NFS file systems.
     17 /* LICENSE
     18 /* .ad
     19 /* .fi
     20 /*	The Secure Mailer license must be distributed with this software.
     21 /* AUTHOR(S)
     22 /*	Wietse Venema
     23 /*	IBM T.J. Watson Research
     24 /*	P.O. Box 704
     25 /*	Yorktown Heights, NY 10598, USA
     26 /*--*/
     27 
     28 /* System library. */
     29 
     30 #include "sys_defs.h"
     31 #include <sys/stat.h>
     32 #include <errno.h>
     33 #include <unistd.h>
     34 
     35 /* Utility library. */
     36 
     37 #include "msg.h"
     38 #include "sane_fsops.h"
     39 #include "warn_stat.h"
     40 
     41 /* sane_link - sanitize link() error returns */
     42 
     43 int     sane_link(const char *from, const char *to)
     44 {
     45     const char *myname = "sane_link";
     46     int     saved_errno;
     47     struct stat from_st;
     48     struct stat to_st;
     49 
     50     /*
     51      * Normal case: link() succeeds.
     52      */
     53     if (link(from, to) >= 0)
     54 	return (0);
     55 
     56     /*
     57      * Woops. Save errno, and see if the error is an NFS artifact. If it is,
     58      * pretend the error never happened.
     59      */
     60     saved_errno = errno;
     61     if (stat(from, &from_st) >= 0 && stat(to, &to_st) >= 0
     62 	&& from_st.st_dev == to_st.st_dev
     63 	&& from_st.st_ino == to_st.st_ino) {
     64 	msg_info("%s(%s,%s): worked around spurious NFS error",
     65 		 myname, from, to);
     66 	return (0);
     67     }
     68 
     69     /*
     70      * Nope, it didn't. Restore errno and report the error.
     71      */
     72     errno = saved_errno;
     73     return (-1);
     74 }
     75