]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
renamed to chdir-long.[ch]
authorJim Meyering <jim@meyering.net>
Tue, 30 Nov 2004 14:47:47 +0000 (14:47 +0000)
committerJim Meyering <jim@meyering.net>
Tue, 30 Nov 2004 14:47:47 +0000 (14:47 +0000)
lib/chdir.c [deleted file]
lib/chdir.h [deleted file]

diff --git a/lib/chdir.c b/lib/chdir.c
deleted file mode 100644 (file)
index e8ce730..0000000
+++ /dev/null
@@ -1,346 +0,0 @@
-/* provide a chdir function that tries not to fail due to ENAMETOOLONG
-   Copyright (C) 2004 Free Software Foundation, Inc.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
-   This program 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 General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software Foundation,
-   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
-
-/* written by Jim Meyering */
-
-#include <config.h>
-
-#include "chdir.h"
-
-/* Disable the definition of chdir to rpl_chdir (from chdir.h) in this
-   file.  Otherwise, we'd get conflicting prototypes for rpl_chdir on
-   most systems.  */
-#undef chdir
-
-#include <stdlib.h>
-#include <stdbool.h>
-#include <string.h>
-#include <errno.h>
-#include <stdio.h>
-#include <assert.h>
-#include <limits.h>
-
-#include "mempcpy.h"
-#include "openat.h"
-
-#ifndef O_DIRECTORY
-# define O_DIRECTORY 0
-#endif
-
-#ifndef MIN
-# define MIN(a, b) ((a) < (b) ? (a) : (b))
-#endif
-
-#ifndef PATH_MAX
-# ifdef        MAXPATHLEN
-#  define PATH_MAX MAXPATHLEN
-# else
-#  error "use this module only if your system defines PATH_MAX"
-# endif
-#endif
-
-/* FIXME: this use of `MIN' is our sole concession to arbitrary limitations.
-   If, for some system, PATH_MAX is larger than 8191 and you call
-   rpl_chdir with a directory name that is longer than PATH_MAX,
-   yet that contains a single component that is more than 8191 bytes
-   long, then this function will fail.  */
-#define MAX_COMPONENT_LENGTH MIN (PATH_MAX - 1, 8 * 1024)
-
-struct cd_buf
-{
-  /* FIXME maybe allocate this via malloc, rather than using the stack.
-     But that would be the sole use of malloc.  Is it worth it to
-     let chdir fail due to a low-memory condition?
-     But when using malloc, and assuming we remove the `concession'
-     above, we'll still have to avoid allocating 2^31 bytes on
-     systems that define PATH_MAX to very large number.
-     Ideally, we'd allocate enough to deal with most names, and
-     dynamically increase the buffer size only necessary.  */
-  char buffer[MAX_COMPONENT_LENGTH + 1];
-  char *avail;
-  int fd;
-};
-
-/* Like memchr, but return the number of bytes from MEM
-   to the first occurrence of C thereafter.  Search only
-   LEN bytes.  Return LEN if C is not found.  */
-static inline size_t
-memchrcspn (char const *mem, int c, size_t len)
-{
-  char const *found = memchr (mem, c, len);
-  if (!found)
-    return len;
-
-  len = found - mem;
-  return len;
-}
-
-static void
-cdb_init (struct cd_buf *cdb)
-{
-  cdb->avail = cdb->buffer;
-  cdb->fd = AT_FDCWD;
-}
-
-static inline bool
-cdb_empty (struct cd_buf const *cdb)
-{
-  return cdb->avail == cdb->buffer;
-}
-
-static inline int
-cdb_fchdir (struct cd_buf const *cdb)
-{
-  return fchdir (cdb->fd);
-}
-
-static int
-cdb_advance_fd (struct cd_buf *cdb, char const *dir)
-{
-  int new_fd = openat (cdb->fd, dir, O_RDONLY | O_DIRECTORY);
-  if (new_fd < 0)
-    {
-      new_fd = openat (cdb->fd, dir, O_WRONLY | O_DIRECTORY);
-      if (new_fd < 0)
-       return -1;
-    }
-
-  if (cdb->fd != AT_FDCWD)
-    close (cdb->fd);
-  cdb->fd = new_fd;
-
-  return 0;
-}
-
-static int
-cdb_flush (struct cd_buf *cdb)
-{
-  if (cdb_empty (cdb))
-    return 0;
-
-  cdb->avail[0] = '\0';
-  if (cdb_advance_fd (cdb, cdb->buffer) != 0)
-    return -1;
-
-  cdb->avail = cdb->buffer;
-
-  return 0;
-}
-
-static void
-cdb_free (struct cd_buf *cdb)
-{
-  if (0 <= cdb->fd && close (cdb->fd) != 0)
-    abort ();
-}
-
-static int
-cdb_append (struct cd_buf *cdb, char const *s, size_t len)
-{
-  char const *end = cdb->buffer + sizeof cdb->buffer;
-
-  /* Insert a slash separator if there is a preceding byte
-     and it's not a slash.  */
-  bool need_slash = (cdb->buffer < cdb->avail && cdb->avail[-1] != '/');
-  size_t n_free;
-
-  if (sizeof cdb->buffer < len + 1)
-    {
-      /* This single component is too long.  */
-      errno = ENAMETOOLONG;
-      return -1;
-    }
-
-  /* See if there's enough room for the `/', the new component and
-     a trailing NUL.  */
-  n_free = end - cdb->avail;
-  if (n_free < need_slash + len + 1)
-    {
-      if (cdb_flush (cdb) != 0)
-       return -1;
-      need_slash = false;
-    }
-
-  if (need_slash)
-    *(cdb->avail)++ = '/';
-
-  cdb->avail = mempcpy (cdb->avail, s, len);
-  return 0;
-}
-
-/* This is a wrapper around chdir that works even on PATH_MAX-limited
-   systems.  It handles an arbitrarily long directory name by extracting
-   and processing manageable portions of the name.  On systems without
-   the openat syscall, this means changing the working directory to
-   more and more `distant' points along the long directory name and
-   then restoring the working directory.
-   If any of those attempts to change or restore the working directory
-   fails, this function exits nonzero.
-
-   Note that this function may still fail with errno == ENAMETOOLONG,
-   but only if the specified directory name contains a component that
-   is long enough to provoke such a failure all by itself (e.g. if the
-   component is longer than PATH_MAX on systems that define PATH_MAX).  */
-
-int
-rpl_chdir (char const *dir)
-{
-  int e = chdir (dir);
-  if (e == 0 || errno != ENAMETOOLONG)
-    return e;
-
-  {
-    size_t len = strlen (dir);
-    char const *dir_end = dir + len;
-    char const *d;
-    struct cd_buf cdb;
-
-    cdb_init (&cdb);
-
-    /* If DIR is the empty string, then the chdir above
-       must have failed and set errno to ENOENT.  */
-    assert (0 < len);
-
-    if (*dir == '/')
-      {
-       /* Names starting with exactly two slashes followed by at least
-          one non-slash are special --
-          for example, in some environments //Hostname/file may
-          denote a file on a different host.
-          Preserve those two leading slashes.  Treat all other
-          sequences of slashes like a single one.  */
-       if (3 <= len && dir[1] == '/' && dir[2] != '/')
-         {
-           size_t name_len = 1 + strcspn (dir + 3, "/");
-           if (cdb_append (&cdb, dir, 2 + name_len) != 0)
-             goto Fail;
-           /* Advance D to next slash or to end of string. */
-           d = dir + 2 + name_len;
-           assert (*d == '/' || *d == '\0');
-         }
-       else
-         {
-           if (cdb_append (&cdb, "/", 1) != 0)
-             goto Fail;
-           d = dir + 1;
-         }
-      }
-    else
-      {
-       d = dir;
-      }
-
-    while (1)
-      {
-       /* Skip any slashes to find start of next component --
-          or the end of DIR. */
-       char const *start = d + strspn (d, "/");
-       if (*start == '\0')
-         {
-           if (cdb_flush (&cdb) != 0)
-             goto Fail;
-           break;
-         }
-       /* If the remaining portion is no longer than PATH_MAX, then
-          flush anything that is buffered and do the rest in one chunk.  */
-       if (dir_end - start <= PATH_MAX)
-         {
-           if (cdb_flush (&cdb) != 0
-               || cdb_advance_fd (&cdb, start) != 0)
-             goto Fail;
-           break;
-         }
-
-       len = memchrcspn (start, '/', dir_end - start);
-       assert (len == strcspn (start, "/"));
-       d = start + len;
-       if (cdb_append (&cdb, start, len) != 0)
-         goto Fail;
-      }
-
-    if (cdb_fchdir (&cdb) != 0)
-      goto Fail;
-
-    cdb_free (&cdb);
-    return 0;
-
-   Fail:
-    {
-      int saved_errno = errno;
-      cdb_free (&cdb);
-      errno = saved_errno;
-      return -1;
-    }
-  }
-}
-
-#if TEST_CHDIR
-
-# include <stdio.h>
-# include "closeout.h"
-# include "error.h"
-
-char *program_name;
-
-int
-main (int argc, char *argv[])
-{
-  char *line = NULL;
-  size_t n = 0;
-  int len;
-
-  program_name = argv[0];
-  atexit (close_stdout);
-
-  len = getline (&line, &n, stdin);
-  if (len < 0)
-    {
-      int saved_errno = errno;
-      if (feof (stdin))
-       exit (0);
-
-      error (EXIT_FAILURE, saved_errno,
-            "reading standard input");
-    }
-  else if (len == 0)
-    exit (0);
-
-  if (line[len-1] == '\n')
-    line[len-1] = '\0';
-
-  if (rpl_chdir (line) != 0)
-    error (EXIT_FAILURE, errno,
-          "chdir failed: %s", line);
-
-  {
-    /* Using `pwd' here makes sense only if it is a robust implementation,
-       like the one in coreutils after the 2004-04-19 changes.  */
-    char const *cmd = "pwd";
-    execlp (cmd, (char *) NULL);
-    error (EXIT_FAILURE, errno, "%s", cmd);
-  }
-
-  /* not reached */
-  abort ();
-}
-#endif
-
-/*
-Local Variables:
-compile-command: "gcc -DTEST_CHDIR=1 -DHAVE_CONFIG_H -I.. -g -O -W -Wall chdir.c libfetish.a"
-End:
-*/
diff --git a/lib/chdir.h b/lib/chdir.h
deleted file mode 100644 (file)
index ee7cfba..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-/* provide a chdir function that tries not to fail due to ENAMETOOLONG
-   Copyright (C) 2004 Free Software Foundation, Inc.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
-   This program 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 General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software Foundation,
-   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
-
-/* Written by Jim Meyering.  */
-
-/* Include the headers that might declare chdir so that they will not
-   cause confusion if included after this file.  */
-
-#include <unistd.h>
-
-/* If necessary, systematically rename identifiers so that they do not
-   collide with the system function.  Renaming avoids problems with
-   some compilers and linkers.  */
-
-#ifdef __CHDIR_PREFIX
-# undef chdir
-# define __CHDIR_CONCAT(x, y) x ## y
-# define __CHDIR_XCONCAT(x, y) __CHDIR_CONCAT (x, y)
-# define __CHDIR_ID(y) __CHDIR_XCONCAT (__CHDIR_PREFIX, y)
-# define chdir __CHDIR_ID (chdir)
-int chdir (char const *dir);
-#endif