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