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