There is an optimization in chmod(1), that makes it not to call chmod(2)

if the new file mode is the same as it was before; however, this
optimization must be disabled for filesystems that support NFSv4 ACLs.
Chmod uses pathconf(2) to determine whether this is the case - however,
pathconf(2) always follows symbolic links, while the 'chmod -h' doesn't.

This change adds lpathconf(3) to make it possible to solve that problem
in a clean way.

Reviewed by:	rwatson (earlier version)
Approved by:	re (kib)
This commit is contained in:
Edward Tomasz Napierala 2009-07-08 15:23:18 +00:00
parent 6b53d5c0e7
commit c38898116a
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=195458
11 changed files with 59 additions and 10 deletions

View File

@ -513,6 +513,7 @@ int initgroups(const char *, gid_t);
int iruserok(unsigned long, int, const char *, const char *); int iruserok(unsigned long, int, const char *, const char *);
int iruserok_sa(const void *, int, int, const char *, const char *); int iruserok_sa(const void *, int, int, const char *, const char *);
int issetugid(void); int issetugid(void);
long lpathconf(const char *, int);
#ifndef _MKDTEMP_DECLARED #ifndef _MKDTEMP_DECLARED
char *mkdtemp(char *); char *mkdtemp(char *);
#define _MKDTEMP_DECLARED #define _MKDTEMP_DECLARED

View File

@ -159,6 +159,7 @@ MLINKS+=mq_send.2 mq_timedsend.2
MLINKS+=ntp_adjtime.2 ntp_gettime.2 MLINKS+=ntp_adjtime.2 ntp_gettime.2
MLINKS+=open.2 openat.2 MLINKS+=open.2 openat.2
MLINKS+=pathconf.2 fpathconf.2 MLINKS+=pathconf.2 fpathconf.2
MLINKS+=pathconf.2 lpathconf.2
MLINKS+=read.2 pread.2 read.2 preadv.2 read.2 readv.2 MLINKS+=read.2 pread.2 read.2 preadv.2 read.2 readv.2
MLINKS+=readlink.2 readlinkat.2 MLINKS+=readlink.2 readlinkat.2
MLINKS+=recv.2 recvfrom.2 recv.2 recvmsg.2 MLINKS+=recv.2 recvfrom.2 recv.2 recvmsg.2

View File

@ -346,6 +346,7 @@ FBSD_1.1 {
jail_set; jail_set;
jail_remove; jail_remove;
linkat; linkat;
lpathconf;
mkdirat; mkdirat;
mkfifoat; mkfifoat;
mknodat; mknodat;

View File

@ -28,11 +28,12 @@
.\" @(#)pathconf.2 8.1 (Berkeley) 6/4/93 .\" @(#)pathconf.2 8.1 (Berkeley) 6/4/93
.\" $FreeBSD$ .\" $FreeBSD$
.\" .\"
.Dd June 25, 2009 .Dd July 7, 2009
.Dt PATHCONF 2 .Dt PATHCONF 2
.Os .Os
.Sh NAME .Sh NAME
.Nm pathconf , .Nm pathconf ,
.Nm lpathconf ,
.Nm fpathconf .Nm fpathconf
.Nd get configurable pathname variables .Nd get configurable pathname variables
.Sh LIBRARY .Sh LIBRARY
@ -42,10 +43,13 @@
.Ft long .Ft long
.Fn pathconf "const char *path" "int name" .Fn pathconf "const char *path" "int name"
.Ft long .Ft long
.Fn lpathconf "const char *path" "int name"
.Ft long
.Fn fpathconf "int fd" "int name" .Fn fpathconf "int fd" "int name"
.Sh DESCRIPTION .Sh DESCRIPTION
The The
.Fn pathconf .Fn pathconf ,
.Fn lpathconf
and and
.Fn fpathconf .Fn fpathconf
system calls provide a method for applications to determine the current system calls provide a method for applications to determine the current
@ -53,7 +57,9 @@ value of a configurable system limit or option variable associated
with a pathname or file descriptor. with a pathname or file descriptor.
.Pp .Pp
For For
.Fn pathconf , .Fn pathconf
and
.Fn lpathconf ,
the the
.Fa path .Fa path
argument is the name of a file or directory. argument is the name of a file or directory.
@ -68,6 +74,18 @@ argument specifies the system variable to be queried.
Symbolic constants for each name value are found in the include file Symbolic constants for each name value are found in the include file
.Li <unistd.h> . .Li <unistd.h> .
.Pp .Pp
The
.Fn lpathconf
system call is like
.Fn pathconf
except in the case where the named file is a symbolic link,
in which case
.Fn lpathconf
returns information about the link,
while
.Fn pathconf
returns information about the file the link references.
.Pp
The available values are as follows: The available values are as follows:
.Pp .Pp
.Bl -tag -width 6n .Bl -tag -width 6n
@ -239,3 +257,7 @@ and
.Fn fpathconf .Fn fpathconf
system calls first appeared in system calls first appeared in
.Bx 4.4 . .Bx 4.4 .
The
.Fn lpathconf
system call first appeared in
.Fx 8.0 .

View File

@ -597,6 +597,7 @@
#define AUE_PWRITE 43193 /* Darwin/FreeBSD. */ #define AUE_PWRITE 43193 /* Darwin/FreeBSD. */
#define AUE_FSCTL 43194 /* Darwin. */ #define AUE_FSCTL 43194 /* Darwin. */
#define AUE_FFSCTL 43195 /* Darwin. */ #define AUE_FFSCTL 43195 /* Darwin. */
#define AUE_LPATHCONF 43196 /* FreeBSD. */
/* /*
* Darwin BSM uses a number of AUE_O_* definitions, which are aliased to the * Darwin BSM uses a number of AUE_O_* definitions, which are aliased to the

View File

@ -900,3 +900,4 @@
struct msqid_ds32 *buf); } struct msqid_ds32 *buf); }
512 AUE_SHMCTL STD { int freebsd32_shmctl(int shmid, int cmd, \ 512 AUE_SHMCTL STD { int freebsd32_shmctl(int shmid, int cmd, \
struct shmid_ds32 *buf); } struct shmid_ds32 *buf); }
513 AUE_LPATHCONF STD { int lpathconf(char *path, int name); }

View File

@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
#include <sys/jail.h> #include <sys/jail.h>
#include <sys/kernel.h> #include <sys/kernel.h>
#include <sys/malloc.h> #include <sys/malloc.h>
#include <sys/namei.h>
#include <sys/unistd.h> #include <sys/unistd.h>
#include <sys/time.h> #include <sys/time.h>
#include <sys/syscallsubr.h> #include <sys/syscallsubr.h>
@ -669,7 +670,7 @@ svr4_sys_pathconf(td, uap)
return (0); return (0);
default: default:
CHECKALTEXIST(td, uap->path, &path); CHECKALTEXIST(td, uap->path, &path);
error = kern_pathconf(td, path, UIO_SYSSPACE, name); error = kern_pathconf(td, path, UIO_SYSSPACE, name, FOLLOW);
free(path, M_TEMP); free(path, M_TEMP);
return (error); return (error);
} }

View File

@ -66,6 +66,7 @@ __FBSDID("$FreeBSD$");
#include <sys/malloc.h> #include <sys/malloc.h>
#include <sys/file.h> /* Must come after sys/malloc.h */ #include <sys/file.h> /* Must come after sys/malloc.h */
#include <sys/mutex.h> #include <sys/mutex.h>
#include <sys/namei.h>
#include <sys/priv.h> #include <sys/priv.h>
#include <sys/reboot.h> #include <sys/reboot.h>
#include <sys/resourcevar.h> #include <sys/resourcevar.h>
@ -763,7 +764,7 @@ ibcs2_pathconf(td, uap)
CHECKALTEXIST(td, uap->path, &path); CHECKALTEXIST(td, uap->path, &path);
uap->name++; /* iBCS2 _PC_* defines are offset by one */ uap->name++; /* iBCS2 _PC_* defines are offset by one */
error = kern_pathconf(td, path, UIO_SYSSPACE, uap->name); error = kern_pathconf(td, path, UIO_SYSSPACE, uap->name, FOLLOW);
free(path, M_TEMP); free(path, M_TEMP);
return (error); return (error);
} }

View File

@ -910,5 +910,6 @@
struct msqid_ds *buf); } struct msqid_ds *buf); }
512 AUE_SHMCTL NOSTD { int shmctl(int shmid, int cmd, \ 512 AUE_SHMCTL NOSTD { int shmctl(int shmid, int cmd, \
struct shmid_ds *buf); } struct shmid_ds *buf); }
513 AUE_LPATHCONF STD { int lpathconf(char *path, int name); }
; Please copy any additions and changes to the following compatability tables: ; Please copy any additions and changes to the following compatability tables:
; sys/compat/freebsd32/syscalls.master ; sys/compat/freebsd32/syscalls.master

View File

@ -2506,17 +2506,36 @@ pathconf(td, uap)
} */ *uap; } */ *uap;
{ {
return (kern_pathconf(td, uap->path, UIO_USERSPACE, uap->name)); return (kern_pathconf(td, uap->path, UIO_USERSPACE, uap->name, FOLLOW));
}
#ifndef _SYS_SYSPROTO_H_
struct lpathconf_args {
char *path;
int name;
};
#endif
int
lpathconf(td, uap)
struct thread *td;
register struct lpathconf_args /* {
char *path;
int name;
} */ *uap;
{
return (kern_pathconf(td, uap->path, UIO_USERSPACE, uap->name, NOFOLLOW));
} }
int int
kern_pathconf(struct thread *td, char *path, enum uio_seg pathseg, int name) kern_pathconf(struct thread *td, char *path, enum uio_seg pathseg, int name,
u_long flags)
{ {
struct nameidata nd; struct nameidata nd;
int error, vfslocked; int error, vfslocked;
NDINIT(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF | MPSAFE | NDINIT(&nd, LOOKUP, LOCKSHARED | LOCKLEAF | MPSAFE | AUDITVNODE1 |
AUDITVNODE1, pathseg, path, td); flags, pathseg, path, td);
if ((error = namei(&nd)) != 0) if ((error = namei(&nd)) != 0)
return (error); return (error);
vfslocked = NDHASGIANT(&nd); vfslocked = NDHASGIANT(&nd);

View File

@ -145,7 +145,7 @@ int kern_open(struct thread *td, char *path, enum uio_seg pathseg,
int kern_openat(struct thread *td, int fd, char *path, int kern_openat(struct thread *td, int fd, char *path,
enum uio_seg pathseg, int flags, int mode); enum uio_seg pathseg, int flags, int mode);
int kern_pathconf(struct thread *td, char *path, enum uio_seg pathseg, int kern_pathconf(struct thread *td, char *path, enum uio_seg pathseg,
int name); int name, u_long flags);
int kern_pipe(struct thread *td, int fildes[2]); int kern_pipe(struct thread *td, int fildes[2]);
int kern_preadv(struct thread *td, int fd, struct uio *auio, off_t offset); int kern_preadv(struct thread *td, int fd, struct uio *auio, off_t offset);
int kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int kern_ptrace(struct thread *td, int req, pid_t pid, void *addr,