bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [patch]gnu tar 1.19 canonicalize-lgpl_c.gdiff


From: Bruno Haible
Subject: Re: [patch]gnu tar 1.19 canonicalize-lgpl_c.gdiff
Date: Tue, 1 Apr 2008 23:54:06 +0200
User-agent: KMail/1.5.4

John E. Malmberg wrote:
> On VMS, all the system functions start out with decc$.  The compiler 
> uses a table to know what they are and automatically adds the prefix, 
> unless macro substitution is active.
> 
> Gnulib does the macro substitution, so the real prefixed symbol name is 
> used to get around that.

Thanks for explaining.

> > The last point is understandable, since (IIRC, someone said) on VMS there 
> > are
> > several root directories and going up with ../, ../../, etc. will most often
> > lead to the wrong one.
> 
> Actually that will normally do the expected on VMS.
> 
> However looking for "/" on VMS is not safe because usually there are 
> multiple disjoint "/".  And doing a readdir on "/" will not usually show 
> up all the files that will open with "/" prepended to them.
> 
> In some cases there is a simulated "/" directory tree, but again, it 
> usually will not show everything that can be accessed using "/" in front 
> of the name.
> 
> On VMS, think of "/<volume>/<directory/file", where <volume> can be any 
> device mounted on the system, or logical name.
> 
> A logical name behaves like a symbolic link either in the current 
> directory, or in the root directory as far as the file system is 
> concerned, but it is stored in system memory, like an environment 
> variable, so that logical names may restricted in scope.
> 
> It also means that they do not show up in reading a directory.

But this means that the lib/getcwd.c code will, in such cases, return NULL
and errno = ENOENT, no?

> When gnutar on VMS starts up, the first thing it does is set a C library 
> feature switch that forces the getcwd() function to always return the 
> path in UNIX syntax.  Which means that passing the extra parameter to it 
> to force the issue is not needed.

But GNU tar is just one program. There are dozens of other programs. And
there are also libraries, which don't have a "start up" phase. So the fix
belongs into lib/getcwd.c.

And it also needs to be fixed in lib/canonicalize-lgpl.c because the
module 'canonicalize-lgpl' is under LGPL and therefore cannot depend on
the 'getcwd' module, which is GPL.

What do you think of this change? Is it correct? Would it allow you to
get rid of the startup hook that you mentioned?

Bruno


2008-04-01  Bruno Haible  <address@hidden>

        * lib/canonicalize-lgpl.c (decc$getcwd) [VMS]: New declaration.
        (__getcwd) [VMS]: Define to use decc$getcwd.
        * lib/getcwd.c (decc$getcwd) [VMS]: New declaration.
        (__getcwd) [VMS]: Define to use decc$getcwd.

*** lib/canonicalize-lgpl.c.orig        2008-04-01 23:44:51.000000000 +0200
--- lib/canonicalize-lgpl.c     2008-04-01 23:44:31.000000000 +0200
***************
*** 34,39 ****
--- 34,44 ----
  
  #if HAVE_UNISTD_H || defined _LIBC
  # include <unistd.h>
+ # ifdef __VMS
+ /* <unistd.h> declares only getcwd, which is an alias to decc$getcwd if not
+    overridden by gnulib, but does not declare decc$getcwd.  */
+ extern char * decc$getcwd (char *buf, unsigned int size, ...);
+ # endif
  #endif
  
  #include <limits.h>
***************
*** 67,75 ****
  # include "pathmax.h"
  # include "malloca.h"
  # if HAVE_GETCWD
! #  ifdef VMS
      /* We want the directory in Unix syntax, not in VMS syntax.  */
! #   define __getcwd(buf, max) getcwd (buf, max, 0)
  #  else
  #   define __getcwd getcwd
  #  endif
--- 72,80 ----
  # include "pathmax.h"
  # include "malloca.h"
  # if HAVE_GETCWD
! #  ifdef __VMS
      /* We want the directory in Unix syntax, not in VMS syntax.  */
! #   define __getcwd(buf, max) decc$getcwd (buf, max, 0)
  #  else
  #   define __getcwd getcwd
  #  endif
*** lib/getcwd.c.orig   2008-04-01 23:44:51.000000000 +0200
--- lib/getcwd.c        2008-04-01 23:44:49.000000000 +0200
***************
*** 1,5 ****
! /* Copyright (C) 1991,92,93,94,95,96,97,98,99,2004,2005,2006,2007 Free 
Software
!    Foundation, Inc.
     This file is part of the GNU C Library.
  
     This program is free software: you can redistribute it and/or modify
--- 1,5 ----
! /* Copyright (C) 1991,92,93,94,95,96,97,98,99,2004,2005,2006,2007,2008 Free
!    Software Foundation, Inc.
     This file is part of the GNU C Library.
  
     This program is free software: you can redistribute it and/or modify
***************
*** 50,55 ****
--- 50,61 ----
  #endif
  
  #include <unistd.h>
+ #ifdef __VMS
+ /* <unistd.h> declares only getcwd, which is an alias to decc$getcwd if not
+    overridden by gnulib, but does not declare decc$getcwd.  */
+ extern char * decc$getcwd (char *buf, unsigned int size, ...);
+ #endif
+ 
  #include <stdlib.h>
  #include <string.h>
  
***************
*** 118,123 ****
--- 124,136 ----
  char *
  __getcwd (char *buf, size_t size)
  {
+ #ifdef __VMS
+ 
+ /* On VMS, we want the directory in Unix syntax, not in VMS syntax.  */
+   return decc$getcwd (buf, size, 0);
+ 
+ #else
+ 
    /* Lengths of big file name components and entire file names, and a
       deep level of file name nesting.  These numbers are not upper
       bounds; they are merely large values suitable for initial
***************
*** 130,144 ****
        DEEP_NESTING = 100
      };
  
! #if HAVE_OPENAT_SUPPORT
    int fd = AT_FDCWD;
    bool fd_needs_closing = false;
! #else
    char dots[DEEP_NESTING * sizeof ".." + BIG_FILE_NAME_COMPONENT_LENGTH + 1];
    char *dotlist = dots;
    size_t dotsize = sizeof dots;
    size_t dotlen = 0;
! #endif
    DIR *dirstream = NULL;
    dev_t rootdev, thisdev;
    ino_t rootino, thisino;
--- 143,157 ----
        DEEP_NESTING = 100
      };
  
! # if HAVE_OPENAT_SUPPORT
    int fd = AT_FDCWD;
    bool fd_needs_closing = false;
! # else
    char dots[DEEP_NESTING * sizeof ".." + BIG_FILE_NAME_COMPONENT_LENGTH + 1];
    char *dotlist = dots;
    size_t dotsize = sizeof dots;
    size_t dotlen = 0;
! # endif
    DIR *dirstream = NULL;
    dev_t rootdev, thisdev;
    ino_t rootino, thisino;
***************
*** 148,154 ****
    size_t allocated = size;
    size_t used;
  
! #if HAVE_PARTLY_WORKING_GETCWD
    /* The system getcwd works, except it sometimes fails when it
       shouldn't, setting errno to ERANGE, ENAMETOOLONG, or ENOENT.  If
       AT_FDCWD is not defined, the algorithm below is O(N**2) and this
--- 161,167 ----
    size_t allocated = size;
    size_t used;
  
! # if HAVE_PARTLY_WORKING_GETCWD
    /* The system getcwd works, except it sometimes fails when it
       shouldn't, setting errno to ERANGE, ENAMETOOLONG, or ENOENT.  If
       AT_FDCWD is not defined, the algorithm below is O(N**2) and this
***************
*** 160,170 ****
       system getcwd works even when a parent is unreadable, while the
       openat-based approach does not.  */
  
! # undef getcwd
    dir = getcwd (buf, size);
    if (dir || (errno != ERANGE && !is_ENAMETOOLONG (errno) && errno != ENOENT))
      return dir;
! #endif
  
    if (size == 0)
      {
--- 173,183 ----
       system getcwd works even when a parent is unreadable, while the
       openat-based approach does not.  */
  
! #  undef getcwd
    dir = getcwd (buf, size);
    if (dir || (errno != ERANGE && !is_ENAMETOOLONG (errno) && errno != ENOENT))
      return dir;
! # endif
  
    if (size == 0)
      {
***************
*** 211,228 ****
        bool use_d_ino = true;
  
        /* Look at the parent directory.  */
! #if HAVE_OPENAT_SUPPORT
        fd = openat (fd, "..", O_RDONLY);
        if (fd < 0)
        goto lose;
        fd_needs_closing = true;
        parent_status = fstat (fd, &st);
! #else
        dotlist[dotlen++] = '.';
        dotlist[dotlen++] = '.';
        dotlist[dotlen] = '\0';
        parent_status = __lstat (dotlist, &st);
! #endif
        if (parent_status != 0)
        goto lose;
  
--- 224,241 ----
        bool use_d_ino = true;
  
        /* Look at the parent directory.  */
! # if HAVE_OPENAT_SUPPORT
        fd = openat (fd, "..", O_RDONLY);
        if (fd < 0)
        goto lose;
        fd_needs_closing = true;
        parent_status = fstat (fd, &st);
! # else
        dotlist[dotlen++] = '.';
        dotlist[dotlen++] = '.';
        dotlist[dotlen] = '\0';
        parent_status = __lstat (dotlist, &st);
! # endif
        if (parent_status != 0)
        goto lose;
  
***************
*** 238,256 ****
        mount_point = dotdev != thisdev;
  
        /* Search for the last directory.  */
! #if HAVE_OPENAT_SUPPORT
        dirstream = fdopendir (fd);
        if (dirstream == NULL)
        goto lose;
        /* Reset fd.  It may have been closed by fdopendir.  */
        fd = dirfd (dirstream);
        fd_needs_closing = false;
! #else
        dirstream = __opendir (dotlist);
        if (dirstream == NULL)
        goto lose;
        dotlist[dotlen++] = '/';
! #endif
        for (;;)
        {
          /* Clear errno to distinguish EOF from error if readdir returns
--- 251,269 ----
        mount_point = dotdev != thisdev;
  
        /* Search for the last directory.  */
! # if HAVE_OPENAT_SUPPORT
        dirstream = fdopendir (fd);
        if (dirstream == NULL)
        goto lose;
        /* Reset fd.  It may have been closed by fdopendir.  */
        fd = dirfd (dirstream);
        fd_needs_closing = false;
! # else
        dirstream = __opendir (dotlist);
        if (dirstream == NULL)
        goto lose;
        dotlist[dotlen++] = '/';
! # endif
        for (;;)
        {
          /* Clear errno to distinguish EOF from error if readdir returns
***************
*** 294,302 ****
  
          {
            int entry_status;
! #if HAVE_OPENAT_SUPPORT
            entry_status = fstatat (fd, d->d_name, &st, AT_SYMLINK_NOFOLLOW);
! #else
            /* Compute size needed for this file name, or for the file
               name ".." in the same directory, whichever is larger.
               Room for ".." might be needed the next time through
--- 307,315 ----
  
          {
            int entry_status;
! # if HAVE_OPENAT_SUPPORT
            entry_status = fstatat (fd, d->d_name, &st, AT_SYMLINK_NOFOLLOW);
! # else
            /* Compute size needed for this file name, or for the file
               name ".." in the same directory, whichever is larger.
               Room for ".." might be needed the next time through
***************
*** 333,339 ****
  
            memcpy (dotlist + dotlen, d->d_name, _D_ALLOC_NAMLEN (d));
            entry_status = __lstat (dotlist, &st);
! #endif
            /* We don't fail here if we cannot stat() a directory entry.
               This can happen when (network) file systems fail.  If this
               entry is in fact the one we are looking for we will find
--- 346,352 ----
  
            memcpy (dotlist + dotlen, d->d_name, _D_ALLOC_NAMLEN (d));
            entry_status = __lstat (dotlist, &st);
! # endif
            /* We don't fail here if we cannot stat() a directory entry.
               This can happen when (network) file systems fail.  If this
               entry is in fact the one we are looking for we will find
***************
*** 390,399 ****
    if (dirp == &dir[allocated - 1])
      *--dirp = '/';
  
! #if ! HAVE_OPENAT_SUPPORT
    if (dotlist != dots)
      free (dotlist);
! #endif
  
    used = dir + allocated - dirp;
    memmove (dir, dirp, used);
--- 403,412 ----
    if (dirp == &dir[allocated - 1])
      *--dirp = '/';
  
! # if ! HAVE_OPENAT_SUPPORT
    if (dotlist != dots)
      free (dotlist);
! # endif
  
    used = dir + allocated - dirp;
    memmove (dir, dirp, used);
***************
*** 416,433 ****
      int save = errno;
      if (dirstream)
        __closedir (dirstream);
! #if HAVE_OPENAT_SUPPORT
      if (fd_needs_closing)
        close (fd);
! #else
      if (dotlist != dots)
        free (dotlist);
! #endif
      if (buf == NULL)
        free (dir);
      __set_errno (save);
    }
    return NULL;
  }
  
  #ifdef weak_alias
--- 429,447 ----
      int save = errno;
      if (dirstream)
        __closedir (dirstream);
! # if HAVE_OPENAT_SUPPORT
      if (fd_needs_closing)
        close (fd);
! # else
      if (dotlist != dots)
        free (dotlist);
! # endif
      if (buf == NULL)
        free (dir);
      __set_errno (save);
    }
    return NULL;
+ #endif
  }
  
  #ifdef weak_alias





reply via email to

[Prev in Thread] Current Thread [Next in Thread]