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