diff options
author | Jim Meyering <jim@meyering.net> | 1995-08-04 15:23:25 +0000 |
---|---|---|
committer | Jim Meyering <jim@meyering.net> | 1995-08-04 15:23:25 +0000 |
commit | 3139de97260c85832caea8eb6b1174885ef907cc (patch) | |
tree | 0e0ce99d6e9346d36ac1688cfbc3276af800460d /lib | |
parent | b4a47508d4c31e02779f1f0a9a4c2fc8fd10d924 (diff) | |
download | coreutils-3139de97260c85832caea8eb6b1174885ef907cc.tar.xz |
.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/save-cwd.c | 136 | ||||
-rw-r--r-- | lib/save-cwd.h | 23 |
2 files changed, 159 insertions, 0 deletions
diff --git a/lib/save-cwd.c b/lib/save-cwd.c new file mode 100644 index 000000000..8e0d6dd51 --- /dev/null +++ b/lib/save-cwd.c @@ -0,0 +1,136 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <stdio.h> + +#ifdef STDC_HEADERS +# include <stdlib.h> +#endif + +#ifdef HAVE_UNISTD_H +# include <unistd.h> +#endif + +#ifdef HAVE_FCNTL_H +# include <fcntl.h> +#else +# include <sys/file.h> +#endif + +#include <errno.h> +# ifndef errno +extern int errno; +#endif + +#include "save-cwd.h" +#include "error.h" + +char *xgetcwd __P((void)); + +/* Record the location of the current working directory in CWD so that + the program may change to other directories and later use restore_cwd + to return to the recorded location. This function may allocate + space using malloc (via xgetcwd) or leave a file descriptor open; + use free_cwd to perform the necessary free or close. Upon failure, + no memory is allocated, any locally opened file descriptors are + closed; return non-zero -- in that case, free_cwd need not be + called, but doing so is ok. Otherwise, return zero. */ + +int +save_cwd (cwd) + struct saved_cwd *cwd; +{ + static int have_working_fchdir = 1; + + cwd->desc = -1; + cwd->name = NULL; + + if (have_working_fchdir) + { +#ifdef HAVE_FCHDIR + cwd->desc = open (".", O_RDONLY); + if (cwd->desc < 0) + { + error (0, errno, "cannot open current directory"); + return 1; + } + +# if __sun__ || sun + /* On SunOS 4, fchdir returns EINVAL if accounting is enabled, + so we have to fall back to chdir. */ + if (fchdir (cwd->desc)) + { + if (errno == EINVAL) + { + close (cwd->desc); + cwd->desc = -1; + have_working_fchdir = 0; + } + else + { + error (0, errno, "current directory"); + close (cwd->desc); + cwd->desc = -1; + return 1; + } + } +# endif /* __sun__ || sun */ +#else +#define fchdir(x) (abort (), 0) + have_working_fchdir = 0; +#endif + } + + if (!have_working_fchdir) + { + cwd->name = xgetcwd (); + if (cwd->name == NULL) + { + error (0, errno, "cannot get current directory"); + return 1; + } + } + return 0; +} + +/* Change to recorded location, CWD, in directory hierarchy. + If "saved working directory", NULL)) + */ + +int +restore_cwd (cwd, dest, from) + const struct saved_cwd *cwd; + const char *dest; + const char *from; +{ + int fail = 0; + if (cwd->desc >= 0) + { + if (fchdir (cwd->desc)) + { + error (0, errno, "cannot return to %s%s%s", + (dest ? dest : "saved working directory"), + (from ? " from " : ""), + (from ? from : "")); + fail = 1; + } + } + else if (chdir (cwd->name) < 0) + { + error (0, errno, "%s", cwd->name); + fail = 1; + } + return fail; +} + +void +free_cwd (cwd) + struct saved_cwd *cwd; +{ + if (cwd->desc >= 0) + close (cwd->desc); + if (cwd->name) + free (cwd->name); +} + diff --git a/lib/save-cwd.h b/lib/save-cwd.h new file mode 100644 index 000000000..8f9d07def --- /dev/null +++ b/lib/save-cwd.h @@ -0,0 +1,23 @@ +#ifndef SAVE_CWD_H +#define SAVE_CWD_H 1 + +struct saved_cwd + { + int desc; + char *name; + }; + +#ifndef __P +#if defined (__GNUC__) || (defined (__STDC__) && __STDC__) +#define __P(args) args +#else +#define __P(args) () +#endif /* GCC. */ +#endif /* Not __P. */ + +int save_cwd __P((struct saved_cwd *cwd)); +int restore_cwd __P((const struct saved_cwd *cwd, const char *dest, + const char *from)); +void free_cwd __P((struct saved_cwd *cwd)); + +#endif /* SAVE_CWD_H */ |