1 /* @(#)savewd.c	1.3 18/05/30 Copyright 2004-2018 J. Schilling */
2 /*
3  *	Save and restore working directory.
4  *
5  *	The code has been adopted from libfind.
6  *
7  *	Copyright (c) 2004-2018 J. Schilling
8  */
9 /*
10  * The contents of this file are subject to the terms of the
11  * Common Development and Distribution License, Version 1.0 only
12  * (the "License").  You may not use this file except in compliance
13  * with the License.
14  *
15  * See the file CDDL.Schily.txt in this distribution for details.
16  * A copy of the CDDL is also available via the Internet at
17  * http://www.opensource.org/licenses/cddl1.txt
18  *
19  * When distributing Covered Code, include this CDDL HEADER in each
20  * file and include the License file CDDL.Schily.txt from this distribution.
21  */
22 
23 #include <schily/unistd.h>
24 #include <schily/types.h>
25 #include <schily/fcntl.h>
26 #include <schily/maxpath.h>
27 #include <schily/string.h>
28 #include <schily/errno.h>
29 #include <schily/standard.h>
30 #include <schily/schily.h>
31 #include "at-defs.h"
32 
33 EXPORT	int	savewd	__PR((struct save_wd *sp));
34 EXPORT	void	closewd	__PR((struct save_wd *sp));
35 EXPORT	int	restorewd __PR((struct save_wd *sp));
36 
37 
38 EXPORT int
savewd(sp)39 savewd(sp)
40 	struct save_wd	*sp;
41 {
42 	sp->fd = -1;
43 	sp->name = NULL;
44 #ifdef	HAVE_FCHDIR
45 	/*
46 	 * Note that we do not need O_RDONLY as we do not like to
47 	 * run readdir() on that directory but just fchdir().
48 	 */
49 	if ((sp->fd = open(".", O_SEARCH|O_DIRECTORY|O_NDELAY)) >= 0) {
50 #ifdef	F_SETFD
51 		(void) fcntl(sp->fd, F_SETFD, FD_CLOEXEC);
52 #endif
53 		return (0);
54 	}
55 #endif
56 	{
57 		char	buf[max(8192, PATH_MAX+1)];
58 
59 		if (getcwd(buf, sizeof (buf)) == NULL) {
60 			return (-1);
61 		}
62 		sp->name = strdup(buf);
63 		if (sp->name == NULL)
64 			return (-1);
65 	}
66 	return (0);
67 }
68 
69 EXPORT void
closewd(sp)70 closewd(sp)
71 	struct save_wd	*sp;
72 {
73 	if (sp->fd >= 0)
74 		close(sp->fd);
75 	if (sp->name != NULL)
76 		free(sp->name);
77 	sp->fd = -1;
78 	sp->name = NULL;
79 }
80 
81 EXPORT int
restorewd(sp)82 restorewd(sp)
83 	struct save_wd	*sp;
84 {
85 #ifdef	HAVE_FCHDIR
86 	if (sp->fd >= 0)
87 		return (fchdir(sp->fd));
88 #endif
89 	if (sp->name != NULL)
90 		return (lxchdir(sp->name));
91 
92 	seterrno(EINVAL);
93 	return (-1);
94 }
95