Discussion:
[ast-developers] Accessing fpathconf() via getconf(1)?
Lionel Cons
2013-09-17 16:53:26 UTC
Permalink
Forwarding a question from a coworker:
How can I access fpathconf() via getconf(1)?

Lionel

---------- Forwarded message ----------
From: Roland Mainz <roland.mainz at nrubsig.org>
Date: 31 August 2013 02:31
Subject: Re: [ast-developers] AT&T Software Technology ast alpha
software download update
To: "ast-developers at research.att.com" <ast-developers at research.att.com>
Cc: lionelcons1972 at gmail.com, ????? ????????????
<olga.kryzhanovska at gmail.com>, Glenn Fowler <gsf at research.att.com>
ksh -c 'mkdir -p foo2 ; redirect {d}<foo2/ ; redirect
foo2 ; ls ; cat myxattr' myxattr SUNWattr_ro SUNWattr_rw
bla
Do you have a patch for that? It sounds you found a middle way which
might satisfy Glenn's love for /dev/file and marry it with a sane
approach to access files in xattr directories.
I'm looking at this over the long US weekend and am having
an off-list discussion picking olga's brain -- this will be resolved
one way or another tuesday
my "love" isn't so much /dev/file but rather an ast C and script
abstraction the contains the effects of attribute directories
Grumpf... I wish it would be easy. The best advice I can offer (after
today's) mayhem: Please just accept that accessing NFSv4 extended
attributes only works through a file descriptor for now (the
"advantage" is that it makes an emulation on Windows easier because
every acces must go through a fd).
If someone wishes to have an absolute path IMO the best option is to
return /proc/$$/fd/$fd/ because it ensures at least access for the
current and other processes as long as the fd is valid.
[snip]

One more datapoint (since Olga asked and forwarded an email): NFSv4
XATTR directories support subdirectories but only if the underlying
filesystem supports it (Solaris "zfs" and "ufs" don't... I'm not sure
about swap filesystem "tmpfs").

Think about the NFSv4 XATTR directories like a "branch" of the normal
filesystem which has been "cut off". All normal operations apply
(except getting XATTR dirs within XATTR dirs, e.g. nesting is not
allowed), including hard- and softlinks, pipes, fifos and
subdirectories if the underlying filesystems support it (Sun tried to
make it "easier" for itself and treats the XATTR directories as plain
single-level data storage, e.g. doesn't support softlinks, pipe/fifos,
subdirs and softlinks but does support hardlinks for zfs and ufs;
other filesystems are not required to be so restrictive) but all
references are contained within this "cut off branch of the
filesystem", e.g. hardlinks can only reference files inside the XATTR
directory and not files outside it (the same restriction would apply
to relative softlinks).

BTW: Last XATTR hint for today: See |fpathconf(2)| ... the *XATTR* attributes:
-- snip --
System Calls fpathconf(2)

NAME
fpathconf, pathconf - get configurable pathname variables

SYNOPSIS
#include <unistd.h>

long fpathconf(int fildes, int name);

long pathconf(const char *path, int name);


DESCRIPTION
The fpathconf() and pathconf() functions determine the
current value of a configurable limit or option ( variable )
that is associated with a file or directory.


For pathconf(), the path argument points to the pathname of
a file or directory.


For fpathconf(), the fildes argument is an open file
descriptor.


The name argument represents the variable to be queried
relative to that file or directory. The variables in the
following table come from <limits.h> or <unistd.h> and the
symbolic constants, defined in <unistd.h>, are the
corresponding values used for name:






System Calls fpathconf(2)
SunOS 5.11 Last change: 1 Sep 2009 2






System Calls fpathconf(2)



_______________________________________________________________________
Variable Value of name Notes
_______________________________________________________________________
{ACL_ENABLED} _PC_ACL_ENABLED 10
_______________________________________________________________________
{FILESIZEBITS} _PC_FILESIZEBITS 3,4
_______________________________________________________________________
{LINK_MAX} _PC_LINK_MAX 1
_______________________________________________________________________
{MAX_CANON} _PC_MAX_CANON 2
_______________________________________________________________________
{MAX_INPUT} _PC_MAX_INPUT 2
_______________________________________________________________________
{MIN_HOLE_SIZE} _PC_MIN_HOLE_SIZE 11
_______________________________________________________________________
{NAME_MAX} _PC_NAME_MAX 3, 4
_______________________________________________________________________
{PATH_MAX} _PC_PATH_MAX 4,5
_______________________________________________________________________
{PIPE_BUF} _PC_PIPE_BUF 6
_______________________________________________________________________
{POSIX_ALLOC_SIZE_MIN} _PC_ALLOC_SIZE_MIN
_______________________________________________________________________
{POSIX_REC_INCR_XFER_SIZE} _PC_REC_INCR_XFER_SIZE
_______________________________________________________________________
{POSIX_REC_MAX_XFER_SIZE} _PC_REC_MAX_XFER_SIZE
_______________________________________________________________________
{POSIX_REC_MIN_XFER_SIZE} _PC_REC_MIN_XFER_SIZE
_______________________________________________________________________
{POSIX_REC_XFER_ALIGN} _PC_REC_XFER_ALIGN
_______________________________________________________________________
{SYMLINK_MAX} _PC_SYMLINK_MAX 4, 9
_______________________________________________________________________
{XATTR_ENABLED} _PC_XATTR_ENABLED 1
_______________________________________________________________________
{SATTR_ENABLED} _PC_SATTR_ENABLED
_______________________________________________________________________
{XATTR_EXISTS} _PC_XATTR_EXISTS 1
_______________________________________________________________________
{SATTR_EXISTS} _PC_SATTR_EXISTS
_______________________________________________________________________
{ACCESS_FILTERING} _PC_ACCESS_FILTERING 12
_______________________________________________________________________
_POSIX_CHOWN_RESTRICTED _PC_CHOWN_RESTRICTED 7
_______________________________________________________________________
_POSIX_NO_TRUNC _PC_NO_TRUNC 3, 4
_______________________________________________________________________
_POSIX_VDISABLE _PC_VDISABLE 2
_______________________________________________________________________
_POSIX_ASYNC_IO _PC_ASYNC_IO 8
_______________________________________________________________________
_POSIX_PRIO_IO _PC_PRIO_IO 8



SunOS 5.11 Last change: 1 Sep 2009 3






System Calls fpathconf(2)



_______________________________________________________________________
| _POSIX_SYNC_IO | _PC_SYNC_IO | 8 |
|____________________________|__________________________|______________|
| _POSIX_TIMESTAMP_RESOLUTION| _PC_TIMESTAMP_RESOLUTION| 1 |
|____________________________|__________________________|______________|



Notes:

1. If path or fildes refers to a directory, the value
returned applies to the directory itself.

2. If path or fildes does not refer to a terminal
file, it is unspecified whether an implementation
supports an association of the variable name with
the specified file.

3. If path or fildes refers to a directory, the value
returned applies to filenames within the directory.

4. If path or fildes does not refer to a directory, it
is unspecified whether an implementation supports
an association of the variable name with the speci-
fied file.

5. If path or fildes refers to a directory, the value
returned is the maximum length of a relative path-
name when the specified directory is the working
directory.

6. If path refers to a FIFO, or fildes refers to a
pipe or FIFO, the value returned applies to the
referenced object. If path or fildes refers to a
directory, the value returned applies to any FIFO
that exists or can be created within the directory.
If path or fildes refers to any other type of file,
it is unspecified whether an implementation sup-
ports an association of the variable name with the
specified file.

7. If path or fildes refers to a directory, the value
returned applies to any files, other than direc-
tories, that exist or can be created within the
directory.

8. If path or fildes refers to a directory, it is
unspecified whether an implementation supports an
association of the variable name with the specified
file.

9. If path or fildes refers to a directory, the value



SunOS 5.11 Last change: 1 Sep 2009 4






System Calls fpathconf(2)



returned is the maximum length of the string that a
symbolic link in that directory can contain.

10. If path or fildes refers to a file or directory in
a file system that supports ACLs, the value
returned is the bitwise inclusive OR of the follow-
ing flags associated with ACL types supported by
the file system; otherwise 0 is returned.

_ACL_ACE_ENABLED The file system supports ACE
ACLs.


_ACL_ACLENT_ENABLED The file system supports UFS
aclent ACLs.


11. If a filesystem supports the reporting of holes
(see lseek(2), pathconf() and fpathconf() return a
positive number that represents the minimum hole
size returned in bytes. The offsets of holes
returned will be aligned to this same value. A spe-
cial value of 1 is returned if the filesystem does
not specify the minimum hole size but still reports
holes.

12. If path or fildes refers to a directory and the
file system in which the directory resides supports
access filtering, a non-zero value is returned.
Otherwise, 0 is returned.

RETURN VALUES
If name is an invalid value, both pathconf() and fpathconf()
return -1 and errno is set to indicate the error.


If the variable corresponding to name has no limit for the
path or file descriptor, both pathconf() and fpathconf()
return -1 without changing errno. If pathconf() needs to use
path to determine the value of name and pathconf() does not
support the association of name with the file specified by
path, or if the process did not have appropriate privileges
to query the file specified by path, or path does not exist,
pathconf() returns -1 and errno is set to indicate the
error.


If fpathconf() needs to use fildes to determine the value of
name and fpathconf() does not support the association of
name with the file specified by fildes, or if fildes is an
invalid file descriptor, fpathconf() returns -1 and errno is
set to indicate the error.



SunOS 5.11 Last change: 1 Sep 2009 5






System Calls fpathconf(2)



Otherwise pathconf() or fpathconf() returns the current
variable value for the file or directory without changing
errno. The value returned will not be more restrictive than
the corresponding value available to the application when it
was compiled with <limits.h> or <unistd.h>.

ERRORS
The pathconf() function will fail if:

EINVAL The value of name is not valid.


ELOOP A loop exists in symbolic links encountered during
resolution of the path argument.



The fpathconf() function will fail if:

EINVAL The value of name is not valid.



The pathconf() function may fail if:

EACCES Search permission is denied for a component
of the path prefix.


EINVAL An association of the variable name with the
specified file is not supported.


ENAMETOOLONG The length of the path argument exceeds
{PATH_MAX} or a pathname component is longer
than {NAME_MAX}.


ENAMETOOLONG As a result of encountering a symbolic link
in resolution of the path argument, the
length of the substituted pathname string
exceeded {PATH_MAX}.


ENOENT A component of path does not name an exist-
ing file or path is an empty string.


ENOTDIR A component of the path prefix is not a
directory.





SunOS 5.11 Last change: 1 Sep 2009 6






System Calls fpathconf(2)



The fpathconf() function may fail if:

EBADF The fildes argument is not a valid file descrip-
tor.


EINVAL An association of the variable name with the
specified file is not supported.


USAGE
The {SYMLINK_MAX} variable applies only to the fpathconf()
function.

ATTRIBUTES
See attributes(5) for descriptions of the following attri-
butes:



____________________________________________________________
| ATTRIBUTE TYPE | ATTRIBUTE VALUE |
|_____________________________|_____________________________|
| Interface Stability | Committed |
|_____________________________|_____________________________|
| MT-Level | Async-Signal-Safe |
|_____________________________|_____________________________|
| Standard | See standards(5). |
|_____________________________|_____________________________|


SEE ALSO
lseek(2), confstr(3C), limits.h(3HEAD), sysconf(3C), attri-
butes(5), standards(5)
-- snip --

----

Bye,
Roland

--
__ . . __
(o.\ \/ /.o) roland.mainz at nrubsig.org
\__\/\/__/ MPEG specialist, C&&JAVA&&Sun&&Unix programmer
/O /==\ O\ TEL +49 641 3992797
(;O/ \/ \O;)
--
Lionel
Glenn Fowler
2013-09-17 18:49:25 UTC
Permalink
from ksh did you try

getconf name ~{fd}
getconf name /dev/fd/${fd}
Post by Lionel Cons
How can I access fpathconf() via getconf(1)?
Lionel
---------- Forwarded message ----------
From: Roland Mainz <roland.mainz at nrubsig.org>
Date: 31 August 2013 02:31
Subject: Re: [ast-developers] AT&T Software Technology ast alpha
software download update
To: "ast-developers at research.att.com" <ast-developers at research.att.com>
Cc: lionelcons1972 at gmail.com, ?????????? ????????????????????????
<olga.kryzhanovska at gmail.com>, Glenn Fowler <gsf at research.att.com>
ksh -c 'mkdir -p foo2 ; redirect {d}<foo2/ ; redirect
foo2 ; ls ; cat myxattr' myxattr SUNWattr_ro SUNWattr_rw
bla
Do you have a patch for that? It sounds you found a middle way which
might satisfy Glenn's love for /dev/file and marry it with a sane
approach to access files in xattr directories.
I'm looking at this over the long US weekend and am having
an off-list discussion picking olga's brain -- this will be resolved
one way or another tuesday
my "love" isn't so much /dev/file but rather an ast C and script
abstraction the contains the effects of attribute directories
Grumpf... I wish it would be easy. The best advice I can offer (after
today's) mayhem: Please just accept that accessing NFSv4 extended
attributes only works through a file descriptor for now (the
"advantage" is that it makes an emulation on Windows easier because
every acces must go through a fd).
If someone wishes to have an absolute path IMO the best option is to
return /proc/$$/fd/$fd/ because it ensures at least access for the
current and other processes as long as the fd is valid.
[snip]
One more datapoint (since Olga asked and forwarded an email): NFSv4
XATTR directories support subdirectories but only if the underlying
filesystem supports it (Solaris "zfs" and "ufs" don't... I'm not sure
about swap filesystem "tmpfs").
Think about the NFSv4 XATTR directories like a "branch" of the normal
filesystem which has been "cut off". All normal operations apply
(except getting XATTR dirs within XATTR dirs, e.g. nesting is not
allowed), including hard- and softlinks, pipes, fifos and
subdirectories if the underlying filesystems support it (Sun tried to
make it "easier" for itself and treats the XATTR directories as plain
single-level data storage, e.g. doesn't support softlinks, pipe/fifos,
subdirs and softlinks but does support hardlinks for zfs and ufs;
other filesystems are not required to be so restrictive) but all
references are contained within this "cut off branch of the
filesystem", e.g. hardlinks can only reference files inside the XATTR
directory and not files outside it (the same restriction would apply
to relative softlinks).
-- snip --
System Calls fpathconf(2)
NAME
fpathconf, pathconf - get configurable pathname variables
SYNOPSIS
#include <unistd.h>
long fpathconf(int fildes, int name);
long pathconf(const char *path, int name);
DESCRIPTION
The fpathconf() and pathconf() functions determine the
current value of a configurable limit or option ( variable )
that is associated with a file or directory.
For pathconf(), the path argument points to the pathname of
a file or directory.
For fpathconf(), the fildes argument is an open file
descriptor.
The name argument represents the variable to be queried
relative to that file or directory. The variables in the
following table come from <limits.h> or <unistd.h> and the
symbolic constants, defined in <unistd.h>, are the
System Calls fpathconf(2)
SunOS 5.11 Last change: 1 Sep 2009 2
System Calls fpathconf(2)
_______________________________________________________________________
Variable Value of name Notes
_______________________________________________________________________
{ACL_ENABLED} _PC_ACL_ENABLED 10
_______________________________________________________________________
{FILESIZEBITS} _PC_FILESIZEBITS 3,4
_______________________________________________________________________
{LINK_MAX} _PC_LINK_MAX 1
_______________________________________________________________________
{MAX_CANON} _PC_MAX_CANON 2
_______________________________________________________________________
{MAX_INPUT} _PC_MAX_INPUT 2
_______________________________________________________________________
{MIN_HOLE_SIZE} _PC_MIN_HOLE_SIZE 11
_______________________________________________________________________
{NAME_MAX} _PC_NAME_MAX 3, 4
_______________________________________________________________________
{PATH_MAX} _PC_PATH_MAX 4,5
_______________________________________________________________________
{PIPE_BUF} _PC_PIPE_BUF 6
_______________________________________________________________________
{POSIX_ALLOC_SIZE_MIN} _PC_ALLOC_SIZE_MIN
_______________________________________________________________________
{POSIX_REC_INCR_XFER_SIZE} _PC_REC_INCR_XFER_SIZE
_______________________________________________________________________
{POSIX_REC_MAX_XFER_SIZE} _PC_REC_MAX_XFER_SIZE
_______________________________________________________________________
{POSIX_REC_MIN_XFER_SIZE} _PC_REC_MIN_XFER_SIZE
_______________________________________________________________________
{POSIX_REC_XFER_ALIGN} _PC_REC_XFER_ALIGN
_______________________________________________________________________
{SYMLINK_MAX} _PC_SYMLINK_MAX 4, 9
_______________________________________________________________________
{XATTR_ENABLED} _PC_XATTR_ENABLED 1
_______________________________________________________________________
{SATTR_ENABLED} _PC_SATTR_ENABLED
_______________________________________________________________________
{XATTR_EXISTS} _PC_XATTR_EXISTS 1
_______________________________________________________________________
{SATTR_EXISTS} _PC_SATTR_EXISTS
_______________________________________________________________________
{ACCESS_FILTERING} _PC_ACCESS_FILTERING 12
_______________________________________________________________________
_POSIX_CHOWN_RESTRICTED _PC_CHOWN_RESTRICTED 7
_______________________________________________________________________
_POSIX_NO_TRUNC _PC_NO_TRUNC 3, 4
_______________________________________________________________________
_POSIX_VDISABLE _PC_VDISABLE 2
_______________________________________________________________________
_POSIX_ASYNC_IO _PC_ASYNC_IO 8
_______________________________________________________________________
_POSIX_PRIO_IO _PC_PRIO_IO 8
SunOS 5.11 Last change: 1 Sep 2009 3
System Calls fpathconf(2)
_______________________________________________________________________
| _POSIX_SYNC_IO | _PC_SYNC_IO | 8 |
|____________________________|__________________________|______________|
| _POSIX_TIMESTAMP_RESOLUTION| _PC_TIMESTAMP_RESOLUTION| 1 |
|____________________________|__________________________|______________|
1. If path or fildes refers to a directory, the value
returned applies to the directory itself.
2. If path or fildes does not refer to a terminal
file, it is unspecified whether an implementation
supports an association of the variable name with
the specified file.
3. If path or fildes refers to a directory, the value
returned applies to filenames within the directory.
4. If path or fildes does not refer to a directory, it
is unspecified whether an implementation supports
an association of the variable name with the speci-
fied file.
5. If path or fildes refers to a directory, the value
returned is the maximum length of a relative path-
name when the specified directory is the working
directory.
6. If path refers to a FIFO, or fildes refers to a
pipe or FIFO, the value returned applies to the
referenced object. If path or fildes refers to a
directory, the value returned applies to any FIFO
that exists or can be created within the directory.
If path or fildes refers to any other type of file,
it is unspecified whether an implementation sup-
ports an association of the variable name with the
specified file.
7. If path or fildes refers to a directory, the value
returned applies to any files, other than direc-
tories, that exist or can be created within the
directory.
8. If path or fildes refers to a directory, it is
unspecified whether an implementation supports an
association of the variable name with the specified
file.
9. If path or fildes refers to a directory, the value
SunOS 5.11 Last change: 1 Sep 2009 4
System Calls fpathconf(2)
returned is the maximum length of the string that a
symbolic link in that directory can contain.
10. If path or fildes refers to a file or directory in
a file system that supports ACLs, the value
returned is the bitwise inclusive OR of the follow-
ing flags associated with ACL types supported by
the file system; otherwise 0 is returned.
_ACL_ACE_ENABLED The file system supports ACE
ACLs.
_ACL_ACLENT_ENABLED The file system supports UFS
aclent ACLs.
11. If a filesystem supports the reporting of holes
(see lseek(2), pathconf() and fpathconf() return a
positive number that represents the minimum hole
size returned in bytes. The offsets of holes
returned will be aligned to this same value. A spe-
cial value of 1 is returned if the filesystem does
not specify the minimum hole size but still reports
holes.
12. If path or fildes refers to a directory and the
file system in which the directory resides supports
access filtering, a non-zero value is returned.
Otherwise, 0 is returned.
RETURN VALUES
If name is an invalid value, both pathconf() and fpathconf()
return -1 and errno is set to indicate the error.
If the variable corresponding to name has no limit for the
path or file descriptor, both pathconf() and fpathconf()
return -1 without changing errno. If pathconf() needs to use
path to determine the value of name and pathconf() does not
support the association of name with the file specified by
path, or if the process did not have appropriate privileges
to query the file specified by path, or path does not exist,
pathconf() returns -1 and errno is set to indicate the
error.
If fpathconf() needs to use fildes to determine the value of
name and fpathconf() does not support the association of
name with the file specified by fildes, or if fildes is an
invalid file descriptor, fpathconf() returns -1 and errno is
set to indicate the error.
SunOS 5.11 Last change: 1 Sep 2009 5
System Calls fpathconf(2)
Otherwise pathconf() or fpathconf() returns the current
variable value for the file or directory without changing
errno. The value returned will not be more restrictive than
the corresponding value available to the application when it
was compiled with <limits.h> or <unistd.h>.
ERRORS
EINVAL The value of name is not valid.
ELOOP A loop exists in symbolic links encountered during
resolution of the path argument.
EINVAL The value of name is not valid.
EACCES Search permission is denied for a component
of the path prefix.
EINVAL An association of the variable name with the
specified file is not supported.
ENAMETOOLONG The length of the path argument exceeds
{PATH_MAX} or a pathname component is longer
than {NAME_MAX}.
ENAMETOOLONG As a result of encountering a symbolic link
in resolution of the path argument, the
length of the substituted pathname string
exceeded {PATH_MAX}.
ENOENT A component of path does not name an exist-
ing file or path is an empty string.
ENOTDIR A component of the path prefix is not a
directory.
SunOS 5.11 Last change: 1 Sep 2009 6
System Calls fpathconf(2)
EBADF The fildes argument is not a valid file descrip-
tor.
EINVAL An association of the variable name with the
specified file is not supported.
USAGE
The {SYMLINK_MAX} variable applies only to the fpathconf()
function.
ATTRIBUTES
See attributes(5) for descriptions of the following attri-
____________________________________________________________
| ATTRIBUTE TYPE | ATTRIBUTE VALUE |
|_____________________________|_____________________________|
| Interface Stability | Committed |
|_____________________________|_____________________________|
| MT-Level | Async-Signal-Safe |
|_____________________________|_____________________________|
| Standard | See standards(5). |
|_____________________________|_____________________________|
SEE ALSO
lseek(2), confstr(3C), limits.h(3HEAD), sysconf(3C), attri-
butes(5), standards(5)
-- snip --
----
Bye,
Roland
--
__ . . __
(o.\ \/ /.o) roland.mainz at nrubsig.org
\__\/\/__/ MPEG specialist, C&&JAVA&&Sun&&Unix programmer
/O /==\ O\ TEL +49 641 3992797
(;O/ \/ \O;)
--
Lionel
Lionel Cons
2013-09-17 19:14:38 UTC
Permalink
Post by Glenn Fowler
from ksh did you try
getconf name ~{fd}
getconf name /dev/fd/${fd}
Forwarding the feedback from a coworker:
It may work for AST but it is not legal: ~{fd} expands to /proc, which
is a filesystem, and /dev/fd is a filesystem on Solaris too. What
happens if I want to find the pathconf properties of /proc or /dev/fd
in a POSIX conforming way?

Lionel
Post by Glenn Fowler
Post by Lionel Cons
How can I access fpathconf() via getconf(1)?
Lionel
---------- Forwarded message ----------
From: Roland Mainz <roland.mainz at nrubsig.org>
Date: 31 August 2013 02:31
Subject: Re: [ast-developers] AT&T Software Technology ast alpha
software download update
To: "ast-developers at research.att.com" <ast-developers at research.att.com>
Cc: lionelcons1972 at gmail.com, ????? ????????????
<olga.kryzhanovska at gmail.com>, Glenn Fowler <gsf at research.att.com>
ksh -c 'mkdir -p foo2 ; redirect {d}<foo2/ ; redirect
foo2 ; ls ; cat myxattr' myxattr SUNWattr_ro SUNWattr_rw
bla
Do you have a patch for that? It sounds you found a middle way which
might satisfy Glenn's love for /dev/file and marry it with a sane
approach to access files in xattr directories.
I'm looking at this over the long US weekend and am having
an off-list discussion picking olga's brain -- this will be resolved
one way or another tuesday
my "love" isn't so much /dev/file but rather an ast C and script
abstraction the contains the effects of attribute directories
Grumpf... I wish it would be easy. The best advice I can offer (after
today's) mayhem: Please just accept that accessing NFSv4 extended
attributes only works through a file descriptor for now (the
"advantage" is that it makes an emulation on Windows easier because
every acces must go through a fd).
If someone wishes to have an absolute path IMO the best option is to
return /proc/$$/fd/$fd/ because it ensures at least access for the
current and other processes as long as the fd is valid.
[snip]
One more datapoint (since Olga asked and forwarded an email): NFSv4
XATTR directories support subdirectories but only if the underlying
filesystem supports it (Solaris "zfs" and "ufs" don't... I'm not sure
about swap filesystem "tmpfs").
Think about the NFSv4 XATTR directories like a "branch" of the normal
filesystem which has been "cut off". All normal operations apply
(except getting XATTR dirs within XATTR dirs, e.g. nesting is not
allowed), including hard- and softlinks, pipes, fifos and
subdirectories if the underlying filesystems support it (Sun tried to
make it "easier" for itself and treats the XATTR directories as plain
single-level data storage, e.g. doesn't support softlinks, pipe/fifos,
subdirs and softlinks but does support hardlinks for zfs and ufs;
other filesystems are not required to be so restrictive) but all
references are contained within this "cut off branch of the
filesystem", e.g. hardlinks can only reference files inside the XATTR
directory and not files outside it (the same restriction would apply
to relative softlinks).
-- snip --
System Calls fpathconf(2)
NAME
fpathconf, pathconf - get configurable pathname variables
SYNOPSIS
#include <unistd.h>
long fpathconf(int fildes, int name);
long pathconf(const char *path, int name);
DESCRIPTION
The fpathconf() and pathconf() functions determine the
current value of a configurable limit or option ( variable )
that is associated with a file or directory.
For pathconf(), the path argument points to the pathname of
a file or directory.
For fpathconf(), the fildes argument is an open file
descriptor.
The name argument represents the variable to be queried
relative to that file or directory. The variables in the
following table come from <limits.h> or <unistd.h> and the
symbolic constants, defined in <unistd.h>, are the
System Calls fpathconf(2)
SunOS 5.11 Last change: 1 Sep 2009 2
System Calls fpathconf(2)
_______________________________________________________________________
Variable Value of name Notes
_______________________________________________________________________
{ACL_ENABLED} _PC_ACL_ENABLED 10
_______________________________________________________________________
{FILESIZEBITS} _PC_FILESIZEBITS 3,4
_______________________________________________________________________
{LINK_MAX} _PC_LINK_MAX 1
_______________________________________________________________________
{MAX_CANON} _PC_MAX_CANON 2
_______________________________________________________________________
{MAX_INPUT} _PC_MAX_INPUT 2
_______________________________________________________________________
{MIN_HOLE_SIZE} _PC_MIN_HOLE_SIZE 11
_______________________________________________________________________
{NAME_MAX} _PC_NAME_MAX 3, 4
_______________________________________________________________________
{PATH_MAX} _PC_PATH_MAX 4,5
_______________________________________________________________________
{PIPE_BUF} _PC_PIPE_BUF 6
_______________________________________________________________________
{POSIX_ALLOC_SIZE_MIN} _PC_ALLOC_SIZE_MIN
_______________________________________________________________________
{POSIX_REC_INCR_XFER_SIZE} _PC_REC_INCR_XFER_SIZE
_______________________________________________________________________
{POSIX_REC_MAX_XFER_SIZE} _PC_REC_MAX_XFER_SIZE
_______________________________________________________________________
{POSIX_REC_MIN_XFER_SIZE} _PC_REC_MIN_XFER_SIZE
_______________________________________________________________________
{POSIX_REC_XFER_ALIGN} _PC_REC_XFER_ALIGN
_______________________________________________________________________
{SYMLINK_MAX} _PC_SYMLINK_MAX 4, 9
_______________________________________________________________________
{XATTR_ENABLED} _PC_XATTR_ENABLED 1
_______________________________________________________________________
{SATTR_ENABLED} _PC_SATTR_ENABLED
_______________________________________________________________________
{XATTR_EXISTS} _PC_XATTR_EXISTS 1
_______________________________________________________________________
{SATTR_EXISTS} _PC_SATTR_EXISTS
_______________________________________________________________________
{ACCESS_FILTERING} _PC_ACCESS_FILTERING 12
_______________________________________________________________________
_POSIX_CHOWN_RESTRICTED _PC_CHOWN_RESTRICTED 7
_______________________________________________________________________
_POSIX_NO_TRUNC _PC_NO_TRUNC 3, 4
_______________________________________________________________________
_POSIX_VDISABLE _PC_VDISABLE 2
_______________________________________________________________________
_POSIX_ASYNC_IO _PC_ASYNC_IO 8
_______________________________________________________________________
_POSIX_PRIO_IO _PC_PRIO_IO 8
SunOS 5.11 Last change: 1 Sep 2009 3
System Calls fpathconf(2)
_______________________________________________________________________
| _POSIX_SYNC_IO | _PC_SYNC_IO | 8 |
|____________________________|__________________________|______________|
| _POSIX_TIMESTAMP_RESOLUTION| _PC_TIMESTAMP_RESOLUTION| 1 |
|____________________________|__________________________|______________|
1. If path or fildes refers to a directory, the value
returned applies to the directory itself.
2. If path or fildes does not refer to a terminal
file, it is unspecified whether an implementation
supports an association of the variable name with
the specified file.
3. If path or fildes refers to a directory, the value
returned applies to filenames within the directory.
4. If path or fildes does not refer to a directory, it
is unspecified whether an implementation supports
an association of the variable name with the speci-
fied file.
5. If path or fildes refers to a directory, the value
returned is the maximum length of a relative path-
name when the specified directory is the working
directory.
6. If path refers to a FIFO, or fildes refers to a
pipe or FIFO, the value returned applies to the
referenced object. If path or fildes refers to a
directory, the value returned applies to any FIFO
that exists or can be created within the directory.
If path or fildes refers to any other type of file,
it is unspecified whether an implementation sup-
ports an association of the variable name with the
specified file.
7. If path or fildes refers to a directory, the value
returned applies to any files, other than direc-
tories, that exist or can be created within the
directory.
8. If path or fildes refers to a directory, it is
unspecified whether an implementation supports an
association of the variable name with the specified
file.
9. If path or fildes refers to a directory, the value
SunOS 5.11 Last change: 1 Sep 2009 4
System Calls fpathconf(2)
returned is the maximum length of the string that a
symbolic link in that directory can contain.
10. If path or fildes refers to a file or directory in
a file system that supports ACLs, the value
returned is the bitwise inclusive OR of the follow-
ing flags associated with ACL types supported by
the file system; otherwise 0 is returned.
_ACL_ACE_ENABLED The file system supports ACE
ACLs.
_ACL_ACLENT_ENABLED The file system supports UFS
aclent ACLs.
11. If a filesystem supports the reporting of holes
(see lseek(2), pathconf() and fpathconf() return a
positive number that represents the minimum hole
size returned in bytes. The offsets of holes
returned will be aligned to this same value. A spe-
cial value of 1 is returned if the filesystem does
not specify the minimum hole size but still reports
holes.
12. If path or fildes refers to a directory and the
file system in which the directory resides supports
access filtering, a non-zero value is returned.
Otherwise, 0 is returned.
RETURN VALUES
If name is an invalid value, both pathconf() and fpathconf()
return -1 and errno is set to indicate the error.
If the variable corresponding to name has no limit for the
path or file descriptor, both pathconf() and fpathconf()
return -1 without changing errno. If pathconf() needs to use
path to determine the value of name and pathconf() does not
support the association of name with the file specified by
path, or if the process did not have appropriate privileges
to query the file specified by path, or path does not exist,
pathconf() returns -1 and errno is set to indicate the
error.
If fpathconf() needs to use fildes to determine the value of
name and fpathconf() does not support the association of
name with the file specified by fildes, or if fildes is an
invalid file descriptor, fpathconf() returns -1 and errno is
set to indicate the error.
SunOS 5.11 Last change: 1 Sep 2009 5
System Calls fpathconf(2)
Otherwise pathconf() or fpathconf() returns the current
variable value for the file or directory without changing
errno. The value returned will not be more restrictive than
the corresponding value available to the application when it
was compiled with <limits.h> or <unistd.h>.
ERRORS
EINVAL The value of name is not valid.
ELOOP A loop exists in symbolic links encountered during
resolution of the path argument.
EINVAL The value of name is not valid.
EACCES Search permission is denied for a component
of the path prefix.
EINVAL An association of the variable name with the
specified file is not supported.
ENAMETOOLONG The length of the path argument exceeds
{PATH_MAX} or a pathname component is longer
than {NAME_MAX}.
ENAMETOOLONG As a result of encountering a symbolic link
in resolution of the path argument, the
length of the substituted pathname string
exceeded {PATH_MAX}.
ENOENT A component of path does not name an exist-
ing file or path is an empty string.
ENOTDIR A component of the path prefix is not a
directory.
SunOS 5.11 Last change: 1 Sep 2009 6
System Calls fpathconf(2)
EBADF The fildes argument is not a valid file descrip-
tor.
EINVAL An association of the variable name with the
specified file is not supported.
USAGE
The {SYMLINK_MAX} variable applies only to the fpathconf()
function.
ATTRIBUTES
See attributes(5) for descriptions of the following attri-
____________________________________________________________
| ATTRIBUTE TYPE | ATTRIBUTE VALUE |
|_____________________________|_____________________________|
| Interface Stability | Committed |
|_____________________________|_____________________________|
| MT-Level | Async-Signal-Safe |
|_____________________________|_____________________________|
| Standard | See standards(5). |
|_____________________________|_____________________________|
SEE ALSO
lseek(2), confstr(3C), limits.h(3HEAD), sysconf(3C), attri-
butes(5), standards(5)
-- snip --
----
Bye,
Roland
--
__ . . __
(o.\ \/ /.o) roland.mainz at nrubsig.org
\__\/\/__/ MPEG specialist, C&&JAVA&&Sun&&Unix programmer
/O /==\ O\ TEL +49 641 3992797
(;O/ \/ \O;)
--
Lionel
--
Lionel
Glenn Fowler
2013-09-17 19:55:26 UTC
Permalink
Post by Lionel Cons
Post by Glenn Fowler
from ksh did you try
getconf name ~{fd}
getconf name /dev/fd/${fd}
It may work for AST but it is not legal: ~{fd} expands to /proc, which
is a filesystem, and /dev/fd is a filesystem on Solaris too. What
happens if I want to find the pathconf properties of /proc or /dev/fd
in a POSIX conforming way?
if you want to do fpathconf(2) from the command line in a posix conforming way then you can't
posix has neither /proc nor /dev/fd

now for a useful answer
using ~{fd} or /dev/fd will only work for builtins or on systems that support /proc/<pid>/fd/<fd>
right now the ksh93 getconf builtin defers to /usr/bin/getconf for most path_var operands
those would have to be instead handled by the builtin to handle fds

until then something like this should work on most modern unix (with /dev/fd/<fd> support)

getconf path_var /dev/fd/0 < ~{fd}
Roland Mainz
2013-09-18 04:06:31 UTC
Permalink
Post by Glenn Fowler
Post by Lionel Cons
Post by Glenn Fowler
from ksh did you try
getconf name ~{fd}
getconf name /dev/fd/${fd}
It may work for AST but it is not legal: ~{fd} expands to /proc, which
is a filesystem, and /dev/fd is a filesystem on Solaris too. What
happens if I want to find the pathconf properties of /proc or /dev/fd
in a POSIX conforming way?
if you want to do fpathconf(2) from the command line in a posix conforming way then you can't
posix has neither /proc nor /dev/fd
now for a useful answer
using ~{fd} or /dev/fd will only work for builtins or on systems that support /proc/<pid>/fd/<fd>
right now the ksh93 getconf builtin defers to /usr/bin/getconf for most path_var operands
those would have to be instead handled by the builtin to handle fds
until then something like this should work on most modern unix (with /dev/fd/<fd> support)
getconf path_var /dev/fd/0 < ~{fd}
Erm... this can't work (and quick testing&&looking at the Solaris and
Linux kernel sources confirms it) because |pathconf()|+|fpathconf()|
is a syscall which is directly forwarded to the matching filesystem
code in the kernel. The syscall passes the path (string for
|pathconf(), fd for |fpathconf()|) to the kernel and then the kernel
looks-up the matching filesystem and then forwards the call to that
filesystem...

Regardless how hard we try the current getconf(1) API won't work for a
given fd, e.g. it can't work using /dev/fd/ because /dev/fd is a
separate filesystem on Solaris and /dev (covering /dev/fd/) on Linux.
The same applies to ~{fd} which expands to /proc/$currpid/fd/$fd and
therefore refers to the proc filesystem instead of the filesystem the
fd is on.

AFAIK the only valid way is to add a --fd option to getconf(1) to deal
with that trouble because at least the Solaris test suite use
/usr/bin/getconf to test the devfs and procfs filesystems... which
means if we implement the AST intercept system to convert a /dev/fd or
/proc/self/fd/ path to a fd internally to call |fpathconf()| we break
such tests... ;-(

... on the bright side... adding |fpathconf()| support looks quite
easy to implement... if Glenn agrees I can make the patch for that
tonight...

----

Bye,
Roland
--
__ . . __
(o.\ \/ /.o) roland.mainz at nrubsig.org
\__\/\/__/ MPEG specialist, C&&JAVA&&Sun&&Unix programmer
/O /==\ O\ TEL +49 641 3992797
(;O/ \/ \O;)
Roland Mainz
2013-09-27 00:17:07 UTC
Permalink
Post by Roland Mainz
Post by Glenn Fowler
Post by Lionel Cons
Post by Glenn Fowler
from ksh did you try
getconf name ~{fd}
getconf name /dev/fd/${fd}
It may work for AST but it is not legal: ~{fd} expands to /proc, which
is a filesystem, and /dev/fd is a filesystem on Solaris too. What
happens if I want to find the pathconf properties of /proc or /dev/fd
in a POSIX conforming way?
if you want to do fpathconf(2) from the command line in a posix conforming way then you can't
posix has neither /proc nor /dev/fd
now for a useful answer
using ~{fd} or /dev/fd will only work for builtins or on systems that support /proc/<pid>/fd/<fd>
right now the ksh93 getconf builtin defers to /usr/bin/getconf for most path_var operands
those would have to be instead handled by the builtin to handle fds
until then something like this should work on most modern unix (with /dev/fd/<fd> support)
getconf path_var /dev/fd/0 < ~{fd}
Erm... this can't work (and quick testing&&looking at the Solaris and
Linux kernel sources confirms it) because |pathconf()|+|fpathconf()|
is a syscall which is directly forwarded to the matching filesystem
code in the kernel. The syscall passes the path (string for
|pathconf(), fd for |fpathconf()|) to the kernel and then the kernel
looks-up the matching filesystem and then forwards the call to that
filesystem...
Regardless how hard we try the current getconf(1) API won't work for a
given fd, e.g. it can't work using /dev/fd/ because /dev/fd is a
separate filesystem on Solaris and /dev (covering /dev/fd/) on Linux.
The same applies to ~{fd} which expands to /proc/$currpid/fd/$fd and
therefore refers to the proc filesystem instead of the filesystem the
fd is on.
AFAIK the only valid way is to add a --fd option to getconf(1) to deal
with that trouble because at least the Solaris test suite use
/usr/bin/getconf to test the devfs and procfs filesystems... which
means if we implement the AST intercept system to convert a /dev/fd or
/proc/self/fd/ path to a fd internally to call |fpathconf()| we break
such tests... ;-(
... on the bright side... adding |fpathconf()| support looks quite
easy to implement... if Glenn agrees I can make the patch for that
tonight...
Erm... ping!

Can I craft the patch for this one, please ?

----

Bye,
Roland
--
__ . . __
(o.\ \/ /.o) roland.mainz at nrubsig.org
\__\/\/__/ MPEG specialist, C&&JAVA&&Sun&&Unix programmer
/O /==\ O\ TEL +49 641 3992797
(;O/ \/ \O;)
Glenn Fowler
2013-09-27 01:29:07 UTC
Permalink
Post by Roland Mainz
Post by Glenn Fowler
Post by Lionel Cons
Post by Glenn Fowler
from ksh did you try
getconf name ~{fd}
getconf name /dev/fd/${fd}
It may work for AST but it is not legal: ~{fd} expands to /proc, which
is a filesystem, and /dev/fd is a filesystem on Solaris too. What
happens if I want to find the pathconf properties of /proc or /dev/fd
in a POSIX conforming way?
if you want to do fpathconf(2) from the command line in a posix conforming way then you can't
posix has neither /proc nor /dev/fd
now for a useful answer
using ~{fd} or /dev/fd will only work for builtins or on systems that support /proc/<pid>/fd/<fd>
right now the ksh93 getconf builtin defers to /usr/bin/getconf for most path_var operands
those would have to be instead handled by the builtin to handle fds
until then something like this should work on most modern unix (with /dev/fd/<fd> support)
getconf path_var /dev/fd/0 < ~{fd}
Erm... this can't work (and quick testing&&looking at the Solaris and
Linux kernel sources confirms it) because |pathconf()|+|fpathconf()|
is a syscall which is directly forwarded to the matching filesystem
code in the kernel. The syscall passes the path (string for
|pathconf(), fd for |fpathconf()|) to the kernel and then the kernel
looks-up the matching filesystem and then forwards the call to that
filesystem...
Regardless how hard we try the current getconf(1) API won't work for a
given fd, e.g. it can't work using /dev/fd/ because /dev/fd is a
separate filesystem on Solaris and /dev (covering /dev/fd/) on Linux.
The same applies to ~{fd} which expands to /proc/$currpid/fd/$fd and
therefore refers to the proc filesystem instead of the filesystem the
fd is on.
AFAIK the only valid way is to add a --fd option to getconf(1) to deal
with that trouble because at least the Solaris test suite use
/usr/bin/getconf to test the devfs and procfs filesystems... which
means if we implement the AST intercept system to convert a /dev/fd or
/proc/self/fd/ path to a fd internally to call |fpathconf()| we break
such tests... ;-(
can you list the explicit paths used in these tests

I can see
/dev/fd
/proc/self/fd
referring to the specific filesystem
but why would
/dev/fd/${fd}/foo
/proc/self/fd/${fd}/foo
stop at the fs and not resolve through ${fd} to foo
or why whould these stop at the fs and not the ${fd}
/dev/fd/${fd}/foo
/proc/self/fd/${fd}/foo
is this just an incomplete implementation of /dev/fd and /proc/${pid}/fd?
we already have iffe evidence of that on some systems
Roland Mainz
2013-09-27 02:35:46 UTC
Permalink
Post by Glenn Fowler
Post by Roland Mainz
Post by Glenn Fowler
Post by Lionel Cons
Post by Glenn Fowler
from ksh did you try
getconf name ~{fd}
getconf name /dev/fd/${fd}
It may work for AST but it is not legal: ~{fd} expands to /proc, which
is a filesystem, and /dev/fd is a filesystem on Solaris too. What
happens if I want to find the pathconf properties of /proc or /dev/fd
in a POSIX conforming way?
if you want to do fpathconf(2) from the command line in a posix conforming way then you can't
posix has neither /proc nor /dev/fd
now for a useful answer
using ~{fd} or /dev/fd will only work for builtins or on systems that support /proc/<pid>/fd/<fd>
right now the ksh93 getconf builtin defers to /usr/bin/getconf for most path_var operands
those would have to be instead handled by the builtin to handle fds
until then something like this should work on most modern unix (with /dev/fd/<fd> support)
getconf path_var /dev/fd/0 < ~{fd}
Erm... this can't work (and quick testing&&looking at the Solaris and
Linux kernel sources confirms it) because |pathconf()|+|fpathconf()|
is a syscall which is directly forwarded to the matching filesystem
code in the kernel. The syscall passes the path (string for
|pathconf(), fd for |fpathconf()|) to the kernel and then the kernel
looks-up the matching filesystem and then forwards the call to that
filesystem...
Regardless how hard we try the current getconf(1) API won't work for a
given fd, e.g. it can't work using /dev/fd/ because /dev/fd is a
separate filesystem on Solaris and /dev (covering /dev/fd/) on Linux.
The same applies to ~{fd} which expands to /proc/$currpid/fd/$fd and
therefore refers to the proc filesystem instead of the filesystem the
fd is on.
AFAIK the only valid way is to add a --fd option to getconf(1) to deal
with that trouble because at least the Solaris test suite use
/usr/bin/getconf to test the devfs and procfs filesystems... which
means if we implement the AST intercept system to convert a /dev/fd or
/proc/self/fd/ path to a fd internally to call |fpathconf()| we break
such tests... ;-(
can you list the explicit paths used in these tests
Erm... Sun never published the main testsuites for Solaris. Polite
questioning resulted in an awk'ed test run log with the paths
extracted for _one_ of the tests:
-- snip --
/dev/dtrace
/dev/dtrace/dtrace
/dev/dtrace/helper
/dev/dtrace/provider
/dev/dtrace/provider/dcpc
/dev/dtrace/provider/fasttrap
/dev/dtrace/provider/fbt
/dev/dtrace/provider/lockstat
/dev/dtrace/provider/lx_systrace
/dev/dtrace/provider/profile
/dev/dtrace/provider/sdt
/dev/dtrace/provider/systrace
/dev
/dev/fd
/dev/fd/${boot}/rpool
/
/devices
/dev
/system/contract
/proc
/etc/mnttab
/etc/svc/volatile
/system/object
/etc/dfs/sharetab
/lib/libc.so.1
/dev/fd
/tmp
/var/run
/export
/export/home
/export/home/test001
/rpool
/home/test001
/proc/$p/fd/$root/loopmount
/proc/$p/fd/$root//kernel/
/proc/$p/fd/$root//kernel/ipp
/proc/$p/fd/$root//kernel/ipp/amd64
/proc/$p/fd/$root//kernel/ipp/amd64/ipgpc
/proc/$p/fd/$root//kernel/ipp/ipgpc
/proc/$p/fd/$root//kernel/misc
/proc/$p/fd/$root//kernel/misc/strplumb
/proc/$p/fd/$root//kernel/misc/ibcm
/proc/$p/fd/$root//kernel/misc/drm
/proc/$p/fd/$root//kernel/misc/md_mirror
/proc/$p/fd/$root//kernel/misc/net80211
/proc/$p/fd/$root//kernel/misc/pci_autoconfig
/proc/$p/fd/$root//kernel/misc/kcf
/proc/$p/fd/$root//kernel/misc/usba10
/proc/$p/fd/$root//kernel/misc/pcmcia
/proc/$p/fd/$root//kernel/misc/des
/proc/$p/fd/$root//kernel/misc/iommulib
/proc/$p/fd/$root//kernel/misc/uwba
/proc/$p/fd/$root//kernel/misc/idmap
/proc/$p/fd/$root//kernel/misc/ksocket
/proc/$p/fd/$root//kernel/misc/rpcsec_gss
/proc/$p/fd/$root//kernel/misc/md_trans
/proc/$p/fd/$root//kernel/misc/fctl
/proc/$p/fd/$root//kernel/misc/fssnap_if
/proc/$p/fd/$root//kernel/misc/qlc
/proc/$p/fd/$root//kernel/misc/qlc/qlc_fw_6322
/proc/$p/fd/$root//kernel/misc/qlc/qlc_fw_2200
/proc/$p/fd/$root//kernel/misc/qlc/qlc_fw_2300
/proc/$p/fd/$root//kernel/misc/qlc/qlc_fw_8100
/proc/$p/fd/$root//kernel/misc/qlc/qlc_fw_2400
/proc/$p/fd/$root//kernel/misc/qlc/qlc_fw_2500
/proc/$p/fd/$root//kernel/misc/qlc/amd64
/proc/$p/fd/$root//kernel/misc/qlc/amd64/qlc_fw_2400
/proc/$p/fd/$root//kernel/misc/qlc/amd64/qlc_fw_8100
/proc/$p/fd/$root//kernel/misc/qlc/amd64/qlc_fw_2500
/proc/$p/fd/$root//kernel/misc/qlc/amd64/qlc_fw_2200
/proc/$p/fd/$root//kernel/misc/qlc/amd64/qlc_fw_6322
/proc/$p/fd/$root//kernel/misc/qlc/amd64/qlc_fw_2300
/proc/$p/fd/$root//kernel/misc/s1394
/proc/$p/fd/$root//kernel/misc/ibdm
/proc/$p/fd/$root//kernel/misc/acpica
/proc/$p/fd/$root//kernel/misc/emlxs
/proc/$p/fd/$root//kernel/misc/emlxs/amd64
/proc/$p/fd/$root//kernel/misc/emlxs/amd64/emlxs_fw
/proc/$p/fd/$root//kernel/misc/emlxs/emlxs_fw
/proc/$p/fd/$root//kernel/misc/agpmaster
/proc/$p/fd/$root//kernel/misc/sata
/proc/$p/fd/$root//kernel/misc/usbser
/proc/$p/fd/$root//kernel/misc/pcihp
/proc/$p/fd/$root//kernel/misc/scsi_vhci
/proc/$p/fd/$root//kernel/misc/scsi_vhci/scsi_vhci_f_sym_emc
/proc/$p/fd/$root//kernel/misc/scsi_vhci/scsi_vhci_f_sym
/proc/$p/fd/$root//kernel/misc/scsi_vhci/scsi_vhci_f_tpgs
/proc/$p/fd/$root//kernel/misc/scsi_vhci/scsi_vhci_f_tape
/proc/$p/fd/$root//kernel/misc/scsi_vhci/scsi_vhci_f_asym_lsi
/proc/$p/fd/$root//kernel/misc/scsi_vhci/scsi_vhci_f_asym_emc
/proc/$p/fd/$root//kernel/misc/scsi_vhci/scsi_vhci_f_tpgs_tape
/proc/$p/fd/$root//kernel/misc/scsi_vhci/amd64
/proc/$p/fd/$root//kernel/misc/scsi_vhci/amd64/scsi_vhci_f_sym
/proc/$p/fd/$root//kernel/misc/scsi_vhci/amd64/scsi_vhci_f_tpgs_tape
/proc/$p/fd/$root//kernel/misc/scsi_vhci/amd64/scsi_vhci_f_sym_emc
/proc/$p/fd/$root//kernel/misc/scsi_vhci/amd64/scsi_vhci_f_tpgs
/proc/$p/fd/$root//kernel/misc/scsi_vhci/amd64/scsi_vhci_f_tape
/proc/$p/fd/$root//kernel/misc/scsi_vhci/amd64/scsi_vhci_f_sym_hds
/proc/$p/fd/$root//kernel/misc/scsi_vhci/amd64/scsi_vhci_f_asym_sun
/proc/$p/fd/$root//kernel/misc/scsi_vhci/amd64/scsi_vhci_f_asym_lsi
/proc/$p/fd/$root//kernel/misc/scsi_vhci/amd64/scsi_vhci_f_asym_emc
/proc/$p/fd/$root//kernel/misc/scsi_vhci/scsi_vhci_f_sym_hds
/proc/$p/fd/$root//kernel/misc/scsi_vhci/scsi_vhci_f_asym_sun
/proc/$p/fd/$root//kernel/misc/dls
/proc/$p/fd/$root//kernel/misc/gld
/proc/$p/fd/$root//kernel/misc/md_stripe
/proc/$p/fd/$root//kernel/misc/kmdbmod
/proc/$p/fd/$root//kernel/misc/ctf
/proc/$p/fd/$root//kernel/misc/bignum
/proc/$p/fd/$root//kernel/misc/pmcs
/proc/$p/fd/$root//kernel/misc/pmcs/amd64
/proc/$p/fd/$root//kernel/misc/pmcs/amd64/pmcs8001fw
/proc/$p/fd/$root//kernel/misc/pmcs/pmcs8001fw
/proc/$p/fd/$root//kernel/misc/tlimod
/proc/$p/fd/$root//kernel/misc/cardbus
/proc/$p/fd/$root//kernel/misc/amd64
/proc/$p/fd/$root//kernel/misc/amd64/strplumb
/proc/$p/fd/$root//kernel/misc/amd64/ipc
/proc/$p/fd/$root//kernel/misc/amd64/uathfw
/proc/$p/fd/$root//kernel/misc/amd64/net80211
/proc/$p/fd/$root//kernel/misc/amd64/sata
/proc/$p/fd/$root//kernel/misc/amd64/hidparser
/proc/$p/fd/$root//kernel/misc/amd64/ctf
/proc/$p/fd/$root//kernel/misc/amd64/iommulib
/proc/$p/fd/$root//kernel/misc/amd64/idmap
-- snip --

There are also automounter tests which do testing for /net, where
/net/<IP-address>/remote-path can automagically mount NFS filesystems
as plain user.
Post by Glenn Fowler
I can see
/dev/fd
/proc/self/fd
referring to the specific filesystem
but why would
/dev/fd/${fd}/foo
/proc/self/fd/${fd}/foo
stop at the fs and not resolve through ${fd} to foo
or why whould these stop at the fs and not the ${fd}
/dev/fd/${fd}/foo
/proc/self/fd/${fd}/foo
is this just an incomplete implementation of /dev/fd and /proc/${pid}/fd?
No... I went to the Sun^H^H^HOracle people for an explanation:
The issue is:
... some of the pathconf _PC_* values probe the file system itself.
Using a file descriptor through /dev/fd or /proc/self/fd/$fd MUST -
required by POSIX - always test the file system specified - which is
either devfs or procfs. Link redirects, including soft- and hard links
and NTFS/CIFS/NFSv4 reparse points, do not apply here, with the
exception of lofs, which is a real filesystem but may pass some
pathconf/fpathconf requests through to the parent file system ...
-- snip --
That's the more or less official Sun judgment.

BTW: lofs is the loopback filesystem... it works similar to a softlink
but can be mounted and then looks&&acts like a real filesystem. This
is used by the automounter to maintain /home in Solaris, e.g. if you
to to /home/foo the automounter will look at /etc/auto_home and
figures it the real location of that home directory (for example
/export/home/foo) and then mounts lofs as /home/foo which redirects
requests to /export/home/foo.

So we're basically in trouble if we only have a fd and want to do
pathconf with that through getconf(1). The issue is actually known and
the Solaris bug db has a bug entry for that trouble. The proposed
solution is... erm... "... add -f <fd> to pass a file descriptor to
fpathconf()..."

----

Bye,
Roland
--
__ . . __
(o.\ \/ /.o) roland.mainz at nrubsig.org
\__\/\/__/ MPEG specialist, C&&JAVA&&Sun&&Unix programmer
/O /==\ O\ TEL +49 641 3992797
(;O/ \/ \O;)
Glenn Fowler
2013-09-27 04:20:29 UTC
Permalink
Post by Roland Mainz
Post by Glenn Fowler
Post by Roland Mainz
Post by Glenn Fowler
Post by Lionel Cons
Post by Glenn Fowler
from ksh did you try
getconf name ~{fd}
getconf name /dev/fd/${fd}
It may work for AST but it is not legal: ~{fd} expands to /proc, which
is a filesystem, and /dev/fd is a filesystem on Solaris too. What
happens if I want to find the pathconf properties of /proc or /dev/fd
in a POSIX conforming way?
if you want to do fpathconf(2) from the command line in a posix conforming way then you can't
posix has neither /proc nor /dev/fd
now for a useful answer
using ~{fd} or /dev/fd will only work for builtins or on systems that support /proc/<pid>/fd/<fd>
right now the ksh93 getconf builtin defers to /usr/bin/getconf for most path_var operands
those would have to be instead handled by the builtin to handle fds
until then something like this should work on most modern unix (with /dev/fd/<fd> support)
getconf path_var /dev/fd/0 < ~{fd}
Erm... this can't work (and quick testing&&looking at the Solaris and
Linux kernel sources confirms it) because |pathconf()|+|fpathconf()|
is a syscall which is directly forwarded to the matching filesystem
code in the kernel. The syscall passes the path (string for
|pathconf(), fd for |fpathconf()|) to the kernel and then the kernel
looks-up the matching filesystem and then forwards the call to that
filesystem...
Regardless how hard we try the current getconf(1) API won't work for a
given fd, e.g. it can't work using /dev/fd/ because /dev/fd is a
separate filesystem on Solaris and /dev (covering /dev/fd/) on Linux.
The same applies to ~{fd} which expands to /proc/$currpid/fd/$fd and
therefore refers to the proc filesystem instead of the filesystem the
fd is on.
AFAIK the only valid way is to add a --fd option to getconf(1) to deal
with that trouble because at least the Solaris test suite use
/usr/bin/getconf to test the devfs and procfs filesystems... which
means if we implement the AST intercept system to convert a /dev/fd or
/proc/self/fd/ path to a fd internally to call |fpathconf()| we break
such tests... ;-(
can you list the explicit paths used in these tests
Erm... Sun never published the main testsuites for Solaris. Polite
questioning resulted in an awk'ed test run log with the paths
-- snip --
/dev/dtrace
/dev/dtrace/dtrace
/dev/dtrace/helper
/dev/dtrace/provider
/dev/dtrace/provider/dcpc
/dev/dtrace/provider/fasttrap
/dev/dtrace/provider/fbt
/dev/dtrace/provider/lockstat
/dev/dtrace/provider/lx_systrace
/dev/dtrace/provider/profile
/dev/dtrace/provider/sdt
/dev/dtrace/provider/systrace
/dev
/dev/fd
/dev/fd/${boot}/rpool
/
/devices
/dev
/system/contract
/proc
/etc/mnttab
/etc/svc/volatile
/system/object
/etc/dfs/sharetab
/lib/libc.so.1
/dev/fd
/tmp
/var/run
/export
/export/home
/export/home/test001
/rpool
/home/test001
/proc/$p/fd/$root/loopmount
/proc/$p/fd/$root//kernel/
/proc/$p/fd/$root//kernel/ipp
/proc/$p/fd/$root//kernel/ipp/amd64
/proc/$p/fd/$root//kernel/ipp/amd64/ipgpc
/proc/$p/fd/$root//kernel/ipp/ipgpc
/proc/$p/fd/$root//kernel/misc
/proc/$p/fd/$root//kernel/misc/strplumb
/proc/$p/fd/$root//kernel/misc/ibcm
/proc/$p/fd/$root//kernel/misc/drm
/proc/$p/fd/$root//kernel/misc/md_mirror
/proc/$p/fd/$root//kernel/misc/net80211
/proc/$p/fd/$root//kernel/misc/pci_autoconfig
/proc/$p/fd/$root//kernel/misc/kcf
/proc/$p/fd/$root//kernel/misc/usba10
/proc/$p/fd/$root//kernel/misc/pcmcia
/proc/$p/fd/$root//kernel/misc/des
/proc/$p/fd/$root//kernel/misc/iommulib
/proc/$p/fd/$root//kernel/misc/uwba
/proc/$p/fd/$root//kernel/misc/idmap
/proc/$p/fd/$root//kernel/misc/ksocket
/proc/$p/fd/$root//kernel/misc/rpcsec_gss
/proc/$p/fd/$root//kernel/misc/md_trans
/proc/$p/fd/$root//kernel/misc/fctl
/proc/$p/fd/$root//kernel/misc/fssnap_if
/proc/$p/fd/$root//kernel/misc/qlc
/proc/$p/fd/$root//kernel/misc/qlc/qlc_fw_6322
/proc/$p/fd/$root//kernel/misc/qlc/qlc_fw_2200
/proc/$p/fd/$root//kernel/misc/qlc/qlc_fw_2300
/proc/$p/fd/$root//kernel/misc/qlc/qlc_fw_8100
/proc/$p/fd/$root//kernel/misc/qlc/qlc_fw_2400
/proc/$p/fd/$root//kernel/misc/qlc/qlc_fw_2500
/proc/$p/fd/$root//kernel/misc/qlc/amd64
/proc/$p/fd/$root//kernel/misc/qlc/amd64/qlc_fw_2400
/proc/$p/fd/$root//kernel/misc/qlc/amd64/qlc_fw_8100
/proc/$p/fd/$root//kernel/misc/qlc/amd64/qlc_fw_2500
/proc/$p/fd/$root//kernel/misc/qlc/amd64/qlc_fw_2200
/proc/$p/fd/$root//kernel/misc/qlc/amd64/qlc_fw_6322
/proc/$p/fd/$root//kernel/misc/qlc/amd64/qlc_fw_2300
/proc/$p/fd/$root//kernel/misc/s1394
/proc/$p/fd/$root//kernel/misc/ibdm
/proc/$p/fd/$root//kernel/misc/acpica
/proc/$p/fd/$root//kernel/misc/emlxs
/proc/$p/fd/$root//kernel/misc/emlxs/amd64
/proc/$p/fd/$root//kernel/misc/emlxs/amd64/emlxs_fw
/proc/$p/fd/$root//kernel/misc/emlxs/emlxs_fw
/proc/$p/fd/$root//kernel/misc/agpmaster
/proc/$p/fd/$root//kernel/misc/sata
/proc/$p/fd/$root//kernel/misc/usbser
/proc/$p/fd/$root//kernel/misc/pcihp
/proc/$p/fd/$root//kernel/misc/scsi_vhci
/proc/$p/fd/$root//kernel/misc/scsi_vhci/scsi_vhci_f_sym_emc
/proc/$p/fd/$root//kernel/misc/scsi_vhci/scsi_vhci_f_sym
/proc/$p/fd/$root//kernel/misc/scsi_vhci/scsi_vhci_f_tpgs
/proc/$p/fd/$root//kernel/misc/scsi_vhci/scsi_vhci_f_tape
/proc/$p/fd/$root//kernel/misc/scsi_vhci/scsi_vhci_f_asym_lsi
/proc/$p/fd/$root//kernel/misc/scsi_vhci/scsi_vhci_f_asym_emc
/proc/$p/fd/$root//kernel/misc/scsi_vhci/scsi_vhci_f_tpgs_tape
/proc/$p/fd/$root//kernel/misc/scsi_vhci/amd64
/proc/$p/fd/$root//kernel/misc/scsi_vhci/amd64/scsi_vhci_f_sym
/proc/$p/fd/$root//kernel/misc/scsi_vhci/amd64/scsi_vhci_f_tpgs_tape
/proc/$p/fd/$root//kernel/misc/scsi_vhci/amd64/scsi_vhci_f_sym_emc
/proc/$p/fd/$root//kernel/misc/scsi_vhci/amd64/scsi_vhci_f_tpgs
/proc/$p/fd/$root//kernel/misc/scsi_vhci/amd64/scsi_vhci_f_tape
/proc/$p/fd/$root//kernel/misc/scsi_vhci/amd64/scsi_vhci_f_sym_hds
/proc/$p/fd/$root//kernel/misc/scsi_vhci/amd64/scsi_vhci_f_asym_sun
/proc/$p/fd/$root//kernel/misc/scsi_vhci/amd64/scsi_vhci_f_asym_lsi
/proc/$p/fd/$root//kernel/misc/scsi_vhci/amd64/scsi_vhci_f_asym_emc
/proc/$p/fd/$root//kernel/misc/scsi_vhci/scsi_vhci_f_sym_hds
/proc/$p/fd/$root//kernel/misc/scsi_vhci/scsi_vhci_f_asym_sun
/proc/$p/fd/$root//kernel/misc/dls
/proc/$p/fd/$root//kernel/misc/gld
/proc/$p/fd/$root//kernel/misc/md_stripe
/proc/$p/fd/$root//kernel/misc/kmdbmod
/proc/$p/fd/$root//kernel/misc/ctf
/proc/$p/fd/$root//kernel/misc/bignum
/proc/$p/fd/$root//kernel/misc/pmcs
/proc/$p/fd/$root//kernel/misc/pmcs/amd64
/proc/$p/fd/$root//kernel/misc/pmcs/amd64/pmcs8001fw
/proc/$p/fd/$root//kernel/misc/pmcs/pmcs8001fw
/proc/$p/fd/$root//kernel/misc/tlimod
/proc/$p/fd/$root//kernel/misc/cardbus
/proc/$p/fd/$root//kernel/misc/amd64
/proc/$p/fd/$root//kernel/misc/amd64/strplumb
/proc/$p/fd/$root//kernel/misc/amd64/ipc
/proc/$p/fd/$root//kernel/misc/amd64/uathfw
/proc/$p/fd/$root//kernel/misc/amd64/net80211
/proc/$p/fd/$root//kernel/misc/amd64/sata
/proc/$p/fd/$root//kernel/misc/amd64/hidparser
/proc/$p/fd/$root//kernel/misc/amd64/ctf
/proc/$p/fd/$root//kernel/misc/amd64/iommulib
/proc/$p/fd/$root//kernel/misc/amd64/idmap
-- snip --
There are also automounter tests which do testing for /net, where
/net/<IP-address>/remote-path can automagically mount NFS filesystems
as plain user.
Post by Glenn Fowler
I can see
/dev/fd
/proc/self/fd
referring to the specific filesystem
but why would
/dev/fd/${fd}/foo
/proc/self/fd/${fd}/foo
stop at the fs and not resolve through ${fd} to foo
or why whould these stop at the fs and not the ${fd}
/dev/fd/${fd}/foo
/proc/self/fd/${fd}/foo
is this just an incomplete implementation of /dev/fd and /proc/${pid}/fd?
... some of the pathconf _PC_* values probe the file system itself.
Using a file descriptor through /dev/fd or /proc/self/fd/$fd MUST -
required by POSIX - always test the file system specified - which is
either devfs or procfs. Link redirects, including soft- and hard links
and NTFS/CIFS/NFSv4 reparse points, do not apply here, with the
exception of lofs, which is a real filesystem but may pass some
pathconf/fpathconf requests through to the parent file system ...
-- snip --
That's the more or less official Sun judgment.
BTW: lofs is the loopback filesystem... it works similar to a softlink
but can be mounted and then looks&&acts like a real filesystem. This
is used by the automounter to maintain /home in Solaris, e.g. if you
to to /home/foo the automounter will look at /etc/auto_home and
figures it the real location of that home directory (for example
/export/home/foo) and then mounts lofs as /home/foo which redirects
requests to /export/home/foo.
So we're basically in trouble if we only have a fd and want to do
pathconf with that through getconf(1). The issue is actually known and
the Solaris bug db has a bug entry for that trouble. The proposed
solution is... erm... "... add -f <fd> to pass a file descriptor to
fpathconf()..."
thanks
Roland Mainz
2013-09-28 13:29:36 UTC
Permalink
[snip]
Post by Roland Mainz
Post by Roland Mainz
... on the bright side... adding |fpathconf()| support looks quite
easy to implement... if Glenn agrees I can make the patch for that
tonight...
Erm... ping!
Can I craft the patch for this one, please ?
Erm... should I make the patch - [yes]/[no]/[chicken] ? :-)

----

Bye,
Roland
--
__ . . __
(o.\ \/ /.o) roland.mainz at nrubsig.org
\__\/\/__/ MPEG specialist, C&&JAVA&&Sun&&Unix programmer
/O /==\ O\ TEL +49 641 3992797
(;O/ \/ \O;)
Glenn Fowler
2013-09-28 23:34:46 UTC
Permalink
Post by Lionel Cons
[snip]
Post by Roland Mainz
Post by Roland Mainz
... on the bright side... adding |fpathconf()| support looks quite
easy to implement... if Glenn agrees I can make the patch for that
tonight...
Erm... ping!
Can I craft the patch for this one, please ?
Erm... should I make the patch - [yes]/[no]/[chicken] ? :-)
go for it
Post by Lionel Cons
----
Bye,
Roland
--
__ . . __
(o.\ \/ /.o) roland.mainz at nrubsig.org
\__\/\/__/ MPEG specialist, C&&JAVA&&Sun&&Unix programmer
/O /==\ O\ TEL +49 641 3992797
(;O/ \/ \O;)
Roland Mainz
2013-09-30 12:48:28 UTC
Permalink
Post by Glenn Fowler
Post by Lionel Cons
[snip]
Post by Roland Mainz
Post by Roland Mainz
... on the bright side... adding |fpathconf()| support looks quite
easy to implement... if Glenn agrees I can make the patch for that
tonight...
Erm... ping!
Can I craft the patch for this one, please ?
Erm... should I make the patch - [yes]/[no]/[chicken] ? :-)
go for it
_Thanks_! ... :-)

Attached (as "astksh20130926_getconf_f_001.diff.txt") is a _prototype_
patch to add a -f $fd option to getconf(1) ...

* Notes:
- this is a prototype... it requires more testing and minor other changes
- still need to hook-up the usual AST versioning system to make sure
we don't hit any symbol collisions
- Need to do build tests with ast-open
- During development we hit a bug that Linux's |fstatfs()| - used by
|fpathconf()| - does not like |O_PATH|. Olga notified Linus himself to
have a look at this issue. The patch contains a workaround. Note that
the workaround is only used if both -f $fd and a _relative_ path are
given, the issue does not affect anything which uses an absolute path.

Erm... Glenn.. any feedback/rants/comments for the patch ?

----

Bye,
Roland
--
__ . . __
(o.\ \/ /.o) roland.mainz at nrubsig.org
\__\/\/__/ MPEG specialist, C&&JAVA&&Sun&&Unix programmer
/O /==\ O\ TEL +49 641 3992797
(;O/ \/ \O;)
-------------- next part --------------
diff -r -u original/src/lib/libast/include/ast.h build_fgetconf/src/lib/libast/include/ast.h
--- src/lib/libast/include/ast.h 2013-09-18 21:53:42.000000000 +0200
+++ src/lib/libast/include/ast.h 2013-09-30 12:55:57.074998985 +0200
@@ -275,10 +275,10 @@
#define extern __EXPORT__
#endif

-extern char* astgetconf(const char*, const char*, const char*, int, Error_f);
+extern char* astgetconf(const char*, int, const char*, const char*, int, Error_f);
extern char* astconf(const char*, const char*, const char*);
extern Ast_confdisc_f astconfdisc(Ast_confdisc_f);
-extern void astconflist(Sfio_t*, const char*, int, const char*);
+extern void astconflist(Sfio_t*, int, const char*, int, const char*);
extern off_t astcopy(int, int, off_t);
extern int astlicense(char*, int, char*, char*, int, int, int);
extern int astquery(int, const char*, ...);
diff -r -u original/src/lib/libast/port/astconf.c build_fgetconf/src/lib/libast/port/astconf.c
--- src/lib/libast/port/astconf.c 2013-08-20 18:55:15.000000000 +0200
+++ src/lib/libast/port/astconf.c 2013-09-30 13:51:22.292943470 +0200
@@ -22,11 +22,11 @@
#pragma prototyped

/*
- * string interface to confstr(),pathconf(),sysconf(),sysinfo()
+ * string interface to confstr(),pathconf(),fpathconf(),sysconf(),sysinfo()
* extended to allow some features to be set per-process
*/

-static const char id[] = "\n@(#)$Id: getconf (AT&T Research) 2012-05-01 $\0\n";
+static const char id[] = "\n@(#)$Id: getconf (AT&T Research) 2013-09-30 $\0\n";

#include "univlib.h"

@@ -76,7 +76,7 @@
#define CONF_GLOBAL (CONF_USER<<3)

#define DEFAULT(o) ((state.std||!dynamic[o].ast)?dynamic[o].std:dynamic[o].ast)
-#define INITIALIZE() do{if(!state.data)synthesize(NiL,NiL,NiL);}while(0)
+#define INITIALIZE() do{if(!state.data)synthesize(NiL,-1,NiL,NiL);}while(0)
#define STANDARD(v) (streq(v,"standard")||streq(v,"strict")||streq(v,"posix")||streq(v,"xopen"))

#define MAXVAL 256
@@ -302,7 +302,7 @@

static State_t state = { "getconf", "_AST_FEATURES", "CONFORMANCE = standard", "POSIXLY_CORRECT", dynamic, -1 };

-static char* feature(Feature_t*, const char*, const char*, const char*, unsigned int, Error_f);
+static char* feature(Feature_t*, const char*, int, const char*, const char*, unsigned int, Error_f);

/*
* return fmtbuf() copy of s
@@ -322,7 +322,7 @@
*/

static char*
-synthesize(register Feature_t* fp, const char* path, const char* value)
+synthesize(register Feature_t* fp, int fd, const char* path, const char* value)
{
register char* s;
register char* d;
@@ -332,7 +332,7 @@

#if DEBUG_astconf
if (fp)
- error(-6, "astconf synthesize name=%s path=%s value=%s fp=%p%s", fp->name, path, value, fp, state.synthesizing ? " SYNTHESIZING" : "");
+ error(-6, "astconf synthesize name=%s fd=%d path=%s value=%s fp=%p%s", fp->name, fd, path, value, fp, state.synthesizing ? " SYNTHESIZING" : "");
#endif
if (state.synthesizing)
{
@@ -380,7 +380,7 @@
ve = 0;
*de = 0;
*se = 0;
- feature(0, s, d, v, 0, 0);
+ feature(0, s, fd, d, v, 0, 0);
*se = ' ';
*de = ' ';
if (!ve)
@@ -501,18 +501,18 @@
/*
* initialize the value for fp
* if command!=0 then it is checked for on $PATH
- * synthesize(fp,path,succeed) called on success
+ * synthesize(fp,fd,path,succeed) called on success
* otherwise synthesize(fp,path,fail) called
*/

static void
-initialize(register Feature_t* fp, const char* path, const char* command, const char* succeed, const char* fail)
+initialize(register Feature_t* fp, int fd, const char* path, const char* command, const char* succeed, const char* fail)
{
register char* p;
register int ok = 1;

#if DEBUG_astconf
- error(-6, "astconf initialize name=%s path=%s command=%s succeed=%s fail=%s fp=%p%s", fp->name, path, command, succeed, fail, fp, state.synthesizing ? " SYNTHESIZING" : "");
+ error(-6, "astconf initialize name=%s fd=%d path=%s command=%s succeed=%s fail=%s fp=%p%s", fp->name, fd, path, command, succeed, fail, fp, state.synthesizing ? " SYNTHESIZING" : "");
#endif
switch (fp->op)
{
@@ -617,7 +617,7 @@
#if DEBUG_astconf
error(-6, "state.std=%d %s [%s] std=%s ast=%s value=%s ok=%d", state.std, fp->name, ok ? succeed : fail, fp->std, fp->ast, fp->value, ok);
#endif
- synthesize(fp, path, ok ? succeed : fail);
+ synthesize(fp, fd, path, ok ? succeed : fail);
}

/*
@@ -625,7 +625,7 @@
*/

static char*
-format(register Feature_t* fp, const char* path, const char* value, unsigned int flags, Error_f conferror)
+format(register Feature_t* fp, int fd, const char* path, const char* value, unsigned int flags, Error_f conferror)
{
register Feature_t* sp;
register int n;
@@ -682,8 +682,8 @@
#endif
if (state.synthesizing && value == (char*)fp->std)
fp->value = (char*)value;
- else if (!synthesize(fp, path, value))
- initialize(fp, path, NiL, fp->std, fp->value);
+ else if (!synthesize(fp, fd, path, value))
+ initialize(fp, fd, path, NiL, fp->std, fp->value);
#if DEBUG_astconf
error(-6, "state.std=%d %s [%s] std=%s ast=%s value=%s", state.std, fp->name, value, fp->std, fp->ast, fp->value);
#endif
@@ -692,7 +692,7 @@
state.std = 1;
for (sp = state.features; sp; sp = sp->next)
if (sp->std && sp->op && sp->op != OP_conformance)
- feature(sp, 0, path, sp->std, 0, 0);
+ feature(sp, 0, fd, path, sp->std, 0, 0);
}
#if DEBUG_astconf
error(-6, "state.std=%d %s [%s] std=%s ast=%s value=%s", state.std, fp->name, value, fp->std, fp->ast, fp->value);
@@ -717,7 +717,11 @@
* _PC_PATH_ATTRIBUTES is a bitmap for 'a' to 'z'
*/

- if ((v = pathconf(path, _PC_PATH_ATTRIBUTES)) == -1L)
+ if (fd != -1)
+ v = fpathconf(fd, _PC_PATH_ATTRIBUTES);
+ else
+ v = pathconf(path, _PC_PATH_ATTRIBUTES);
+ if (v) == -1L)
return 0;
s = fp->value;
e = s + sizeof(fp->value) - 1;
@@ -736,8 +740,8 @@
case OP_path_resolve:
if (state.synthesizing && value == (char*)fp->std)
fp->value = (char*)value;
- else if (!synthesize(fp, path, value))
- initialize(fp, path, NiL, "logical", DEFAULT(OP_path_resolve));
+ else if (!synthesize(fp, fd, path, value))
+ initialize(fp, fd, path, NiL, "logical", DEFAULT(OP_path_resolve));
break;

case OP_universe:
@@ -788,10 +792,10 @@
}
}
else
- synthesize(fp, path, value);
+ synthesize(fp, fd, path, value);
}
else
- initialize(fp, path, "echo", DEFAULT(OP_universe), "ucb");
+ initialize(fp, fd, path, "echo", DEFAULT(OP_universe), "ucb");
#endif
#endif
break;
@@ -800,7 +804,7 @@
if (state.synthesizing && value == (char*)fp->std)
fp->value = (char*)value;
else
- synthesize(fp, path, value);
+ synthesize(fp, fd, path, value);
break;

}
@@ -816,7 +820,7 @@
*/

static char*
-feature(register Feature_t* fp, const char* name, const char* path, const char* value, unsigned int flags, Error_f conferror)
+feature(register Feature_t* fp, const char* name, int fd, const char* path, const char* value, unsigned int flags, Error_f conferror)
{
register int n;

@@ -861,7 +865,7 @@
}
else
state.recent = fp;
- return format(fp, path, value, flags, conferror);
+ return format(fp, fd, path, value, flags, conferror);
}

/*
@@ -1006,7 +1010,7 @@
*/

static char*
-print(Sfio_t* sp, register Lookup_t* look, const char* name, const char* path, int listflags, Error_f conferror)
+print(Sfio_t* sp, register Lookup_t* look, const char* name, int fd, const char* path, int listflags, Error_f conferror)
{
register Conf_t* p = look->conf;
register unsigned int flags = look->flags;
@@ -1058,14 +1062,14 @@
switch (p->call)
{
case CONF_pathconf:
- if (path == root)
+ if ((path == root) && (fd == -1))
{
(*conferror)(&state, &state, 2, "%s: path expected", name);
goto bad;
}
break;
default:
- if (path != root)
+ if ((path != root) || (fd != -1))
{
(*conferror)(&state, &state, 2, "%s: path not expected", name);
goto bad;
@@ -1119,7 +1123,11 @@
case CONF_pathconf:
call = "pathconf";
#if _lib_pathconf
- if ((v = pathconf(path, p->op)) < 0)
+ if (fd != -1)
+ v = fpathconf(fd, p->op);
+ else
+ v = pathconf(path, p->op);
+ if (v < 0)
defined = 0;
break;
#else
@@ -1369,7 +1377,7 @@
if (!(listflags & ~(ASTCONF_error|ASTCONF_system)))
for (fp = state.features; fp; fp = fp->next)
if (streq(name, fp->name))
- return format(fp, path, 0, listflags, conferror);
+ return format(fp, fd, path, 0, listflags, conferror);
return (listflags & ASTCONF_error) ? (char*)0 : null;
}

@@ -1414,10 +1422,10 @@
* settable return values are in permanent store
* non-settable return values copied to a tmp fmtbuf() buffer
*
- * if (streq(astgetconf("PATH_RESOLVE", NiL, NiL, 0, 0), "logical"))
+ * if (streq(astgetconf("PATH_RESOLVE", -1, NiL, NiL, 0, 0), "logical"))
* our_way();
*
- * universe = astgetconf("UNIVERSE", NiL, "att", 0, 0);
+ * universe = astgetconf("UNIVERSE", -1, NiL, "att", 0, 0);
* astgetconf("UNIVERSE", NiL, universe, 0, 0);
*
* if (flags&ASTCONF_error)!=0 then error return value is 0
@@ -1427,7 +1435,7 @@
#define ALT 16

char*
-astgetconf(const char* name, const char* path, const char* value, int flags, Error_f conferror)
+astgetconf(const char* name, int fd, const char* path, const char* value, int flags, Error_f conferror)
{
register char* s;
int n;
@@ -1445,7 +1453,7 @@
#endif
if (!name)
{
- if (path)
+ if (path || (fd != -1))
return null;
if (!(name = value))
{
@@ -1467,9 +1475,9 @@
value = 0;
}
INITIALIZE();
- if (!path)
+ if (!path && (fd == -1))
path = root;
- if (state.recent && streq(name, state.recent->name) && (s = format(state.recent, path, value, flags, conferror)))
+ if (state.recent && streq(name, state.recent->name) && (s = format(state.recent, fd, path, value, flags, conferror)))
return s;
if (lookup(&look, name, flags))
{
@@ -1481,7 +1489,7 @@
(*conferror)(&state, &state, 2, "%s: cannot set value", name);
return (flags & ASTCONF_error) ? (char*)0 : null;
}
- return print(NiL, &look, name, path, flags, conferror);
+ return print(NiL, &look, name, fd, path, flags, conferror);
}
if ((n = strlen(name)) > 3 && n < (ALT + 3))
{
@@ -1521,7 +1529,7 @@
(*conferror)(&state, &state, 2, "%s: cannot set value", altname);
return (flags & ASTCONF_error) ? (char*)0 : null;
}
- return print(NiL, &altlook, altname, path, flags, conferror);
+ return print(NiL, &altlook, altname, fd, path, flags, conferror);
}
for (s = altname; *s; s++)
if (isupper(*s))
@@ -1544,7 +1552,7 @@
}
}
}
- if ((look.standard < 0 || look.standard == CONF_AST) && look.call <= 0 && look.section <= 1 && (s = feature(0, look.name, path, value, flags, conferror)))
+ if ((look.standard < 0 || look.standard == CONF_AST) && look.call <= 0 && look.section <= 1 && (s = feature(0, look.name, fd, path, value, flags, conferror)))
return s;
errno = EINVAL;
if (conferror && !(flags & ASTCONF_system))
@@ -1562,11 +1570,11 @@
#if DEBUG_astconf
char* r;

- r = astgetconf(name, path, value, 0, 0);
+ r = astgetconf(name, -1, path, value, 0, 0);
error(-1, "astconf(%s,%s,%s) => '%s'", name, path, value, r);
return r;
#else
- return astgetconf(name, path, value, 0, 0);
+ return astgetconf(name, -1, path, value, 0, 0);
#endif
}

@@ -1592,7 +1600,7 @@
*/

void
-astconflist(Sfio_t* sp, const char* path, int flags, const char* pattern)
+astconflist(Sfio_t* sp, int fd, const char* path, int flags, const char* pattern)
{
char* s;
char* f;
@@ -1609,7 +1617,21 @@
#endif

INITIALIZE();
- if (!path)
+
+ if((path != NULL) && (fd != -1))
+ {
+ /*
+ * |fd| and |path| arguments are currently mutually exclusive.
+ * If we ever allow this then we should create an |ASTCONF_open|
+ * flag to explicitly use |openat(fd, path, ...)| to open the
+ * file requested. On the other hand it may be better to let
+ * the caller handle this detail
+ */
+ errorf(&state, &state, 2, "Cannot pass both fd and path");
+ return;
+ }
+
+ if (!path || (fd != -1))
path = root;
else if (access(path, F_OK))
{
@@ -1657,7 +1679,7 @@
}
look.standard = look.conf->standard;
look.section = look.conf->section;
- print(sp, &look, NiL, path, flags, errorf);
+ print(sp, &look, NiL, -1, path, flags, errorf);
}
#ifdef _pth_getconf_a
if (pp = nativeconf(&proc, _pth_getconf_a))
@@ -1712,7 +1734,7 @@
continue;
}
}
- if (!(s = feature(fp, 0, path, NiL, 0, 0)) || !*s)
+ if (!(s = feature(fp, 0, fd, path, NiL, 0, 0)) || !*s)
s = "0";
if (flags & ASTCONF_table)
{
diff -r -u original/src/lib/libcmd/getconf.c build_fgetconf/src/lib/libcmd/getconf.c
--- src/lib/libcmd/getconf.c 2012-06-26 00:45:10.000000000 +0200
+++ src/lib/libcmd/getconf.c 2013-09-30 14:33:16.645535121 +0200
@@ -27,7 +27,7 @@
*/

static const char usage[] =
-"[-?\n@(#)$Id: getconf (AT&T Research) 2012-06-25 $\n]"
+"[-?\n@(#)$Id: getconf (AT&T Research) 2013-09-30 $\n]"
USAGE_LICENSE
"[+NAME?getconf - get configuration values]"
"[+DESCRIPTION?\bgetconf\b displays the system configuration value for"
@@ -52,8 +52,9 @@
" \aname\a=\avalue\a form to the standard output, one per line."
" Only one of \b--call\b, \b--name\b or \b--standard\b may be specified.]"
"[+?This implementation uses the \bastgetconf\b(3) string interface to the native"
-" \bsysconf\b(2), \bconfstr\b(2), \bpathconf\b(2), and \bsysinfo\b(2)"
-" system calls. If \bgetconf\b on \b$PATH\b is not the default native"
+" \bsysconf\b(2), \bconfstr\b(2), \bpathconf\b(2), \bfpathconf\b(2), "
+" and \bsysinfo\b(2) system calls. "
+" If \bgetconf\b on \b$PATH\b is not the default native"
" \bgetconf\b, named by \b$(getconf GETCONF)\b, then \bastgetconf\b(3)"
" checks only \bast\b specific extensions and the native system calls;"
" invalid options and/or names not supported by \bastgetconf\b(3) cause"
@@ -65,11 +66,13 @@
" prefixes are:]:[RE]{"
" [+CS?\bconfstr\b(2)]"
" [+PC?\bpathconf\b(2)]"
+" [+PC?\bfpathconf\b(2)]"
" [+SC?\bsysconf\b(2)]"
" [+SI?\bsysinfo\b(2)]"
" [+XX?Constant value.]"
"}"
"[d:defined?Only display defined values when no operands are specified.]"
+"[f?Use \bfd\b instead of a file name.]#[fd]"
"[l:lowercase?List variable names in lower case.]"
"[n:name?Display variables with name that match \aRE\a.]:[RE]"
"[p:portable?Display the named \bwritable\b variables and values in a form that"
@@ -116,7 +119,7 @@
"is an implementation detail of process inheritance; it may "
"change or vanish in the future; don't rely on it.]"
"}"
-"[+SEE ALSO?\bpathchk\b(1), \bconfstr\b(2), \bpathconf\b(2),"
+"[+SEE ALSO?\bpathchk\b(1), \bconfstr\b(2), \bpathconf\b(2), \bfpathconf\b(2),"
" \bsysconf\b(2), \bastgetconf\b(3)]"
;

@@ -133,6 +136,7 @@
int
b_getconf(int argc, char** argv, Shbltin_t* context)
{
+ register int fd = -1;
register char* name;
register char* path;
register char* value;
@@ -182,6 +186,9 @@
case 'd':
flags |= ASTCONF_defined;
continue;
+ case 'f':
+ fd = opt_info.num;
+ continue;
case 'l':
flags |= ASTCONF_lower;
continue;
@@ -236,17 +243,19 @@
path = 0;
}
}
- if (error_info.errors || !name && *argv)
+ if (error_info.errors || !name && (fd == -1) && *argv)
error(ERROR_usage(2), "%s", optusage(NiL));
if (!name)
- astconflist(sfstdout, path, flags, pattern);
+ astconflist(sfstdout, fd, path, flags, pattern);
else
{
if (native)
flags |= (ASTCONF_system|ASTCONF_error);
do
{
- if (!(path = *++argv))
+ int pfd = -1; /* |fpathconf()| file descriptor */
+
+ if (!(path = *++argv) || (fd != -1))
value = 0;
else
{
@@ -261,7 +270,33 @@
flags = 0;
}
}
- s = astgetconf(name, path, value, flags, errorf);
+ if (path && (path[0] != '/') && (path[0] != '\0'))
+ {
+#ifdef O_PATH
+ /*
+ * Note that we have to try with |O_RDONLY| first for now since
+ * Linux's |fstatfs()| (used by glibc |fpathconf()|) currently
+ * does not like |O_PATH| (we alias |O_SEARCH| to |O_PATH| if
+ * |O_SEARCH| is not natively available) and returns a |EBADF|.
+ * This workaround limits the damage until Linus fixes |fstatfs()|.
+ */
+ pfd = openat((fd != -1)?fd:(context?context->pwdfd:AT_FDCWD), path, O_RDONLY);
+ if (pfd == -1)
+#endif /* O_PATH */
+ {
+ pfd = openat((fd != -1)?fd:(context?context->pwdfd:AT_FDCWD), path, O_SEARCH);
+ }
+ if (pfd == -1)
+ {
+ error(ERROR_SYSTEM|2, "Cannot open %s", path);
+ break;
+ }
+ }
+ s = astgetconf(name, (pfd >= 0)?pfd:fd, path, value, flags, errorf);
+ if (pfd >= 0)
+ {
+ close(pfd);
+ }
if (error_info.errors)
break;
if (!s)
diff -r -u original/src/lib/libcmd/uname.c build_fgetconf/src/lib/libcmd/uname.c
--- src/lib/libcmd/uname.c 2012-01-10 19:57:03.000000000 +0100
+++ src/lib/libcmd/uname.c 2013-09-30 12:51:48.222260396 +0200
@@ -356,7 +356,7 @@
error(ERROR_system(1), "%s: cannot set host name", sethost);
}
else if (list)
- astconflist(sfstdout, NiL, ASTCONF_base|ASTCONF_defined|ASTCONF_lower|ASTCONF_quote|ASTCONF_matchcall, "CS|SI");
+ astconflist(sfstdout, -1, NiL, ASTCONF_base|ASTCONF_defined|ASTCONF_lower|ASTCONF_quote|ASTCONF_matchcall, "CS|SI");
else if (*argv)
{
e = &buf[sizeof(buf)-1];
ольга крыжановская
2013-10-12 22:26:26 UTC
Permalink
Glenn, David, the patch is missing in ast-ksh.2013-10-10. Could you
have a look at this issue please?

Olga
Post by Roland Mainz
Post by Glenn Fowler
Post by Lionel Cons
[snip]
Post by Roland Mainz
Post by Roland Mainz
... on the bright side... adding |fpathconf()| support looks quite
easy to implement... if Glenn agrees I can make the patch for that
tonight...
Erm... ping!
Can I craft the patch for this one, please ?
Erm... should I make the patch - [yes]/[no]/[chicken] ? :-)
go for it
_Thanks_! ... :-)
Attached (as "astksh20130926_getconf_f_001.diff.txt") is a _prototype_
patch to add a -f $fd option to getconf(1) ...
- this is a prototype... it requires more testing and minor other changes
- still need to hook-up the usual AST versioning system to make sure
we don't hit any symbol collisions
- Need to do build tests with ast-open
- During development we hit a bug that Linux's |fstatfs()| - used by
|fpathconf()| - does not like |O_PATH|. Olga notified Linus himself to
have a look at this issue. The patch contains a workaround. Note that
the workaround is only used if both -f $fd and a _relative_ path are
given, the issue does not affect anything which uses an absolute path.
Erm... Glenn.. any feedback/rants/comments for the patch ?
----
Bye,
Roland
--
__ . . __
(o.\ \/ /.o) roland.mainz at nrubsig.org
\__\/\/__/ MPEG specialist, C&&JAVA&&Sun&&Unix programmer
/O /==\ O\ TEL +49 641 3992797
(;O/ \/ \O;)
--
, _ _ ,
{ \/`o;====- Olga Kryzhanovska -====;o`\/ }
.----'-/`-/ olga.kryzhanovska at gmail.com \-`\-'----.
`'-..-| / http://twitter.com/fleyta \ |-..-'`
/\/\ Solaris/BSD//C/C++ programmer /\/\
`--` `--`
-------------- next part --------------
diff -r -u original/src/lib/libast/include/ast.h build_fgetconf/src/lib/libast/include/ast.h
--- src/lib/libast/include/ast.h 2013-09-18 21:53:42.000000000 +0200
+++ src/lib/libast/include/ast.h 2013-09-30 12:55:57.074998985 +0200
@@ -275,10 +275,10 @@
#define extern __EXPORT__
#endif

-extern char* astgetconf(const char*, const char*, const char*, int, Error_f);
+extern char* astgetconf(const char*, int, const char*, const char*, int, Error_f);
extern char* astconf(const char*, const char*, const char*);
extern Ast_confdisc_f astconfdisc(Ast_confdisc_f);
-extern void astconflist(Sfio_t*, const char*, int, const char*);
+extern void astconflist(Sfio_t*, int, const char*, int, const char*);
extern off_t astcopy(int, int, off_t);
extern int astlicense(char*, int, char*, char*, int, int, int);
extern int astquery(int, const char*, ...);
diff -r -u original/src/lib/libast/port/astconf.c build_fgetconf/src/lib/libast/port/astconf.c
--- src/lib/libast/port/astconf.c 2013-08-20 18:55:15.000000000 +0200
+++ src/lib/libast/port/astconf.c 2013-09-30 13:51:22.292943470 +0200
@@ -22,11 +22,11 @@
#pragma prototyped

/*
- * string interface to confstr(),pathconf(),sysconf(),sysinfo()
+ * string interface to confstr(),pathconf(),fpathconf(),sysconf(),sysinfo()
* extended to allow some features to be set per-process
*/

-static const char id[] = "\n@(#)$Id: getconf (AT&T Research) 2012-05-01 $\0\n";
+static const char id[] = "\n@(#)$Id: getconf (AT&T Research) 2013-09-30 $\0\n";

#include "univlib.h"

@@ -76,7 +76,7 @@
#define CONF_GLOBAL (CONF_USER<<3)

#define DEFAULT(o) ((state.std||!dynamic[o].ast)?dynamic[o].std:dynamic[o].ast)
-#define INITIALIZE() do{if(!state.data)synthesize(NiL,NiL,NiL);}while(0)
+#define INITIALIZE() do{if(!state.data)synthesize(NiL,-1,NiL,NiL);}while(0)
#define STANDARD(v) (streq(v,"standard")||streq(v,"strict")||streq(v,"posix")||streq(v,"xopen"))

#define MAXVAL 256
@@ -302,7 +302,7 @@

static State_t state = { "getconf", "_AST_FEATURES", "CONFORMANCE = standard", "POSIXLY_CORRECT", dynamic, -1 };

-static char* feature(Feature_t*, const char*, const char*, const char*, unsigned int, Error_f);
+static char* feature(Feature_t*, const char*, int, const char*, const char*, unsigned int, Error_f);

/*
* return fmtbuf() copy of s
@@ -322,7 +322,7 @@
*/

static char*
-synthesize(register Feature_t* fp, const char* path, const char* value)
+synthesize(register Feature_t* fp, int fd, const char* path, const char* value)
{
register char* s;
register char* d;
@@ -332,7 +332,7 @@

#if DEBUG_astconf
if (fp)
- error(-6, "astconf synthesize name=%s path=%s value=%s fp=%p%s", fp->name, path, value, fp, state.synthesizing ? " SYNTHESIZING" : "");
+ error(-6, "astconf synthesize name=%s fd=%d path=%s value=%s fp=%p%s", fp->name, fd, path, value, fp, state.synthesizing ? " SYNTHESIZING" : "");
#endif
if (state.synthesizing)
{
@@ -380,7 +380,7 @@
ve = 0;
*de = 0;
*se = 0;
- feature(0, s, d, v, 0, 0);
+ feature(0, s, fd, d, v, 0, 0);
*se = ' ';
*de = ' ';
if (!ve)
@@ -501,18 +501,18 @@
/*
* initialize the value for fp
* if command!=0 then it is checked for on $PATH
- * synthesize(fp,path,succeed) called on success
+ * synthesize(fp,fd,path,succeed) called on success
* otherwise synthesize(fp,path,fail) called
*/

static void
-initialize(register Feature_t* fp, const char* path, const char* command, const char* succeed, const char* fail)
+initialize(register Feature_t* fp, int fd, const char* path, const char* command, const char* succeed, const char* fail)
{
register char* p;
register int ok = 1;

#if DEBUG_astconf
- error(-6, "astconf initialize name=%s path=%s command=%s succeed=%s fail=%s fp=%p%s", fp->name, path, command, succeed, fail, fp, state.synthesizing ? " SYNTHESIZING" : "");
+ error(-6, "astconf initialize name=%s fd=%d path=%s command=%s succeed=%s fail=%s fp=%p%s", fp->name, fd, path, command, succeed, fail, fp, state.synthesizing ? " SYNTHESIZING" : "");
#endif
switch (fp->op)
{
@@ -617,7 +617,7 @@
#if DEBUG_astconf
error(-6, "state.std=%d %s [%s] std=%s ast=%s value=%s ok=%d", state.std, fp->name, ok ? succeed : fail, fp->std, fp->ast, fp->value, ok);
#endif
- synthesize(fp, path, ok ? succeed : fail);
+ synthesize(fp, fd, path, ok ? succeed : fail);
}

/*
@@ -625,7 +625,7 @@
*/

static char*
-format(register Feature_t* fp, const char* path, const char* value, unsigned int flags, Error_f conferror)
+format(register Feature_t* fp, int fd, const char* path, const char* value, unsigned int flags, Error_f conferror)
{
register Feature_t* sp;
register int n;
@@ -682,8 +682,8 @@
#endif
if (state.synthesizing && value == (char*)fp->std)
fp->value = (char*)value;
- else if (!synthesize(fp, path, value))
- initialize(fp, path, NiL, fp->std, fp->value);
+ else if (!synthesize(fp, fd, path, value))
+ initialize(fp, fd, path, NiL, fp->std, fp->value);
#if DEBUG_astconf
error(-6, "state.std=%d %s [%s] std=%s ast=%s value=%s", state.std, fp->name, value, fp->std, fp->ast, fp->value);
#endif
@@ -692,7 +692,7 @@
state.std = 1;
for (sp = state.features; sp; sp = sp->next)
if (sp->std && sp->op && sp->op != OP_conformance)
- feature(sp, 0, path, sp->std, 0, 0);
+ feature(sp, 0, fd, path, sp->std, 0, 0);
}
#if DEBUG_astconf
error(-6, "state.std=%d %s [%s] std=%s ast=%s value=%s", state.std, fp->name, value, fp->std, fp->ast, fp->value);
@@ -717,7 +717,11 @@
* _PC_PATH_ATTRIBUTES is a bitmap for 'a' to 'z'
*/

- if ((v = pathconf(path, _PC_PATH_ATTRIBUTES)) == -1L)
+ if (fd != -1)
+ v = fpathconf(fd, _PC_PATH_ATTRIBUTES);
+ else
+ v = pathconf(path, _PC_PATH_ATTRIBUTES);
+ if (v) == -1L)
return 0;
s = fp->value;
e = s + sizeof(fp->value) - 1;
@@ -736,8 +740,8 @@
case OP_path_resolve:
if (state.synthesizing && value == (char*)fp->std)
fp->value = (char*)value;
- else if (!synthesize(fp, path, value))
- initialize(fp, path, NiL, "logical", DEFAULT(OP_path_resolve));
+ else if (!synthesize(fp, fd, path, value))
+ initialize(fp, fd, path, NiL, "logical", DEFAULT(OP_path_resolve));
break;

case OP_universe:
@@ -788,10 +792,10 @@
}
}
else
- synthesize(fp, path, value);
+ synthesize(fp, fd, path, value);
}
else
- initialize(fp, path, "echo", DEFAULT(OP_universe), "ucb");
+ initialize(fp, fd, path, "echo", DEFAULT(OP_universe), "ucb");
#endif
#endif
break;
@@ -800,7 +804,7 @@
if (state.synthesizing && value == (char*)fp->std)
fp->value = (char*)value;
else
- synthesize(fp, path, value);
+ synthesize(fp, fd, path, value);
break;

}
@@ -816,7 +820,7 @@
*/

static char*
-feature(register Feature_t* fp, const char* name, const char* path, const char* value, unsigned int flags, Error_f conferror)
+feature(register Feature_t* fp, const char* name, int fd, const char* path, const char* value, unsigned int flags, Error_f conferror)
{
register int n;

@@ -861,7 +865,7 @@
}
else
state.recent = fp;
- return format(fp, path, value, flags, conferror);
+ return format(fp, fd, path, value, flags, conferror);
}

/*
@@ -1006,7 +1010,7 @@
*/

static char*
-print(Sfio_t* sp, register Lookup_t* look, const char* name, const char* path, int listflags, Error_f conferror)
+print(Sfio_t* sp, register Lookup_t* look, const char* name, int fd, const char* path, int listflags, Error_f conferror)
{
register Conf_t* p = look->conf;
register unsigned int flags = look->flags;
@@ -1058,14 +1062,14 @@
switch (p->call)
{
case CONF_pathconf:
- if (path == root)
+ if ((path == root) && (fd == -1))
{
(*conferror)(&state, &state, 2, "%s: path expected", name);
goto bad;
}
break;
default:
- if (path != root)
+ if ((path != root) || (fd != -1))
{
(*conferror)(&state, &state, 2, "%s: path not expected", name);
goto bad;
@@ -1119,7 +1123,11 @@
case CONF_pathconf:
call = "pathconf";
#if _lib_pathconf
- if ((v = pathconf(path, p->op)) < 0)
+ if (fd != -1)
+ v = fpathconf(fd, p->op);
+ else
+ v = pathconf(path, p->op);
+ if (v < 0)
defined = 0;
break;
#else
@@ -1369,7 +1377,7 @@
if (!(listflags & ~(ASTCONF_error|ASTCONF_system)))
for (fp = state.features; fp; fp = fp->next)
if (streq(name, fp->name))
- return format(fp, path, 0, listflags, conferror);
+ return format(fp, fd, path, 0, listflags, conferror);
return (listflags & ASTCONF_error) ? (char*)0 : null;
}

@@ -1414,10 +1422,10 @@
* settable return values are in permanent store
* non-settable return values copied to a tmp fmtbuf() buffer
*
- * if (streq(astgetconf("PATH_RESOLVE", NiL, NiL, 0, 0), "logical"))
+ * if (streq(astgetconf("PATH_RESOLVE", -1, NiL, NiL, 0, 0), "logical"))
* our_way();
*
- * universe = astgetconf("UNIVERSE", NiL, "att", 0, 0);
+ * universe = astgetconf("UNIVERSE", -1, NiL, "att", 0, 0);
* astgetconf("UNIVERSE", NiL, universe, 0, 0);
*
* if (flags&ASTCONF_error)!=0 then error return value is 0
@@ -1427,7 +1435,7 @@
#define ALT 16

char*
-astgetconf(const char* name, const char* path, const char* value, int flags, Error_f conferror)
+astgetconf(const char* name, int fd, const char* path, const char* value, int flags, Error_f conferror)
{
register char* s;
int n;
@@ -1445,7 +1453,7 @@
#endif
if (!name)
{
- if (path)
+ if (path || (fd != -1))
return null;
if (!(name = value))
{
@@ -1467,9 +1475,9 @@
value = 0;
}
INITIALIZE();
- if (!path)
+ if (!path && (fd == -1))
path = root;
- if (state.recent && streq(name, state.recent->name) && (s = format(state.recent, path, value, flags, conferror)))
+ if (state.recent && streq(name, state.recent->name) && (s = format(state.recent, fd, path, value, flags, conferror)))
return s;
if (lookup(&look, name, flags))
{
@@ -1481,7 +1489,7 @@
(*conferror)(&state, &state, 2, "%s: cannot set value", name);
return (flags & ASTCONF_error) ? (char*)0 : null;
}
- return print(NiL, &look, name, path, flags, conferror);
+ return print(NiL, &look, name, fd, path, flags, conferror);
}
if ((n = strlen(name)) > 3 && n < (ALT + 3))
{
@@ -1521,7 +1529,7 @@
(*conferror)(&state, &state, 2, "%s: cannot set value", altname);
return (flags & ASTCONF_error) ? (char*)0 : null;
}
- return print(NiL, &altlook, altname, path, flags, conferror);
+ return print(NiL, &altlook, altname, fd, path, flags, conferror);
}
for (s = altname; *s; s++)
if (isupper(*s))
@@ -1544,7 +1552,7 @@
}
}
}
- if ((look.standard < 0 || look.standard == CONF_AST) && look.call <= 0 && look.section <= 1 && (s = feature(0, look.name, path, value, flags, conferror)))
+ if ((look.standard < 0 || look.standard == CONF_AST) && look.call <= 0 && look.section <= 1 && (s = feature(0, look.name, fd, path, value, flags, conferror)))
return s;
errno = EINVAL;
if (conferror && !(flags & ASTCONF_system))
@@ -1562,11 +1570,11 @@
#if DEBUG_astconf
char* r;

- r = astgetconf(name, path, value, 0, 0);
+ r = astgetconf(name, -1, path, value, 0, 0);
error(-1, "astconf(%s,%s,%s) => '%s'", name, path, value, r);
return r;
#else
- return astgetconf(name, path, value, 0, 0);
+ return astgetconf(name, -1, path, value, 0, 0);
#endif
}

@@ -1592,7 +1600,7 @@
*/

void
-astconflist(Sfio_t* sp, const char* path, int flags, const char* pattern)
+astconflist(Sfio_t* sp, int fd, const char* path, int flags, const char* pattern)
{
char* s;
char* f;
@@ -1609,7 +1617,21 @@
#endif

INITIALIZE();
- if (!path)
+
+ if((path != NULL) && (fd != -1))
+ {
+ /*
+ * |fd| and |path| arguments are currently mutually exclusive.
+ * If we ever allow this then we should create an |ASTCONF_open|
+ * flag to explicitly use |openat(fd, path, ...)| to open the
+ * file requested. On the other hand it may be better to let
+ * the caller handle this detail
+ */
+ errorf(&state, &state, 2, "Cannot pass both fd and path");
+ return;
+ }
+
+ if (!path || (fd != -1))
path = root;
else if (access(path, F_OK))
{
@@ -1657,7 +1679,7 @@
}
look.standard = look.conf->standard;
look.section = look.conf->section;
- print(sp, &look, NiL, path, flags, errorf);
+ print(sp, &look, NiL, -1, path, flags, errorf);
}
#ifdef _pth_getconf_a
if (pp = nativeconf(&proc, _pth_getconf_a))
@@ -1712,7 +1734,7 @@
continue;
}
}
- if (!(s = feature(fp, 0, path, NiL, 0, 0)) || !*s)
+ if (!(s = feature(fp, 0, fd, path, NiL, 0, 0)) || !*s)
s = "0";
if (flags & ASTCONF_table)
{
diff -r -u original/src/lib/libcmd/getconf.c build_fgetconf/src/lib/libcmd/getconf.c
--- src/lib/libcmd/getconf.c 2012-06-26 00:45:10.000000000 +0200
+++ src/lib/libcmd/getconf.c 2013-09-30 14:33:16.645535121 +0200
@@ -27,7 +27,7 @@
*/

static const char usage[] =
-"[-?\n@(#)$Id: getconf (AT&T Research) 2012-06-25 $\n]"
+"[-?\n@(#)$Id: getconf (AT&T Research) 2013-09-30 $\n]"
USAGE_LICENSE
"[+NAME?getconf - get configuration values]"
"[+DESCRIPTION?\bgetconf\b displays the system configuration value for"
@@ -52,8 +52,9 @@
" \aname\a=\avalue\a form to the standard output, one per line."
" Only one of \b--call\b, \b--name\b or \b--standard\b may be specified.]"
"[+?This implementation uses the \bastgetconf\b(3) string interface to the native"
-" \bsysconf\b(2), \bconfstr\b(2), \bpathconf\b(2), and \bsysinfo\b(2)"
-" system calls. If \bgetconf\b on \b$PATH\b is not the default native"
+" \bsysconf\b(2), \bconfstr\b(2), \bpathconf\b(2), \bfpathconf\b(2), "
+" and \bsysinfo\b(2) system calls. "
+" If \bgetconf\b on \b$PATH\b is not the default native"
" \bgetconf\b, named by \b$(getconf GETCONF)\b, then \bastgetconf\b(3)"
" checks only \bast\b specific extensions and the native system calls;"
" invalid options and/or names not supported by \bastgetconf\b(3) cause"
@@ -65,11 +66,13 @@
" prefixes are:]:[RE]{"
" [+CS?\bconfstr\b(2)]"
" [+PC?\bpathconf\b(2)]"
+" [+PC?\bfpathconf\b(2)]"
" [+SC?\bsysconf\b(2)]"
" [+SI?\bsysinfo\b(2)]"
" [+XX?Constant value.]"
"}"
"[d:defined?Only display defined values when no operands are specified.]"
+"[f?Use \bfd\b instead of a file name.]#[fd]"
"[l:lowercase?List variable names in lower case.]"
"[n:name?Display variables with name that match \aRE\a.]:[RE]"
"[p:portable?Display the named \bwritable\b variables and values in a form that"
@@ -116,7 +119,7 @@
"is an implementation detail of process inheritance; it may "
"change or vanish in the future; don't rely on it.]"
"}"
-"[+SEE ALSO?\bpathchk\b(1), \bconfstr\b(2), \bpathconf\b(2),"
+"[+SEE ALSO?\bpathchk\b(1), \bconfstr\b(2), \bpathconf\b(2), \bfpathconf\b(2),"
" \bsysconf\b(2), \bastgetconf\b(3)]"
;

@@ -133,6 +136,7 @@
int
b_getconf(int argc, char** argv, Shbltin_t* context)
{
+ register int fd = -1;
register char* name;
register char* path;
register char* value;
@@ -182,6 +186,9 @@
case 'd':
flags |= ASTCONF_defined;
continue;
+ case 'f':
+ fd = opt_info.num;
+ continue;
case 'l':
flags |= ASTCONF_lower;
continue;
@@ -236,17 +243,19 @@
path = 0;
}
}
- if (error_info.errors || !name && *argv)
+ if (error_info.errors || !name && (fd == -1) && *argv)
error(ERROR_usage(2), "%s", optusage(NiL));
if (!name)
- astconflist(sfstdout, path, flags, pattern);
+ astconflist(sfstdout, fd, path, flags, pattern);
else
{
if (native)
flags |= (ASTCONF_system|ASTCONF_error);
do
{
- if (!(path = *++argv))
+ int pfd = -1; /* |fpathconf()| file descriptor */
+
+ if (!(path = *++argv) || (fd != -1))
value = 0;
else
{
@@ -261,7 +270,33 @@
flags = 0;
}
}
- s = astgetconf(name, path, value, flags, errorf);
+ if (path && (path[0] != '/') && (path[0] != '\0'))
+ {
+#ifdef O_PATH
+ /*
+ * Note that we have to try with |O_RDONLY| first for now since
+ * Linux's |fstatfs()| (used by glibc |fpathconf()|) currently
+ * does not like |O_PATH| (we alias |O_SEARCH| to |O_PATH| if
+ * |O_SEARCH| is not natively available) and returns a |EBADF|.
+ * This workaround limits the damage until Linus fixes |fstatfs()|.
+ */
+ pfd = openat((fd != -1)?fd:(context?context->pwdfd:AT_FDCWD), path, O_RDONLY);
+ if (pfd == -1)
+#endif /* O_PATH */
+ {
+ pfd = openat((fd != -1)?fd:(context?context->pwdfd:AT_FDCWD), path, O_SEARCH);
+ }
+ if (pfd == -1)
+ {
+ error(ERROR_SYSTEM|2, "Cannot open %s", path);
+ break;
+ }
+ }
+ s = astgetconf(name, (pfd >= 0)?pfd:fd, path, value, flags, errorf);
+ if (pfd >= 0)
+ {
+ close(pfd);
+ }
if (error_info.errors)
break;
if (!s)
diff -r -u original/src/lib/libcmd/uname.c build_fgetconf/src/lib/libcmd/uname.c
--- src/lib/libcmd/uname.c 2012-01-10 19:57:03.000000000 +0100
+++ src/lib/libcmd/uname.c 2013-09-30 12:51:48.222260396 +0200
@@ -356,7 +356,7 @@
error(ERROR_system(1), "%s: cannot set host name", sethost);
}
else if (list)
- astconflist(sfstdout, NiL, ASTCONF_base|ASTCONF_defined|ASTCONF_lower|ASTCONF_quote|ASTCONF_matchcall, "CS|SI");
+ astconflist(sfstdout, -1, NiL, ASTCONF_base|ASTCONF_defined|ASTCONF_lower|ASTCONF_quote|ASTCONF_matchcall, "CS|SI");
else if (*argv)
{
e = &buf[sizeof(buf)-1];
Roland Mainz
2013-11-27 00:41:18 UTC
Permalink
On Sun, Oct 13, 2013 at 12:26 AM, ????? ????????????
Post by ольга крыжановская
Glenn, David, the patch is missing in ast-ksh.2013-10-10. Could you
have a look at this issue please?
Olga
Post by Roland Mainz
Post by Glenn Fowler
Post by Lionel Cons
[snip]
Post by Roland Mainz
Post by Roland Mainz
... on the bright side... adding |fpathconf()| support looks quite
easy to implement... if Glenn agrees I can make the patch for that
tonight...
Erm... ping!
Can I craft the patch for this one, please ?
Erm... should I make the patch - [yes]/[no]/[chicken] ? :-)
go for it
_Thanks_! ... :-)
Attached (as "astksh20130926_getconf_f_001.diff.txt") is a _prototype_
patch to add a -f $fd option to getconf(1) ...
- this is a prototype... it requires more testing and minor other changes
- still need to hook-up the usual AST versioning system to make sure
we don't hit any symbol collisions
- Need to do build tests with ast-open
- During development we hit a bug that Linux's |fstatfs()| - used by
|fpathconf()| - does not like |O_PATH|. Olga notified Linus himself to
have a look at this issue. The patch contains a workaround. Note that
the workaround is only used if both -f $fd and a _relative_ path are
given, the issue does not affect anything which uses an absolute path.
Erm... Glenn.. any feedback/rants/comments for the patch ?
*ping*! ...
Glenn: Any comments/feedback ?

----

Bye,
Roland
--
__ . . __
(o.\ \/ /.o) roland.mainz at nrubsig.org
\__\/\/__/ MPEG specialist, C&&JAVA&&Sun&&Unix programmer
/O /==\ O\ TEL +49 641 3992797
(;O/ \/ \O;)
Roland Mainz
2013-11-27 01:01:36 UTC
Permalink
On Sun, Oct 13, 2013 at 12:26 AM, ????? ????????????
Post by ольга крыжановская
Glenn, David, the patch is missing in ast-ksh.2013-10-10. Could you
have a look at this issue please?
Olga
Post by Roland Mainz
Post by Glenn Fowler
Post by Lionel Cons
[snip]
Post by Roland Mainz
Post by Roland Mainz
... on the bright side... adding |fpathconf()| support looks quite
easy to implement... if Glenn agrees I can make the patch for that
tonight...
Erm... ping!
Can I craft the patch for this one, please ?
Erm... should I make the patch - [yes]/[no]/[chicken] ? :-)
go for it
_Thanks_! ... :-)
Attached (as "astksh20130926_getconf_f_001.diff.txt") is a _prototype_
patch to add a -f $fd option to getconf(1) ...
- this is a prototype... it requires more testing and minor other changes
- still need to hook-up the usual AST versioning system to make sure
we don't hit any symbol collisions
- Need to do build tests with ast-open
- During development we hit a bug that Linux's |fstatfs()| - used by
|fpathconf()| - does not like |O_PATH|. Olga notified Linus himself to
have a look at this issue. The patch contains a workaround. Note that
the workaround is only used if both -f $fd and a _relative_ path are
given, the issue does not affect anything which uses an absolute path.
Erm... Glenn.. any feedback/rants/comments for the patch ?
Trying again, this time with the original patch attached...
... Glenn: Any feedback (or better: Integration into ast-ksh - since a
lot of people either are desperately waiting for the patch or just use
it already (like Lionel&&Cedric)) welcome ...

----

Bye,
Roland
--
__ . . __
(o.\ \/ /.o) roland.mainz at nrubsig.org
\__\/\/__/ MPEG specialist, C&&JAVA&&Sun&&Unix programmer
/O /==\ O\ TEL +49 641 3992797
(;O/ \/ \O;)
-------------- next part --------------
diff -r -u original/src/lib/libast/include/ast.h build_fgetconf/src/lib/libast/include/ast.h
--- src/lib/libast/include/ast.h 2013-09-18 21:53:42.000000000 +0200
+++ src/lib/libast/include/ast.h 2013-09-30 12:55:57.074998985 +0200
@@ -275,10 +275,10 @@
#define extern __EXPORT__
#endif

-extern char* astgetconf(const char*, const char*, const char*, int, Error_f);
+extern char* astgetconf(const char*, int, const char*, const char*, int, Error_f);
extern char* astconf(const char*, const char*, const char*);
extern Ast_confdisc_f astconfdisc(Ast_confdisc_f);
-extern void astconflist(Sfio_t*, const char*, int, const char*);
+extern void astconflist(Sfio_t*, int, const char*, int, const char*);
extern off_t astcopy(int, int, off_t);
extern int astlicense(char*, int, char*, char*, int, int, int);
extern int astquery(int, const char*, ...);
diff -r -u original/src/lib/libast/port/astconf.c build_fgetconf/src/lib/libast/port/astconf.c
--- src/lib/libast/port/astconf.c 2013-08-20 18:55:15.000000000 +0200
+++ src/lib/libast/port/astconf.c 2013-09-30 13:51:22.292943470 +0200
@@ -22,11 +22,11 @@
#pragma prototyped

/*
- * string interface to confstr(),pathconf(),sysconf(),sysinfo()
+ * string interface to confstr(),pathconf(),fpathconf(),sysconf(),sysinfo()
* extended to allow some features to be set per-process
*/

-static const char id[] = "\n@(#)$Id: getconf (AT&T Research) 2012-05-01 $\0\n";
+static const char id[] = "\n@(#)$Id: getconf (AT&T Research) 2013-09-30 $\0\n";

#include "univlib.h"

@@ -76,7 +76,7 @@
#define CONF_GLOBAL (CONF_USER<<3)

#define DEFAULT(o) ((state.std||!dynamic[o].ast)?dynamic[o].std:dynamic[o].ast)
-#define INITIALIZE() do{if(!state.data)synthesize(NiL,NiL,NiL);}while(0)
+#define INITIALIZE() do{if(!state.data)synthesize(NiL,-1,NiL,NiL);}while(0)
#define STANDARD(v) (streq(v,"standard")||streq(v,"strict")||streq(v,"posix")||streq(v,"xopen"))

#define MAXVAL 256
@@ -302,7 +302,7 @@

static State_t state = { "getconf", "_AST_FEATURES", "CONFORMANCE = standard", "POSIXLY_CORRECT", dynamic, -1 };

-static char* feature(Feature_t*, const char*, const char*, const char*, unsigned int, Error_f);
+static char* feature(Feature_t*, const char*, int, const char*, const char*, unsigned int, Error_f);

/*
* return fmtbuf() copy of s
@@ -322,7 +322,7 @@
*/

static char*
-synthesize(register Feature_t* fp, const char* path, const char* value)
+synthesize(register Feature_t* fp, int fd, const char* path, const char* value)
{
register char* s;
register char* d;
@@ -332,7 +332,7 @@

#if DEBUG_astconf
if (fp)
- error(-6, "astconf synthesize name=%s path=%s value=%s fp=%p%s", fp->name, path, value, fp, state.synthesizing ? " SYNTHESIZING" : "");
+ error(-6, "astconf synthesize name=%s fd=%d path=%s value=%s fp=%p%s", fp->name, fd, path, value, fp, state.synthesizing ? " SYNTHESIZING" : "");
#endif
if (state.synthesizing)
{
@@ -380,7 +380,7 @@
ve = 0;
*de = 0;
*se = 0;
- feature(0, s, d, v, 0, 0);
+ feature(0, s, fd, d, v, 0, 0);
*se = ' ';
*de = ' ';
if (!ve)
@@ -501,18 +501,18 @@
/*
* initialize the value for fp
* if command!=0 then it is checked for on $PATH
- * synthesize(fp,path,succeed) called on success
+ * synthesize(fp,fd,path,succeed) called on success
* otherwise synthesize(fp,path,fail) called
*/

static void
-initialize(register Feature_t* fp, const char* path, const char* command, const char* succeed, const char* fail)
+initialize(register Feature_t* fp, int fd, const char* path, const char* command, const char* succeed, const char* fail)
{
register char* p;
register int ok = 1;

#if DEBUG_astconf
- error(-6, "astconf initialize name=%s path=%s command=%s succeed=%s fail=%s fp=%p%s", fp->name, path, command, succeed, fail, fp, state.synthesizing ? " SYNTHESIZING" : "");
+ error(-6, "astconf initialize name=%s fd=%d path=%s command=%s succeed=%s fail=%s fp=%p%s", fp->name, fd, path, command, succeed, fail, fp, state.synthesizing ? " SYNTHESIZING" : "");
#endif
switch (fp->op)
{
@@ -617,7 +617,7 @@
#if DEBUG_astconf
error(-6, "state.std=%d %s [%s] std=%s ast=%s value=%s ok=%d", state.std, fp->name, ok ? succeed : fail, fp->std, fp->ast, fp->value, ok);
#endif
- synthesize(fp, path, ok ? succeed : fail);
+ synthesize(fp, fd, path, ok ? succeed : fail);
}

/*
@@ -625,7 +625,7 @@
*/

static char*
-format(register Feature_t* fp, const char* path, const char* value, unsigned int flags, Error_f conferror)
+format(register Feature_t* fp, int fd, const char* path, const char* value, unsigned int flags, Error_f conferror)
{
register Feature_t* sp;
register int n;
@@ -682,8 +682,8 @@
#endif
if (state.synthesizing && value == (char*)fp->std)
fp->value = (char*)value;
- else if (!synthesize(fp, path, value))
- initialize(fp, path, NiL, fp->std, fp->value);
+ else if (!synthesize(fp, fd, path, value))
+ initialize(fp, fd, path, NiL, fp->std, fp->value);
#if DEBUG_astconf
error(-6, "state.std=%d %s [%s] std=%s ast=%s value=%s", state.std, fp->name, value, fp->std, fp->ast, fp->value);
#endif
@@ -692,7 +692,7 @@
state.std = 1;
for (sp = state.features; sp; sp = sp->next)
if (sp->std && sp->op && sp->op != OP_conformance)
- feature(sp, 0, path, sp->std, 0, 0);
+ feature(sp, 0, fd, path, sp->std, 0, 0);
}
#if DEBUG_astconf
error(-6, "state.std=%d %s [%s] std=%s ast=%s value=%s", state.std, fp->name, value, fp->std, fp->ast, fp->value);
@@ -717,7 +717,11 @@
* _PC_PATH_ATTRIBUTES is a bitmap for 'a' to 'z'
*/

- if ((v = pathconf(path, _PC_PATH_ATTRIBUTES)) == -1L)
+ if (fd != -1)
+ v = fpathconf(fd, _PC_PATH_ATTRIBUTES);
+ else
+ v = pathconf(path, _PC_PATH_ATTRIBUTES);
+ if (v) == -1L)
return 0;
s = fp->value;
e = s + sizeof(fp->value) - 1;
@@ -736,8 +740,8 @@
case OP_path_resolve:
if (state.synthesizing && value == (char*)fp->std)
fp->value = (char*)value;
- else if (!synthesize(fp, path, value))
- initialize(fp, path, NiL, "logical", DEFAULT(OP_path_resolve));
+ else if (!synthesize(fp, fd, path, value))
+ initialize(fp, fd, path, NiL, "logical", DEFAULT(OP_path_resolve));
break;

case OP_universe:
@@ -788,10 +792,10 @@
}
}
else
- synthesize(fp, path, value);
+ synthesize(fp, fd, path, value);
}
else
- initialize(fp, path, "echo", DEFAULT(OP_universe), "ucb");
+ initialize(fp, fd, path, "echo", DEFAULT(OP_universe), "ucb");
#endif
#endif
break;
@@ -800,7 +804,7 @@
if (state.synthesizing && value == (char*)fp->std)
fp->value = (char*)value;
else
- synthesize(fp, path, value);
+ synthesize(fp, fd, path, value);
break;

}
@@ -816,7 +820,7 @@
*/

static char*
-feature(register Feature_t* fp, const char* name, const char* path, const char* value, unsigned int flags, Error_f conferror)
+feature(register Feature_t* fp, const char* name, int fd, const char* path, const char* value, unsigned int flags, Error_f conferror)
{
register int n;

@@ -861,7 +865,7 @@
}
else
state.recent = fp;
- return format(fp, path, value, flags, conferror);
+ return format(fp, fd, path, value, flags, conferror);
}

/*
@@ -1006,7 +1010,7 @@
*/

static char*
-print(Sfio_t* sp, register Lookup_t* look, const char* name, const char* path, int listflags, Error_f conferror)
+print(Sfio_t* sp, register Lookup_t* look, const char* name, int fd, const char* path, int listflags, Error_f conferror)
{
register Conf_t* p = look->conf;
register unsigned int flags = look->flags;
@@ -1058,14 +1062,14 @@
switch (p->call)
{
case CONF_pathconf:
- if (path == root)
+ if ((path == root) && (fd == -1))
{
(*conferror)(&state, &state, 2, "%s: path expected", name);
goto bad;
}
break;
default:
- if (path != root)
+ if ((path != root) || (fd != -1))
{
(*conferror)(&state, &state, 2, "%s: path not expected", name);
goto bad;
@@ -1119,7 +1123,11 @@
case CONF_pathconf:
call = "pathconf";
#if _lib_pathconf
- if ((v = pathconf(path, p->op)) < 0)
+ if (fd != -1)
+ v = fpathconf(fd, p->op);
+ else
+ v = pathconf(path, p->op);
+ if (v < 0)
defined = 0;
break;
#else
@@ -1369,7 +1377,7 @@
if (!(listflags & ~(ASTCONF_error|ASTCONF_system)))
for (fp = state.features; fp; fp = fp->next)
if (streq(name, fp->name))
- return format(fp, path, 0, listflags, conferror);
+ return format(fp, fd, path, 0, listflags, conferror);
return (listflags & ASTCONF_error) ? (char*)0 : null;
}

@@ -1414,10 +1422,10 @@
* settable return values are in permanent store
* non-settable return values copied to a tmp fmtbuf() buffer
*
- * if (streq(astgetconf("PATH_RESOLVE", NiL, NiL, 0, 0), "logical"))
+ * if (streq(astgetconf("PATH_RESOLVE", -1, NiL, NiL, 0, 0), "logical"))
* our_way();
*
- * universe = astgetconf("UNIVERSE", NiL, "att", 0, 0);
+ * universe = astgetconf("UNIVERSE", -1, NiL, "att", 0, 0);
* astgetconf("UNIVERSE", NiL, universe, 0, 0);
*
* if (flags&ASTCONF_error)!=0 then error return value is 0
@@ -1427,7 +1435,7 @@
#define ALT 16

char*
-astgetconf(const char* name, const char* path, const char* value, int flags, Error_f conferror)
+astgetconf(const char* name, int fd, const char* path, const char* value, int flags, Error_f conferror)
{
register char* s;
int n;
@@ -1445,7 +1453,7 @@
#endif
if (!name)
{
- if (path)
+ if (path || (fd != -1))
return null;
if (!(name = value))
{
@@ -1467,9 +1475,9 @@
value = 0;
}
INITIALIZE();
- if (!path)
+ if (!path && (fd == -1))
path = root;
- if (state.recent && streq(name, state.recent->name) && (s = format(state.recent, path, value, flags, conferror)))
+ if (state.recent && streq(name, state.recent->name) && (s = format(state.recent, fd, path, value, flags, conferror)))
return s;
if (lookup(&look, name, flags))
{
@@ -1481,7 +1489,7 @@
(*conferror)(&state, &state, 2, "%s: cannot set value", name);
return (flags & ASTCONF_error) ? (char*)0 : null;
}
- return print(NiL, &look, name, path, flags, conferror);
+ return print(NiL, &look, name, fd, path, flags, conferror);
}
if ((n = strlen(name)) > 3 && n < (ALT + 3))
{
@@ -1521,7 +1529,7 @@
(*conferror)(&state, &state, 2, "%s: cannot set value", altname);
return (flags & ASTCONF_error) ? (char*)0 : null;
}
- return print(NiL, &altlook, altname, path, flags, conferror);
+ return print(NiL, &altlook, altname, fd, path, flags, conferror);
}
for (s = altname; *s; s++)
if (isupper(*s))
@@ -1544,7 +1552,7 @@
}
}
}
- if ((look.standard < 0 || look.standard == CONF_AST) && look.call <= 0 && look.section <= 1 && (s = feature(0, look.name, path, value, flags, conferror)))
+ if ((look.standard < 0 || look.standard == CONF_AST) && look.call <= 0 && look.section <= 1 && (s = feature(0, look.name, fd, path, value, flags, conferror)))
return s;
errno = EINVAL;
if (conferror && !(flags & ASTCONF_system))
@@ -1562,11 +1570,11 @@
#if DEBUG_astconf
char* r;

- r = astgetconf(name, path, value, 0, 0);
+ r = astgetconf(name, -1, path, value, 0, 0);
error(-1, "astconf(%s,%s,%s) => '%s'", name, path, value, r);
return r;
#else
- return astgetconf(name, path, value, 0, 0);
+ return astgetconf(name, -1, path, value, 0, 0);
#endif
}

@@ -1592,7 +1600,7 @@
*/

void
-astconflist(Sfio_t* sp, const char* path, int flags, const char* pattern)
+astconflist(Sfio_t* sp, int fd, const char* path, int flags, const char* pattern)
{
char* s;
char* f;
@@ -1609,7 +1617,21 @@
#endif

INITIALIZE();
- if (!path)
+
+ if((path != NULL) && (fd != -1))
+ {
+ /*
+ * |fd| and |path| arguments are currently mutually exclusive.
+ * If we ever allow this then we should create an |ASTCONF_open|
+ * flag to explicitly use |openat(fd, path, ...)| to open the
+ * file requested. On the other hand it may be better to let
+ * the caller handle this detail
+ */
+ errorf(&state, &state, 2, "Cannot pass both fd and path");
+ return;
+ }
+
+ if (!path || (fd != -1))
path = root;
else if (access(path, F_OK))
{
@@ -1657,7 +1679,7 @@
}
look.standard = look.conf->standard;
look.section = look.conf->section;
- print(sp, &look, NiL, path, flags, errorf);
+ print(sp, &look, NiL, -1, path, flags, errorf);
}
#ifdef _pth_getconf_a
if (pp = nativeconf(&proc, _pth_getconf_a))
@@ -1712,7 +1734,7 @@
continue;
}
}
- if (!(s = feature(fp, 0, path, NiL, 0, 0)) || !*s)
+ if (!(s = feature(fp, 0, fd, path, NiL, 0, 0)) || !*s)
s = "0";
if (flags & ASTCONF_table)
{
diff -r -u original/src/lib/libcmd/getconf.c build_fgetconf/src/lib/libcmd/getconf.c
--- src/lib/libcmd/getconf.c 2012-06-26 00:45:10.000000000 +0200
+++ src/lib/libcmd/getconf.c 2013-09-30 14:33:16.645535121 +0200
@@ -27,7 +27,7 @@
*/

static const char usage[] =
-"[-?\n@(#)$Id: getconf (AT&T Research) 2012-06-25 $\n]"
+"[-?\n@(#)$Id: getconf (AT&T Research) 2013-09-30 $\n]"
USAGE_LICENSE
"[+NAME?getconf - get configuration values]"
"[+DESCRIPTION?\bgetconf\b displays the system configuration value for"
@@ -52,8 +52,9 @@
" \aname\a=\avalue\a form to the standard output, one per line."
" Only one of \b--call\b, \b--name\b or \b--standard\b may be specified.]"
"[+?This implementation uses the \bastgetconf\b(3) string interface to the native"
-" \bsysconf\b(2), \bconfstr\b(2), \bpathconf\b(2), and \bsysinfo\b(2)"
-" system calls. If \bgetconf\b on \b$PATH\b is not the default native"
+" \bsysconf\b(2), \bconfstr\b(2), \bpathconf\b(2), \bfpathconf\b(2), "
+" and \bsysinfo\b(2) system calls. "
+" If \bgetconf\b on \b$PATH\b is not the default native"
" \bgetconf\b, named by \b$(getconf GETCONF)\b, then \bastgetconf\b(3)"
" checks only \bast\b specific extensions and the native system calls;"
" invalid options and/or names not supported by \bastgetconf\b(3) cause"
@@ -65,11 +66,13 @@
" prefixes are:]:[RE]{"
" [+CS?\bconfstr\b(2)]"
" [+PC?\bpathconf\b(2)]"
+" [+PC?\bfpathconf\b(2)]"
" [+SC?\bsysconf\b(2)]"
" [+SI?\bsysinfo\b(2)]"
" [+XX?Constant value.]"
"}"
"[d:defined?Only display defined values when no operands are specified.]"
+"[f?Use \bfd\b instead of a file name.]#[fd]"
"[l:lowercase?List variable names in lower case.]"
"[n:name?Display variables with name that match \aRE\a.]:[RE]"
"[p:portable?Display the named \bwritable\b variables and values in a form that"
@@ -116,7 +119,7 @@
"is an implementation detail of process inheritance; it may "
"change or vanish in the future; don't rely on it.]"
"}"
-"[+SEE ALSO?\bpathchk\b(1), \bconfstr\b(2), \bpathconf\b(2),"
+"[+SEE ALSO?\bpathchk\b(1), \bconfstr\b(2), \bpathconf\b(2), \bfpathconf\b(2),"
" \bsysconf\b(2), \bastgetconf\b(3)]"
;

@@ -133,6 +136,7 @@
int
b_getconf(int argc, char** argv, Shbltin_t* context)
{
+ register int fd = -1;
register char* name;
register char* path;
register char* value;
@@ -182,6 +186,9 @@
case 'd':
flags |= ASTCONF_defined;
continue;
+ case 'f':
+ fd = opt_info.num;
+ continue;
case 'l':
flags |= ASTCONF_lower;
continue;
@@ -236,17 +243,19 @@
path = 0;
}
}
- if (error_info.errors || !name && *argv)
+ if (error_info.errors || !name && (fd == -1) && *argv)
error(ERROR_usage(2), "%s", optusage(NiL));
if (!name)
- astconflist(sfstdout, path, flags, pattern);
+ astconflist(sfstdout, fd, path, flags, pattern);
else
{
if (native)
flags |= (ASTCONF_system|ASTCONF_error);
do
{
- if (!(path = *++argv))
+ int pfd = -1; /* |fpathconf()| file descriptor */
+
+ if (!(path = *++argv) || (fd != -1))
value = 0;
else
{
@@ -261,7 +270,33 @@
flags = 0;
}
}
- s = astgetconf(name, path, value, flags, errorf);
+ if (path && (path[0] != '/') && (path[0] != '\0'))
+ {
+#ifdef O_PATH
+ /*
+ * Note that we have to try with |O_RDONLY| first for now since
+ * Linux's |fstatfs()| (used by glibc |fpathconf()|) currently
+ * does not like |O_PATH| (we alias |O_SEARCH| to |O_PATH| if
+ * |O_SEARCH| is not natively available) and returns a |EBADF|.
+ * This workaround limits the damage until Linus fixes |fstatfs()|.
+ */
+ pfd = openat((fd != -1)?fd:(context?context->pwdfd:AT_FDCWD), path, O_RDONLY);
+ if (pfd == -1)
+#endif /* O_PATH */
+ {
+ pfd = openat((fd != -1)?fd:(context?context->pwdfd:AT_FDCWD), path, O_SEARCH);
+ }
+ if (pfd == -1)
+ {
+ error(ERROR_SYSTEM|2, "Cannot open %s", path);
+ break;
+ }
+ }
+ s = astgetconf(name, (pfd >= 0)?pfd:fd, path, value, flags, errorf);
+ if (pfd >= 0)
+ {
+ close(pfd);
+ }
if (error_info.errors)
break;
if (!s)
diff -r -u original/src/lib/libcmd/uname.c build_fgetconf/src/lib/libcmd/uname.c
--- src/lib/libcmd/uname.c 2012-01-10 19:57:03.000000000 +0100
+++ src/lib/libcmd/uname.c 2013-09-30 12:51:48.222260396 +0200
@@ -356,7 +356,7 @@
error(ERROR_system(1), "%s: cannot set host name", sethost);
}
else if (list)
- astconflist(sfstdout, NiL, ASTCONF_base|ASTCONF_defined|ASTCONF_lower|ASTCONF_quote|ASTCONF_matchcall, "CS|SI");
+ astconflist(sfstdout, -1, NiL, ASTCONF_base|ASTCONF_defined|ASTCONF_lower|ASTCONF_quote|ASTCONF_matchcall, "CS|SI");
else if (*argv)
{
e = &buf[sizeof(buf)-1];
Loading...