]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/cvs/lib/savecwd.c
This commit was generated by cvs2svn to compensate for changes in r48146,
[FreeBSD/FreeBSD.git] / contrib / cvs / lib / savecwd.c
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 (chdir (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