127702724Smrg/*
227702724Smrg
327702724SmrgCopyright 1988, 1998  The Open Group
427702724Smrg
527702724SmrgPermission to use, copy, modify, distribute, and sell this software and its
627702724Smrgdocumentation for any purpose is hereby granted without fee, provided that
727702724Smrgthe above copyright notice appear in all copies and that both that
827702724Smrgcopyright notice and this permission notice appear in supporting
927702724Smrgdocumentation.
1027702724Smrg
1127702724SmrgThe above copyright notice and this permission notice shall be included in
1227702724Smrgall copies or substantial portions of the Software.
1327702724Smrg
1427702724SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1527702724SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1627702724SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
1727702724SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1827702724SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1927702724SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2027702724Smrg
2127702724SmrgExcept as contained in this notice, the name of The Open Group shall not be
2227702724Smrgused in advertising or otherwise to promote the sale, use or other dealings
2327702724Smrgin this Software without prior written authorization from The Open Group.
2427702724Smrg
2527702724Smrg*/
2627702724Smrg
2727702724Smrg#ifdef HAVE_CONFIG_H
2827702724Smrg#include <config.h>
2927702724Smrg#endif
3027702724Smrg#include <X11/Xauth.h>
3127702724Smrg#include <X11/Xos.h>
3227702724Smrg#include <sys/stat.h>
3327702724Smrg#include <errno.h>
3427702724Smrg#include <time.h>
3527702724Smrg#define Time_t time_t
36313a12fdSmrg#ifdef HAVE_UNISTD_H
37313a12fdSmrg# include <unistd.h>
3827702724Smrg#endif
39313a12fdSmrg#ifdef WIN32
40313a12fdSmrg# include <X11/Xwindows.h>
41313a12fdSmrg# define link rename
4227702724Smrg#endif
4327702724Smrg
44ae545d91Smrg#ifndef O_CLOEXEC
45ae545d91Smrg#define O_CLOEXEC	0
46ae545d91Smrg#endif
47ae545d91Smrg
4827702724Smrgint
4927702724SmrgXauLockAuth (
5027702724Smrg_Xconst char *file_name,
5127702724Smrgint	retries,
5227702724Smrgint	timeout,
5327702724Smrglong	dead)
5427702724Smrg{
5527702724Smrg    char	creat_name[1025], link_name[1025];
5627702724Smrg    struct stat	statb;
5727702724Smrg    Time_t	now;
5827702724Smrg    int		creat_fd = -1;
5927702724Smrg
6027702724Smrg    if (strlen (file_name) > 1022)
6127702724Smrg	return LOCK_ERROR;
62313a12fdSmrg    snprintf (creat_name, sizeof(creat_name), "%s-c", file_name);
63313a12fdSmrg    snprintf (link_name, sizeof(link_name), "%s-l", file_name);
6427702724Smrg    if (stat (creat_name, &statb) != -1) {
6527702724Smrg	now = time ((Time_t *) 0);
6627702724Smrg	/*
6727702724Smrg	 * NFS may cause ctime to be before now, special
6827702724Smrg	 * case a 0 deadtime to force lock removal
6927702724Smrg	 */
7027702724Smrg	if (dead == 0 || now - statb.st_ctime > dead) {
71313a12fdSmrg	    (void) remove (creat_name);
72313a12fdSmrg	    (void) remove (link_name);
7327702724Smrg	}
7427702724Smrg    }
75313a12fdSmrg
7627702724Smrg    while (retries > 0) {
7727702724Smrg	if (creat_fd == -1) {
78ae545d91Smrg	    creat_fd = open (creat_name, O_WRONLY | O_CREAT | O_EXCL | O_CLOEXEC,
79ae545d91Smrg			     0600);
8027702724Smrg	    if (creat_fd == -1) {
81313a12fdSmrg		if (errno != EACCES && errno != EEXIST)
8227702724Smrg		    return LOCK_ERROR;
8327702724Smrg	    } else
8427702724Smrg		(void) close (creat_fd);
8527702724Smrg	}
8627702724Smrg	if (creat_fd != -1) {
87313a12fdSmrg#ifdef HAVE_PATHCONF
88e19dfac4Smrg	    /* The file system may not support hard links, and pathconf should tell us that. */
89e19dfac4Smrg	    if (1 == pathconf(creat_name, _PC_LINK_MAX)) {
90e19dfac4Smrg		if (-1 == rename(creat_name, link_name)) {
91e19dfac4Smrg		    /* Is this good enough?  Perhaps we should retry.  TEST */
92e19dfac4Smrg		    return LOCK_ERROR;
93e19dfac4Smrg		} else {
94e19dfac4Smrg		    return LOCK_SUCCESS;
95e19dfac4Smrg		}
96313a12fdSmrg	    } else
97e19dfac4Smrg#endif
98313a12fdSmrg	    {
99e19dfac4Smrg	    	if (link (creat_name, link_name) != -1)
100e19dfac4Smrg		    return LOCK_SUCCESS;
101e19dfac4Smrg		if (errno == ENOENT) {
102e19dfac4Smrg		    creat_fd = -1;	/* force re-creat next time around */
103e19dfac4Smrg		    continue;
104e19dfac4Smrg	    	}
105e19dfac4Smrg	    	if (errno != EEXIST)
106e19dfac4Smrg		    return LOCK_ERROR;
107e19dfac4Smrg	   }
10827702724Smrg	}
10927702724Smrg	(void) sleep ((unsigned) timeout);
11027702724Smrg	--retries;
11127702724Smrg    }
11227702724Smrg    return LOCK_TIMEOUT;
11327702724Smrg}
114