xref: /openbsd-src/gnu/usr.bin/cvs/emx/savecwd.c (revision 2286d8ed900f26153a3cd5227a124b1c0adce72f)
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