[Top][All Lists]
[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