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