diff options
author | Karl Berry <karl@freefriends.org> | 2006-01-17 21:41:51 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2006-01-17 21:41:51 +0000 |
commit | 487ca4806cc046076293cf6cc5fbba0db282bac7 (patch) | |
tree | 847b412ab5158dd7bdd7ed7e5a4cc3fbca94be32 /Build/source/texk/kpathsea/xgetcwd.c | |
parent | a3d3111bfe26b8e5f5bc6049dfb2a4ca2edc7881 (diff) |
texk 1
git-svn-id: svn://tug.org/texlive/trunk@1485 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/kpathsea/xgetcwd.c')
-rw-r--r-- | Build/source/texk/kpathsea/xgetcwd.c | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/Build/source/texk/kpathsea/xgetcwd.c b/Build/source/texk/kpathsea/xgetcwd.c new file mode 100644 index 00000000000..8c97c6a8bd8 --- /dev/null +++ b/Build/source/texk/kpathsea/xgetcwd.c @@ -0,0 +1,150 @@ +/* xgetcwd.c: a from-scratch version of getwd. Ideas from the tcsh 5.20 + source, apparently uncopyrighted. + + Copyright 2005 Olaf Weber. + Copyright 1992, 94, 96 Karl Berry. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include <kpathsea/config.h> + +#if defined (HAVE_GETCWD) || defined (HAVE_GETWD) +#include <kpathsea/c-pathmx.h> +#else /* not HAVE_GETCWD && not HAVE_GETWD*/ +#include <kpathsea/c-dir.h> +#include <kpathsea/xopendir.h> +#include <kpathsea/xstat.h> + + +static void +xchdir P1C(string, dirname) +{ + if (chdir(dirname) != 0) + FATAL_PERROR(dirname); +} + +#endif /* not HAVE_GETCWD && not HAVE_GETWD */ + + +/* Return the pathname of the current directory, or give a fatal error. */ + +string +xgetcwd P1H(void) +{ + /* If the system provides getcwd, use it. If not, use getwd if + available. But provide a way not to use getcwd: on some systems + getcwd forks, which is expensive and may in fact be impossible for + large programs like tex. If your system needs this define and it + is not detected by configure, let me know. + -- Olaf Weber <infovore@xs4all.nl */ +#if defined (HAVE_GETCWD) && !defined (GETCWD_FORKS) + string path = (string)xmalloc(PATH_MAX + 1); + + if (getcwd (path, PATH_MAX + 1) == 0) { + fprintf(stderr, "getcwd: %s", path); + exit(EXIT_FAILURE); + } + + return path; +#elif defined (HAVE_GETWD) + string path = (string)xmalloc(PATH_MAX + 1); + + if (getwd (path) == 0) { + fprintf(stderr, "getwd: %s", path); + exit(EXIT_FAILURE); + } + + return path; +#else /* not HAVE_GETCWD && not HAVE_GETWD */ + struct stat root_stat, cwd_stat; + string cwd_path = (string)xmalloc(2); /* In case we assign "/" below. */ + + *cwd_path = 0; + + /* Find the inodes of the root and current directories. */ + root_stat = xstat("/"); + cwd_stat = xstat("."); + + /* Go up the directory hierarchy until we get to root, prepending each + directory we pass through to `cwd_path'. */ + while (!SAME_FILE_P(root_stat, cwd_stat)) { + struct dirent *e; + DIR *parent_dir; + boolean found = false; + + xchdir(".."); + parent_dir = xopendir("."); + + /* Look through the parent directory for the entry with the same + inode, so we can get its name. */ + while ((e = readdir (parent_dir)) != NULL && !found) { + struct stat test_stat; + test_stat = xlstat(e->d_name); + + if (SAME_FILE_P(test_stat, cwd_stat)) { + /* We've found it. Prepend the pathname. */ + string temp = cwd_path; + cwd_path = concat3("/", e->d_name, cwd_path); + free(temp); + + /* Set up to test the next parent. */ + cwd_stat = xstat("."); + + /* Stop reading this directory. */ + found = true; + } + } + if (!found) + FATAL2("No inode %d/device %d in parent directory", + cwd_stat.st_ino, cwd_stat.st_dev); + + xclosedir(parent_dir); + } + + /* If the current directory is the root, cwd_path will be the empty + string, and we will have not gone through the loop. */ + if (*cwd_path == 0) + strcpy(cwd_path, "/"); + else + /* Go back to where we were. */ + xchdir(cwd_path); + +#ifdef DOSISH + /* Prepend the drive letter to CWD_PATH, since this technique + never tells us what the drive is. + + Note that on MS-DOS/MS-Windows, the branch that works around + missing `getwd' will probably only work for DJGPP (which does + have `getwd'), because only DJGPP reports meaningful + st_ino numbers. But someday, somebody might need this... */ + { + char drive[3]; + string temp = cwd_path; + + /* Make the drive letter lower-case, unless it is beyond Z: (yes, + there ARE such drives, in case of Novell Netware on MS-DOS). */ + drive[0] = root_stat.st_dev + (root_stat.st_dev < 26 ? 'a' : 'A'); + drive[1] = ':'; + drive[2] = '\0'; + + cwd_path = concat(drive, cwd_path); + free(temp); + } +#endif + + return cwd_path; +#endif /* not HAVE_GETCWD && not HAVE_GETWD */ +} |