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