1 #ifdef HAVE_CONFIG_H
2 # include "config.h"
3 #endif
4
5 #include <stdio.h>
6
7 #ifdef STDC_HEADERS
8 # include <stdlib.h>
9 #endif
10
11 #ifdef HAVE_UNISTD_H
12 # include <unistd.h>
13 #endif
14
15 #ifdef HAVE_FCNTL_H
16 # include <sys/types.h>
17 # include <fcntl.h>
18 #else
19 # include <sys/file.h>
20 #endif
21
22 #ifdef HAVE_DIRECT_H
23 # include <direct.h>
24 #endif
25
26 #ifdef HAVE_IO_H
27 # include <io.h>
28 #endif
29
30 #include <errno.h>
31 # ifndef errno
32 extern int errno;
33 #endif
34
35 #include "savecwd.h"
36 #include "error.h"
37
38 char *xgetwd __PROTO((void));
39
40 /* Record the location of the current working directory in CWD so that
41 the program may change to other directories and later use restore_cwd
42 to return to the recorded location. This function may allocate
43 space using malloc (via xgetwd) or leave a file descriptor open;
44 use free_cwd to perform the necessary free or close. Upon failure,
45 no memory is allocated, any locally opened file descriptors are
46 closed; return non-zero -- in that case, free_cwd need not be
47 called, but doing so is ok. Otherwise, return zero. */
48
49 int
save_cwd(cwd)50 save_cwd (cwd)
51 struct saved_cwd *cwd;
52 {
53 static int have_working_fchdir = 1;
54
55 cwd->desc = -1;
56 cwd->name = NULL;
57
58 if (have_working_fchdir)
59 {
60 #ifdef HAVE_FCHDIR
61 cwd->desc = open (".", O_RDONLY);
62 if (cwd->desc < 0)
63 {
64 error (0, errno, "cannot open current directory");
65 return 1;
66 }
67
68 # if __sun__ || sun
69 /* On SunOS 4, fchdir returns EINVAL if accounting is enabled,
70 so we have to fall back to chdir. */
71 if (fchdir (cwd->desc))
72 {
73 if (errno == EINVAL)
74 {
75 close (cwd->desc);
76 cwd->desc = -1;
77 have_working_fchdir = 0;
78 }
79 else
80 {
81 error (0, errno, "current directory");
82 close (cwd->desc);
83 cwd->desc = -1;
84 return 1;
85 }
86 }
87 # endif /* __sun__ || sun */
88 #else
89 #define fchdir(x) (abort (), 0)
90 have_working_fchdir = 0;
91 #endif
92 }
93
94 if (!have_working_fchdir)
95 {
96 cwd->name = xgetwd ();
97 if (cwd->name == NULL)
98 {
99 error (0, errno, "cannot get current directory");
100 return 1;
101 }
102 }
103 return 0;
104 }
105
106 /* Change to recorded location, CWD, in directory hierarchy.
107 If "saved working directory", NULL))
108 */
109
110 int
restore_cwd(cwd,dest)111 restore_cwd (cwd, dest)
112 const struct saved_cwd *cwd;
113 const char *dest;
114 {
115 int fail = 0;
116 if (cwd->desc >= 0)
117 {
118 if (fchdir (cwd->desc))
119 {
120 error (0, errno, "cannot return to %s",
121 (dest ? dest : "saved working directory"));
122 fail = 1;
123 }
124 }
125 else if (chdir (cwd->name) < 0)
126 {
127 error (0, errno, "%s", cwd->name);
128 fail = 1;
129 }
130 return fail;
131 }
132
133 void
free_cwd(cwd)134 free_cwd (cwd)
135 struct saved_cwd *cwd;
136 {
137 if (cwd->desc >= 0)
138 close (cwd->desc);
139 if (cwd->name)
140 free (cwd->name);
141 }
142
143