aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cddl/lib/libzfs/Makefile1
-rw-r--r--contrib/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc10
-rw-r--r--contrib/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h3
-rw-r--r--contrib/openbsm/libbsm/bsm_wrappers.c4
-rw-r--r--include/dirent.h23
-rw-r--r--lib/libarchive/Makefile2
-rw-r--r--lib/libc/gen/Makefile.inc10
-rw-r--r--lib/libc/gen/Symbol.map40
-rw-r--r--lib/libc/gen/closedir.c1
-rw-r--r--lib/libc/gen/devname-compat11.c50
-rw-r--r--lib/libc/gen/fts-compat.c33
-rw-r--r--lib/libc/gen/fts-compat.h10
-rw-r--r--lib/libc/gen/fts-compat11.c1199
-rw-r--r--lib/libc/gen/fts-compat11.h95
-rw-r--r--lib/libc/gen/ftw-compat11.c98
-rw-r--r--lib/libc/gen/gen-compat.h57
-rw-r--r--lib/libc/gen/gen-private.h6
-rw-r--r--lib/libc/gen/getmntinfo-compat11.c72
-rw-r--r--lib/libc/gen/glob-compat11.c1093
-rw-r--r--lib/libc/gen/glob-compat11.h72
-rw-r--r--lib/libc/gen/nftw-compat11.c115
-rw-r--r--lib/libc/gen/opendir.c1
-rw-r--r--lib/libc/gen/readdir-compat11.c120
-rw-r--r--lib/libc/gen/readdir.c32
-rw-r--r--lib/libc/gen/scandir-compat11.c174
-rw-r--r--lib/libc/gen/scandir.c13
-rw-r--r--lib/libc/gen/telldir.h5
-rw-r--r--lib/libc/include/compat.h21
-rw-r--r--lib/libc/include/libc_private.h3
-rw-r--r--lib/libc/sys/Makefile.inc2
-rw-r--r--lib/libc/sys/Symbol.map41
-rw-r--r--lib/libc/sys/getdents.c41
-rw-r--r--lib/libc/sys/getdirentries.28
-rw-r--r--lib/libc/sys/lstat.c43
-rw-r--r--lib/libc/sys/mknod.c45
-rw-r--r--lib/libc/sys/stat.c43
-rw-r--r--lib/libc/sys/statfs.26
-rw-r--r--lib/libkvm/kvm_proc.c1
-rw-r--r--lib/libmilter/Makefile1
-rw-r--r--lib/libprocstat/Makefile4
-rw-r--r--lib/libprocstat/Symbol.map8
-rw-r--r--lib/libprocstat/libprocstat.c12
-rw-r--r--lib/libprocstat/libprocstat.h6
-rw-r--r--lib/libprocstat/libprocstat_compat.c144
-rw-r--r--lib/libufs/libufs.h4
-rw-r--r--sbin/badsect/badsect.c13
-rw-r--r--sbin/fsck_ffs/suj.c8
-rw-r--r--share/man/man5/acct.58
-rw-r--r--share/man/man5/dir.531
-rw-r--r--sys/bsm/audit.h4
-rw-r--r--sys/cddl/compat/opensolaris/sys/dirent.h4
-rw-r--r--sys/compat/freebsd32/capabilities.conf5
-rw-r--r--sys/compat/freebsd32/freebsd32.h57
-rw-r--r--sys/compat/freebsd32/freebsd32_misc.c214
-rw-r--r--sys/compat/freebsd32/syscalls.master77
-rw-r--r--sys/compat/linux/linux_file.c28
-rw-r--r--sys/dev/snp/snp.c8
-rw-r--r--sys/fs/devfs/devfs_devs.c14
-rw-r--r--sys/fs/devfs/devfs_vnops.c1
-rw-r--r--sys/fs/fdescfs/fdesc_vnops.c2
-rw-r--r--sys/fs/nandfs/nandfs_fs.h2
-rw-r--r--sys/fs/nfs/nfsport.h6
-rw-r--r--sys/fs/nfsclient/nfs_clrpcops.c68
-rw-r--r--sys/fs/nfsclient/nfs_clvnops.c2
-rw-r--r--sys/fs/nfsserver/nfs_nfsdport.c39
-rw-r--r--sys/kern/capabilities.conf5
-rw-r--r--sys/kern/kern_acct.c9
-rw-r--r--sys/kern/kern_descrip.c53
-rw-r--r--sys/kern/kern_proc.c11
-rw-r--r--sys/kern/makesyscalls.sh37
-rw-r--r--sys/kern/sys_socket.c21
-rw-r--r--sys/kern/syscalls.master64
-rw-r--r--sys/kern/tty.c2
-rw-r--r--sys/kern/tty_pts.c2
-rw-r--r--sys/kern/vfs_syscalls.c602
-rw-r--r--sys/kern/vfs_vnops.c6
-rw-r--r--sys/nlm/nlm_advlock.c5
-rw-r--r--sys/security/audit/audit_private.h8
-rw-r--r--sys/sys/_types.h6
-rw-r--r--sys/sys/acct.h35
-rw-r--r--sys/sys/dirent.h43
-rw-r--r--sys/sys/mount.h32
-rw-r--r--sys/sys/param.h2
-rw-r--r--sys/sys/stat.h63
-rw-r--r--sys/sys/syscallsubr.h11
-rw-r--r--sys/sys/tty.h2
-rw-r--r--sys/sys/user.h74
-rw-r--r--sys/sys/vnode.h9
-rw-r--r--sys/vm/swap_pager.c27
-rw-r--r--sys/vm/vm_object.c3
-rw-r--r--sys/vm/vm_param.h2
-rw-r--r--usr.bin/kdump/kdump.c1
-rw-r--r--usr.bin/lastcomm/lastcomm.c12
-rw-r--r--usr.bin/lastcomm/readrec.c94
-rw-r--r--usr.sbin/pstat/pstat.c2
-rw-r--r--usr.sbin/sa/extern.h2
-rw-r--r--usr.sbin/sa/main.c2
97 files changed, 4966 insertions, 644 deletions
diff --git a/cddl/lib/libzfs/Makefile b/cddl/lib/libzfs/Makefile
index a13c50281cd8..e8de72f18275 100644
--- a/cddl/lib/libzfs/Makefile
+++ b/cddl/lib/libzfs/Makefile
@@ -37,6 +37,7 @@ SRCS+= libzfs_changelist.c \
zprop_common.c \
WARNS?= 0
+SHLIB_MAJOR= 3
CSTD= c99
CFLAGS+= -DZFS_NO_ACL
CFLAGS+= -I${SRCTOP}/sbin/mount
diff --git a/contrib/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc b/contrib/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc
index 7328a5c0ac18..4b59a39ee272 100644
--- a/contrib/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc
+++ b/contrib/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc
@@ -223,7 +223,8 @@ static void kernel_stat_to_stat(struct kernel_stat *in, struct stat *out) {
uptr internal_stat(const char *path, void *buf) {
#if SANITIZER_FREEBSD
- return internal_syscall(SYSCALL(stat), path, buf);
+ return internal_syscall(SYSCALL(fstatat), AT_FDCWD, (uptr)path,
+ (uptr)buf, 0);
#elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path,
(uptr)buf, 0);
@@ -247,7 +248,8 @@ uptr internal_stat(const char *path, void *buf) {
uptr internal_lstat(const char *path, void *buf) {
#if SANITIZER_FREEBSD
- return internal_syscall(SYSCALL(lstat), path, buf);
+ return internal_syscall(SYSCALL(fstatat), AT_FDCWD, (uptr)path,
+ (uptr)buf, AT_SYMLINK_NOFOLLOW);
#elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
return internal_syscall(SYSCALL(newfstatat), AT_FDCWD, (uptr)path,
(uptr)buf, AT_SYMLINK_NOFOLLOW);
@@ -590,7 +592,9 @@ uptr internal_getppid() {
}
uptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count) {
-#if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
+#if SANITIZER_FREEBSD
+ return internal_syscall(SYSCALL(getdirentries), fd, (uptr)dirp, count, NULL);
+#elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS
return internal_syscall(SYSCALL(getdents64), fd, (uptr)dirp, count);
#else
return internal_syscall(SYSCALL(getdents), fd, (uptr)dirp, count);
diff --git a/contrib/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h b/contrib/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h
index 5cbd78d3c1bf..d7ce7b501f7b 100644
--- a/contrib/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h
+++ b/contrib/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h
@@ -489,7 +489,8 @@ namespace __sanitizer {
};
#elif SANITIZER_FREEBSD
struct __sanitizer_dirent {
- unsigned int d_fileno;
+ unsigned long long d_fileno;
+ unsigned long long d_off;
unsigned short d_reclen;
// more fields that we don't care about
};
diff --git a/contrib/openbsm/libbsm/bsm_wrappers.c b/contrib/openbsm/libbsm/bsm_wrappers.c
index ca367c957837..cd40a6555a54 100644
--- a/contrib/openbsm/libbsm/bsm_wrappers.c
+++ b/contrib/openbsm/libbsm/bsm_wrappers.c
@@ -264,12 +264,14 @@ audit_set_terminal_host(uint32_t *m)
int
audit_set_terminal_id(au_tid_t *tid)
{
+ dev_t port;
int ret;
if (tid == NULL)
return (kAUBadParamErr);
- if ((ret = audit_set_terminal_port(&tid->port)) != kAUNoErr)
+ if ((ret = audit_set_terminal_port(&port)) != kAUNoErr)
return (ret);
+ tid->port = port;
return (audit_set_terminal_host(&tid->machine));
}
diff --git a/include/dirent.h b/include/dirent.h
index 1ab949ccb378..e98752683c8e 100644
--- a/include/dirent.h
+++ b/include/dirent.h
@@ -41,6 +41,25 @@
#include <sys/_types.h>
#include <sys/dirent.h>
+#if __BSD_VISIBLE
+
+#ifndef _SIZE_T_DECLARED
+typedef __size_t size_t;
+#define _SIZE_T_DECLARED
+#endif
+
+#ifndef _SSIZE_T_DECLARED
+typedef __ssize_t ssize_t;
+#define _SSIZE_T_DECLARED
+#endif
+
+#ifndef _OFF_T_DECLARED
+typedef __off_t off_t;
+#define _OFF_T_DECLARED
+#endif
+
+#endif /* __BSD_VISIBLE */
+
#if __XSI_VISIBLE
#ifndef _INO_T_DECLARED
@@ -89,8 +108,8 @@ int dirfd(DIR *);
#if __BSD_VISIBLE
DIR *__opendir2(const char *, int);
int fdclosedir(DIR *);
-int getdents(int, char *, int);
-int getdirentries(int, char *, int, long *);
+ssize_t getdents(int, char *, size_t);
+ssize_t getdirentries(int, char *, size_t, off_t *);
#endif
DIR *opendir(const char *);
DIR *fdopendir(int);
diff --git a/lib/libarchive/Makefile b/lib/libarchive/Makefile
index 53d4cc994183..646ee28f6c94 100644
--- a/lib/libarchive/Makefile
+++ b/lib/libarchive/Makefile
@@ -11,7 +11,7 @@ CFLAGS+= -DHAVE_BZLIB_H=1 -DHAVE_LIBLZMA=1 -DHAVE_LZMA_H=1
# FreeBSD SHLIB_MAJOR value is managed as part of the FreeBSD system.
# It has no real relation to the libarchive version number.
-SHLIB_MAJOR= 6
+SHLIB_MAJOR= 7
CFLAGS+= -DPLATFORM_CONFIG_H=\"${.CURDIR}/config_freebsd.h\"
CFLAGS+= -I${.OBJDIR}
diff --git a/lib/libc/gen/Makefile.inc b/lib/libc/gen/Makefile.inc
index ac6e077207a8..b8a969276c5e 100644
--- a/lib/libc/gen/Makefile.inc
+++ b/lib/libc/gen/Makefile.inc
@@ -148,7 +148,15 @@ SRCS+= __getosreldate.c \
waitid.c \
wordexp.c
.if ${MK_SYMVER} == yes
-SRCS+= fts-compat.c \
+SRCS+= devname-compat11.c \
+ fts-compat.c \
+ fts-compat11.c \
+ ftw-compat11.c \
+ getmntinfo-compat11.c \
+ glob-compat11.c \
+ nftw-compat11.c \
+ readdir-compat11.c \
+ scandir-compat11.c \
unvis-compat.c
.endif
diff --git a/lib/libc/gen/Symbol.map b/lib/libc/gen/Symbol.map
index bada246e0b3c..3108f822b675 100644
--- a/lib/libc/gen/Symbol.map
+++ b/lib/libc/gen/Symbol.map
@@ -75,8 +75,6 @@ FBSD_1.0 {
ctermid;
ctermid_r;
daemon;
- devname;
- devname_r;
getdiskbyname;
dladdr;
dlclose;
@@ -128,9 +126,6 @@ FBSD_1.0 {
setfsent;
endfsent;
ftok;
- ftw;
- glob;
- globfree;
getbootfile;
getbsize;
cgetset;
@@ -163,7 +158,6 @@ FBSD_1.0 {
getloadavg;
getlogin;
getlogin_r;
- getmntinfo;
setnetgrent;
getnetgrent;
endnetgrent;
@@ -209,7 +203,6 @@ FBSD_1.0 {
lrand48;
modf;
mrand48;
- nftw;
nice;
nlist;
nrand48;
@@ -220,13 +213,9 @@ FBSD_1.0 {
pclose;
psignal;
raise;
- readdir;
- readdir_r;
readpassphrase;
getpass;
rewinddir;
- scandir;
- alphasort;
seed48;
seekdir;
user_from_uid;
@@ -314,14 +303,6 @@ FBSD_1.1 {
fdevname_r;
fdopendir;
feature_present;
- fts_children;
- fts_close;
- fts_get_clientptr;
- fts_get_stream;
- fts_open;
- fts_read;
- fts_set;
- fts_set_clientptr;
posix_spawn;
posix_spawn_file_actions_addclose;
posix_spawn_file_actions_adddup2;
@@ -408,13 +389,32 @@ FBSD_1.4 {
pthread_mutex_consistent;
pthread_mutexattr_getrobust;
pthread_mutexattr_setrobust;
- scandir_b;
stravis;
};
FBSD_1.5 {
+ alphasort;
basename;
+ devname;
+ devname_r;
dirname;
+ fts_children;
+ fts_close;
+ fts_get_clientptr;
+ fts_get_stream;
+ fts_open;
+ fts_read;
+ fts_set;
+ fts_set_clientptr;
+ ftw;
+ getmntinfo;
+ glob;
+ globfree;
+ nftw;
+ readdir;
+ readdir_r;
+ scandir;
+ scandir_b;
sem_clockwait_np;
};
diff --git a/lib/libc/gen/closedir.c b/lib/libc/gen/closedir.c
index afdab45f6c49..098bc1959eb0 100644
--- a/lib/libc/gen/closedir.c
+++ b/lib/libc/gen/closedir.c
@@ -59,6 +59,7 @@ fdclosedir(DIR *dirp)
dirp->dd_fd = -1;
dirp->dd_loc = 0;
free((void *)dirp->dd_buf);
+ free(dirp->dd_compat_de);
_reclaim_telldir(dirp);
if (__isthreaded) {
_pthread_mutex_unlock(&dirp->dd_lock);
diff --git a/lib/libc/gen/devname-compat11.c b/lib/libc/gen/devname-compat11.c
new file mode 100644
index 000000000000..70cb6f0d641e
--- /dev/null
+++ b/lib/libc/gen/devname-compat11.c
@@ -0,0 +1,50 @@
+/*-
+ * Copyright (c) 2011 Gleb Kurtsou <gleb@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include "gen-compat.h"
+
+char *
+freebsd11_devname(uint32_t dev, mode_t type)
+{
+
+ return (devname(dev, type));
+}
+
+char *
+freebsd11_devname_r(uint32_t dev, mode_t type, char *buf, int len)
+{
+
+ return (devname_r(dev, type, buf, len));
+}
+
+__sym_compat(devname, freebsd11_devname, FBSD_1.0);
+__sym_compat(devname_r, freebsd11_devname_r, FBSD_1.0);
diff --git a/lib/libc/gen/fts-compat.c b/lib/libc/gen/fts-compat.c
index 64a73e9ea28a..0415a59ec212 100644
--- a/lib/libc/gen/fts-compat.c
+++ b/lib/libc/gen/fts-compat.c
@@ -40,15 +40,19 @@ __FBSDID("$FreeBSD$");
#include "namespace.h"
#include <sys/param.h>
+#define _WANT_FREEBSD11_STATFS
#include <sys/mount.h>
+#define _WANT_FREEBSD11_STAT
#include <sys/stat.h>
+#define _WANT_FREEBSD11_DIRENT
#include <dirent.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include "gen-compat.h"
#include "fts-compat.h"
#include "un-namespace.h"
@@ -96,8 +100,8 @@ static int fts_ufslinks(FTS *, const FTSENT *);
*/
struct _fts_private {
FTS ftsp_fts;
- struct statfs ftsp_statfs;
- dev_t ftsp_dev;
+ struct freebsd11_statfs ftsp_statfs;
+ uint32_t ftsp_dev;
int ftsp_linksreliable;
};
@@ -626,7 +630,7 @@ __fts_set_clientptr_44bsd(FTS *sp, void *clientptr)
static FTSENT *
fts_build(FTS *sp, int type)
{
- struct dirent *dp;
+ struct freebsd11_dirent *dp;
FTSENT *p, *head;
int nitems;
FTSENT *cur, *tail;
@@ -738,7 +742,8 @@ fts_build(FTS *sp, int type)
/* Read the directory, attaching each entry to the `link' pointer. */
doadjust = 0;
- for (head = tail = NULL, nitems = 0; dirp && (dp = readdir(dirp));) {
+ for (head = tail = NULL, nitems = 0;
+ dirp && (dp = freebsd11_readdir(dirp));) {
dnamlen = dp->d_namlen;
if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name))
continue;
@@ -891,9 +896,9 @@ static u_short
fts_stat(FTS *sp, FTSENT *p, int follow)
{
FTSENT *t;
- dev_t dev;
- ino_t ino;
- struct stat *sbp, sb;
+ uint32_t dev;
+ uint32_t ino;
+ struct freebsd11_stat *sbp, sb;
int saved_errno;
/* If user needs stat info, stat buffer already allocated. */
@@ -916,16 +921,16 @@ fts_stat(FTS *sp, FTSENT *p, int follow)
* fail, set the errno from the stat call.
*/
if (ISSET(FTS_LOGICAL) || follow) {
- if (stat(p->fts_accpath, sbp)) {
+ if (freebsd11_stat(p->fts_accpath, sbp)) {
saved_errno = errno;
- if (!lstat(p->fts_accpath, sbp)) {
+ if (!freebsd11_lstat(p->fts_accpath, sbp)) {
errno = 0;
return (FTS_SLNONE);
}
p->fts_errno = saved_errno;
goto err;
}
- } else if (lstat(p->fts_accpath, sbp)) {
+ } else if (freebsd11_lstat(p->fts_accpath, sbp)) {
p->fts_errno = errno;
err: memset(sbp, 0, sizeof(struct stat));
return (FTS_NS);
@@ -1019,7 +1024,7 @@ fts_alloc(FTS *sp, char *name, int namelen)
struct ftsent_withstat {
FTSENT ent;
- struct stat statbuf;
+ struct freebsd11_stat statbuf;
};
/*
@@ -1145,14 +1150,14 @@ static int
fts_safe_changedir(FTS *sp, FTSENT *p, int fd, char *path)
{
int ret, oerrno, newfd;
- struct stat sb;
+ struct freebsd11_stat sb;
newfd = fd;
if (ISSET(FTS_NOCHDIR))
return (0);
if (fd < 0 && (newfd = _open(path, O_RDONLY | O_CLOEXEC, 0)) < 0)
return (-1);
- if (_fstat(newfd, &sb)) {
+ if (freebsd11_fstat(newfd, &sb)) {
ret = -1;
goto bail;
}
@@ -1187,7 +1192,7 @@ fts_ufslinks(FTS *sp, const FTSENT *ent)
* avoidance.
*/
if (priv->ftsp_dev != ent->fts_dev) {
- if (statfs(ent->fts_path, &priv->ftsp_statfs) != -1) {
+ if (freebsd11_statfs(ent->fts_path, &priv->ftsp_statfs) != -1) {
priv->ftsp_dev = ent->fts_dev;
priv->ftsp_linksreliable = 0;
for (cpp = ufslike_filesystems; *cpp; cpp++) {
diff --git a/lib/libc/gen/fts-compat.h b/lib/libc/gen/fts-compat.h
index d8fe6895f11c..4c661e5cf7cc 100644
--- a/lib/libc/gen/fts-compat.h
+++ b/lib/libc/gen/fts-compat.h
@@ -37,7 +37,7 @@ typedef struct {
struct _ftsent *fts_cur; /* current node */
struct _ftsent *fts_child; /* linked list of children */
struct _ftsent **fts_array; /* sort array */
- dev_t fts_dev; /* starting device # */
+ uint32_t fts_dev; /* starting device # */
char *fts_path; /* path for this descent */
int fts_rfd; /* fd for root */
int fts_pathlen; /* sizeof(path) */
@@ -82,9 +82,9 @@ typedef struct _ftsent {
u_short fts_pathlen; /* strlen(fts_path) */
u_short fts_namelen; /* strlen(fts_name) */
- ino_t fts_ino; /* inode */
- dev_t fts_dev; /* device */
- nlink_t fts_nlink; /* link count */
+ uint32_t fts_ino; /* inode */
+ uint32_t fts_dev; /* device */
+ uint16_t fts_nlink; /* link count */
#define FTS_ROOTPARENTLEVEL -1
#define FTS_ROOTLEVEL 0
@@ -117,7 +117,7 @@ typedef struct _ftsent {
#define FTS_SKIP 4 /* discard node */
u_short fts_instr; /* fts_set() instructions */
- struct stat *fts_statp; /* stat(2) information */
+ struct freebsd11_stat *fts_statp; /* stat(2) information */
char *fts_name; /* file name */
FTS *fts_fts; /* back pointer to main FTS */
} FTSENT;
diff --git a/lib/libc/gen/fts-compat11.c b/lib/libc/gen/fts-compat11.c
new file mode 100644
index 000000000000..7653d32752f6
--- /dev/null
+++ b/lib/libc/gen/fts-compat11.c
@@ -0,0 +1,1199 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: $OpenBSD: fts.c,v 1.22 1999/10/03 19:22:22 millert Exp $
+ */
+
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fts.c 8.6 (Berkeley) 8/14/94";
+#endif /* LIBC_SCCS and not lint */
+#endif
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/param.h>
+#define _WANT_FREEBSD11_STATFS
+#include <sys/mount.h>
+#define _WANT_FREEBSD11_STAT
+#include <sys/stat.h>
+
+#define _WANT_FREEBSD11_DIRENT
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <fts.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "gen-compat.h"
+#include "fts-compat11.h"
+#include "un-namespace.h"
+
+#include "gen-private.h"
+
+static FTSENT11 *fts_alloc(FTS11 *, char *, size_t);
+static FTSENT11 *fts_build(FTS11 *, int);
+static void fts_lfree(FTSENT11 *);
+static void fts_load(FTS11 *, FTSENT11 *);
+static size_t fts_maxarglen(char * const *);
+static void fts_padjust(FTS11 *, FTSENT11 *);
+static int fts_palloc(FTS11 *, size_t);
+static FTSENT11 *fts_sort(FTS11 *, FTSENT11 *, size_t);
+static int fts_stat(FTS11 *, FTSENT11 *, int, int);
+static int fts_safe_changedir(FTS11 *, FTSENT11 *, int, char *);
+static int fts_ufslinks(FTS11 *, const FTSENT11 *);
+
+#define ISDOT(a) (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2])))
+
+#define CLR(opt) (sp->fts_options &= ~(opt))
+#define ISSET(opt) (sp->fts_options & (opt))
+#define SET(opt) (sp->fts_options |= (opt))
+
+#define FCHDIR(sp, fd) (!ISSET(FTS_NOCHDIR) && fchdir(fd))
+
+/* fts_build flags */
+#define BCHILD 1 /* fts_children */
+#define BNAMES 2 /* fts_children, names only */
+#define BREAD 3 /* fts_read */
+
+/*
+ * Internal representation of an FTS, including extra implementation
+ * details. The FTS returned from fts_open points to this structure's
+ * ftsp_fts member (and can be cast to an _fts_private as required)
+ */
+struct _fts_private11 {
+ FTS11 ftsp_fts;
+ struct freebsd11_statfs ftsp_statfs;
+ uint32_t ftsp_dev;
+ int ftsp_linksreliable;
+};
+
+/*
+ * The "FTS_NOSTAT" option can avoid a lot of calls to stat(2) if it
+ * knows that a directory could not possibly have subdirectories. This
+ * is decided by looking at the link count: a subdirectory would
+ * increment its parent's link count by virtue of its own ".." entry.
+ * This assumption only holds for UFS-like filesystems that implement
+ * links and directories this way, so we must punt for others.
+ */
+
+static const char *ufslike_filesystems[] = {
+ "ufs",
+ "zfs",
+ "nfs",
+ "ext2fs",
+ 0
+};
+
+FTS11 *
+freebsd11_fts_open(char * const *argv, int options,
+ int (*compar)(const FTSENT11 * const *, const FTSENT11 * const *))
+{
+ struct _fts_private11 *priv;
+ FTS11 *sp;
+ FTSENT11 *p, *root;
+ FTSENT11 *parent, *tmp;
+ size_t len, nitems;
+
+ /* Options check. */
+ if (options & ~FTS_OPTIONMASK) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ /* fts_open() requires at least one path */
+ if (*argv == NULL) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ /* Allocate/initialize the stream. */
+ if ((priv = calloc(1, sizeof(*priv))) == NULL)
+ return (NULL);
+ sp = &priv->ftsp_fts;
+ sp->fts_compar = compar;
+ sp->fts_options = options;
+
+ /* Shush, GCC. */
+ tmp = NULL;
+
+ /* Logical walks turn on NOCHDIR; symbolic links are too hard. */
+ if (ISSET(FTS_LOGICAL))
+ SET(FTS_NOCHDIR);
+
+ /*
+ * Start out with 1K of path space, and enough, in any case,
+ * to hold the user's paths.
+ */
+ if (fts_palloc(sp, MAX(fts_maxarglen(argv), MAXPATHLEN)))
+ goto mem1;
+
+ /* Allocate/initialize root's parent. */
+ if ((parent = fts_alloc(sp, "", 0)) == NULL)
+ goto mem2;
+ parent->fts_level = FTS_ROOTPARENTLEVEL;
+
+ /* Allocate/initialize root(s). */
+ for (root = NULL, nitems = 0; *argv != NULL; ++argv, ++nitems) {
+ len = strlen(*argv);
+
+ p = fts_alloc(sp, *argv, len);
+ p->fts_level = FTS_ROOTLEVEL;
+ p->fts_parent = parent;
+ p->fts_accpath = p->fts_name;
+ p->fts_info = fts_stat(sp, p, ISSET(FTS_COMFOLLOW), -1);
+
+ /* Command-line "." and ".." are real directories. */
+ if (p->fts_info == FTS_DOT)
+ p->fts_info = FTS_D;
+
+ /*
+ * If comparison routine supplied, traverse in sorted
+ * order; otherwise traverse in the order specified.
+ */
+ if (compar) {
+ p->fts_link = root;
+ root = p;
+ } else {
+ p->fts_link = NULL;
+ if (root == NULL)
+ tmp = root = p;
+ else {
+ tmp->fts_link = p;
+ tmp = p;
+ }
+ }
+ }
+ if (compar && nitems > 1)
+ root = fts_sort(sp, root, nitems);
+
+ /*
+ * Allocate a dummy pointer and make fts_read think that we've just
+ * finished the node before the root(s); set p->fts_info to FTS_INIT
+ * so that everything about the "current" node is ignored.
+ */
+ if ((sp->fts_cur = fts_alloc(sp, "", 0)) == NULL)
+ goto mem3;
+ sp->fts_cur->fts_link = root;
+ sp->fts_cur->fts_info = FTS_INIT;
+
+ /*
+ * If using chdir(2), grab a file descriptor pointing to dot to ensure
+ * that we can get back here; this could be avoided for some paths,
+ * but almost certainly not worth the effort. Slashes, symbolic links,
+ * and ".." are all fairly nasty problems. Note, if we can't get the
+ * descriptor we run anyway, just more slowly.
+ */
+ if (!ISSET(FTS_NOCHDIR) &&
+ (sp->fts_rfd = _open(".", O_RDONLY | O_CLOEXEC, 0)) < 0)
+ SET(FTS_NOCHDIR);
+
+ return (sp);
+
+mem3: fts_lfree(root);
+ free(parent);
+mem2: free(sp->fts_path);
+mem1: free(sp);
+ return (NULL);
+}
+
+static void
+fts_load(FTS11 *sp, FTSENT11 *p)
+{
+ size_t len;
+ char *cp;
+
+ /*
+ * Load the stream structure for the next traversal. Since we don't
+ * actually enter the directory until after the preorder visit, set
+ * the fts_accpath field specially so the chdir gets done to the right
+ * place and the user can access the first node. From fts_open it's
+ * known that the path will fit.
+ */
+ len = p->fts_pathlen = p->fts_namelen;
+ memmove(sp->fts_path, p->fts_name, len + 1);
+ if ((cp = strrchr(p->fts_name, '/')) && (cp != p->fts_name || cp[1])) {
+ len = strlen(++cp);
+ memmove(p->fts_name, cp, len + 1);
+ p->fts_namelen = len;
+ }
+ p->fts_accpath = p->fts_path = sp->fts_path;
+ sp->fts_dev = p->fts_dev;
+}
+
+int
+freebsd11_fts_close(FTS11 *sp)
+{
+ FTSENT11 *freep, *p;
+ int saved_errno;
+
+ /*
+ * This still works if we haven't read anything -- the dummy structure
+ * points to the root list, so we step through to the end of the root
+ * list which has a valid parent pointer.
+ */
+ if (sp->fts_cur) {
+ for (p = sp->fts_cur; p->fts_level >= FTS_ROOTLEVEL;) {
+ freep = p;
+ p = p->fts_link != NULL ? p->fts_link : p->fts_parent;
+ free(freep);
+ }
+ free(p);
+ }
+
+ /* Free up child linked list, sort array, path buffer. */
+ if (sp->fts_child)
+ fts_lfree(sp->fts_child);
+ if (sp->fts_array)
+ free(sp->fts_array);
+ free(sp->fts_path);
+
+ /* Return to original directory, save errno if necessary. */
+ if (!ISSET(FTS_NOCHDIR)) {
+ saved_errno = fchdir(sp->fts_rfd) ? errno : 0;
+ (void)_close(sp->fts_rfd);
+
+ /* Set errno and return. */
+ if (saved_errno != 0) {
+ /* Free up the stream pointer. */
+ free(sp);
+ errno = saved_errno;
+ return (-1);
+ }
+ }
+
+ /* Free up the stream pointer. */
+ free(sp);
+ return (0);
+}
+
+/*
+ * Special case of "/" at the end of the path so that slashes aren't
+ * appended which would cause paths to be written as "....//foo".
+ */
+#define NAPPEND(p) \
+ (p->fts_path[p->fts_pathlen - 1] == '/' \
+ ? p->fts_pathlen - 1 : p->fts_pathlen)
+
+FTSENT11 *
+freebsd11_fts_read(FTS11 *sp)
+{
+ FTSENT11 *p, *tmp;
+ int instr;
+ char *t;
+ int saved_errno;
+
+ /* If finished or unrecoverable error, return NULL. */
+ if (sp->fts_cur == NULL || ISSET(FTS_STOP))
+ return (NULL);
+
+ /* Set current node pointer. */
+ p = sp->fts_cur;
+
+ /* Save and zero out user instructions. */
+ instr = p->fts_instr;
+ p->fts_instr = FTS_NOINSTR;
+
+ /* Any type of file may be re-visited; re-stat and re-turn. */
+ if (instr == FTS_AGAIN) {
+ p->fts_info = fts_stat(sp, p, 0, -1);
+ return (p);
+ }
+
+ /*
+ * Following a symlink -- SLNONE test allows application to see
+ * SLNONE and recover. If indirecting through a symlink, have
+ * keep a pointer to current location. If unable to get that
+ * pointer, follow fails.
+ */
+ if (instr == FTS_FOLLOW &&
+ (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) {
+ p->fts_info = fts_stat(sp, p, 1, -1);
+ if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
+ if ((p->fts_symfd = _open(".", O_RDONLY | O_CLOEXEC,
+ 0)) < 0) {
+ p->fts_errno = errno;
+ p->fts_info = FTS_ERR;
+ } else
+ p->fts_flags |= FTS_SYMFOLLOW;
+ }
+ return (p);
+ }
+
+ /* Directory in pre-order. */
+ if (p->fts_info == FTS_D) {
+ /* If skipped or crossed mount point, do post-order visit. */
+ if (instr == FTS_SKIP ||
+ (ISSET(FTS_XDEV) && p->fts_dev != sp->fts_dev)) {
+ if (p->fts_flags & FTS_SYMFOLLOW)
+ (void)_close(p->fts_symfd);
+ if (sp->fts_child) {
+ fts_lfree(sp->fts_child);
+ sp->fts_child = NULL;
+ }
+ p->fts_info = FTS_DP;
+ return (p);
+ }
+
+ /* Rebuild if only read the names and now traversing. */
+ if (sp->fts_child != NULL && ISSET(FTS_NAMEONLY)) {
+ CLR(FTS_NAMEONLY);
+ fts_lfree(sp->fts_child);
+ sp->fts_child = NULL;
+ }
+
+ /*
+ * Cd to the subdirectory.
+ *
+ * If have already read and now fail to chdir, whack the list
+ * to make the names come out right, and set the parent errno
+ * so the application will eventually get an error condition.
+ * Set the FTS_DONTCHDIR flag so that when we logically change
+ * directories back to the parent we don't do a chdir.
+ *
+ * If haven't read do so. If the read fails, fts_build sets
+ * FTS_STOP or the fts_info field of the node.
+ */
+ if (sp->fts_child != NULL) {
+ if (fts_safe_changedir(sp, p, -1, p->fts_accpath)) {
+ p->fts_errno = errno;
+ p->fts_flags |= FTS_DONTCHDIR;
+ for (p = sp->fts_child; p != NULL;
+ p = p->fts_link)
+ p->fts_accpath =
+ p->fts_parent->fts_accpath;
+ }
+ } else if ((sp->fts_child = fts_build(sp, BREAD)) == NULL) {
+ if (ISSET(FTS_STOP))
+ return (NULL);
+ return (p);
+ }
+ p = sp->fts_child;
+ sp->fts_child = NULL;
+ goto name;
+ }
+
+ /* Move to the next node on this level. */
+next: tmp = p;
+ if ((p = p->fts_link) != NULL) {
+ /*
+ * If reached the top, return to the original directory (or
+ * the root of the tree), and load the paths for the next root.
+ */
+ if (p->fts_level == FTS_ROOTLEVEL) {
+ if (FCHDIR(sp, sp->fts_rfd)) {
+ SET(FTS_STOP);
+ return (NULL);
+ }
+ free(tmp);
+ fts_load(sp, p);
+ return (sp->fts_cur = p);
+ }
+
+ /*
+ * User may have called fts_set on the node. If skipped,
+ * ignore. If followed, get a file descriptor so we can
+ * get back if necessary.
+ */
+ if (p->fts_instr == FTS_SKIP) {
+ free(tmp);
+ goto next;
+ }
+ if (p->fts_instr == FTS_FOLLOW) {
+ p->fts_info = fts_stat(sp, p, 1, -1);
+ if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
+ if ((p->fts_symfd =
+ _open(".", O_RDONLY | O_CLOEXEC, 0)) < 0) {
+ p->fts_errno = errno;
+ p->fts_info = FTS_ERR;
+ } else
+ p->fts_flags |= FTS_SYMFOLLOW;
+ }
+ p->fts_instr = FTS_NOINSTR;
+ }
+
+ free(tmp);
+
+name: t = sp->fts_path + NAPPEND(p->fts_parent);
+ *t++ = '/';
+ memmove(t, p->fts_name, p->fts_namelen + 1);
+ return (sp->fts_cur = p);
+ }
+
+ /* Move up to the parent node. */
+ p = tmp->fts_parent;
+
+ if (p->fts_level == FTS_ROOTPARENTLEVEL) {
+ /*
+ * Done; free everything up and set errno to 0 so the user
+ * can distinguish between error and EOF.
+ */
+ free(tmp);
+ free(p);
+ errno = 0;
+ return (sp->fts_cur = NULL);
+ }
+
+ /* NUL terminate the pathname. */
+ sp->fts_path[p->fts_pathlen] = '\0';
+
+ /*
+ * Return to the parent directory. If at a root node or came through
+ * a symlink, go back through the file descriptor. Otherwise, cd up
+ * one directory.
+ */
+ if (p->fts_level == FTS_ROOTLEVEL) {
+ if (FCHDIR(sp, sp->fts_rfd)) {
+ SET(FTS_STOP);
+ return (NULL);
+ }
+ } else if (p->fts_flags & FTS_SYMFOLLOW) {
+ if (FCHDIR(sp, p->fts_symfd)) {
+ saved_errno = errno;
+ (void)_close(p->fts_symfd);
+ errno = saved_errno;
+ SET(FTS_STOP);
+ return (NULL);
+ }
+ (void)_close(p->fts_symfd);
+ } else if (!(p->fts_flags & FTS_DONTCHDIR) &&
+ fts_safe_changedir(sp, p->fts_parent, -1, "..")) {
+ SET(FTS_STOP);
+ return (NULL);
+ }
+ free(tmp);
+ p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP;
+ return (sp->fts_cur = p);
+}
+
+/*
+ * Fts_set takes the stream as an argument although it's not used in this
+ * implementation; it would be necessary if anyone wanted to add global
+ * semantics to fts using fts_set. An error return is allowed for similar
+ * reasons.
+ */
+/* ARGSUSED */
+int
+freebsd11_fts_set(FTS11 *sp, FTSENT11 *p, int instr)
+{
+ if (instr != 0 && instr != FTS_AGAIN && instr != FTS_FOLLOW &&
+ instr != FTS_NOINSTR && instr != FTS_SKIP) {
+ errno = EINVAL;
+ return (1);
+ }
+ p->fts_instr = instr;
+ return (0);
+}
+
+FTSENT11 *
+freebsd11_fts_children(FTS11 *sp, int instr)
+{
+ FTSENT11 *p;
+ int fd, rc, serrno;
+
+ if (instr != 0 && instr != FTS_NAMEONLY) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ /* Set current node pointer. */
+ p = sp->fts_cur;
+
+ /*
+ * Errno set to 0 so user can distinguish empty directory from
+ * an error.
+ */
+ errno = 0;
+
+ /* Fatal errors stop here. */
+ if (ISSET(FTS_STOP))
+ return (NULL);
+
+ /* Return logical hierarchy of user's arguments. */
+ if (p->fts_info == FTS_INIT)
+ return (p->fts_link);
+
+ /*
+ * If not a directory being visited in pre-order, stop here. Could
+ * allow FTS_DNR, assuming the user has fixed the problem, but the
+ * same effect is available with FTS_AGAIN.
+ */
+ if (p->fts_info != FTS_D /* && p->fts_info != FTS_DNR */)
+ return (NULL);
+
+ /* Free up any previous child list. */
+ if (sp->fts_child != NULL)
+ fts_lfree(sp->fts_child);
+
+ if (instr == FTS_NAMEONLY) {
+ SET(FTS_NAMEONLY);
+ instr = BNAMES;
+ } else
+ instr = BCHILD;
+
+ /*
+ * If using chdir on a relative path and called BEFORE fts_read does
+ * its chdir to the root of a traversal, we can lose -- we need to
+ * chdir into the subdirectory, and we don't know where the current
+ * directory is, so we can't get back so that the upcoming chdir by
+ * fts_read will work.
+ */
+ if (p->fts_level != FTS_ROOTLEVEL || p->fts_accpath[0] == '/' ||
+ ISSET(FTS_NOCHDIR))
+ return (sp->fts_child = fts_build(sp, instr));
+
+ if ((fd = _open(".", O_RDONLY | O_CLOEXEC, 0)) < 0)
+ return (NULL);
+ sp->fts_child = fts_build(sp, instr);
+ serrno = (sp->fts_child == NULL) ? errno : 0;
+ rc = fchdir(fd);
+ if (rc < 0 && serrno == 0)
+ serrno = errno;
+ (void)_close(fd);
+ errno = serrno;
+ if (rc < 0)
+ return (NULL);
+ return (sp->fts_child);
+}
+
+#ifndef freebsd11_fts_get_clientptr
+#error "freebsd11_fts_get_clientptr not defined"
+#endif
+
+void *
+(freebsd11_fts_get_clientptr)(FTS11 *sp)
+{
+
+ return (freebsd11_fts_get_clientptr(sp));
+}
+
+#ifndef freebsd11_fts_get_stream
+#error "freebsd11_fts_get_stream not defined"
+#endif
+
+FTS11 *
+(freebsd11_fts_get_stream)(FTSENT11 *p)
+{
+ return (freebsd11_fts_get_stream(p));
+}
+
+void
+freebsd11_fts_set_clientptr(FTS11 *sp, void *clientptr)
+{
+
+ sp->fts_clientptr = clientptr;
+}
+
+/*
+ * This is the tricky part -- do not casually change *anything* in here. The
+ * idea is to build the linked list of entries that are used by fts_children
+ * and fts_read. There are lots of special cases.
+ *
+ * The real slowdown in walking the tree is the stat calls. If FTS_NOSTAT is
+ * set and it's a physical walk (so that symbolic links can't be directories),
+ * we can do things quickly. First, if it's a 4.4BSD file system, the type
+ * of the file is in the directory entry. Otherwise, we assume that the number
+ * of subdirectories in a node is equal to the number of links to the parent.
+ * The former skips all stat calls. The latter skips stat calls in any leaf
+ * directories and for any files after the subdirectories in the directory have
+ * been found, cutting the stat calls by about 2/3.
+ */
+static FTSENT11 *
+fts_build(FTS11 *sp, int type)
+{
+ struct freebsd11_dirent *dp;
+ FTSENT11 *p, *head;
+ FTSENT11 *cur, *tail;
+ DIR *dirp;
+ void *oldaddr;
+ char *cp;
+ int cderrno, descend, oflag, saved_errno, nostat, doadjust;
+ long level;
+ long nlinks; /* has to be signed because -1 is a magic value */
+ size_t dnamlen, len, maxlen, nitems;
+
+ /* Set current node pointer. */
+ cur = sp->fts_cur;
+
+ /*
+ * Open the directory for reading. If this fails, we're done.
+ * If being called from fts_read, set the fts_info field.
+ */
+#ifdef FTS_WHITEOUT
+ if (ISSET(FTS_WHITEOUT))
+ oflag = DTF_NODUP | DTF_REWIND;
+ else
+ oflag = DTF_HIDEW | DTF_NODUP | DTF_REWIND;
+#else
+#define __opendir2(path, flag) opendir(path)
+#endif
+ if ((dirp = __opendir2(cur->fts_accpath, oflag)) == NULL) {
+ if (type == BREAD) {
+ cur->fts_info = FTS_DNR;
+ cur->fts_errno = errno;
+ }
+ return (NULL);
+ }
+
+ /*
+ * Nlinks is the number of possible entries of type directory in the
+ * directory if we're cheating on stat calls, 0 if we're not doing
+ * any stat calls at all, -1 if we're doing stats on everything.
+ */
+ if (type == BNAMES) {
+ nlinks = 0;
+ /* Be quiet about nostat, GCC. */
+ nostat = 0;
+ } else if (ISSET(FTS_NOSTAT) && ISSET(FTS_PHYSICAL)) {
+ if (fts_ufslinks(sp, cur))
+ nlinks = cur->fts_nlink - (ISSET(FTS_SEEDOT) ? 0 : 2);
+ else
+ nlinks = -1;
+ nostat = 1;
+ } else {
+ nlinks = -1;
+ nostat = 0;
+ }
+
+#ifdef notdef
+ (void)printf("nlinks == %d (cur: %d)\n", nlinks, cur->fts_nlink);
+ (void)printf("NOSTAT %d PHYSICAL %d SEEDOT %d\n",
+ ISSET(FTS_NOSTAT), ISSET(FTS_PHYSICAL), ISSET(FTS_SEEDOT));
+#endif
+ /*
+ * If we're going to need to stat anything or we want to descend
+ * and stay in the directory, chdir. If this fails we keep going,
+ * but set a flag so we don't chdir after the post-order visit.
+ * We won't be able to stat anything, but we can still return the
+ * names themselves. Note, that since fts_read won't be able to
+ * chdir into the directory, it will have to return different path
+ * names than before, i.e. "a/b" instead of "b". Since the node
+ * has already been visited in pre-order, have to wait until the
+ * post-order visit to return the error. There is a special case
+ * here, if there was nothing to stat then it's not an error to
+ * not be able to stat. This is all fairly nasty. If a program
+ * needed sorted entries or stat information, they had better be
+ * checking FTS_NS on the returned nodes.
+ */
+ cderrno = 0;
+ if (nlinks || type == BREAD) {
+ if (fts_safe_changedir(sp, cur, _dirfd(dirp), NULL)) {
+ if (nlinks && type == BREAD)
+ cur->fts_errno = errno;
+ cur->fts_flags |= FTS_DONTCHDIR;
+ descend = 0;
+ cderrno = errno;
+ } else
+ descend = 1;
+ } else
+ descend = 0;
+
+ /*
+ * Figure out the max file name length that can be stored in the
+ * current path -- the inner loop allocates more path as necessary.
+ * We really wouldn't have to do the maxlen calculations here, we
+ * could do them in fts_read before returning the path, but it's a
+ * lot easier here since the length is part of the dirent structure.
+ *
+ * If not changing directories set a pointer so that can just append
+ * each new name into the path.
+ */
+ len = NAPPEND(cur);
+ if (ISSET(FTS_NOCHDIR)) {
+ cp = sp->fts_path + len;
+ *cp++ = '/';
+ } else {
+ /* GCC, you're too verbose. */
+ cp = NULL;
+ }
+ len++;
+ maxlen = sp->fts_pathlen - len;
+
+ level = cur->fts_level + 1;
+
+ /* Read the directory, attaching each entry to the `link' pointer. */
+ doadjust = 0;
+ for (head = tail = NULL, nitems = 0;
+ dirp && (dp = freebsd11_readdir(dirp));) {
+ dnamlen = dp->d_namlen;
+ if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name))
+ continue;
+
+ if ((p = fts_alloc(sp, dp->d_name, dnamlen)) == NULL)
+ goto mem1;
+ if (dnamlen >= maxlen) { /* include space for NUL */
+ oldaddr = sp->fts_path;
+ if (fts_palloc(sp, dnamlen + len + 1)) {
+ /*
+ * No more memory for path or structures. Save
+ * errno, free up the current structure and the
+ * structures already allocated.
+ */
+mem1: saved_errno = errno;
+ if (p)
+ free(p);
+ fts_lfree(head);
+ (void)closedir(dirp);
+ cur->fts_info = FTS_ERR;
+ SET(FTS_STOP);
+ errno = saved_errno;
+ return (NULL);
+ }
+ /* Did realloc() change the pointer? */
+ if (oldaddr != sp->fts_path) {
+ doadjust = 1;
+ if (ISSET(FTS_NOCHDIR))
+ cp = sp->fts_path + len;
+ }
+ maxlen = sp->fts_pathlen - len;
+ }
+
+ p->fts_level = level;
+ p->fts_parent = sp->fts_cur;
+ p->fts_pathlen = len + dnamlen;
+
+#ifdef FTS_WHITEOUT
+ if (dp->d_type == DT_WHT)
+ p->fts_flags |= FTS_ISW;
+#endif
+
+ if (cderrno) {
+ if (nlinks) {
+ p->fts_info = FTS_NS;
+ p->fts_errno = cderrno;
+ } else
+ p->fts_info = FTS_NSOK;
+ p->fts_accpath = cur->fts_accpath;
+ } else if (nlinks == 0
+#ifdef DT_DIR
+ || (nostat &&
+ dp->d_type != DT_DIR && dp->d_type != DT_UNKNOWN)
+#endif
+ ) {
+ p->fts_accpath =
+ ISSET(FTS_NOCHDIR) ? p->fts_path : p->fts_name;
+ p->fts_info = FTS_NSOK;
+ } else {
+ /* Build a file name for fts_stat to stat. */
+ if (ISSET(FTS_NOCHDIR)) {
+ p->fts_accpath = p->fts_path;
+ memmove(cp, p->fts_name, p->fts_namelen + 1);
+ p->fts_info = fts_stat(sp, p, 0, _dirfd(dirp));
+ } else {
+ p->fts_accpath = p->fts_name;
+ p->fts_info = fts_stat(sp, p, 0, -1);
+ }
+
+ /* Decrement link count if applicable. */
+ if (nlinks > 0 && (p->fts_info == FTS_D ||
+ p->fts_info == FTS_DC || p->fts_info == FTS_DOT))
+ --nlinks;
+ }
+
+ /* We walk in directory order so "ls -f" doesn't get upset. */
+ p->fts_link = NULL;
+ if (head == NULL)
+ head = tail = p;
+ else {
+ tail->fts_link = p;
+ tail = p;
+ }
+ ++nitems;
+ }
+ if (dirp)
+ (void)closedir(dirp);
+
+ /*
+ * If realloc() changed the address of the path, adjust the
+ * addresses for the rest of the tree and the dir list.
+ */
+ if (doadjust)
+ fts_padjust(sp, head);
+
+ /*
+ * If not changing directories, reset the path back to original
+ * state.
+ */
+ if (ISSET(FTS_NOCHDIR))
+ sp->fts_path[cur->fts_pathlen] = '\0';
+
+ /*
+ * If descended after called from fts_children or after called from
+ * fts_read and nothing found, get back. At the root level we use
+ * the saved fd; if one of fts_open()'s arguments is a relative path
+ * to an empty directory, we wind up here with no other way back. If
+ * can't get back, we're done.
+ */
+ if (descend && (type == BCHILD || !nitems) &&
+ (cur->fts_level == FTS_ROOTLEVEL ?
+ FCHDIR(sp, sp->fts_rfd) :
+ fts_safe_changedir(sp, cur->fts_parent, -1, ".."))) {
+ fts_lfree(head);
+ cur->fts_info = FTS_ERR;
+ SET(FTS_STOP);
+ return (NULL);
+ }
+
+ /* If didn't find anything, return NULL. */
+ if (!nitems) {
+ if (type == BREAD)
+ cur->fts_info = FTS_DP;
+ return (NULL);
+ }
+
+ /* Sort the entries. */
+ if (sp->fts_compar && nitems > 1)
+ head = fts_sort(sp, head, nitems);
+ return (head);
+}
+
+static int
+fts_stat(FTS11 *sp, FTSENT11 *p, int follow, int dfd)
+{
+ FTSENT11 *t;
+ uint32_t dev;
+ uint32_t ino;
+ struct freebsd11_stat *sbp, sb;
+ int saved_errno;
+ const char *path;
+
+ if (dfd == -1)
+ path = p->fts_accpath, dfd = AT_FDCWD;
+ else
+ path = p->fts_name;
+
+ /* If user needs stat info, stat buffer already allocated. */
+ sbp = ISSET(FTS_NOSTAT) ? &sb : p->fts_statp;
+
+#ifdef FTS_WHITEOUT
+ /* Check for whiteout. */
+ if (p->fts_flags & FTS_ISW) {
+ if (sbp != &sb) {
+ memset(sbp, '\0', sizeof(*sbp));
+ sbp->st_mode = S_IFWHT;
+ }
+ return (FTS_W);
+ }
+#endif
+
+ /*
+ * If doing a logical walk, or application requested FTS_FOLLOW, do
+ * a stat(2). If that fails, check for a non-existent symlink. If
+ * fail, set the errno from the stat call.
+ */
+ if (ISSET(FTS_LOGICAL) || follow) {
+ if (freebsd11_fstatat(dfd, path, sbp, 0)) {
+ saved_errno = errno;
+ if (freebsd11_fstatat(dfd, path, sbp,
+ AT_SYMLINK_NOFOLLOW)) {
+ p->fts_errno = saved_errno;
+ goto err;
+ }
+ errno = 0;
+ if (S_ISLNK(sbp->st_mode))
+ return (FTS_SLNONE);
+ }
+ } else if (freebsd11_fstatat(dfd, path, sbp, AT_SYMLINK_NOFOLLOW)) {
+ p->fts_errno = errno;
+err: memset(sbp, 0, sizeof(*sbp));
+ return (FTS_NS);
+ }
+
+ if (S_ISDIR(sbp->st_mode)) {
+ /*
+ * Set the device/inode. Used to find cycles and check for
+ * crossing mount points. Also remember the link count, used
+ * in fts_build to limit the number of stat calls. It is
+ * understood that these fields are only referenced if fts_info
+ * is set to FTS_D.
+ */
+ dev = p->fts_dev = sbp->st_dev;
+ ino = p->fts_ino = sbp->st_ino;
+ p->fts_nlink = sbp->st_nlink;
+
+ if (ISDOT(p->fts_name))
+ return (FTS_DOT);
+
+ /*
+ * Cycle detection is done by brute force when the directory
+ * is first encountered. If the tree gets deep enough or the
+ * number of symbolic links to directories is high enough,
+ * something faster might be worthwhile.
+ */
+ for (t = p->fts_parent;
+ t->fts_level >= FTS_ROOTLEVEL; t = t->fts_parent)
+ if (ino == t->fts_ino && dev == t->fts_dev) {
+ p->fts_cycle = t;
+ return (FTS_DC);
+ }
+ return (FTS_D);
+ }
+ if (S_ISLNK(sbp->st_mode))
+ return (FTS_SL);
+ if (S_ISREG(sbp->st_mode))
+ return (FTS_F);
+ return (FTS_DEFAULT);
+}
+
+/*
+ * The comparison function takes pointers to pointers to FTSENT structures.
+ * Qsort wants a comparison function that takes pointers to void.
+ * (Both with appropriate levels of const-poisoning, of course!)
+ * Use a trampoline function to deal with the difference.
+ */
+static int
+fts_compar(const void *a, const void *b)
+{
+ FTS11 *parent;
+
+ parent = (*(const FTSENT11 * const *)a)->fts_fts;
+ return (*parent->fts_compar)(a, b);
+}
+
+static FTSENT11 *
+fts_sort(FTS11 *sp, FTSENT11 *head, size_t nitems)
+{
+ FTSENT11 **ap, *p;
+
+ /*
+ * Construct an array of pointers to the structures and call qsort(3).
+ * Reassemble the array in the order returned by qsort. If unable to
+ * sort for memory reasons, return the directory entries in their
+ * current order. Allocate enough space for the current needs plus
+ * 40 so don't realloc one entry at a time.
+ */
+ if (nitems > sp->fts_nitems) {
+ sp->fts_nitems = nitems + 40;
+ if ((sp->fts_array = reallocf(sp->fts_array,
+ sp->fts_nitems * sizeof(FTSENT11 *))) == NULL) {
+ sp->fts_nitems = 0;
+ return (head);
+ }
+ }
+ for (ap = sp->fts_array, p = head; p; p = p->fts_link)
+ *ap++ = p;
+ qsort(sp->fts_array, nitems, sizeof(FTSENT11 *), fts_compar);
+ for (head = *(ap = sp->fts_array); --nitems; ++ap)
+ ap[0]->fts_link = ap[1];
+ ap[0]->fts_link = NULL;
+ return (head);
+}
+
+static FTSENT11 *
+fts_alloc(FTS11 *sp, char *name, size_t namelen)
+{
+ FTSENT11 *p;
+ size_t len;
+
+ struct ftsent11_withstat {
+ FTSENT11 ent;
+ struct freebsd11_stat statbuf;
+ };
+
+ /*
+ * The file name is a variable length array and no stat structure is
+ * necessary if the user has set the nostat bit. Allocate the FTSENT
+ * structure, the file name and the stat structure in one chunk, but
+ * be careful that the stat structure is reasonably aligned.
+ */
+ if (ISSET(FTS_NOSTAT))
+ len = sizeof(FTSENT11) + namelen + 1;
+ else
+ len = sizeof(struct ftsent11_withstat) + namelen + 1;
+
+ if ((p = malloc(len)) == NULL)
+ return (NULL);
+
+ if (ISSET(FTS_NOSTAT)) {
+ p->fts_name = (char *)(p + 1);
+ p->fts_statp = NULL;
+ } else {
+ p->fts_name = (char *)((struct ftsent11_withstat *)p + 1);
+ p->fts_statp = &((struct ftsent11_withstat *)p)->statbuf;
+ }
+
+ /* Copy the name and guarantee NUL termination. */
+ memcpy(p->fts_name, name, namelen);
+ p->fts_name[namelen] = '\0';
+ p->fts_namelen = namelen;
+ p->fts_path = sp->fts_path;
+ p->fts_errno = 0;
+ p->fts_flags = 0;
+ p->fts_instr = FTS_NOINSTR;
+ p->fts_number = 0;
+ p->fts_pointer = NULL;
+ p->fts_fts = sp;
+ return (p);
+}
+
+static void
+fts_lfree(FTSENT11 *head)
+{
+ FTSENT11 *p;
+
+ /* Free a linked list of structures. */
+ while ((p = head)) {
+ head = head->fts_link;
+ free(p);
+ }
+}
+
+/*
+ * Allow essentially unlimited paths; find, rm, ls should all work on any tree.
+ * Most systems will allow creation of paths much longer than MAXPATHLEN, even
+ * though the kernel won't resolve them. Add the size (not just what's needed)
+ * plus 256 bytes so don't realloc the path 2 bytes at a time.
+ */
+static int
+fts_palloc(FTS11 *sp, size_t more)
+{
+
+ sp->fts_pathlen += more + 256;
+ sp->fts_path = reallocf(sp->fts_path, sp->fts_pathlen);
+ return (sp->fts_path == NULL);
+}
+
+/*
+ * When the path is realloc'd, have to fix all of the pointers in structures
+ * already returned.
+ */
+static void
+fts_padjust(FTS11 *sp, FTSENT11 *head)
+{
+ FTSENT11 *p;
+ char *addr = sp->fts_path;
+
+#define ADJUST(p) do { \
+ if ((p)->fts_accpath != (p)->fts_name) { \
+ (p)->fts_accpath = \
+ (char *)addr + ((p)->fts_accpath - (p)->fts_path); \
+ } \
+ (p)->fts_path = addr; \
+} while (0)
+ /* Adjust the current set of children. */
+ for (p = sp->fts_child; p; p = p->fts_link)
+ ADJUST(p);
+
+ /* Adjust the rest of the tree, including the current level. */
+ for (p = head; p->fts_level >= FTS_ROOTLEVEL;) {
+ ADJUST(p);
+ p = p->fts_link ? p->fts_link : p->fts_parent;
+ }
+}
+
+static size_t
+fts_maxarglen(char * const *argv)
+{
+ size_t len, max;
+
+ for (max = 0; *argv; ++argv)
+ if ((len = strlen(*argv)) > max)
+ max = len;
+ return (max + 1);
+}
+
+/*
+ * Change to dir specified by fd or p->fts_accpath without getting
+ * tricked by someone changing the world out from underneath us.
+ * Assumes p->fts_dev and p->fts_ino are filled in.
+ */
+static int
+fts_safe_changedir(FTS11 *sp, FTSENT11 *p, int fd, char *path)
+{
+ int ret, oerrno, newfd;
+ struct freebsd11_stat sb;
+
+ newfd = fd;
+ if (ISSET(FTS_NOCHDIR))
+ return (0);
+ if (fd < 0 && (newfd = _open(path, O_RDONLY | O_DIRECTORY |
+ O_CLOEXEC, 0)) < 0)
+ return (-1);
+ if (freebsd11_fstat(newfd, &sb)) {
+ ret = -1;
+ goto bail;
+ }
+ if (p->fts_dev != sb.st_dev || p->fts_ino != sb.st_ino) {
+ errno = ENOENT; /* disinformation */
+ ret = -1;
+ goto bail;
+ }
+ ret = fchdir(newfd);
+bail:
+ oerrno = errno;
+ if (fd < 0)
+ (void)_close(newfd);
+ errno = oerrno;
+ return (ret);
+}
+
+/*
+ * Check if the filesystem for "ent" has UFS-style links.
+ */
+static int
+fts_ufslinks(FTS11 *sp, const FTSENT11 *ent)
+{
+ struct _fts_private11 *priv;
+ const char **cpp;
+
+ priv = (struct _fts_private11 *)sp;
+ /*
+ * If this node's device is different from the previous, grab
+ * the filesystem information, and decide on the reliability
+ * of the link information from this filesystem for stat(2)
+ * avoidance.
+ */
+ if (priv->ftsp_dev != ent->fts_dev) {
+ if (freebsd11_statfs(ent->fts_path, &priv->ftsp_statfs) != -1) {
+ priv->ftsp_dev = ent->fts_dev;
+ priv->ftsp_linksreliable = 0;
+ for (cpp = ufslike_filesystems; *cpp; cpp++) {
+ if (strcmp(priv->ftsp_statfs.f_fstypename,
+ *cpp) == 0) {
+ priv->ftsp_linksreliable = 1;
+ break;
+ }
+ }
+ } else {
+ priv->ftsp_linksreliable = 0;
+ }
+ }
+ return (priv->ftsp_linksreliable);
+}
+
+__sym_compat(fts_open, freebsd11_fts_open, FBSD_1.1);
+__sym_compat(fts_close, freebsd11_fts_close, FBSD_1.1);
+__sym_compat(fts_read, freebsd11_fts_read, FBSD_1.1);
+__sym_compat(fts_set, freebsd11_fts_set, FBSD_1.1);
+__sym_compat(fts_children, freebsd11_fts_children, FBSD_1.1);
+__sym_compat(fts_get_clientptr, freebsd11_fts_get_clientptr, FBSD_1.1);
+__sym_compat(fts_get_stream, freebsd11_fts_get_stream, FBSD_1.1);
+__sym_compat(fts_set_clientptr, freebsd11_fts_set_clientptr, FBSD_1.1);
diff --git a/lib/libc/gen/fts-compat11.h b/lib/libc/gen/fts-compat11.h
new file mode 100644
index 000000000000..52c0637395fb
--- /dev/null
+++ b/lib/libc/gen/fts-compat11.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)fts.h 8.3 (Berkeley) 8/14/94
+ * $FreeBSD$
+ */
+
+#ifndef _FTS_COPMAT11_H_
+#define _FTS_COPMAT11_H_
+
+typedef struct {
+ struct _ftsent11 *fts_cur; /* current node */
+ struct _ftsent11 *fts_child; /* linked list of children */
+ struct _ftsent11 **fts_array; /* sort array */
+ uint32_t fts_dev; /* starting device # */
+ char *fts_path; /* path for this descent */
+ int fts_rfd; /* fd for root */
+ __size_t fts_pathlen; /* sizeof(path) */
+ __size_t fts_nitems; /* elements in the sort array */
+ int (*fts_compar) /* compare function */
+ (const struct _ftsent11 * const *,
+ const struct _ftsent11 * const *);
+ int fts_options; /* fts_open options, global flags */
+ void *fts_clientptr; /* thunk for sort function */
+} FTS11;
+
+typedef struct _ftsent11 {
+ struct _ftsent11 *fts_cycle; /* cycle node */
+ struct _ftsent11 *fts_parent; /* parent directory */
+ struct _ftsent11 *fts_link; /* next file in directory */
+ long long fts_number; /* local numeric value */
+ void *fts_pointer; /* local address value */
+ char *fts_accpath; /* access path */
+ char *fts_path; /* root path */
+ int fts_errno; /* errno for this node */
+ int fts_symfd; /* fd for symlink */
+ __size_t fts_pathlen; /* strlen(fts_path) */
+ __size_t fts_namelen; /* strlen(fts_name) */
+
+ uint32_t fts_ino; /* inode */
+ uint32_t fts_dev; /* device */
+ uint16_t fts_nlink; /* link count */
+
+ long fts_level; /* depth (-1 to N) */
+
+ int fts_info; /* user status for FTSENT structure */
+
+ unsigned fts_flags; /* private flags for FTSENT structure */
+
+ int fts_instr; /* fts_set() instructions */
+
+ struct freebsd11_stat *fts_statp; /* stat(2) information */
+ char *fts_name; /* file name */
+ FTS11 *fts_fts; /* back pointer to main FTS */
+} FTSENT11;
+
+FTSENT11 *freebsd11_fts_children(FTS11 *, int);
+int freebsd11_fts_close(FTS11 *);
+void *freebsd11_fts_get_clientptr(FTS11 *);
+#define freebsd11_fts_get_clientptr(fts) ((fts)->fts_clientptr)
+FTS11 *freebsd11_fts_get_stream(FTSENT11 *);
+#define freebsd11_fts_get_stream(ftsent) ((ftsent)->fts_fts)
+FTS11 *freebsd11_fts_open(char * const *, int,
+ int (*)(const FTSENT11 * const *,
+ const FTSENT11 * const *));
+FTSENT11 *freebsd11_fts_read(FTS11 *);
+int freebsd11_fts_set(FTS11 *, FTSENT11 *, int);
+void freebsd11_fts_set_clientptr(FTS11 *, void *);
+
+#endif /* !_FTS_COMPAT11_H_ */
diff --git a/lib/libc/gen/ftw-compat11.c b/lib/libc/gen/ftw-compat11.c
new file mode 100644
index 000000000000..cad536d2dcd6
--- /dev/null
+++ b/lib/libc/gen/ftw-compat11.c
@@ -0,0 +1,98 @@
+/* $OpenBSD: ftw.c,v 1.5 2005/08/08 08:05:34 espie Exp $ */
+
+/*
+ * Copyright (c) 2003, 2004 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ *
+ * from: $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <fts.h>
+#include <ftw.h>
+
+#include "fts-compat11.h"
+
+int
+freebsd11_ftw(const char *path,
+ int (*fn)(const char *, const struct freebsd11_stat *, int), int nfds)
+{
+ char * const paths[2] = { (char *)path, NULL };
+ FTSENT11 *cur;
+ FTS11 *ftsp;
+ int error = 0, fnflag, sverrno;
+
+ /* XXX - nfds is currently unused */
+ if (nfds < 1) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ ftsp = freebsd11_fts_open(paths,
+ FTS_LOGICAL | FTS_COMFOLLOW | FTS_NOCHDIR, NULL);
+ if (ftsp == NULL)
+ return (-1);
+ while ((cur = freebsd11_fts_read(ftsp)) != NULL) {
+ switch (cur->fts_info) {
+ case FTS_D:
+ fnflag = FTW_D;
+ break;
+ case FTS_DNR:
+ fnflag = FTW_DNR;
+ break;
+ case FTS_DP:
+ /* we only visit in preorder */
+ continue;
+ case FTS_F:
+ case FTS_DEFAULT:
+ fnflag = FTW_F;
+ break;
+ case FTS_NS:
+ case FTS_NSOK:
+ case FTS_SLNONE:
+ fnflag = FTW_NS;
+ break;
+ case FTS_SL:
+ fnflag = FTW_SL;
+ break;
+ case FTS_DC:
+ errno = ELOOP;
+ /* FALLTHROUGH */
+ default:
+ error = -1;
+ goto done;
+ }
+ error = fn(cur->fts_path, cur->fts_statp, fnflag);
+ if (error != 0)
+ break;
+ }
+done:
+ sverrno = errno;
+ if (freebsd11_fts_close(ftsp) != 0 && error == 0)
+ error = -1;
+ else
+ errno = sverrno;
+ return (error);
+}
+
+__sym_compat(ftw, freebsd11_ftw, FBSD_1.0);
diff --git a/lib/libc/gen/gen-compat.h b/lib/libc/gen/gen-compat.h
new file mode 100644
index 000000000000..728a15a51b18
--- /dev/null
+++ b/lib/libc/gen/gen-compat.h
@@ -0,0 +1,57 @@
+/*-
+ * Copyright (c) 2012 Gleb Kurtsou <gleb@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _GEN_COMPAT_H_
+#define _GEN_COMPAT_H_
+
+#include <dirent.h>
+
+#define FREEBSD11_DIRSIZ(dp) \
+ (sizeof(struct freebsd11_dirent) - sizeof((dp)->d_name) + \
+ (((dp)->d_namlen + 1 + 3) &~ 3))
+
+struct freebsd11_dirent;
+struct freebsd11_stat;
+struct freebsd11_statfs;
+
+struct freebsd11_dirent *freebsd11_readdir(DIR *);
+int freebsd11_readdir_r(DIR *, struct freebsd11_dirent *,
+ struct freebsd11_dirent **);
+int freebsd11_stat(const char *, struct freebsd11_stat *);
+int freebsd11_lstat(const char *, struct freebsd11_stat *);
+int freebsd11_fstat(int, struct freebsd11_stat *);
+int freebsd11_fstatat(int, const char *, struct freebsd11_stat *, int);
+
+int freebsd11_statfs(const char *, struct freebsd11_statfs *);
+int freebsd11_getfsstat(struct freebsd11_statfs *, long, int);
+int freebsd11_getmntinfo(struct freebsd11_statfs **, int);
+
+char *freebsd11_devname(__uint32_t dev, __mode_t type);
+char *freebsd11_devname_r(__uint32_t dev, __mode_t type, char *buf, int len);
+
+#endif /* _GEN_COMPAT_H_ */
diff --git a/lib/libc/gen/gen-private.h b/lib/libc/gen/gen-private.h
index d1fab5f31462..0366cbfad8b9 100644
--- a/lib/libc/gen/gen-private.h
+++ b/lib/libc/gen/gen-private.h
@@ -47,12 +47,16 @@ struct _dirdesc {
long dd_size; /* amount of data returned by getdirentries */
char *dd_buf; /* data buffer */
int dd_len; /* size of data buffer */
- long dd_seek; /* magic cookie returned by getdirentries */
+ off_t dd_seek; /* magic cookie returned by getdirentries */
int dd_flags; /* flags for readdir */
struct pthread_mutex *dd_lock; /* lock */
struct _telldir *dd_td; /* telldir position recording */
+ void *dd_compat_de; /* compat dirent */
};
#define _dirfd(dirp) ((dirp)->dd_fd)
+struct dirent;
+int __readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result);
+
#endif /* !_GEN_PRIVATE_H_ */
diff --git a/lib/libc/gen/getmntinfo-compat11.c b/lib/libc/gen/getmntinfo-compat11.c
new file mode 100644
index 000000000000..05ffb74dc8c5
--- /dev/null
+++ b/lib/libc/gen/getmntinfo-compat11.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getmntinfo.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/ucred.h>
+#define _WANT_FREEBSD11_STATFS
+#include <sys/mount.h>
+#include <stdlib.h>
+#include "gen-compat.h"
+
+/*
+ * Return information about mounted filesystems.
+ */
+int
+freebsd11_getmntinfo(struct freebsd11_statfs **mntbufp, int flags)
+{
+ static struct freebsd11_statfs *mntbuf;
+ static int mntsize;
+ static long bufsize;
+
+ if (mntsize <= 0 &&
+ (mntsize = freebsd11_getfsstat(0, 0, MNT_NOWAIT)) < 0)
+ return (0);
+ if (bufsize > 0 &&
+ (mntsize = freebsd11_getfsstat(mntbuf, bufsize, flags)) < 0)
+ return (0);
+ while (bufsize <= mntsize * sizeof(struct freebsd11_statfs)) {
+ if (mntbuf)
+ free(mntbuf);
+ bufsize = (mntsize + 1) * sizeof(struct freebsd11_statfs);
+ if ((mntbuf = (struct freebsd11_statfs *)malloc(bufsize)) == 0)
+ return (0);
+ if ((mntsize = freebsd11_getfsstat(mntbuf, bufsize, flags)) < 0)
+ return (0);
+ }
+ *mntbufp = mntbuf;
+ return (mntsize);
+}
+
+__sym_compat(getmntinfo, freebsd11_getmntinfo, FBSD_1.0);
diff --git a/lib/libc/gen/glob-compat11.c b/lib/libc/gen/glob-compat11.c
new file mode 100644
index 000000000000..2bdf99a0bf64
--- /dev/null
+++ b/lib/libc/gen/glob-compat11.c
@@ -0,0 +1,1093 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Guido van Rossum.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: $FreeBSD$
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)glob.c 8.3 (Berkeley) 10/13/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#define _WANT_FREEBSD11_STAT
+#include <sys/stat.h>
+
+#include <ctype.h>
+#define _WANT_FREEBSD11_DIRENT
+#include <dirent.h>
+#include <errno.h>
+#include <glob.h>
+#include <limits.h>
+#include <pwd.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <wchar.h>
+
+#include "collate.h"
+#include "gen-compat.h"
+#include "glob-compat11.h"
+
+/*
+ * glob(3) expansion limits. Stop the expansion if any of these limits
+ * is reached. This caps the runtime in the face of DoS attacks. See
+ * also CVE-2010-2632
+ */
+#define GLOB_LIMIT_BRACE 128 /* number of brace calls */
+#define GLOB_LIMIT_PATH 65536 /* number of path elements */
+#define GLOB_LIMIT_READDIR 16384 /* number of readdirs */
+#define GLOB_LIMIT_STAT 1024 /* number of stat system calls */
+#define GLOB_LIMIT_STRING ARG_MAX /* maximum total size for paths */
+
+struct glob_limit {
+ size_t l_brace_cnt;
+ size_t l_path_lim;
+ size_t l_readdir_cnt;
+ size_t l_stat_cnt;
+ size_t l_string_cnt;
+};
+
+#define DOT L'.'
+#define EOS L'\0'
+#define LBRACKET L'['
+#define NOT L'!'
+#define QUESTION L'?'
+#define QUOTE L'\\'
+#define RANGE L'-'
+#define RBRACKET L']'
+#define SEP L'/'
+#define STAR L'*'
+#define TILDE L'~'
+#define LBRACE L'{'
+#define RBRACE L'}'
+#define COMMA L','
+
+#define M_QUOTE 0x8000000000ULL
+#define M_PROTECT 0x4000000000ULL
+#define M_MASK 0xffffffffffULL
+#define M_CHAR 0x00ffffffffULL
+
+typedef uint_fast64_t Char;
+
+#define CHAR(c) ((Char)((c)&M_CHAR))
+#define META(c) ((Char)((c)|M_QUOTE))
+#define UNPROT(c) ((c) & ~M_PROTECT)
+#define M_ALL META(L'*')
+#define M_END META(L']')
+#define M_NOT META(L'!')
+#define M_ONE META(L'?')
+#define M_RNG META(L'-')
+#define M_SET META(L'[')
+#define ismeta(c) (((c)&M_QUOTE) != 0)
+#ifdef DEBUG
+#define isprot(c) (((c)&M_PROTECT) != 0)
+#endif
+
+static int compare(const void *, const void *);
+static int g_Ctoc(const Char *, char *, size_t);
+static int g_lstat(Char *, struct freebsd11_stat *, glob11_t *);
+static DIR *g_opendir(Char *, glob11_t *);
+static const Char *g_strchr(const Char *, wchar_t);
+#ifdef notdef
+static Char *g_strcat(Char *, const Char *);
+#endif
+static int g_stat(Char *, struct freebsd11_stat *, glob11_t *);
+static int glob0(const Char *, glob11_t *, struct glob_limit *,
+ const char *);
+static int glob1(Char *, glob11_t *, struct glob_limit *);
+static int glob2(Char *, Char *, Char *, Char *, glob11_t *,
+ struct glob_limit *);
+static int glob3(Char *, Char *, Char *, Char *, Char *, glob11_t *,
+ struct glob_limit *);
+static int globextend(const Char *, glob11_t *, struct glob_limit *,
+ const char *);
+static const Char *
+ globtilde(const Char *, Char *, size_t, glob11_t *);
+static int globexp0(const Char *, glob11_t *, struct glob_limit *,
+ const char *);
+static int globexp1(const Char *, glob11_t *, struct glob_limit *);
+static int globexp2(const Char *, const Char *, glob11_t *,
+ struct glob_limit *);
+static int globfinal(glob11_t *, struct glob_limit *, size_t,
+ const char *);
+static int match(Char *, Char *, Char *);
+static int err_nomatch(glob11_t *, struct glob_limit *, const char *);
+static int err_aborted(glob11_t *, int, char *);
+#ifdef DEBUG
+static void qprintf(const char *, Char *);
+#endif
+
+int
+freebsd11_glob(const char * __restrict pattern, int flags,
+ int (*errfunc)(const char *, int), glob11_t * __restrict pglob)
+{
+ struct glob_limit limit = { 0, 0, 0, 0, 0 };
+ const char *patnext;
+ Char *bufnext, *bufend, patbuf[MAXPATHLEN], prot;
+ mbstate_t mbs;
+ wchar_t wc;
+ size_t clen;
+ int too_long;
+
+ patnext = pattern;
+ if (!(flags & GLOB_APPEND)) {
+ pglob->gl_pathc = 0;
+ pglob->gl_pathv = NULL;
+ if (!(flags & GLOB_DOOFFS))
+ pglob->gl_offs = 0;
+ }
+ if (flags & GLOB_LIMIT) {
+ limit.l_path_lim = pglob->gl_matchc;
+ if (limit.l_path_lim == 0)
+ limit.l_path_lim = GLOB_LIMIT_PATH;
+ }
+ pglob->gl_flags = flags & ~GLOB_MAGCHAR;
+ pglob->gl_errfunc = errfunc;
+ pglob->gl_matchc = 0;
+
+ bufnext = patbuf;
+ bufend = bufnext + MAXPATHLEN - 1;
+ too_long = 1;
+ if (flags & GLOB_NOESCAPE) {
+ memset(&mbs, 0, sizeof(mbs));
+ while (bufnext <= bufend) {
+ clen = mbrtowc(&wc, patnext, MB_LEN_MAX, &mbs);
+ if (clen == (size_t)-1 || clen == (size_t)-2)
+ return (err_nomatch(pglob, &limit, pattern));
+ else if (clen == 0) {
+ too_long = 0;
+ break;
+ }
+ *bufnext++ = wc;
+ patnext += clen;
+ }
+ } else {
+ /* Protect the quoted characters. */
+ memset(&mbs, 0, sizeof(mbs));
+ while (bufnext <= bufend) {
+ if (*patnext == '\\') {
+ if (*++patnext == '\0') {
+ *bufnext++ = QUOTE;
+ continue;
+ }
+ prot = M_PROTECT;
+ } else
+ prot = 0;
+ clen = mbrtowc(&wc, patnext, MB_LEN_MAX, &mbs);
+ if (clen == (size_t)-1 || clen == (size_t)-2)
+ return (err_nomatch(pglob, &limit, pattern));
+ else if (clen == 0) {
+ too_long = 0;
+ break;
+ }
+ *bufnext++ = wc | prot;
+ patnext += clen;
+ }
+ }
+ if (too_long)
+ return (err_nomatch(pglob, &limit, pattern));
+ *bufnext = EOS;
+
+ if (flags & GLOB_BRACE)
+ return (globexp0(patbuf, pglob, &limit, pattern));
+ else
+ return (glob0(patbuf, pglob, &limit, pattern));
+}
+
+static int
+globexp0(const Char *pattern, glob11_t *pglob, struct glob_limit *limit,
+ const char *origpat) {
+ int rv;
+ size_t oldpathc;
+
+ /* Protect a single {}, for find(1), like csh */
+ if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS) {
+ if ((pglob->gl_flags & GLOB_LIMIT) &&
+ limit->l_brace_cnt++ >= GLOB_LIMIT_BRACE) {
+ errno = E2BIG;
+ return (GLOB_NOSPACE);
+ }
+ return (glob0(pattern, pglob, limit, origpat));
+ }
+
+ oldpathc = pglob->gl_pathc;
+
+ if ((rv = globexp1(pattern, pglob, limit)) != 0)
+ return rv;
+
+ return (globfinal(pglob, limit, oldpathc, origpat));
+}
+
+/*
+ * Expand recursively a glob {} pattern. When there is no more expansion
+ * invoke the standard globbing routine to glob the rest of the magic
+ * characters
+ */
+static int
+globexp1(const Char *pattern, glob11_t *pglob, struct glob_limit *limit)
+{
+ const Char* ptr;
+
+ if ((ptr = g_strchr(pattern, LBRACE)) != NULL) {
+ if ((pglob->gl_flags & GLOB_LIMIT) &&
+ limit->l_brace_cnt++ >= GLOB_LIMIT_BRACE) {
+ errno = E2BIG;
+ return (GLOB_NOSPACE);
+ }
+ return (globexp2(ptr, pattern, pglob, limit));
+ }
+
+ return (glob0(pattern, pglob, limit, NULL));
+}
+
+
+/*
+ * Recursive brace globbing helper. Tries to expand a single brace.
+ * If it succeeds then it invokes globexp1 with the new pattern.
+ * If it fails then it tries to glob the rest of the pattern and returns.
+ */
+static int
+globexp2(const Char *ptr, const Char *pattern, glob11_t *pglob,
+ struct glob_limit *limit)
+{
+ int i, rv;
+ Char *lm, *ls;
+ const Char *pe, *pm, *pm1, *pl;
+ Char patbuf[MAXPATHLEN];
+
+ /* copy part up to the brace */
+ for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++)
+ continue;
+ *lm = EOS;
+ ls = lm;
+
+ /* Find the balanced brace */
+ for (i = 0, pe = ++ptr; *pe != EOS; pe++)
+ if (*pe == LBRACKET) {
+ /* Ignore everything between [] */
+ for (pm = pe++; *pe != RBRACKET && *pe != EOS; pe++)
+ continue;
+ if (*pe == EOS) {
+ /*
+ * We could not find a matching RBRACKET.
+ * Ignore and just look for RBRACE
+ */
+ pe = pm;
+ }
+ }
+ else if (*pe == LBRACE)
+ i++;
+ else if (*pe == RBRACE) {
+ if (i == 0)
+ break;
+ i--;
+ }
+
+ /* Non matching braces; just glob the pattern */
+ if (i != 0 || *pe == EOS)
+ return (glob0(pattern, pglob, limit, NULL));
+
+ for (i = 0, pl = pm = ptr; pm <= pe; pm++)
+ switch (*pm) {
+ case LBRACKET:
+ /* Ignore everything between [] */
+ for (pm1 = pm++; *pm != RBRACKET && *pm != EOS; pm++)
+ continue;
+ if (*pm == EOS) {
+ /*
+ * We could not find a matching RBRACKET.
+ * Ignore and just look for RBRACE
+ */
+ pm = pm1;
+ }
+ break;
+
+ case LBRACE:
+ i++;
+ break;
+
+ case RBRACE:
+ if (i) {
+ i--;
+ break;
+ }
+ /* FALLTHROUGH */
+ case COMMA:
+ if (i && *pm == COMMA)
+ break;
+ else {
+ /* Append the current string */
+ for (lm = ls; (pl < pm); *lm++ = *pl++)
+ continue;
+ /*
+ * Append the rest of the pattern after the
+ * closing brace
+ */
+ for (pl = pe + 1; (*lm++ = *pl++) != EOS;)
+ continue;
+
+ /* Expand the current pattern */
+#ifdef DEBUG
+ qprintf("globexp2:", patbuf);
+#endif
+ rv = globexp1(patbuf, pglob, limit);
+ if (rv)
+ return (rv);
+
+ /* move after the comma, to the next string */
+ pl = pm + 1;
+ }
+ break;
+
+ default:
+ break;
+ }
+ return (0);
+}
+
+
+
+/*
+ * expand tilde from the passwd file.
+ */
+static const Char *
+globtilde(const Char *pattern, Char *patbuf, size_t patbuf_len, glob11_t *pglob)
+{
+ struct passwd *pwd;
+ char *h, *sc;
+ const Char *p;
+ Char *b, *eb;
+ wchar_t wc;
+ wchar_t wbuf[MAXPATHLEN];
+ wchar_t *wbufend, *dc;
+ size_t clen;
+ mbstate_t mbs;
+ int too_long;
+
+ if (*pattern != TILDE || !(pglob->gl_flags & GLOB_TILDE))
+ return (pattern);
+
+ /*
+ * Copy up to the end of the string or /
+ */
+ eb = &patbuf[patbuf_len - 1];
+ for (p = pattern + 1, b = patbuf;
+ b < eb && *p != EOS && UNPROT(*p) != SEP; *b++ = *p++)
+ continue;
+
+ if (*p != EOS && UNPROT(*p) != SEP)
+ return (NULL);
+
+ *b = EOS;
+ h = NULL;
+
+ if (patbuf[0] == EOS) {
+ /*
+ * handle a plain ~ or ~/ by expanding $HOME first (iff
+ * we're not running setuid or setgid) and then trying
+ * the password file
+ */
+ if (issetugid() != 0 ||
+ (h = getenv("HOME")) == NULL) {
+ if (((h = getlogin()) != NULL &&
+ (pwd = getpwnam(h)) != NULL) ||
+ (pwd = getpwuid(getuid())) != NULL)
+ h = pwd->pw_dir;
+ else
+ return (pattern);
+ }
+ }
+ else {
+ /*
+ * Expand a ~user
+ */
+ if (g_Ctoc(patbuf, (char *)wbuf, sizeof(wbuf)))
+ return (NULL);
+ if ((pwd = getpwnam((char *)wbuf)) == NULL)
+ return (pattern);
+ else
+ h = pwd->pw_dir;
+ }
+
+ /* Copy the home directory */
+ dc = wbuf;
+ sc = h;
+ wbufend = wbuf + MAXPATHLEN - 1;
+ too_long = 1;
+ memset(&mbs, 0, sizeof(mbs));
+ while (dc <= wbufend) {
+ clen = mbrtowc(&wc, sc, MB_LEN_MAX, &mbs);
+ if (clen == (size_t)-1 || clen == (size_t)-2) {
+ /* XXX See initial comment #2. */
+ wc = (unsigned char)*sc;
+ clen = 1;
+ memset(&mbs, 0, sizeof(mbs));
+ }
+ if ((*dc++ = wc) == EOS) {
+ too_long = 0;
+ break;
+ }
+ sc += clen;
+ }
+ if (too_long)
+ return (NULL);
+
+ dc = wbuf;
+ for (b = patbuf; b < eb && *dc != EOS; *b++ = *dc++ | M_PROTECT)
+ continue;
+ if (*dc != EOS)
+ return (NULL);
+
+ /* Append the rest of the pattern */
+ if (*p != EOS) {
+ too_long = 1;
+ while (b <= eb) {
+ if ((*b++ = *p++) == EOS) {
+ too_long = 0;
+ break;
+ }
+ }
+ if (too_long)
+ return (NULL);
+ } else
+ *b = EOS;
+
+ return (patbuf);
+}
+
+
+/*
+ * The main glob() routine: compiles the pattern (optionally processing
+ * quotes), calls glob1() to do the real pattern matching, and finally
+ * sorts the list (unless unsorted operation is requested). Returns 0
+ * if things went well, nonzero if errors occurred.
+ */
+static int
+glob0(const Char *pattern, glob11_t *pglob, struct glob_limit *limit,
+ const char *origpat) {
+ const Char *qpatnext;
+ int err;
+ size_t oldpathc;
+ Char *bufnext, c, patbuf[MAXPATHLEN];
+
+ qpatnext = globtilde(pattern, patbuf, MAXPATHLEN, pglob);
+ if (qpatnext == NULL) {
+ errno = E2BIG;
+ return (GLOB_NOSPACE);
+ }
+ oldpathc = pglob->gl_pathc;
+ bufnext = patbuf;
+
+ /* We don't need to check for buffer overflow any more. */
+ while ((c = *qpatnext++) != EOS) {
+ switch (c) {
+ case LBRACKET:
+ c = *qpatnext;
+ if (c == NOT)
+ ++qpatnext;
+ if (*qpatnext == EOS ||
+ g_strchr(qpatnext+1, RBRACKET) == NULL) {
+ *bufnext++ = LBRACKET;
+ if (c == NOT)
+ --qpatnext;
+ break;
+ }
+ *bufnext++ = M_SET;
+ if (c == NOT)
+ *bufnext++ = M_NOT;
+ c = *qpatnext++;
+ do {
+ *bufnext++ = CHAR(c);
+ if (*qpatnext == RANGE &&
+ (c = qpatnext[1]) != RBRACKET) {
+ *bufnext++ = M_RNG;
+ *bufnext++ = CHAR(c);
+ qpatnext += 2;
+ }
+ } while ((c = *qpatnext++) != RBRACKET);
+ pglob->gl_flags |= GLOB_MAGCHAR;
+ *bufnext++ = M_END;
+ break;
+ case QUESTION:
+ pglob->gl_flags |= GLOB_MAGCHAR;
+ *bufnext++ = M_ONE;
+ break;
+ case STAR:
+ pglob->gl_flags |= GLOB_MAGCHAR;
+ /* collapse adjacent stars to one,
+ * to avoid exponential behavior
+ */
+ if (bufnext == patbuf || bufnext[-1] != M_ALL)
+ *bufnext++ = M_ALL;
+ break;
+ default:
+ *bufnext++ = CHAR(c);
+ break;
+ }
+ }
+ *bufnext = EOS;
+#ifdef DEBUG
+ qprintf("glob0:", patbuf);
+#endif
+
+ if ((err = glob1(patbuf, pglob, limit)) != 0)
+ return(err);
+
+ if (origpat != NULL)
+ return (globfinal(pglob, limit, oldpathc, origpat));
+
+ return (0);
+}
+
+static int
+globfinal(glob11_t *pglob, struct glob_limit *limit, size_t oldpathc,
+ const char *origpat) {
+ if (pglob->gl_pathc == oldpathc)
+ return (err_nomatch(pglob, limit, origpat));
+
+ if (!(pglob->gl_flags & GLOB_NOSORT))
+ qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc,
+ pglob->gl_pathc - oldpathc, sizeof(char *), compare);
+
+ return (0);
+}
+
+static int
+compare(const void *p, const void *q)
+{
+ return (strcoll(*(char **)p, *(char **)q));
+}
+
+static int
+glob1(Char *pattern, glob11_t *pglob, struct glob_limit *limit)
+{
+ Char pathbuf[MAXPATHLEN];
+
+ /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */
+ if (*pattern == EOS)
+ return (0);
+ return (glob2(pathbuf, pathbuf, pathbuf + MAXPATHLEN - 1,
+ pattern, pglob, limit));
+}
+
+/*
+ * The functions glob2 and glob3 are mutually recursive; there is one level
+ * of recursion for each segment in the pattern that contains one or more
+ * meta characters.
+ */
+static int
+glob2(Char *pathbuf, Char *pathend, Char *pathend_last, Char *pattern,
+ glob11_t *pglob, struct glob_limit *limit)
+{
+ struct freebsd11_stat sb;
+ Char *p, *q;
+ int anymeta;
+
+ /*
+ * Loop over pattern segments until end of pattern or until
+ * segment with meta character found.
+ */
+ for (anymeta = 0;;) {
+ if (*pattern == EOS) { /* End of pattern? */
+ *pathend = EOS;
+ if (g_lstat(pathbuf, &sb, pglob))
+ return (0);
+
+ if ((pglob->gl_flags & GLOB_LIMIT) &&
+ limit->l_stat_cnt++ >= GLOB_LIMIT_STAT) {
+ errno = E2BIG;
+ return (GLOB_NOSPACE);
+ }
+ if ((pglob->gl_flags & GLOB_MARK) &&
+ UNPROT(pathend[-1]) != SEP &&
+ (S_ISDIR(sb.st_mode) ||
+ (S_ISLNK(sb.st_mode) &&
+ g_stat(pathbuf, &sb, pglob) == 0 &&
+ S_ISDIR(sb.st_mode)))) {
+ if (pathend + 1 > pathend_last) {
+ errno = E2BIG;
+ return (GLOB_NOSPACE);
+ }
+ *pathend++ = SEP;
+ *pathend = EOS;
+ }
+ ++pglob->gl_matchc;
+ return (globextend(pathbuf, pglob, limit, NULL));
+ }
+
+ /* Find end of next segment, copy tentatively to pathend. */
+ q = pathend;
+ p = pattern;
+ while (*p != EOS && UNPROT(*p) != SEP) {
+ if (ismeta(*p))
+ anymeta = 1;
+ if (q + 1 > pathend_last) {
+ errno = E2BIG;
+ return (GLOB_NOSPACE);
+ }
+ *q++ = *p++;
+ }
+
+ if (!anymeta) { /* No expansion, do next segment. */
+ pathend = q;
+ pattern = p;
+ while (UNPROT(*pattern) == SEP) {
+ if (pathend + 1 > pathend_last) {
+ errno = E2BIG;
+ return (GLOB_NOSPACE);
+ }
+ *pathend++ = *pattern++;
+ }
+ } else /* Need expansion, recurse. */
+ return (glob3(pathbuf, pathend, pathend_last, pattern,
+ p, pglob, limit));
+ }
+ /* NOTREACHED */
+}
+
+static int
+glob3(Char *pathbuf, Char *pathend, Char *pathend_last,
+ Char *pattern, Char *restpattern,
+ glob11_t *pglob, struct glob_limit *limit)
+{
+ struct freebsd11_dirent *dp;
+ DIR *dirp;
+ int err, too_long, saverrno, saverrno2;
+ char buf[MAXPATHLEN + MB_LEN_MAX - 1];
+
+ struct freebsd11_dirent *(*readdirfunc)(DIR *);
+
+ if (pathend > pathend_last) {
+ errno = E2BIG;
+ return (GLOB_NOSPACE);
+ }
+ *pathend = EOS;
+ if (pglob->gl_errfunc != NULL &&
+ g_Ctoc(pathbuf, buf, sizeof(buf))) {
+ errno = E2BIG;
+ return (GLOB_NOSPACE);
+ }
+
+ saverrno = errno;
+ errno = 0;
+ if ((dirp = g_opendir(pathbuf, pglob)) == NULL) {
+ if (errno == ENOENT || errno == ENOTDIR)
+ return (0);
+ err = err_aborted(pglob, errno, buf);
+ if (errno == 0)
+ errno = saverrno;
+ return (err);
+ }
+
+ err = 0;
+
+ /* pglob->gl_readdir takes a void *, fix this manually */
+ if (pglob->gl_flags & GLOB_ALTDIRFUNC)
+ readdirfunc =
+ (struct freebsd11_dirent *(*)(DIR *))pglob->gl_readdir;
+ else
+ readdirfunc = freebsd11_readdir;
+
+ errno = 0;
+ /* Search directory for matching names. */
+ while ((dp = (*readdirfunc)(dirp)) != NULL) {
+ char *sc;
+ Char *dc;
+ wchar_t wc;
+ size_t clen;
+ mbstate_t mbs;
+
+ if ((pglob->gl_flags & GLOB_LIMIT) &&
+ limit->l_readdir_cnt++ >= GLOB_LIMIT_READDIR) {
+ errno = E2BIG;
+ err = GLOB_NOSPACE;
+ break;
+ }
+
+ /* Initial DOT must be matched literally. */
+ if (dp->d_name[0] == '.' && UNPROT(*pattern) != DOT) {
+ errno = 0;
+ continue;
+ }
+ memset(&mbs, 0, sizeof(mbs));
+ dc = pathend;
+ sc = dp->d_name;
+ too_long = 1;
+ while (dc <= pathend_last) {
+ clen = mbrtowc(&wc, sc, MB_LEN_MAX, &mbs);
+ if (clen == (size_t)-1 || clen == (size_t)-2) {
+ /* XXX See initial comment #2. */
+ wc = (unsigned char)*sc;
+ clen = 1;
+ memset(&mbs, 0, sizeof(mbs));
+ }
+ if ((*dc++ = wc) == EOS) {
+ too_long = 0;
+ break;
+ }
+ sc += clen;
+ }
+ if (too_long && (err = err_aborted(pglob, ENAMETOOLONG,
+ buf))) {
+ errno = ENAMETOOLONG;
+ break;
+ }
+ if (too_long || !match(pathend, pattern, restpattern)) {
+ *pathend = EOS;
+ errno = 0;
+ continue;
+ }
+ if (errno == 0)
+ errno = saverrno;
+ err = glob2(pathbuf, --dc, pathend_last, restpattern,
+ pglob, limit);
+ if (err)
+ break;
+ errno = 0;
+ }
+
+ saverrno2 = errno;
+ if (pglob->gl_flags & GLOB_ALTDIRFUNC)
+ (*pglob->gl_closedir)(dirp);
+ else
+ closedir(dirp);
+ errno = saverrno2;
+
+ if (err)
+ return (err);
+
+ if (dp == NULL && errno != 0 &&
+ (err = err_aborted(pglob, errno, buf)))
+ return (err);
+
+ if (errno == 0)
+ errno = saverrno;
+ return (0);
+}
+
+
+/*
+ * Extend the gl_pathv member of a glob11_t structure to accommodate a new item,
+ * add the new item, and update gl_pathc.
+ *
+ * This assumes the BSD realloc, which only copies the block when its size
+ * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic
+ * behavior.
+ *
+ * Return 0 if new item added, error code if memory couldn't be allocated.
+ *
+ * Invariant of the glob11_t structure:
+ * Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and
+ * gl_pathv points to (gl_offs + gl_pathc + 1) items.
+ */
+static int
+globextend(const Char *path, glob11_t *pglob, struct glob_limit *limit,
+ const char *origpat)
+{
+ char **pathv;
+ size_t i, newn, len;
+ char *copy;
+ const Char *p;
+
+ if ((pglob->gl_flags & GLOB_LIMIT) &&
+ pglob->gl_matchc > limit->l_path_lim) {
+ errno = E2BIG;
+ return (GLOB_NOSPACE);
+ }
+
+ newn = 2 + pglob->gl_pathc + pglob->gl_offs;
+ /* reallocarray(NULL, newn, size) is equivalent to malloc(newn*size). */
+ pathv = reallocarray(pglob->gl_pathv, newn, sizeof(*pathv));
+ if (pathv == NULL)
+ return (GLOB_NOSPACE);
+
+ if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) {
+ /* first time around -- clear initial gl_offs items */
+ pathv += pglob->gl_offs;
+ for (i = pglob->gl_offs + 1; --i > 0; )
+ *--pathv = NULL;
+ }
+ pglob->gl_pathv = pathv;
+
+ if (origpat != NULL)
+ copy = strdup(origpat);
+ else {
+ for (p = path; *p++ != EOS;)
+ continue;
+ len = MB_CUR_MAX * (size_t)(p - path); /* XXX overallocation */
+ if ((copy = malloc(len)) != NULL) {
+ if (g_Ctoc(path, copy, len)) {
+ free(copy);
+ errno = E2BIG;
+ return (GLOB_NOSPACE);
+ }
+ }
+ }
+ if (copy != NULL) {
+ limit->l_string_cnt += strlen(copy) + 1;
+ if ((pglob->gl_flags & GLOB_LIMIT) &&
+ limit->l_string_cnt >= GLOB_LIMIT_STRING) {
+ free(copy);
+ errno = E2BIG;
+ return (GLOB_NOSPACE);
+ }
+ pathv[pglob->gl_offs + pglob->gl_pathc++] = copy;
+ }
+ pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
+ return (copy == NULL ? GLOB_NOSPACE : 0);
+}
+
+/*
+ * pattern matching function for filenames.
+ */
+static int
+match(Char *name, Char *pat, Char *patend)
+{
+ int ok, negate_range;
+ Char c, k, *nextp, *nextn;
+ struct xlocale_collate *table =
+ (struct xlocale_collate*)__get_locale()->components[XLC_COLLATE];
+
+ nextn = NULL;
+ nextp = NULL;
+
+ while (1) {
+ while (pat < patend) {
+ c = *pat++;
+ switch (c & M_MASK) {
+ case M_ALL:
+ if (pat == patend)
+ return (1);
+ if (*name == EOS)
+ return (0);
+ nextn = name + 1;
+ nextp = pat - 1;
+ break;
+ case M_ONE:
+ if (*name++ == EOS)
+ goto fail;
+ break;
+ case M_SET:
+ ok = 0;
+ if ((k = *name++) == EOS)
+ goto fail;
+ negate_range = ((*pat & M_MASK) == M_NOT);
+ if (negate_range != 0)
+ ++pat;
+ while (((c = *pat++) & M_MASK) != M_END)
+ if ((*pat & M_MASK) == M_RNG) {
+ if (table->__collate_load_error ?
+ CHAR(c) <= CHAR(k) &&
+ CHAR(k) <= CHAR(pat[1]) :
+ __wcollate_range_cmp(CHAR(c),
+ CHAR(k)) <= 0 &&
+ __wcollate_range_cmp(CHAR(k),
+ CHAR(pat[1])) <= 0)
+ ok = 1;
+ pat += 2;
+ } else if (c == k)
+ ok = 1;
+ if (ok == negate_range)
+ goto fail;
+ break;
+ default:
+ if (*name++ != c)
+ goto fail;
+ break;
+ }
+ }
+ if (*name == EOS)
+ return (1);
+
+ fail:
+ if (nextn == NULL)
+ break;
+ pat = nextp;
+ name = nextn;
+ }
+ return (0);
+}
+
+/* Free allocated data belonging to a glob11_t structure. */
+void
+freebsd11_globfree(glob11_t *pglob)
+{
+ size_t i;
+ char **pp;
+
+ if (pglob->gl_pathv != NULL) {
+ pp = pglob->gl_pathv + pglob->gl_offs;
+ for (i = pglob->gl_pathc; i--; ++pp)
+ if (*pp)
+ free(*pp);
+ free(pglob->gl_pathv);
+ pglob->gl_pathv = NULL;
+ }
+}
+
+static DIR *
+g_opendir(Char *str, glob11_t *pglob)
+{
+ char buf[MAXPATHLEN + MB_LEN_MAX - 1];
+
+ if (*str == EOS)
+ strcpy(buf, ".");
+ else {
+ if (g_Ctoc(str, buf, sizeof(buf))) {
+ errno = ENAMETOOLONG;
+ return (NULL);
+ }
+ }
+
+ if (pglob->gl_flags & GLOB_ALTDIRFUNC)
+ return ((*pglob->gl_opendir)(buf));
+
+ return (opendir(buf));
+}
+
+static int
+g_lstat(Char *fn, struct freebsd11_stat *sb, glob11_t *pglob)
+{
+ char buf[MAXPATHLEN + MB_LEN_MAX - 1];
+
+ if (g_Ctoc(fn, buf, sizeof(buf))) {
+ errno = ENAMETOOLONG;
+ return (-1);
+ }
+ if (pglob->gl_flags & GLOB_ALTDIRFUNC)
+ return((*pglob->gl_lstat)(buf, sb));
+ return (freebsd11_lstat(buf, sb));
+}
+
+static int
+g_stat(Char *fn, struct freebsd11_stat *sb, glob11_t *pglob)
+{
+ char buf[MAXPATHLEN + MB_LEN_MAX - 1];
+
+ if (g_Ctoc(fn, buf, sizeof(buf))) {
+ errno = ENAMETOOLONG;
+ return (-1);
+ }
+ if (pglob->gl_flags & GLOB_ALTDIRFUNC)
+ return ((*pglob->gl_stat)(buf, sb));
+ return (freebsd11_stat(buf, sb));
+}
+
+static const Char *
+g_strchr(const Char *str, wchar_t ch)
+{
+
+ do {
+ if (*str == ch)
+ return (str);
+ } while (*str++);
+ return (NULL);
+}
+
+static int
+g_Ctoc(const Char *str, char *buf, size_t len)
+{
+ mbstate_t mbs;
+ size_t clen;
+
+ memset(&mbs, 0, sizeof(mbs));
+ while (len >= MB_CUR_MAX) {
+ clen = wcrtomb(buf, CHAR(*str), &mbs);
+ if (clen == (size_t)-1) {
+ /* XXX See initial comment #2. */
+ *buf = (char)CHAR(*str);
+ clen = 1;
+ memset(&mbs, 0, sizeof(mbs));
+ }
+ if (CHAR(*str) == EOS)
+ return (0);
+ str++;
+ buf += clen;
+ len -= clen;
+ }
+ return (1);
+}
+
+static int
+err_nomatch(glob11_t *pglob, struct glob_limit *limit, const char *origpat) {
+ /*
+ * If there was no match we are going to append the origpat
+ * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified
+ * and the origpat did not contain any magic characters
+ * GLOB_NOMAGIC is there just for compatibility with csh.
+ */
+ if ((pglob->gl_flags & GLOB_NOCHECK) ||
+ ((pglob->gl_flags & GLOB_NOMAGIC) &&
+ !(pglob->gl_flags & GLOB_MAGCHAR)))
+ return (globextend(NULL, pglob, limit, origpat));
+ return (GLOB_NOMATCH);
+}
+
+static int
+err_aborted(glob11_t *pglob, int err, char *buf) {
+ if ((pglob->gl_errfunc != NULL && pglob->gl_errfunc(buf, err)) ||
+ (pglob->gl_flags & GLOB_ERR))
+ return (GLOB_ABORTED);
+ return (0);
+}
+
+#ifdef DEBUG
+static void
+qprintf(const char *str, Char *s)
+{
+ Char *p;
+
+ (void)printf("%s\n", str);
+ if (s != NULL) {
+ for (p = s; *p != EOS; p++)
+ (void)printf("%c", (char)CHAR(*p));
+ (void)printf("\n");
+ for (p = s; *p != EOS; p++)
+ (void)printf("%c", (isprot(*p) ? '\\' : ' '));
+ (void)printf("\n");
+ for (p = s; *p != EOS; p++)
+ (void)printf("%c", (ismeta(*p) ? '_' : ' '));
+ (void)printf("\n");
+ }
+}
+#endif
+
+__sym_compat(glob, freebsd11_glob, FBSD_1.0);
+__sym_compat(globfree, freebsd11_globfree, FBSD_1.0);
diff --git a/lib/libc/gen/glob-compat11.h b/lib/libc/gen/glob-compat11.h
new file mode 100644
index 000000000000..d43086f819c5
--- /dev/null
+++ b/lib/libc/gen/glob-compat11.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Guido van Rossum.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)glob.h 8.1 (Berkeley) 6/2/93
+ * from: $FreeBSD$
+ * $FreeBSD$
+ */
+
+#ifndef _GLOB_COMPAT11_H_
+#define _GLOB_COMPAT11_H_
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <glob.h>
+
+struct freebsd11_stat;
+typedef struct {
+ size_t gl_pathc; /* Count of total paths so far. */
+ size_t gl_matchc; /* Count of paths matching pattern. */
+ size_t gl_offs; /* Reserved at beginning of gl_pathv. */
+ int gl_flags; /* Copy of flags parameter to glob. */
+ char **gl_pathv; /* List of paths matching pattern. */
+ /* Copy of errfunc parameter to glob. */
+ int (*gl_errfunc)(const char *, int);
+
+ /*
+ * Alternate filesystem access methods for glob; replacement
+ * versions of closedir(3), readdir(3), opendir(3), stat(2)
+ * and lstat(2).
+ */
+ void (*gl_closedir)(void *);
+ struct freebsd11_dirent *(*gl_readdir)(void *);
+ void *(*gl_opendir)(const char *);
+ int (*gl_lstat)(const char *, struct freebsd11_stat *);
+ int (*gl_stat)(const char *, struct freebsd11_stat *);
+} glob11_t;
+
+__BEGIN_DECLS
+int freebsd11_glob(const char * __restrict, int,
+ int (*)(const char *, int), glob11_t * __restrict);
+void freebsd11_globfree(glob11_t *);
+__END_DECLS
+
+#endif /* !_GLOB_COMPAT11_H_ */
diff --git a/lib/libc/gen/nftw-compat11.c b/lib/libc/gen/nftw-compat11.c
new file mode 100644
index 000000000000..5293f9ed6ad4
--- /dev/null
+++ b/lib/libc/gen/nftw-compat11.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2003, 2004 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ *
+ * from: $OpenBSD: nftw.c,v 1.7 2006/03/31 19:41:44 millert Exp $
+ * from: $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <fts.h>
+#include <ftw.h>
+
+#include "fts-compat11.h"
+
+int
+freebsd11_nftw(const char *path,
+ int (*fn)(const char *, const struct freebsd11_stat *, int, struct FTW *),
+ int nfds, int ftwflags)
+{
+ char * const paths[2] = { (char *)path, NULL };
+ struct FTW ftw;
+ FTSENT11 *cur;
+ FTS11 *ftsp;
+ int error = 0, ftsflags, fnflag, postorder, sverrno;
+
+ /* XXX - nfds is currently unused */
+ if (nfds < 1) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ ftsflags = FTS_COMFOLLOW;
+ if (!(ftwflags & FTW_CHDIR))
+ ftsflags |= FTS_NOCHDIR;
+ if (ftwflags & FTW_MOUNT)
+ ftsflags |= FTS_XDEV;
+ if (ftwflags & FTW_PHYS)
+ ftsflags |= FTS_PHYSICAL;
+ else
+ ftsflags |= FTS_LOGICAL;
+ postorder = (ftwflags & FTW_DEPTH) != 0;
+ ftsp = freebsd11_fts_open(paths, ftsflags, NULL);
+ if (ftsp == NULL)
+ return (-1);
+ while ((cur = freebsd11_fts_read(ftsp)) != NULL) {
+ switch (cur->fts_info) {
+ case FTS_D:
+ if (postorder)
+ continue;
+ fnflag = FTW_D;
+ break;
+ case FTS_DC:
+ continue;
+ case FTS_DNR:
+ fnflag = FTW_DNR;
+ break;
+ case FTS_DP:
+ if (!postorder)
+ continue;
+ fnflag = FTW_DP;
+ break;
+ case FTS_F:
+ case FTS_DEFAULT:
+ fnflag = FTW_F;
+ break;
+ case FTS_NS:
+ case FTS_NSOK:
+ fnflag = FTW_NS;
+ break;
+ case FTS_SL:
+ fnflag = FTW_SL;
+ break;
+ case FTS_SLNONE:
+ fnflag = FTW_SLN;
+ break;
+ default:
+ error = -1;
+ goto done;
+ }
+ ftw.base = cur->fts_pathlen - cur->fts_namelen;
+ ftw.level = cur->fts_level;
+ error = fn(cur->fts_path, cur->fts_statp, fnflag, &ftw);
+ if (error != 0)
+ break;
+ }
+done:
+ sverrno = errno;
+ if (freebsd11_fts_close(ftsp) != 0 && error == 0)
+ error = -1;
+ else
+ errno = sverrno;
+ return (error);
+}
+
+__sym_compat(nftw, freebsd11_nftw, FBSD_1.0);
diff --git a/lib/libc/gen/opendir.c b/lib/libc/gen/opendir.c
index f828b8d7598f..927e08b8fcc8 100644
--- a/lib/libc/gen/opendir.c
+++ b/lib/libc/gen/opendir.c
@@ -296,6 +296,7 @@ __opendir_common(int fd, int flags, bool use_current_pos)
dirp->dd_td = (struct _telldir *)((char *)dirp + sizeof(DIR));
LIST_INIT(&dirp->dd_td->td_locq);
dirp->dd_td->td_loccnt = 0;
+ dirp->dd_compat_de = NULL;
/*
* Use the system page size if that is a multiple of DIRBLKSIZ.
diff --git a/lib/libc/gen/readdir-compat11.c b/lib/libc/gen/readdir-compat11.c
new file mode 100644
index 000000000000..c374d35e7392
--- /dev/null
+++ b/lib/libc/gen/readdir-compat11.c
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from:
+ * $FreeBSD$
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)readdir.c 8.3 (Berkeley) 9/29/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/param.h>
+#define _WANT_FREEBSD11_DIRENT
+#include <dirent.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+#include "un-namespace.h"
+
+#include "libc_private.h"
+#include "gen-private.h"
+#include "telldir.h"
+
+#include "gen-compat.h"
+
+static bool
+freebsd11_cvtdirent(struct freebsd11_dirent *dstdp, struct dirent *srcdp)
+{
+
+ if (srcdp->d_namlen >= sizeof(dstdp->d_name))
+ return (false);
+ dstdp->d_type = srcdp->d_type;
+ dstdp->d_namlen = srcdp->d_namlen;
+ dstdp->d_fileno = srcdp->d_fileno; /* truncate */
+ dstdp->d_reclen = FREEBSD11_DIRSIZ(dstdp);
+ bcopy(srcdp->d_name, dstdp->d_name, dstdp->d_namlen);
+ bzero(dstdp->d_name + dstdp->d_namlen,
+ dstdp->d_reclen - offsetof(struct freebsd11_dirent, d_name) -
+ dstdp->d_namlen);
+ return (true);
+}
+
+struct freebsd11_dirent *
+freebsd11_readdir(DIR *dirp)
+{
+ struct freebsd11_dirent *dstdp;
+ struct dirent *dp;
+
+ if (__isthreaded)
+ _pthread_mutex_lock(&dirp->dd_lock);
+ dp = _readdir_unlocked(dirp, RDU_SKIP);
+ if (dp != NULL) {
+ if (dirp->dd_compat_de == NULL)
+ dirp->dd_compat_de = malloc(sizeof(struct
+ freebsd11_dirent));
+ if (freebsd11_cvtdirent(dirp->dd_compat_de, dp))
+ dstdp = dirp->dd_compat_de;
+ else
+ dstdp = NULL;
+ } else
+ dstdp = NULL;
+ if (__isthreaded)
+ _pthread_mutex_unlock(&dirp->dd_lock);
+
+ return (dstdp);
+}
+
+int
+freebsd11_readdir_r(DIR *dirp, struct freebsd11_dirent *entry,
+ struct freebsd11_dirent **result)
+{
+ struct dirent xentry, *xresult;
+ int error;
+
+ error = __readdir_r(dirp, &xentry, &xresult);
+ if (error != 0)
+ return (error);
+ if (xresult != NULL) {
+ if (freebsd11_cvtdirent(entry, &xentry))
+ *result = entry;
+ else /* should not happen due to RDU_SHORT */
+ *result = NULL;
+ } else
+ *result = NULL;
+ return (0);
+}
+
+__sym_compat(readdir, freebsd11_readdir, FBSD_1.0);
+__sym_compat(readdir_r, freebsd11_readdir_r, FBSD_1.0);
diff --git a/lib/libc/gen/readdir.c b/lib/libc/gen/readdir.c
index a547f47857bb..22623bb0876b 100644
--- a/lib/libc/gen/readdir.c
+++ b/lib/libc/gen/readdir.c
@@ -49,7 +49,7 @@ __FBSDID("$FreeBSD$");
* get next entry in a directory.
*/
struct dirent *
-_readdir_unlocked(DIR *dirp, int skip)
+_readdir_unlocked(DIR *dirp, int flags)
{
struct dirent *dp;
long initial_seek;
@@ -80,10 +80,13 @@ _readdir_unlocked(DIR *dirp, int skip)
dp->d_reclen > dirp->dd_len + 1 - dirp->dd_loc)
return (NULL);
dirp->dd_loc += dp->d_reclen;
- if (dp->d_ino == 0 && skip)
+ if (dp->d_ino == 0 && (flags & RDU_SKIP) != 0)
continue;
if (dp->d_type == DT_WHT && (dirp->dd_flags & DTF_HIDEW))
continue;
+ if (dp->d_namlen >= sizeof(dp->d_name) &&
+ (flags & RDU_SHORT) != 0)
+ continue;
return (dp);
}
}
@@ -91,34 +94,31 @@ _readdir_unlocked(DIR *dirp, int skip)
struct dirent *
readdir(DIR *dirp)
{
- struct dirent *dp;
+ struct dirent *dp;
- if (__isthreaded) {
+ if (__isthreaded)
_pthread_mutex_lock(&dirp->dd_lock);
- dp = _readdir_unlocked(dirp, 1);
+ dp = _readdir_unlocked(dirp, RDU_SKIP);
+ if (__isthreaded)
_pthread_mutex_unlock(&dirp->dd_lock);
- }
- else
- dp = _readdir_unlocked(dirp, 1);
return (dp);
}
int
-readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result)
+__readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result)
{
struct dirent *dp;
int saved_errno;
saved_errno = errno;
errno = 0;
- if (__isthreaded) {
+ if (__isthreaded)
_pthread_mutex_lock(&dirp->dd_lock);
- if ((dp = _readdir_unlocked(dirp, 1)) != NULL)
- memcpy(entry, dp, _GENERIC_DIRSIZ(dp));
- _pthread_mutex_unlock(&dirp->dd_lock);
- }
- else if ((dp = _readdir_unlocked(dirp, 1)) != NULL)
+ dp = _readdir_unlocked(dirp, RDU_SKIP | RDU_SHORT);
+ if (dp != NULL)
memcpy(entry, dp, _GENERIC_DIRSIZ(dp));
+ if (__isthreaded)
+ _pthread_mutex_unlock(&dirp->dd_lock);
if (errno != 0) {
if (dp == NULL)
@@ -133,3 +133,5 @@ readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result)
return (0);
}
+
+__strong_reference(__readdir_r, readdir_r);
diff --git a/lib/libc/gen/scandir-compat11.c b/lib/libc/gen/scandir-compat11.c
new file mode 100644
index 000000000000..28120c0bc13d
--- /dev/null
+++ b/lib/libc/gen/scandir-compat11.c
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from:
+ * $FreeBSD$
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)scandir.c 8.3 (Berkeley) 1/2/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Scan the directory dirname calling select to make a list of selected
+ * directory entries then sort using qsort and compare routine dcomp.
+ * Returns the number of entries and a pointer to a list of pointers to
+ * struct dirent (through namelist). Returns -1 if there were any errors.
+ */
+
+#include "namespace.h"
+#define _WANT_FREEBSD11_DIRENT
+#include <dirent.h>
+#include <stdlib.h>
+#include <string.h>
+#include "un-namespace.h"
+
+#include "gen-compat.h"
+
+#ifdef I_AM_SCANDIR_B
+#include "block_abi.h"
+#define SELECT(x) CALL_BLOCK(select, x)
+#ifndef __BLOCKS__
+void
+qsort_b(void *, size_t, size_t, void*);
+#endif
+#else
+#define SELECT(x) select(x)
+#endif
+
+static int freebsd11_alphasort_thunk(void *thunk, const void *p1,
+ const void *p2);
+
+int
+#ifdef I_AM_SCANDIR_B
+freebsd11_scandir_b(const char *dirname, struct freebsd11_dirent ***namelist,
+ DECLARE_BLOCK(int, select, const struct freebsd11_dirent *),
+ DECLARE_BLOCK(int, dcomp, const struct freebsd11_dirent **,
+ const struct freebsd11_dirent **))
+#else
+freebsd11_scandir(const char *dirname, struct freebsd11_dirent ***namelist,
+ int (*select)(const struct freebsd11_dirent *),
+ int (*dcomp)(const struct freebsd11_dirent **,
+ const struct freebsd11_dirent **))
+#endif
+{
+ struct freebsd11_dirent *d, *p, **names = NULL;
+ size_t arraysz, numitems;
+ DIR *dirp;
+
+ if ((dirp = opendir(dirname)) == NULL)
+ return(-1);
+
+ numitems = 0;
+ arraysz = 32; /* initial estimate of the array size */
+ names = (struct freebsd11_dirent **)malloc(
+ arraysz * sizeof(struct freebsd11_dirent *));
+ if (names == NULL)
+ goto fail;
+
+ while ((d = freebsd11_readdir(dirp)) != NULL) {
+ if (select != NULL && !SELECT(d))
+ continue; /* just selected names */
+ /*
+ * Make a minimum size copy of the data
+ */
+ p = (struct freebsd11_dirent *)malloc(FREEBSD11_DIRSIZ(d));
+ if (p == NULL)
+ goto fail;
+ p->d_fileno = d->d_fileno;
+ p->d_type = d->d_type;
+ p->d_reclen = d->d_reclen;
+ p->d_namlen = d->d_namlen;
+ bcopy(d->d_name, p->d_name, p->d_namlen + 1);
+ /*
+ * Check to make sure the array has space left and
+ * realloc the maximum size.
+ */
+ if (numitems >= arraysz) {
+ struct freebsd11_dirent **names2;
+
+ names2 = reallocarray(names, arraysz,
+ 2 * sizeof(struct freebsd11_dirent *));
+ if (names2 == NULL) {
+ free(p);
+ goto fail;
+ }
+ names = names2;
+ arraysz *= 2;
+ }
+ names[numitems++] = p;
+ }
+ closedir(dirp);
+ if (numitems && dcomp != NULL)
+#ifdef I_AM_SCANDIR_B
+ qsort_b(names, numitems, sizeof(struct freebsd11_dirent *),
+ (void*)dcomp);
+#else
+ qsort_r(names, numitems, sizeof(struct freebsd11_dirent *),
+ &dcomp, freebsd11_alphasort_thunk);
+#endif
+ *namelist = names;
+ return (numitems);
+
+fail:
+ while (numitems > 0)
+ free(names[--numitems]);
+ free(names);
+ closedir(dirp);
+ return (-1);
+}
+
+/*
+ * Alphabetic order comparison routine for those who want it.
+ * POSIX 2008 requires that alphasort() uses strcoll().
+ */
+int
+freebsd11_alphasort(const struct freebsd11_dirent **d1,
+ const struct freebsd11_dirent **d2)
+{
+
+ return (strcoll((*d1)->d_name, (*d2)->d_name));
+}
+
+static int
+freebsd11_alphasort_thunk(void *thunk, const void *p1, const void *p2)
+{
+ int (*dc)(const struct freebsd11_dirent **, const struct
+ freebsd11_dirent **);
+
+ dc = *(int (**)(const struct freebsd11_dirent **,
+ const struct freebsd11_dirent **))thunk;
+ return (dc((const struct freebsd11_dirent **)p1,
+ (const struct freebsd11_dirent **)p2));
+}
+
+__sym_compat(alphasort, freebsd11_alphasort, FBSD_1.0);
+__sym_compat(scandir, freebsd11_scandir, FBSD_1.0);
+__sym_compat(scandir_b, freebsd11_scandir_b, FBSD_1.4);
diff --git a/lib/libc/gen/scandir.c b/lib/libc/gen/scandir.c
index 00183b61de73..b7ec171764c4 100644
--- a/lib/libc/gen/scandir.c
+++ b/lib/libc/gen/scandir.c
@@ -59,17 +59,6 @@ qsort_b(void *, size_t, size_t, void*);
static int alphasort_thunk(void *thunk, const void *p1, const void *p2);
-/*
- * The DIRSIZ macro is the minimum record length which will hold the directory
- * entry. This requires the amount of space in struct dirent without the
- * d_name field, plus enough space for the name and a terminating nul byte
- * (dp->d_namlen + 1), rounded up to a 4 byte boundary.
- */
-#undef DIRSIZ
-#define DIRSIZ(dp) \
- ((sizeof(struct dirent) - sizeof(dp)->d_name) + \
- (((dp)->d_namlen + 1 + 3) &~ 3))
-
int
#ifdef I_AM_SCANDIR_B
scandir_b(const char *dirname, struct dirent ***namelist,
@@ -100,7 +89,7 @@ scandir(const char *dirname, struct dirent ***namelist,
/*
* Make a minimum size copy of the data
*/
- p = (struct dirent *)malloc(DIRSIZ(d));
+ p = (struct dirent *)malloc(_GENERIC_DIRSIZ(d));
if (p == NULL)
goto fail;
p->d_fileno = d->d_fileno;
diff --git a/lib/libc/gen/telldir.h b/lib/libc/gen/telldir.h
index bccabb1aea53..50adb351e91d 100644
--- a/lib/libc/gen/telldir.h
+++ b/lib/libc/gen/telldir.h
@@ -47,7 +47,7 @@
struct ddloc {
LIST_ENTRY(ddloc) loc_lqe; /* entry in list */
long loc_index; /* key associated with structure */
- long loc_seek; /* magic cookie returned by getdirentries */
+ off_t loc_seek; /* magic cookie returned by getdirentries */
long loc_loc; /* offset of entry in buffer */
};
@@ -66,4 +66,7 @@ void _reclaim_telldir(DIR *);
void _seekdir(DIR *, long);
void _fixtelldir(DIR *dirp, long oldseek, long oldloc);
+#define RDU_SKIP 0x0001
+#define RDU_SHORT 0x0002
+
#endif
diff --git a/lib/libc/include/compat.h b/lib/libc/include/compat.h
index d0abfdf70fdb..559c8502fb93 100644
--- a/lib/libc/include/compat.h
+++ b/lib/libc/include/compat.h
@@ -44,6 +44,27 @@ __sym_compat(msgctl, freebsd7_msgctl, FBSD_1.0);
__sym_compat(shmctl, freebsd7_shmctl, FBSD_1.0);
#endif
+__sym_compat(nfstat, freebsd11_nfstat, FBSD_1.0);
+__sym_compat(nlstat, freebsd11_nlstat, FBSD_1.0);
+__sym_compat(nstat, freebsd11_nstat, FBSD_1.0);
+
+__sym_compat(fhstat, freebsd11_fhstat, FBSD_1.0);
+__sym_compat(fstat, freebsd11_fstat, FBSD_1.0);
+__sym_compat(fstatat, freebsd11_fstatat, FBSD_1.1);
+__sym_compat(lstat, freebsd11_lstat, FBSD_1.0);
+__sym_compat(stat, freebsd11_stat, FBSD_1.0);
+
+__sym_compat(getdents, freebsd11_getdents, FBSD_1.0);
+__sym_compat(getdirentries, freebsd11_getdirentries, FBSD_1.0);
+
+__sym_compat(getfsstat, freebsd11_getfsstat, FBSD_1.0);
+__sym_compat(fhstatfs, freebsd11_fhstatfs, FBSD_1.0);
+__sym_compat(fstatfs, freebsd11_fstatfs, FBSD_1.0);
+__sym_compat(statfs, freebsd11_statfs, FBSD_1.0);
+
+__sym_compat(mknod, freebsd11_mknod, FBSD_1.0);
+__sym_compat(mknodat, freebsd11_mknodat, FBSD_1.1);
+
#undef __sym_compat
#define __weak_reference(sym,alias) \
diff --git a/lib/libc/include/libc_private.h b/lib/libc/include/libc_private.h
index 384f61fb223b..6409ff331754 100644
--- a/lib/libc/include/libc_private.h
+++ b/lib/libc/include/libc_private.h
@@ -307,6 +307,7 @@ struct pollfd;
struct rusage;
struct sigaction;
struct sockaddr;
+struct stat;
struct timespec;
struct timeval;
struct timezone;
@@ -323,8 +324,10 @@ int __sys_clock_nanosleep(__clockid_t, int,
const struct timespec *, struct timespec *);
int __sys_close(int);
int __sys_connect(int, const struct sockaddr *, __socklen_t);
+__ssize_t __sys_getdirentries(int, char *, __size_t, __off_t *);
int __sys_fcntl(int, int, ...);
int __sys_fdatasync(int);
+int __sys_fstatat(int, const char *, struct stat *, int);
int __sys_fsync(int);
__pid_t __sys_fork(void);
int __sys_ftruncate(int, __off_t);
diff --git a/lib/libc/sys/Makefile.inc b/lib/libc/sys/Makefile.inc
index 76eeebd9d71c..b641125096d1 100644
--- a/lib/libc/sys/Makefile.inc
+++ b/lib/libc/sys/Makefile.inc
@@ -35,6 +35,8 @@ SRCS+= \
__error.c \
interposing_table.c
+SRCS+= getdents.c lstat.c mknod.c stat.c
+
SRCS+= futimens.c utimensat.c
NOASM+= futimens.o utimensat.o
PSEUDO+= _futimens.o _utimensat.o
diff --git a/lib/libc/sys/Symbol.map b/lib/libc/sys/Symbol.map
index 6a5c838a762b..feccda6f6bf4 100644
--- a/lib/libc/sys/Symbol.map
+++ b/lib/libc/sys/Symbol.map
@@ -85,26 +85,19 @@ FBSD_1.0 {
fchown;
fcntl;
fhopen;
- fhstat;
- fhstatfs;
flock;
fork;
fpathconf;
- fstat;
- fstatfs;
fsync;
futimes;
getaudit;
getaudit_addr;
getauid;
getcontext;
- getdents;
- getdirentries;
getdtablesize;
getegid;
geteuid;
getfh;
- getfsstat;
getgid;
getgroups;
getitimer;
@@ -163,7 +156,6 @@ FBSD_1.0 {
link;
lio_listio;
listen;
- lstat;
lutimes;
mac_syscall;
madvise;
@@ -171,7 +163,6 @@ FBSD_1.0 {
minherit;
mkdir;
mkfifo;
- mknod;
mlock;
mlockall;
modfind;
@@ -192,10 +183,7 @@ FBSD_1.0 {
netbsd_lchown;
netbsd_msync;
nfssvc;
- nfstat;
- nlstat;
nmount;
- nstat;
ntp_adjtime;
ntp_gettime;
open;
@@ -275,8 +263,6 @@ FBSD_1.0 {
sigwaitinfo;
socket;
socketpair;
- stat;
- statfs;
swapoff;
swapon;
symlink;
@@ -330,7 +316,6 @@ FBSD_1.1 {
fchmodat;
fchownat;
fexecve;
- fstatat;
futimesat;
jail_get;
jail_set;
@@ -339,7 +324,6 @@ FBSD_1.1 {
lpathconf;
mkdirat;
mkfifoat;
- mknodat;
msgctl;
readlinkat;
renameat;
@@ -401,6 +385,19 @@ FBSD_1.4 {
FBSD_1.5 {
clock_nanosleep;
fdatasync;
+ fhstat;
+ fhstatfs;
+ fstat;
+ fstatat;
+ fstatfs;
+ getdents;
+ getdirentries;
+ getfsstat;
+ lstat;
+ mknod;
+ mknodat;
+ stat;
+ statfs;
};
FBSDprivate_1.0 {
@@ -606,8 +603,6 @@ FBSDprivate_1.0 {
__sys_getauid;
_getcontext;
__sys_getcontext;
- _getdents;
- __sys_getdents;
_getdirentries;
__sys_getdirentries;
_getdtablesize;
@@ -736,8 +731,6 @@ FBSDprivate_1.0 {
__sys_lio_listio;
_listen;
__sys_listen;
- _lstat;
- __sys_lstat;
_lutimes;
__sys_lutimes;
_mac_syscall;
@@ -796,14 +789,8 @@ FBSDprivate_1.0 {
__sys_netbsd_msync;
_nfssvc;
__sys_nfssvc;
- _nfstat;
- __sys_nfstat;
- _nlstat;
- __sys_nlstat;
_nmount;
__sys_nmount;
- _nstat;
- __sys_nstat;
_ntp_adjtime;
__sys_ntp_adjtime;
_ntp_gettime;
@@ -971,8 +958,6 @@ FBSDprivate_1.0 {
__sys_socket;
_socketpair;
__sys_socketpair;
- _stat;
- __sys_stat;
_statfs;
__sys_statfs;
_swapcontext;
diff --git a/lib/libc/sys/getdents.c b/lib/libc/sys/getdents.c
new file mode 100644
index 000000000000..c8a2878c972f
--- /dev/null
+++ b/lib/libc/sys/getdents.c
@@ -0,0 +1,41 @@
+/*-
+ * Copyright (c) 2012 Gleb Kurtsou <gleb@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/param.h>
+#include <sys/syscall.h>
+#include <dirent.h>
+#include "libc_private.h"
+
+ssize_t
+getdents(int fd, char *buf, size_t nbytes)
+{
+
+ return (__sys_getdirentries(fd, buf, nbytes, NULL));
+}
diff --git a/lib/libc/sys/getdirentries.2 b/lib/libc/sys/getdirentries.2
index ace8faa7521c..d3f2129d400f 100644
--- a/lib/libc/sys/getdirentries.2
+++ b/lib/libc/sys/getdirentries.2
@@ -40,10 +40,10 @@
.Sh SYNOPSIS
.In sys/types.h
.In dirent.h
-.Ft int
-.Fn getdirentries "int fd" "char *buf" "int nbytes" "long *basep"
-.Ft int
-.Fn getdents "int fd" "char *buf" "int nbytes"
+.Ft ssize_t
+.Fn getdirentries "int fd" "char *buf" "size_t nbytes" "off_t *basep"
+.Ft ssize_t
+.Fn getdents "int fd" "char *buf" "size_t nbytes"
.Sh DESCRIPTION
The
.Fn getdirentries
diff --git a/lib/libc/sys/lstat.c b/lib/libc/sys/lstat.c
new file mode 100644
index 000000000000..ccc73e3d3d06
--- /dev/null
+++ b/lib/libc/sys/lstat.c
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 2012 Gleb Kurtsou <gleb@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/param.h>
+#include <sys/fcntl.h>
+#include <sys/syscall.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include "libc_private.h"
+
+int
+lstat(const char *path, struct stat *sb)
+{
+
+ return (__sys_fstatat(AT_FDCWD, path, sb, AT_SYMLINK_NOFOLLOW));
+}
diff --git a/lib/libc/sys/mknod.c b/lib/libc/sys/mknod.c
new file mode 100644
index 000000000000..3bb3853b5849
--- /dev/null
+++ b/lib/libc/sys/mknod.c
@@ -0,0 +1,45 @@
+/*-
+ * Copyright (c) 2011 Gleb Kurtsou <gleb@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/param.h>
+#include <sys/fcntl.h>
+#include <sys/syscall.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include "libc_private.h"
+
+int __sys_mknodat(int, const char *, mode_t, dev_t);
+
+int
+mknod(const char *path, mode_t mode, dev_t dev)
+{
+
+ return (__sys_mknodat(AT_FDCWD, path, mode, dev));
+}
diff --git a/lib/libc/sys/stat.c b/lib/libc/sys/stat.c
new file mode 100644
index 000000000000..6b58daa9e515
--- /dev/null
+++ b/lib/libc/sys/stat.c
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 2012 Gleb Kurtsou <gleb@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/param.h>
+#include <sys/fcntl.h>
+#include <sys/syscall.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include "libc_private.h"
+
+int
+stat(const char *path, struct stat *sb)
+{
+
+ return (__sys_fstatat(AT_FDCWD, path, sb, 0));
+}
diff --git a/lib/libc/sys/statfs.2 b/lib/libc/sys/statfs.2
index 7a95871125ca..a7383c4ce12b 100644
--- a/lib/libc/sys/statfs.2
+++ b/lib/libc/sys/statfs.2
@@ -28,7 +28,7 @@
.\" @(#)statfs.2 8.5 (Berkeley) 5/24/95
.\" $FreeBSD$
.\"
-.Dd November 1, 2006
+.Dd February 13, 2017
.Dt STATFS 2
.Os
.Sh NAME
@@ -66,8 +66,8 @@ typedef struct fsid { int32_t val[2]; } fsid_t; /* file system id type */
*/
#define MFSNAMELEN 16 /* length of type name including null */
-#define MNAMELEN 88 /* size of on/from name bufs */
-#define STATFS_VERSION 0x20030518 /* current version number */
+#define MNAMELEN 1024 /* size of on/from name bufs */
+#define STATFS_VERSION 0x20140518 /* current version number */
struct statfs {
uint32_t f_version; /* structure version number */
diff --git a/lib/libkvm/kvm_proc.c b/lib/libkvm/kvm_proc.c
index ac14ef613990..a7886ab556ab 100644
--- a/lib/libkvm/kvm_proc.c
+++ b/lib/libkvm/kvm_proc.c
@@ -452,6 +452,7 @@ nopgrp:
} else {
kp->ki_stat = SZOMB;
}
+ kp->ki_tdev_freebsd11 = kp->ki_tdev; /* truncate */
bcopy(&kinfo_proc, bp, sizeof(kinfo_proc));
++bp;
++cnt;
diff --git a/lib/libmilter/Makefile b/lib/libmilter/Makefile
index a8efe9cec7bd..17bb09857fcf 100644
--- a/lib/libmilter/Makefile
+++ b/lib/libmilter/Makefile
@@ -29,6 +29,7 @@ SRCS+= main.c engine.c listener.c handler.c comm.c monitor.c smfi.c \
CLEANFILES+=sm_os.h
WARNS?= 0
+SHLIB_MAJOR= 6
sm_os.h: ${SENDMAIL_DIR}/include/sm/os/sm_os_freebsd.h .NOMETA
ln -sf ${.ALLSRC} ${.TARGET}
diff --git a/lib/libprocstat/Makefile b/lib/libprocstat/Makefile
index 8d4fae0dffe9..9d80d17e16a8 100644
--- a/lib/libprocstat/Makefile
+++ b/lib/libprocstat/Makefile
@@ -13,6 +13,10 @@ SRCS= cd9660.c \
smbfs.c \
udf.c
+.if ${MK_SYMVER} == yes
+SRCS+= libprocstat_compat.c
+.endif
+
VERSION_DEF= ${LIBCSRCDIR}/Versions.def
SYMBOL_MAPS= ${.CURDIR}/Symbol.map
diff --git a/lib/libprocstat/Symbol.map b/lib/libprocstat/Symbol.map
index 75a8916aca67..a78a4691fe5d 100644
--- a/lib/libprocstat/Symbol.map
+++ b/lib/libprocstat/Symbol.map
@@ -6,9 +6,7 @@ FBSD_1.2 {
procstat_freefiles;
procstat_freeprocs;
procstat_get_pipe_info;
- procstat_get_pts_info;
procstat_get_socket_info;
- procstat_get_vnode_info;
procstat_getfiles;
procstat_getprocs;
procstat_open_kvm;
@@ -22,8 +20,6 @@ FBSD_1.3 {
procstat_freegroups;
procstat_freekstack;
procstat_freevmmap;
- procstat_get_sem_info;
- procstat_get_shm_info;
procstat_getargv;
procstat_getauxv;
procstat_getenvv;
@@ -40,4 +36,8 @@ FBSD_1.3 {
FBSD_1.5 {
procstat_freeptlwpinfo;
procstat_getptlwpinfo;
+ procstat_get_pts_info;
+ procstat_get_sem_info;
+ procstat_get_shm_info;
+ procstat_get_vnode_info;
};
diff --git a/lib/libprocstat/libprocstat.c b/lib/libprocstat/libprocstat.c
index 7d42acce4201..d674adc4f9ea 100644
--- a/lib/libprocstat/libprocstat.c
+++ b/lib/libprocstat/libprocstat.c
@@ -1337,12 +1337,12 @@ procstat_get_vnode_info_sysctl(struct filestat *fst, struct vnstat *vn,
struct statfs stbuf;
struct kinfo_file *kif;
struct kinfo_vmentry *kve;
+ char *name, *path;
uint64_t fileid;
uint64_t size;
- char *name, *path;
- uint32_t fsid;
+ uint64_t fsid;
+ uint64_t rdev;
uint16_t mode;
- uint32_t rdev;
int vntype;
int status;
@@ -1545,8 +1545,10 @@ procstat_get_socket_info_sysctl(struct filestat *fst, struct sockstat *sock,
sock->dom_family = kif->kf_sock_domain;
sock->so_pcb = kif->kf_un.kf_sock.kf_sock_pcb;
strlcpy(sock->dname, kif->kf_path, sizeof(sock->dname));
- bcopy(&kif->kf_sa_local, &sock->sa_local, kif->kf_sa_local.ss_len);
- bcopy(&kif->kf_sa_peer, &sock->sa_peer, kif->kf_sa_peer.ss_len);
+ bcopy(&kif->kf_un.kf_sock.kf_sa_local, &sock->sa_local,
+ kif->kf_un.kf_sock.kf_sa_local.ss_len);
+ bcopy(&kif->kf_un.kf_sock.kf_sa_peer, &sock->sa_peer,
+ kif->kf_un.kf_sock.kf_sa_peer.ss_len);
/*
* Protocol specific data.
diff --git a/lib/libprocstat/libprocstat.h b/lib/libprocstat/libprocstat.h
index 00b6f1c1c110..7584878252d4 100644
--- a/lib/libprocstat/libprocstat.h
+++ b/lib/libprocstat/libprocstat.h
@@ -120,15 +120,15 @@ struct filestat {
struct vnstat {
uint64_t vn_fileid;
uint64_t vn_size;
+ uint64_t vn_dev;
+ uint64_t vn_fsid;
char *vn_mntdir;
- uint32_t vn_dev;
- uint32_t vn_fsid;
int vn_type;
uint16_t vn_mode;
char vn_devname[SPECNAMELEN + 1];
};
struct ptsstat {
- uint32_t dev;
+ uint64_t dev;
char devname[SPECNAMELEN + 1];
};
struct pipestat {
diff --git a/lib/libprocstat/libprocstat_compat.c b/lib/libprocstat/libprocstat_compat.c
new file mode 100644
index 000000000000..52d80c7afab4
--- /dev/null
+++ b/lib/libprocstat/libprocstat_compat.c
@@ -0,0 +1,144 @@
+/*-
+ * Copyright (c) 2014 Gleb Kurtsou <gleb@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/user.h>
+#include <sys/socket.h>
+#include <string.h>
+
+#include "libprocstat.h"
+
+struct freebsd11_ptsstat {
+ uint32_t dev;
+ char devname[SPECNAMELEN + 1];
+};
+
+struct freebsd11_vnstat {
+ uint64_t vn_fileid;
+ uint64_t vn_size;
+ char *vn_mntdir;
+ uint32_t vn_dev;
+ uint32_t vn_fsid;
+ int vn_type;
+ uint16_t vn_mode;
+ char vn_devname[SPECNAMELEN + 1];
+};
+struct freebsd11_semstat {
+ uint32_t value;
+ uint16_t mode;
+};
+struct freebsd11_shmstat {
+ uint64_t size;
+ uint16_t mode;
+};
+
+int freebsd11_procstat_get_pts_info(struct procstat *procstat,
+ struct filestat *fst, struct freebsd11_ptsstat *pts, char *errbuf);
+int freebsd11_procstat_get_sem_info(struct procstat *procstat,
+ struct filestat *fst, struct freebsd11_semstat *sem, char *errbuf);
+int freebsd11_procstat_get_shm_info(struct procstat *procstat,
+ struct filestat *fst, struct freebsd11_shmstat *shm, char *errbuf);
+int freebsd11_procstat_get_vnode_info(struct procstat *procstat,
+ struct filestat *fst, struct freebsd11_vnstat *vn, char *errbuf);
+
+int
+freebsd11_procstat_get_pts_info(struct procstat *procstat,
+ struct filestat *fst, struct freebsd11_ptsstat *pts_compat, char *errbuf)
+{
+ struct ptsstat pts;
+ int r;
+
+ r = procstat_get_pts_info(procstat, fst, &pts, errbuf);
+ if (r != 0)
+ return (r);
+ pts_compat->dev = pts.dev;
+ memcpy(pts_compat->devname, pts.devname,
+ sizeof(pts_compat->devname));
+ return (0);
+}
+
+int
+freebsd11_procstat_get_sem_info(struct procstat *procstat,
+ struct filestat *fst, struct freebsd11_semstat *sem_compat, char *errbuf)
+{
+ struct semstat sem;
+ int r;
+
+ r = procstat_get_sem_info(procstat, fst, &sem, errbuf);
+ if (r != 0)
+ return (r);
+ sem_compat->value = sem.value;
+ sem_compat->mode = sem.mode;
+ return (0);
+}
+
+int
+freebsd11_procstat_get_shm_info(struct procstat *procstat,
+ struct filestat *fst, struct freebsd11_shmstat *shm_compat, char *errbuf)
+{
+ struct shmstat shm;
+ int r;
+
+ r = procstat_get_shm_info(procstat, fst, &shm, errbuf);
+ if (r != 0)
+ return (r);
+ shm_compat->size = shm.size;
+ shm_compat->mode = shm.mode;
+ return (0);
+}
+
+int
+freebsd11_procstat_get_vnode_info(struct procstat *procstat,
+ struct filestat *fst, struct freebsd11_vnstat *vn_compat, char *errbuf)
+{
+ struct vnstat vn;
+ int r;
+
+ r = procstat_get_vnode_info(procstat, fst, &vn, errbuf);
+ if (r != 0)
+ return (r);
+ vn_compat->vn_fileid = vn.vn_fileid;
+ vn_compat->vn_size = vn.vn_size;
+ vn_compat->vn_mntdir = vn.vn_mntdir;
+ vn_compat->vn_dev = vn.vn_dev;
+ vn_compat->vn_fsid = vn.vn_fsid;
+ vn_compat->vn_type = vn.vn_type;
+ vn_compat->vn_mode = vn.vn_mode;
+ memcpy(vn_compat->vn_devname, vn.vn_devname,
+ sizeof(vn_compat->vn_devname));
+ return (0);
+}
+
+__sym_compat(procstat_get_pts_info, freebsd11_procstat_get_pts_info, FBSD_1.2);
+__sym_compat(procstat_get_vnode_info, freebsd11_procstat_get_vnode_info,
+ FBSD_1.2);
+__sym_compat(procstat_get_sem_info, freebsd11_procstat_get_sem_info, FBSD_1.3);
+__sym_compat(procstat_get_shm_info, freebsd11_procstat_get_shm_info, FBSD_1.3);
diff --git a/lib/libufs/libufs.h b/lib/libufs/libufs.h
index a16d82b604ad..ddc5c9b6b055 100644
--- a/lib/libufs/libufs.h
+++ b/lib/libufs/libufs.h
@@ -45,8 +45,8 @@ struct uufsd {
ufs2_daddr_t d_sblock; /* superblock location */
struct csum *d_sbcsum; /* Superblock summary info */
caddr_t d_inoblock; /* inode block */
- ino_t d_inomin; /* low inode */
- ino_t d_inomax; /* high inode */
+ uint32_t d_inomin; /* low inode (not ino_t for ABI compat) */
+ uint32_t d_inomax; /* high inode (not ino_t for ABI compat) */
union {
struct fs d_fs; /* filesystem information */
char d_sb[MAXBSIZE];
diff --git a/sbin/badsect/badsect.c b/sbin/badsect/badsect.c
index f9d2a1afe727..097e3b112f67 100644
--- a/sbin/badsect/badsect.c
+++ b/sbin/badsect/badsect.c
@@ -129,19 +129,8 @@ main(int argc, char *argv[])
err(8, "%s", *argv);
if (chkuse(number, 1))
continue;
- /*
- * Print a warning if converting the block number to a dev_t
- * will truncate it. badsect was not very useful in versions
- * of BSD before 4.4 because dev_t was 16 bits and another
- * bit was lost by bogus sign extensions.
- */
diskbn = dbtofsb(fs, number);
- if ((dev_t)diskbn != diskbn) {
- printf("sector %ld cannot be represented as a dev_t\n",
- (long)number);
- errs++;
- }
- else if (mknod(*argv, IFMT|0600, (dev_t)diskbn) < 0) {
+ if (mknod(*argv, IFMT|0600, (dev_t)diskbn) < 0) {
warn("%s", *argv);
errs++;
}
diff --git a/sbin/fsck_ffs/suj.c b/sbin/fsck_ffs/suj.c
index f0c6524e3ff1..72bf83cdb2f5 100644
--- a/sbin/fsck_ffs/suj.c
+++ b/sbin/fsck_ffs/suj.c
@@ -1347,8 +1347,8 @@ ino_adjust(struct suj_ino *sino)
struct suj_ino *stmp;
union dinode *ip;
nlink_t nlink;
+ nlink_t reqlink;
int recmode;
- int reqlink;
int isdot;
int mode;
ino_t ino;
@@ -1635,9 +1635,9 @@ ino_check(struct suj_ino *sino)
struct suj_rec *srec;
struct jrefrec *rrec;
nlink_t dotlinks;
- int newlinks;
- int removes;
- int nlink;
+ nlink_t newlinks;
+ nlink_t removes;
+ nlink_t nlink;
ino_t ino;
int isdot;
int isat;
diff --git a/share/man/man5/acct.5 b/share/man/man5/acct.5
index 06c72b2af727..549eef2c70bb 100644
--- a/share/man/man5/acct.5
+++ b/share/man/man5/acct.5
@@ -28,7 +28,7 @@
.\" @(#)acct.5 8.1 (Berkeley) 6/5/93
.\" $FreeBSD$
.\"
-.Dd May 15, 2007
+.Dd February 13, 2017
.Dt ACCT 5
.Os
.Sh NAME
@@ -51,12 +51,12 @@ to the accounting file.
#define AC_COMM_LEN 16
/*
- * Accounting structure version 2 (current).
+ * Accounting structure version 3 (current).
* The first byte is always zero.
* Time units are microseconds.
*/
-struct acctv2 {
+struct acctv3 {
uint8_t ac_zero; /* zero identifies new version */
uint8_t ac_version; /* record version number */
uint16_t ac_len; /* record length */
@@ -74,7 +74,7 @@ struct acctv2 {
uint16_t ac_len2; /* record length */
union {
- __dev_t ac_align; /* force v1 compatible alignment */
+ uint32_t ac_align; /* force v1 compatible alignment */
#define AFORK 0x01 /* forked but not exec'ed */
/* ASU is no longer supported */
diff --git a/share/man/man5/dir.5 b/share/man/man5/dir.5
index 19dfc56705c2..01b7d850a3b0 100644
--- a/share/man/man5/dir.5
+++ b/share/man/man5/dir.5
@@ -28,7 +28,7 @@
.\" @(#)dir.5 8.3 (Berkeley) 4/19/94
.\" $FreeBSD$
.\"
-.Dd April 19, 1994
+.Dd February 13, 2017
.Dt DIR 5
.Os
.Sh NAME
@@ -93,18 +93,24 @@ The directory entry format is defined in the file
* contained in the entry. These are followed by the name padded to a 4
* byte boundary with null bytes. All names are guaranteed null terminated.
* The maximum length of a name in a directory is MAXNAMLEN.
+ * Explicit pad is added between the last member of the header and
+ * d_name, to avoid having the ABI padding in the end of dirent on
+ * LP64 arches. There is code depending on d_name being last. Also,
+ * keeping this pad for ILP32 architectures simplifies compat32 layer.
*/
struct dirent {
- __uint32_t d_fileno; /* file number of entry */
+ ino_t d_fileno; /* file number of entry */
+ off_t d_off; /* directory offset of entry */
__uint16_t d_reclen; /* length of this record */
- __uint8_t d_type; /* file type, see below */
+ __uint8_t d_type; /* file type, see below */
__uint8_t d_namlen; /* length of string in d_name */
-#ifdef _POSIX_SOURCE
- char d_name[255 + 1]; /* name must be no longer than this */
-#else
+ __uint32_t d_pad0;
+#if __BSD_VISIBLE
#define MAXNAMLEN 255
char d_name[MAXNAMLEN + 1]; /* name must be no longer than this */
+#else
+ char d_name[255 + 1]; /* name must be no longer than this */
#endif
};
@@ -129,12 +135,17 @@ struct dirent {
/*
* The _GENERIC_DIRSIZ macro gives the minimum record length which will hold
- * the directory entry. This requires the amount of space in struct direct
+ * the directory entry. This returns the amount of space in struct direct
* without the d_name field, plus enough space for the name with a terminating
- * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary.
+ * null byte (dp->d_namlen+1), rounded up to a 8 byte boundary.
+ *
+ * XXX although this macro is in the implementation namespace, it requires
+ * a manifest constant that is not.
*/
-#define _GENERIC_DIRSIZ(dp) \
- ((sizeof (struct dirent) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3))
+#define _GENERIC_DIRLEN(namlen) \
+ ((__offsetof(struct dirent, d_name) + (namlen) + 1 + 7) & ~7)
+#define _GENERIC_DIRSIZ(dp) _GENERIC_DIRLEN((dp)->d_namlen)
+#endif /* __BSD_VISIBLE */
#ifdef _KERNEL
#define GENERIC_DIRSIZ(dp) _GENERIC_DIRSIZ(dp)
diff --git a/sys/bsm/audit.h b/sys/bsm/audit.h
index af9622af314e..57edb5e4e83f 100644
--- a/sys/bsm/audit.h
+++ b/sys/bsm/audit.h
@@ -183,13 +183,13 @@ typedef u_int32_t au_class_t;
typedef u_int64_t au_asflgs_t __attribute__ ((aligned (8)));
struct au_tid {
- dev_t port;
+ u_int32_t port; /* XXX dev_t compatibility */
u_int32_t machine;
};
typedef struct au_tid au_tid_t;
struct au_tid_addr {
- dev_t at_port;
+ u_int32_t at_port; /* XXX dev_t compatibility */
u_int32_t at_type;
u_int32_t at_addr[4];
};
diff --git a/sys/cddl/compat/opensolaris/sys/dirent.h b/sys/cddl/compat/opensolaris/sys/dirent.h
index d273f8a0fce4..81ea4fa3a97f 100644
--- a/sys/cddl/compat/opensolaris/sys/dirent.h
+++ b/sys/cddl/compat/opensolaris/sys/dirent.h
@@ -40,8 +40,6 @@ typedef ino_t ino64_t;
#define d_ino d_fileno
-#define DIRENT64_RECLEN(len) ((sizeof(struct dirent) - \
- sizeof(((struct dirent *)NULL)->d_name) + \
- (len) + 1 + 3) & ~3)
+#define DIRENT64_RECLEN(len) _GENERIC_DIRLEN(len)
#endif /* !_OPENSOLARIS_SYS_DIRENT_H_ */
diff --git a/sys/compat/freebsd32/capabilities.conf b/sys/compat/freebsd32/capabilities.conf
index 6d815f1ab522..1a5670cade91 100644
--- a/sys/compat/freebsd32/capabilities.conf
+++ b/sys/compat/freebsd32/capabilities.conf
@@ -94,6 +94,11 @@ freebsd32_fexecve
flock
fork
fpathconf
+freebsd11_freebsd32_fstat
+freebsd11_freebsd32_fstatat
+freebsd11_freebsd32_getdirentries
+freebsd11_freebsd32_fstatfs
+freebsd11_freebsd32_mknodat
freebsd6_freebsd32_ftruncate
freebsd6_freebsd32_lseek
freebsd6_freebsd32_mmap
diff --git a/sys/compat/freebsd32/freebsd32.h b/sys/compat/freebsd32/freebsd32.h
index 39213aec94d3..05447da3696b 100644
--- a/sys/compat/freebsd32/freebsd32.h
+++ b/sys/compat/freebsd32/freebsd32.h
@@ -107,7 +107,8 @@ struct itimerval32 {
struct timeval32 it_value;
};
-#define FREEBSD4_MNAMELEN (88 - 2 * sizeof(int32_t)) /* size of on/from name bufs */
+#define FREEBSD4_MFSNAMELEN 16
+#define FREEBSD4_MNAMELEN (88 - 2 * sizeof(int32_t))
/* 4.x version */
struct statfs32 {
@@ -125,7 +126,7 @@ struct statfs32 {
int32_t f_flags;
int32_t f_syncwrites;
int32_t f_asyncwrites;
- char f_fstypename[MFSNAMELEN];
+ char f_fstypename[FREEBSD4_MFSNAMELEN];
char f_mntonname[FREEBSD4_MNAMELEN];
int32_t f_syncreads;
int32_t f_asyncreads;
@@ -159,14 +160,51 @@ struct msghdr32 {
int msg_flags;
};
+#if defined(__amd64__)
+#define __STAT32_TIME_T_EXT 1
+#endif
+
struct stat32 {
- dev_t st_dev;
- ino_t st_ino;
+ dev_t st_dev;
+ ino_t st_ino;
+ nlink_t st_nlink;
+ mode_t st_mode;
+ u_int16_t st_padding0;
+ uid_t st_uid;
+ gid_t st_gid;
+ u_int32_t st_padding1;
+ dev_t st_rdev;
+#ifdef __STAT32_TIME_T_EXT
+ __int32_t st_atim_ext;
+#endif
+ struct timespec32 st_atim;
+#ifdef __STAT32_TIME_T_EXT
+ __int32_t st_mtim_ext;
+#endif
+ struct timespec32 st_mtim;
+#ifdef __STAT32_TIME_T_EXT
+ __int32_t st_ctim_ext;
+#endif
+ struct timespec32 st_ctim;
+#ifdef __STAT32_TIME_T_EXT
+ __int32_t st_btim_ext;
+#endif
+ struct timespec32 st_birthtim;
+ off_t st_size;
+ int64_t st_blocks;
+ u_int32_t st_blksize;
+ u_int32_t st_flags;
+ u_int64_t st_gen;
+ u_int64_t st_spare[10];
+};
+struct freebsd11_stat32 {
+ u_int32_t st_dev;
+ u_int32_t st_ino;
mode_t st_mode;
- nlink_t st_nlink;
+ u_int16_t st_nlink;
uid_t st_uid;
gid_t st_gid;
- dev_t st_rdev;
+ u_int32_t st_rdev;
struct timespec32 st_atim;
struct timespec32 st_mtim;
struct timespec32 st_ctim;
@@ -183,9 +221,9 @@ struct stat32 {
struct ostat32 {
__uint16_t st_dev;
- ino_t st_ino;
+ __uint32_t st_ino;
mode_t st_mode;
- nlink_t st_nlink;
+ __uint16_t st_nlink;
__uint16_t st_uid;
__uint16_t st_gid;
__uint16_t st_rdev;
@@ -270,7 +308,7 @@ struct kinfo_proc32 {
pid_t ki_tsid;
short ki_jobc;
short ki_spare_short1;
- dev_t ki_tdev;
+ uint32_t ki_tdev_freebsd11;
sigset_t ki_siglist;
sigset_t ki_sigmask;
sigset_t ki_sigignore;
@@ -318,6 +356,7 @@ struct kinfo_proc32 {
char ki_moretdname[MAXCOMLEN-TDNAMLEN+1];
char ki_sparestrings[46];
int ki_spareints[KI_NSPARE_INT];
+ uint64_t ki_tdev;
int ki_oncpu;
int ki_lastcpu;
int ki_tracer;
diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c
index a8e69b731fe7..d73f95f3d071 100644
--- a/sys/compat/freebsd32/freebsd32_misc.c
+++ b/sys/compat/freebsd32/freebsd32_misc.c
@@ -122,8 +122,11 @@ CTASSERT(sizeof(struct sigaltstack32) == 12);
CTASSERT(sizeof(struct kevent32) == 20);
CTASSERT(sizeof(struct iovec32) == 8);
CTASSERT(sizeof(struct msghdr32) == 28);
+#ifdef __amd64__
+CTASSERT(sizeof(struct stat32) == 208);
+#endif
#ifndef __mips__
-CTASSERT(sizeof(struct stat32) == 96);
+CTASSERT(sizeof(struct freebsd11_stat32) == 96);
#endif
CTASSERT(sizeof(struct sigaction32) == 24);
@@ -448,6 +451,26 @@ freebsd32_fexecve(struct thread *td, struct freebsd32_fexecve_args *uap)
return (error);
}
+#if defined(COMPAT_FREEBSD11)
+int
+freebsd11_freebsd32_mknod(struct thread *td,
+ struct freebsd11_freebsd32_mknod_args *uap)
+{
+
+ return (kern_mknodat(td, AT_FDCWD, uap->path, UIO_USERSPACE, uap->mode,
+ uap->dev));
+}
+
+int
+freebsd11_freebsd32_mknodat(struct thread *td,
+ struct freebsd11_freebsd32_mknodat_args *uap)
+{
+
+ return (kern_mknodat(td, uap->fd, uap->path, UIO_USERSPACE, uap->mode,
+ uap->dev));
+}
+#endif /* COMPAT_FREEBSD11 */
+
int
freebsd32_mprotect(struct thread *td, struct freebsd32_mprotect_args *uap)
{
@@ -1519,6 +1542,40 @@ ofreebsd32_getdirentries(struct thread *td,
}
#endif
+#if defined(COMPAT_FREEBSD11)
+int
+freebsd11_freebsd32_getdirentries(struct thread *td,
+ struct freebsd11_freebsd32_getdirentries_args *uap)
+{
+ long base;
+ int32_t base32;
+ int error;
+
+ error = freebsd11_kern_getdirentries(td, uap->fd, uap->buf, uap->count,
+ &base, NULL);
+ if (error)
+ return (error);
+ if (uap->basep != NULL) {
+ base32 = base;
+ error = copyout(&base32, uap->basep, sizeof(int32_t));
+ }
+ return (error);
+}
+
+int
+freebsd11_freebsd32_getdents(struct thread *td,
+ struct freebsd11_freebsd32_getdents_args *uap)
+{
+ struct freebsd11_freebsd32_getdirentries_args ap;
+
+ ap.fd = uap->fd;
+ ap.buf = uap->buf;
+ ap.count = uap->count;
+ ap.basep = NULL;
+ return (freebsd11_freebsd32_getdirentries(td, &ap));
+}
+#endif /* COMPAT_FREEBSD11 */
+
int
freebsd32_getdirentries(struct thread *td,
struct freebsd32_getdirentries_args *uap)
@@ -1709,6 +1766,15 @@ copy_stat(struct stat *in, struct stat32 *out)
CP(*in, *out, st_flags);
CP(*in, *out, st_gen);
TS_CP(*in, *out, st_birthtim);
+ out->st_padding0 = 0;
+ out->st_padding1 = 0;
+#ifdef __STAT32_TIME_T_EXT
+ out->st_atim_ext = 0;
+ out->st_mtim_ext = 0;
+ out->st_ctim_ext = 0;
+ out->st_btim_ext = 0;
+#endif
+ bzero(out->st_spare, sizeof(out->st_spare));
}
#ifdef COMPAT_43
@@ -1734,22 +1800,6 @@ copy_ostat(struct stat *in, struct ostat32 *out)
}
#endif
-int
-freebsd32_stat(struct thread *td, struct freebsd32_stat_args *uap)
-{
- struct stat sb;
- struct stat32 sb32;
- int error;
-
- error = kern_statat(td, 0, AT_FDCWD, uap->path, UIO_USERSPACE,
- &sb, NULL);
- if (error)
- return (error);
- copy_stat(&sb, &sb32);
- error = copyout(&sb32, uap->ub, sizeof (sb32));
- return (error);
-}
-
#ifdef COMPAT_43
int
ofreebsd32_stat(struct thread *td, struct ofreebsd32_stat_args *uap)
@@ -1816,38 +1866,156 @@ freebsd32_fstatat(struct thread *td, struct freebsd32_fstatat_args *uap)
return (error);
}
+#ifdef COMPAT_43
int
-freebsd32_lstat(struct thread *td, struct freebsd32_lstat_args *uap)
+ofreebsd32_lstat(struct thread *td, struct ofreebsd32_lstat_args *uap)
{
struct stat sb;
- struct stat32 sb32;
+ struct ostat32 sb32;
int error;
error = kern_statat(td, AT_SYMLINK_NOFOLLOW, AT_FDCWD, uap->path,
UIO_USERSPACE, &sb, NULL);
if (error)
return (error);
+ copy_ostat(&sb, &sb32);
+ error = copyout(&sb32, uap->ub, sizeof (sb32));
+ return (error);
+}
+#endif
+
+int
+freebsd32_fhstat(struct thread *td, struct freebsd32_fhstat_args *uap)
+{
+ struct stat sb;
+ struct stat32 sb32;
+ struct fhandle fh;
+ int error;
+
+ error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t));
+ if (error != 0)
+ return (error);
+ error = kern_fhstat(td, fh, &sb);
+ if (error != 0)
+ return (error);
copy_stat(&sb, &sb32);
+ error = copyout(&sb32, uap->sb, sizeof (sb32));
+ return (error);
+}
+
+#if defined(COMPAT_FREEBSD11)
+static void
+freebsd11_cvtstat32(struct stat *in, struct freebsd11_stat32 *out)
+{
+
+ CP(*in, *out, st_ino);
+ CP(*in, *out, st_nlink);
+ CP(*in, *out, st_dev);
+ CP(*in, *out, st_mode);
+ CP(*in, *out, st_uid);
+ CP(*in, *out, st_gid);
+ CP(*in, *out, st_rdev);
+ TS_CP(*in, *out, st_atim);
+ TS_CP(*in, *out, st_mtim);
+ TS_CP(*in, *out, st_ctim);
+ CP(*in, *out, st_size);
+ CP(*in, *out, st_blocks);
+ CP(*in, *out, st_blksize);
+ CP(*in, *out, st_flags);
+ CP(*in, *out, st_gen);
+ TS_CP(*in, *out, st_birthtim);
+ out->st_lspare = 0;
+ bzero((char *)&out->st_birthtim + sizeof(out->st_birthtim),
+ sizeof(*out) - offsetof(struct freebsd11_stat32,
+ st_birthtim) - sizeof(out->st_birthtim));
+}
+
+int
+freebsd11_freebsd32_stat(struct thread *td,
+ struct freebsd11_freebsd32_stat_args *uap)
+{
+ struct stat sb;
+ struct freebsd11_stat32 sb32;
+ int error;
+
+ error = kern_statat(td, 0, AT_FDCWD, uap->path, UIO_USERSPACE,
+ &sb, NULL);
+ if (error != 0)
+ return (error);
+ freebsd11_cvtstat32(&sb, &sb32);
error = copyout(&sb32, uap->ub, sizeof (sb32));
return (error);
}
-#ifdef COMPAT_43
int
-ofreebsd32_lstat(struct thread *td, struct ofreebsd32_lstat_args *uap)
+freebsd11_freebsd32_fstat(struct thread *td,
+ struct freebsd11_freebsd32_fstat_args *uap)
{
struct stat sb;
- struct ostat32 sb32;
+ struct freebsd11_stat32 sb32;
+ int error;
+
+ error = kern_fstat(td, uap->fd, &sb);
+ if (error != 0)
+ return (error);
+ freebsd11_cvtstat32(&sb, &sb32);
+ error = copyout(&sb32, uap->ub, sizeof (sb32));
+ return (error);
+}
+
+int
+freebsd11_freebsd32_fstatat(struct thread *td,
+ struct freebsd11_freebsd32_fstatat_args *uap)
+{
+ struct stat sb;
+ struct freebsd11_stat32 sb32;
+ int error;
+
+ error = kern_statat(td, uap->flag, uap->fd, uap->path, UIO_USERSPACE,
+ &sb, NULL);
+ if (error != 0)
+ return (error);
+ freebsd11_cvtstat32(&sb, &sb32);
+ error = copyout(&sb32, uap->buf, sizeof (sb32));
+ return (error);
+}
+
+int
+freebsd11_freebsd32_lstat(struct thread *td,
+ struct freebsd11_freebsd32_lstat_args *uap)
+{
+ struct stat sb;
+ struct freebsd11_stat32 sb32;
int error;
error = kern_statat(td, AT_SYMLINK_NOFOLLOW, AT_FDCWD, uap->path,
UIO_USERSPACE, &sb, NULL);
if (error)
return (error);
- copy_ostat(&sb, &sb32);
+ freebsd11_cvtstat32(&sb, &sb32);
error = copyout(&sb32, uap->ub, sizeof (sb32));
return (error);
}
+
+int
+freebsd11_freebsd32_fhstat(struct thread *td,
+ struct freebsd11_freebsd32_fhstat_args *uap)
+{
+ struct stat sb;
+ struct freebsd11_stat32 sb32;
+ struct fhandle fh;
+ int error;
+
+ error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t));
+ if (error != 0)
+ return (error);
+ error = kern_fhstat(td, fh, &sb);
+ if (error != 0)
+ return (error);
+ freebsd11_cvtstat32(&sb, &sb32);
+ error = copyout(&sb32, uap->sb, sizeof (sb32));
+ return (error);
+}
#endif
int
diff --git a/sys/compat/freebsd32/syscalls.master b/sys/compat/freebsd32/syscalls.master
index ac624e4f7df2..fce75fe3488a 100644
--- a/sys/compat/freebsd32/syscalls.master
+++ b/sys/compat/freebsd32/syscalls.master
@@ -13,7 +13,7 @@
; case where the event exists, but we don't want auditing, the
; event should be #defined to AUE_NULL in audit_kevents.h.
; type one of STD, OBSOL, UNIMPL, COMPAT, COMPAT4, COMPAT6,
-; COMPAT7, NODEF, NOARGS, NOPROTO, NOSTD
+; COMPAT7, COMPAT11, NODEF, NOARGS, NOPROTO, NOSTD
; The COMPAT* options may be combined with one or more NO*
; options separated by '|' with no spaces (e.g. COMPAT|NOARGS)
; name psuedo-prototype of syscall routine
@@ -30,6 +30,7 @@
; COMPAT6 included on COMPAT6 #ifdef (FreeBSD 6 compat)
; COMPAT7 included on COMPAT7 #ifdef (FreeBSD 7 compat)
; COMPAT10 included on COMPAT10 #ifdef (FreeBSD 10 compat)
+; COMPAT11 included on COMPAT11 #ifdef (FreeBSD 11 compat)
; OBSOL obsolete, not included in system, only specifies name
; UNIMPL not implemented, placeholder only
; NOSTD implemented but as a lkm that can be statically
@@ -82,7 +83,8 @@
11 AUE_NULL OBSOL execv
12 AUE_CHDIR NOPROTO { int chdir(char *path); }
13 AUE_FCHDIR NOPROTO { int fchdir(int fd); }
-14 AUE_MKNOD NOPROTO { int mknod(char *path, int mode, int dev); }
+14 AUE_MKNOD COMPAT11 { int freebsd32_mknod(char *path, \
+ int mode, int dev); }
15 AUE_CHMOD NOPROTO { int chmod(char *path, int mode); }
16 AUE_CHOWN NOPROTO { int chown(char *path, int uid, int gid); }
17 AUE_NULL NOPROTO { int obreak(char *nsize); } break \
@@ -348,12 +350,12 @@
185 AUE_NULL UNIMPL lfs_markv
186 AUE_NULL UNIMPL lfs_segclean
187 AUE_NULL UNIMPL lfs_segwait
-188 AUE_STAT STD { int freebsd32_stat(char *path, \
- struct stat32 *ub); }
-189 AUE_FSTAT STD { int freebsd32_fstat(int fd, \
- struct stat32 *ub); }
-190 AUE_LSTAT STD { int freebsd32_lstat(char *path, \
- struct stat32 *ub); }
+188 AUE_STAT COMPAT11 { int freebsd32_stat(char *path, \
+ struct freebsd11_stat32 *ub); }
+189 AUE_FSTAT COMPAT11 { int freebsd32_fstat(int fd, \
+ struct freebsd11_stat32 *ub); }
+190 AUE_LSTAT COMPAT11 { int freebsd32_lstat(char *path, \
+ struct freebsd11_stat32 *ub); }
191 AUE_PATHCONF NOPROTO { int pathconf(char *path, int name); }
192 AUE_FPATHCONF NOPROTO { int fpathconf(int fd, int name); }
193 AUE_NULL UNIMPL nosys
@@ -363,7 +365,7 @@
195 AUE_SETRLIMIT NOPROTO { int setrlimit(u_int which, \
struct rlimit *rlp); } setrlimit \
__setrlimit_args int
-196 AUE_GETDIRENTRIES STD { int freebsd32_getdirentries(int fd, \
+196 AUE_GETDIRENTRIES COMPAT11 { int freebsd32_getdirentries(int fd, \
char *buf, u_int count, int32_t *basep); }
197 AUE_MMAP COMPAT6 { caddr_t freebsd32_mmap(caddr_t addr, \
size_t len, int prot, int flags, int fd, \
@@ -501,8 +503,8 @@
269 AUE_NULL UNIMPL nosys
270 AUE_NULL UNIMPL nosys
271 AUE_NULL UNIMPL nosys
-272 AUE_O_GETDENTS NOPROTO { int getdents(int fd, char *buf, \
- size_t count); }
+272 AUE_O_GETDENTS COMPAT11 { int freebsd32_getdents(int fd, char *buf, \
+ int count); }
273 AUE_NULL UNIMPL nosys
274 AUE_LCHMOD NOPROTO { int lchmod(char *path, mode_t mode); }
275 AUE_LCHOWN NOPROTO { int lchown(char *path, uid_t uid, \
@@ -512,9 +514,9 @@
struct timeval32 *tptr); }
277 AUE_MSYNC NOPROTO { int msync(void *addr, size_t len, \
int flags); } netbsd_msync msync_args int
-278 AUE_STAT NOPROTO { int nstat(char *path, struct nstat *ub); }
-279 AUE_FSTAT NOPROTO { int nfstat(int fd, struct nstat *sb); }
-280 AUE_LSTAT NOPROTO { int nlstat(char *path, struct nstat *ub); }
+278 AUE_STAT COMPAT11|NOPROTO { int nstat(char *path, struct nstat *ub); }
+279 AUE_FSTAT COMPAT11|NOPROTO { int nfstat(int fd, struct nstat *sb); }
+280 AUE_LSTAT COMPAT11|NOPROTO { int nlstat(char *path, struct nstat *ub); }
281 AUE_NULL UNIMPL nosys
282 AUE_NULL UNIMPL nosys
283 AUE_NULL UNIMPL nosys
@@ -544,8 +546,9 @@
struct statfs32 *buf); }
298 AUE_FHOPEN NOPROTO { int fhopen(const struct fhandle *u_fhp, \
int flags); }
-299 AUE_FHSTAT NOPROTO { int fhstat(const struct fhandle *u_fhp, \
- struct stat *sb); }
+299 AUE_FHSTAT COMPAT11 { int freebsd32_fhstat( \
+ const struct fhandle *u_fhp, \
+ struct freebsd11_stat32 *sb); }
; syscall numbers for FreeBSD
300 AUE_NULL NOPROTO { int modnext(int modid); }
301 AUE_NULL STD { int freebsd32_modstat(int modid, \
@@ -713,13 +716,16 @@
size_t nbytes, struct sf_hdtr32 *hdtr, \
off_t *sbytes, int flags); }
394 AUE_NULL UNIMPL mac_syscall
-395 AUE_GETFSSTAT NOPROTO { int getfsstat(struct statfs *buf, \
+395 AUE_GETFSSTAT COMPAT11|NOPROTO { int getfsstat( \
+ struct freebsd11_statfs *buf, \
long bufsize, int mode); }
-396 AUE_STATFS NOPROTO { int statfs(char *path, \
- struct statfs *buf); }
-397 AUE_FSTATFS NOPROTO { int fstatfs(int fd, struct statfs *buf); }
-398 AUE_FHSTATFS NOPROTO { int fhstatfs(const struct fhandle *u_fhp, \
+396 AUE_STATFS COMPAT11|NOPROTO { int statfs(char *path, \
struct statfs *buf); }
+397 AUE_FSTATFS COMPAT11|NOPROTO { int fstatfs(int fd, \
+ struct freebsd11_statfs *buf); }
+398 AUE_FHSTATFS COMPAT11|NOPROTO { int fhstatfs( \
+ const struct fhandle *u_fhp, \
+ struct freebsd11_statfs *buf); }
399 AUE_NULL UNIMPL nosys
400 AUE_SEMCLOSE NOSTD|NOPROTO { int ksem_close(semid_t id); }
401 AUE_SEMPOST NOSTD|NOPROTO { int ksem_post(semid_t id); }
@@ -936,8 +942,9 @@
gid_t gid, int flag); }
492 AUE_FEXECVE STD { int freebsd32_fexecve(int fd, \
uint32_t *argv, uint32_t *envv); }
-493 AUE_FSTATAT STD { int freebsd32_fstatat(int fd, char *path, \
- struct stat *buf, int flag); }
+493 AUE_FSTATAT COMPAT11 { int freebsd32_fstatat(int fd, \
+ char *path, struct freebsd11_stat32 *buf, \
+ int flag); }
494 AUE_FUTIMESAT STD { int freebsd32_futimesat(int fd, char *path, \
struct timeval *times); }
495 AUE_LINKAT NOPROTO { int linkat(int fd1, char *path1, int fd2, \
@@ -946,8 +953,8 @@
mode_t mode); }
497 AUE_MKFIFOAT NOPROTO { int mkfifoat(int fd, char *path, \
mode_t mode); }
-498 AUE_MKNODAT NOPROTO { int mknodat(int fd, char *path, \
- mode_t mode, dev_t dev); }
+498 AUE_MKNODAT COMPAT11 { int freebsd32_mknodat(int fd, char *path, \
+ mode_t mode, uint32_t dev); }
499 AUE_OPENAT_RWTC NOPROTO { int openat(int fd, char *path, int flag, \
mode_t mode); }
500 AUE_READLINKAT NOPROTO { int readlinkat(int fd, char *path, char *buf, \
@@ -1084,3 +1091,23 @@
id_t id, \
const struct vm_domain_policy *policy); }
550 AUE_FSYNC NOPROTO { int fdatasync(int fd); }
+551 AUE_FSTAT STD { int freebsd32_fstat(int fd, \
+ struct stat32 *ub); }
+552 AUE_FSTATAT STD { int freebsd32_fstatat(int fd, \
+ char *path, struct stat32 *buf, \
+ int flag); }
+553 AUE_FHSTAT STD { int freebsd32_fhstat( \
+ const struct fhandle *u_fhp, \
+ struct stat32 *sb); }
+554 AUE_GETDIRENTRIES STD { ssize_t freebsd32_getdirentries( \
+ int fd, char *buf, size_t count, \
+ int32_t *basep); }
+555 AUE_STATFS NOPROTO { int statfs(char *path, \
+ struct statfs32 *buf); }
+556 AUE_FSTATFS NOPROTO { int fstatfs(int fd, struct statfs32 *buf); }
+557 AUE_GETFSSTAT NOPROTO { int getfsstat(struct statfs32 *buf, \
+ long bufsize, int mode); }
+558 AUE_FHSTATFS NOPROTO { int fhstatfs(const struct fhandle *u_fhp, \
+ struct statfs32 *buf); }
+559 AUE_MKNODAT NOPROTO { int mknodat(int fd, char *path, mode_t mode, \
+ dev_t dev); }
diff --git a/sys/compat/linux/linux_file.c b/sys/compat/linux/linux_file.c
index 6480fc823a55..4bacee37df38 100644
--- a/sys/compat/linux/linux_file.c
+++ b/sys/compat/linux/linux_file.c
@@ -328,7 +328,7 @@ linux_getdents(struct thread *td, struct linux_getdents_args *args)
caddr_t outp; /* Linux-format */
int resid, linuxreclen; /* Linux-format */
caddr_t lbuf; /* Linux-format */
- long base;
+ off_t base;
struct l_dirent *linux_dirent;
int buflen, error;
size_t retval;
@@ -409,7 +409,7 @@ linux_getdents64(struct thread *td, struct linux_getdents64_args *args)
caddr_t outp; /* Linux-format */
int resid, linuxreclen; /* Linux-format */
caddr_t lbuf; /* Linux-format */
- long base;
+ off_t base;
struct l_dirent64 *linux_dirent64;
int buflen, error;
size_t retval;
@@ -486,7 +486,7 @@ linux_readdir(struct thread *td, struct linux_readdir_args *args)
caddr_t buf; /* BSD-format */
int linuxreclen; /* Linux-format */
caddr_t lbuf; /* Linux-format */
- long base;
+ off_t base;
struct l_dirent *linux_dirent;
int buflen, error;
@@ -1087,20 +1087,21 @@ int
linux_mount(struct thread *td, struct linux_mount_args *args)
{
char fstypename[MFSNAMELEN];
- char mntonname[MNAMELEN], mntfromname[MNAMELEN];
- int error;
- int fsflags;
+ char *mntonname, *mntfromname;
+ int error, fsflags;
+ mntonname = malloc(MNAMELEN, M_TEMP, M_WAITOK);
+ mntfromname = malloc(MNAMELEN, M_TEMP, M_WAITOK);
error = copyinstr(args->filesystemtype, fstypename, MFSNAMELEN - 1,
NULL);
- if (error)
- return (error);
+ if (error != 0)
+ goto out;
error = copyinstr(args->specialfile, mntfromname, MNAMELEN - 1, NULL);
- if (error)
- return (error);
+ if (error != 0)
+ goto out;
error = copyinstr(args->dir, mntonname, MNAMELEN - 1, NULL);
- if (error)
- return (error);
+ if (error != 0)
+ goto out;
#ifdef DEBUG
if (ldebug(mount))
@@ -1138,6 +1139,9 @@ linux_mount(struct thread *td, struct linux_mount_args *args)
"fspath", mntonname,
"from", mntfromname,
NULL);
+out:
+ free(mntonname, M_TEMP);
+ free(mntfromname, M_TEMP);
return (error);
}
diff --git a/sys/dev/snp/snp.c b/sys/dev/snp/snp.c
index 1c02660bec1d..84260182265c 100644
--- a/sys/dev/snp/snp.c
+++ b/sys/dev/snp/snp.c
@@ -60,6 +60,8 @@ SX_SYSINIT(snp_register_lock, &snp_register_lock,
#define SNP_UNLOCK() sx_xunlock(&snp_register_lock)
#endif
+#define SNPGTYY_32DEV _IOR('T', 89, uint32_t)
+
/*
* There is no need to have a big input buffer. In most typical setups,
* we won't inject much data into the TTY, because users can't type
@@ -275,6 +277,12 @@ snp_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flags,
else
*(dev_t *)data = tty_udev(ss->snp_tty);
return (0);
+ case SNPGTYY_32DEV:
+ if (ss->snp_tty == NULL)
+ *(uint32_t *)data = -1;
+ else
+ *(uint32_t *)data = tty_udev(ss->snp_tty); /* trunc */
+ return (0);
case FIONREAD:
tp = ss->snp_tty;
if (tp != NULL) {
diff --git a/sys/fs/devfs/devfs_devs.c b/sys/fs/devfs/devfs_devs.c
index e600ff1cea47..695d3315cca6 100644
--- a/sys/fs/devfs/devfs_devs.c
+++ b/sys/fs/devfs/devfs_devs.c
@@ -28,6 +28,8 @@
* $FreeBSD$
*/
+#include "opt_compat.h"
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/conf.h>
@@ -80,10 +82,20 @@ sysctl_devname(SYSCTL_HANDLER_ARGS)
{
int error;
dev_t ud;
+#ifdef COMPAT_FREEBSD11
+ uint32_t ud_compat;
+#endif
struct cdev_priv *cdp;
struct cdev *dev;
- error = SYSCTL_IN(req, &ud, sizeof (ud));
+#ifdef COMPAT_FREEBSD11
+ if (req->newlen == sizeof(ud_compat)) {
+ error = SYSCTL_IN(req, &ud_compat, sizeof(ud_compat));
+ if (error == 0)
+ ud = ud_compat == (uint32_t)NODEV ? NODEV : ud_compat;
+ } else
+#endif
+ error = SYSCTL_IN(req, &ud, sizeof (ud));
if (error)
return (error);
if (ud == NODEV)
diff --git a/sys/fs/devfs/devfs_vnops.c b/sys/fs/devfs/devfs_vnops.c
index 49435608e2da..18b962eadffc 100644
--- a/sys/fs/devfs/devfs_vnops.c
+++ b/sys/fs/devfs/devfs_vnops.c
@@ -1315,6 +1315,7 @@ devfs_readdir(struct vop_readdir_args *ap)
else
de = dd;
dp = dd->de_dirent;
+ MPASS(dp->d_reclen == GENERIC_DIRSIZ(dp));
if (dp->d_reclen > uio->uio_resid)
break;
dp->d_fileno = de->de_inode;
diff --git a/sys/fs/fdescfs/fdesc_vnops.c b/sys/fs/fdescfs/fdesc_vnops.c
index 65b8a54657be..885cc35b038e 100644
--- a/sys/fs/fdescfs/fdesc_vnops.c
+++ b/sys/fs/fdescfs/fdesc_vnops.c
@@ -485,7 +485,7 @@ fdesc_setattr(struct vop_setattr_args *ap)
return (error);
}
-#define UIO_MX 16
+#define UIO_MX _GENERIC_DIRLEN(10) /* number of symbols in INT_MAX printout */
static int
fdesc_readdir(struct vop_readdir_args *ap)
diff --git a/sys/fs/nandfs/nandfs_fs.h b/sys/fs/nandfs/nandfs_fs.h
index 3e23d7729993..d010830a9042 100644
--- a/sys/fs/nandfs/nandfs_fs.h
+++ b/sys/fs/nandfs/nandfs_fs.h
@@ -537,7 +537,7 @@ struct nandfs_bdesc {
#ifndef _KERNEL
#ifndef MNAMELEN
-#define MNAMELEN 88
+#define MNAMELEN 1024
#endif
#endif
diff --git a/sys/fs/nfs/nfsport.h b/sys/fs/nfs/nfsport.h
index 0bdd26b1f8c5..67849e1543dc 100644
--- a/sys/fs/nfs/nfsport.h
+++ b/sys/fs/nfs/nfsport.h
@@ -730,12 +730,6 @@ int nfsmsleep(void *, void *, int, const char *, struct timespec *);
#define NFSMINOR(d) minor(d)
/*
- * Define this to be the macro that returns the minimum size required
- * for a directory entry.
- */
-#define DIRENT_SIZE(dp) GENERIC_DIRSIZ(dp)
-
-/*
* The vnode tag for nfsv4root.
*/
#define VT_NFSV4ROOT "nfsv4root"
diff --git a/sys/fs/nfsclient/nfs_clrpcops.c b/sys/fs/nfsclient/nfs_clrpcops.c
index c5c6592b84c5..c93ab0865b9e 100644
--- a/sys/fs/nfsclient/nfs_clrpcops.c
+++ b/sys/fs/nfsclient/nfs_clrpcops.c
@@ -72,7 +72,7 @@ short nfsv4_cbport = NFSV4_CBPORT;
int nfstest_openallsetattr = 0;
#endif /* !APPLEKEXT */
-#define DIRHDSIZ (sizeof (struct dirent) - (MAXNAMLEN + 1))
+#define DIRHDSIZ offsetof(struct dirent, d_name)
/*
* nfscl_getsameserver() can return one of three values:
@@ -2861,17 +2861,18 @@ nfsrpc_readdir(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,
if (error)
return (error);
nd->nd_mrep = NULL;
- dp = (struct dirent *) CAST_DOWN(caddr_t, uio_iov_base(uiop));
+ dp = (struct dirent *)uio_iov_base(uiop);
+ dp->d_off = 0;
dp->d_type = DT_DIR;
dp->d_fileno = dotfileid;
dp->d_namlen = 1;
+ *((uint64_t *)dp->d_name) = 0; /* Zero pad it. */
dp->d_name[0] = '.';
- dp->d_name[1] = '\0';
- dp->d_reclen = DIRENT_SIZE(dp) + NFSX_HYPER;
+ dp->d_reclen = _GENERIC_DIRSIZ(dp) + NFSX_HYPER;
/*
* Just make these offset cookie 0.
*/
- tl = (u_int32_t *)&dp->d_name[4];
+ tl = (u_int32_t *)&dp->d_name[8];
*tl++ = 0;
*tl = 0;
blksiz += dp->d_reclen;
@@ -2879,18 +2880,19 @@ nfsrpc_readdir(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,
uiop->uio_offset += dp->d_reclen;
uio_iov_base_add(uiop, dp->d_reclen);
uio_iov_len_add(uiop, -(dp->d_reclen));
- dp = (struct dirent *) CAST_DOWN(caddr_t, uio_iov_base(uiop));
+ dp = (struct dirent *)uio_iov_base(uiop);
+ dp->d_off = 0;
dp->d_type = DT_DIR;
dp->d_fileno = dotdotfileid;
dp->d_namlen = 2;
+ *((uint64_t *)dp->d_name) = 0;
dp->d_name[0] = '.';
dp->d_name[1] = '.';
- dp->d_name[2] = '\0';
- dp->d_reclen = DIRENT_SIZE(dp) + NFSX_HYPER;
+ dp->d_reclen = _GENERIC_DIRSIZ(dp) + NFSX_HYPER;
/*
* Just make these offset cookie 0.
*/
- tl = (u_int32_t *)&dp->d_name[4];
+ tl = (u_int32_t *)&dp->d_name[8];
*tl++ = 0;
*tl = 0;
blksiz += dp->d_reclen;
@@ -2987,11 +2989,11 @@ nfsrpc_readdir(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,
error = EBADRPC;
goto nfsmout;
}
- tlen = NFSM_RNDUP(len);
+ tlen = roundup2(len, 8);
if (tlen == len)
- tlen += 4; /* To ensure null termination */
+ tlen += 8; /* To ensure null termination. */
left = DIRBLKSIZ - blksiz;
- if ((int)(tlen + DIRHDSIZ + NFSX_HYPER) > left) {
+ if (_GENERIC_DIRLEN(len) + NFSX_HYPER > left) {
dp->d_reclen += left;
uio_iov_base_add(uiop, left);
uio_iov_len_add(uiop, -(left));
@@ -2999,12 +3001,15 @@ nfsrpc_readdir(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,
uiop->uio_offset += left;
blksiz = 0;
}
- if ((int)(tlen + DIRHDSIZ + NFSX_HYPER) > uio_uio_resid(uiop))
+ if (_GENERIC_DIRLEN(len) + NFSX_HYPER >
+ uio_uio_resid(uiop))
bigenough = 0;
if (bigenough) {
- dp = (struct dirent *) CAST_DOWN(caddr_t, uio_iov_base(uiop));
+ dp = (struct dirent *)uio_iov_base(uiop);
+ dp->d_off = 0;
dp->d_namlen = len;
- dp->d_reclen = tlen + DIRHDSIZ + NFSX_HYPER;
+ dp->d_reclen = _GENERIC_DIRLEN(len) +
+ NFSX_HYPER;
dp->d_type = DT_UNKNOWN;
blksiz += dp->d_reclen;
if (blksiz == DIRBLKSIZ)
@@ -3016,7 +3021,7 @@ nfsrpc_readdir(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,
error = nfsm_mbufuio(nd, uiop, len);
if (error)
goto nfsmout;
- cp = CAST_DOWN(caddr_t, uio_iov_base(uiop));
+ cp = uio_iov_base(uiop);
tlen -= len;
*cp = '\0'; /* null terminate */
cp += tlen; /* points to cookie storage */
@@ -3131,8 +3136,8 @@ nfsrpc_readdir(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,
/*
* Add extra empty records to any remaining DIRBLKSIZ chunks.
*/
- while (uio_uio_resid(uiop) > 0 && ((size_t)(uio_uio_resid(uiop))) != tresid) {
- dp = (struct dirent *) CAST_DOWN(caddr_t, uio_iov_base(uiop));
+ while (uio_uio_resid(uiop) > 0 && uio_uio_resid(uiop) != tresid) {
+ dp = (struct dirent *)uio_iov_base(uiop);
dp->d_type = DT_UNKNOWN;
dp->d_fileno = 0;
dp->d_namlen = 0;
@@ -3289,16 +3294,17 @@ nfsrpc_readdirplus(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,
return (error);
nd->nd_mrep = NULL;
dp = (struct dirent *)uio_iov_base(uiop);
+ dp->d_off = 0;
dp->d_type = DT_DIR;
dp->d_fileno = dotfileid;
dp->d_namlen = 1;
+ *((uint64_t *)dp->d_name) = 0; /* Zero pad it. */
dp->d_name[0] = '.';
- dp->d_name[1] = '\0';
- dp->d_reclen = DIRENT_SIZE(dp) + NFSX_HYPER;
+ dp->d_reclen = _GENERIC_DIRSIZ(dp) + NFSX_HYPER;
/*
* Just make these offset cookie 0.
*/
- tl = (u_int32_t *)&dp->d_name[4];
+ tl = (u_int32_t *)&dp->d_name[8];
*tl++ = 0;
*tl = 0;
blksiz += dp->d_reclen;
@@ -3307,17 +3313,18 @@ nfsrpc_readdirplus(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,
uio_iov_base_add(uiop, dp->d_reclen);
uio_iov_len_add(uiop, -(dp->d_reclen));
dp = (struct dirent *)uio_iov_base(uiop);
+ dp->d_off = 0;
dp->d_type = DT_DIR;
dp->d_fileno = dotdotfileid;
dp->d_namlen = 2;
+ *((uint64_t *)dp->d_name) = 0;
dp->d_name[0] = '.';
dp->d_name[1] = '.';
- dp->d_name[2] = '\0';
- dp->d_reclen = DIRENT_SIZE(dp) + NFSX_HYPER;
+ dp->d_reclen = _GENERIC_DIRSIZ(dp) + NFSX_HYPER;
/*
* Just make these offset cookie 0.
*/
- tl = (u_int32_t *)&dp->d_name[4];
+ tl = (u_int32_t *)&dp->d_name[8];
*tl++ = 0;
*tl = 0;
blksiz += dp->d_reclen;
@@ -3395,11 +3402,11 @@ nfsrpc_readdirplus(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,
error = EBADRPC;
goto nfsmout;
}
- tlen = NFSM_RNDUP(len);
+ tlen = roundup2(len, 8);
if (tlen == len)
- tlen += 4; /* To ensure null termination */
+ tlen += 8; /* To ensure null termination. */
left = DIRBLKSIZ - blksiz;
- if ((tlen + DIRHDSIZ + NFSX_HYPER) > left) {
+ if (_GENERIC_DIRLEN(len) + NFSX_HYPER > left) {
dp->d_reclen += left;
uio_iov_base_add(uiop, left);
uio_iov_len_add(uiop, -(left));
@@ -3407,12 +3414,15 @@ nfsrpc_readdirplus(vnode_t vp, struct uio *uiop, nfsuint64 *cookiep,
uiop->uio_offset += left;
blksiz = 0;
}
- if ((tlen + DIRHDSIZ + NFSX_HYPER) > uio_uio_resid(uiop))
+ if (_GENERIC_DIRLEN(len) + NFSX_HYPER >
+ uio_uio_resid(uiop))
bigenough = 0;
if (bigenough) {
dp = (struct dirent *)uio_iov_base(uiop);
+ dp->d_off = 0;
dp->d_namlen = len;
- dp->d_reclen = tlen + DIRHDSIZ + NFSX_HYPER;
+ dp->d_reclen = _GENERIC_DIRLEN(len) +
+ NFSX_HYPER;
dp->d_type = DT_UNKNOWN;
blksiz += dp->d_reclen;
if (blksiz == DIRBLKSIZ)
diff --git a/sys/fs/nfsclient/nfs_clvnops.c b/sys/fs/nfsclient/nfs_clvnops.c
index fae2551e1239..e00c25130b07 100644
--- a/sys/fs/nfsclient/nfs_clvnops.c
+++ b/sys/fs/nfsclient/nfs_clvnops.c
@@ -207,8 +207,6 @@ static int nfs_renameit(struct vnode *sdvp, struct vnode *svp,
/*
* Global variables
*/
-#define DIRHDSIZ (sizeof (struct dirent) - (MAXNAMLEN + 1))
-
SYSCTL_DECL(_vfs_nfs);
static int nfsaccess_cache_timeout = NFS_MAXATTRTIMO;
diff --git a/sys/fs/nfsserver/nfs_nfsdport.c b/sys/fs/nfsserver/nfs_nfsdport.c
index b0fd83e086b1..e6380238d1e6 100644
--- a/sys/fs/nfsserver/nfs_nfsdport.c
+++ b/sys/fs/nfsserver/nfs_nfsdport.c
@@ -2020,17 +2020,25 @@ again:
}
/*
- * For now ZFS requires VOP_LOOKUP as a workaround. Until ino_t is changed
- * to 64 bit type a ZFS filesystem with over 1 billion files in it
- * will suffer from 64bit -> 32bit truncation.
+ * Check to see if entries in this directory can be safely acquired
+ * via VFS_VGET() or if a switch to VOP_LOOKUP() is required.
+ * ZFS snapshot directories need VOP_LOOKUP(), so that any
+ * automount of the snapshot directory that is required will
+ * be done.
+ * This needs to be done here for NFSv4, since NFSv4 never does
+ * a VFS_VGET() for "." or "..".
*/
- if (is_zfs == 1)
- usevget = 0;
-
- cn.cn_nameiop = LOOKUP;
- cn.cn_lkflags = LK_SHARED | LK_RETRY;
- cn.cn_cred = nd->nd_cred;
- cn.cn_thread = p;
+ if (is_zfs == 1) {
+ r = VFS_VGET(mp, at.na_fileid, LK_SHARED, &nvp);
+ if (r == EOPNOTSUPP) {
+ usevget = 0;
+ cn.cn_nameiop = LOOKUP;
+ cn.cn_lkflags = LK_SHARED | LK_RETRY;
+ cn.cn_cred = nd->nd_cred;
+ cn.cn_thread = p;
+ } else if (r == 0)
+ vput(nvp);
+ }
/*
* Save this position, in case there is an error before one entry
@@ -2099,7 +2107,16 @@ again:
else
r = EOPNOTSUPP;
if (r == EOPNOTSUPP) {
- usevget = 0;
+ if (usevget) {
+ usevget = 0;
+ cn.cn_nameiop = LOOKUP;
+ cn.cn_lkflags =
+ LK_SHARED |
+ LK_RETRY;
+ cn.cn_cred =
+ nd->nd_cred;
+ cn.cn_thread = p;
+ }
cn.cn_nameptr = dp->d_name;
cn.cn_namelen = nlen;
cn.cn_flags = ISLASTCN |
diff --git a/sys/kern/capabilities.conf b/sys/kern/capabilities.conf
index 1c8ca0811d8d..a59601345c9c 100644
--- a/sys/kern/capabilities.conf
+++ b/sys/kern/capabilities.conf
@@ -197,6 +197,11 @@ fpathconf
## Allow various file descriptor-based I/O operations, subject to capability
## rights.
##
+freebsd11_fstat
+freebsd11_fstatat
+freebsd11_getdirentries
+freebsd11_fstatfs
+freebsd11_mknodat
freebsd6_ftruncate
freebsd6_lseek
freebsd6_mmap
diff --git a/sys/kern/kern_acct.c b/sys/kern/kern_acct.c
index 622a6a49ea19..c13baa5d3891 100644
--- a/sys/kern/kern_acct.c
+++ b/sys/kern/kern_acct.c
@@ -96,6 +96,11 @@ __FBSDID("$FreeBSD$");
#include <security/mac/mac_framework.h>
+_Static_assert(sizeof(struct acctv3) - offsetof(struct acctv3, ac_trailer) ==
+ sizeof(struct acctv2) - offsetof(struct acctv2, ac_trailer), "trailer");
+_Static_assert(sizeof(struct acctv3) - offsetof(struct acctv3, ac_len2) ==
+ sizeof(struct acctv2) - offsetof(struct acctv2, ac_len2), "len2");
+
/*
* The routines implemented in this file are described in:
* Leffler, et al.: The Design and Implementation of the 4.3BSD
@@ -339,7 +344,7 @@ acct_disable(struct thread *td, int logging)
int
acct_process(struct thread *td)
{
- struct acctv2 acct;
+ struct acctv3 acct;
struct timeval ut, st, tmp;
struct plimit *oldlim;
struct proc *p;
@@ -421,7 +426,7 @@ acct_process(struct thread *td)
/* Setup ancillary structure fields. */
acct.ac_flagx |= ANVER;
acct.ac_zero = 0;
- acct.ac_version = 2;
+ acct.ac_version = 3;
acct.ac_len = acct.ac_len2 = sizeof(acct);
/*
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index bb54f9d8acb7..2baaff77666b 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -1304,6 +1304,23 @@ ofstat(struct thread *td, struct ofstat_args *uap)
}
#endif /* COMPAT_43 */
+#if defined(COMPAT_FREEBSD11)
+int
+freebsd11_fstat(struct thread *td, struct freebsd11_fstat_args *uap)
+{
+ struct stat sb;
+ struct freebsd11_stat osb;
+ int error;
+
+ error = kern_fstat(td, uap->fd, &sb);
+ if (error != 0)
+ return (error);
+ freebsd11_cvtstat(&sb, &osb);
+ error = copyout(&osb, uap->sb, sizeof(osb));
+ return (error);
+}
+#endif /* COMPAT_FREEBSD11 */
+
/*
* Return status information about a file descriptor.
*/
@@ -1343,6 +1360,14 @@ kern_fstat(struct thread *td, int fd, struct stat *sbp)
error = fo_stat(fp, sbp, td->td_ucred, td);
fdrop(fp, td);
+#ifdef __STAT_TIME_T_EXT
+ if (error == 0) {
+ sbp->st_atim_ext = 0;
+ sbp->st_mtim_ext = 0;
+ sbp->st_ctim_ext = 0;
+ sbp->st_btim_ext = 0;
+ }
+#endif
#ifdef KTRACE
if (error == 0 && KTRPOINT(td, KTR_STRUCT))
ktrstat(sbp);
@@ -1350,18 +1375,19 @@ kern_fstat(struct thread *td, int fd, struct stat *sbp)
return (error);
}
+#if defined(COMPAT_FREEBSD11)
/*
* Return status information about a file descriptor.
*/
#ifndef _SYS_SYSPROTO_H_
-struct nfstat_args {
+struct freebsd11_nfstat_args {
int fd;
struct nstat *sb;
};
#endif
/* ARGSUSED */
int
-sys_nfstat(struct thread *td, struct nfstat_args *uap)
+freebsd11_nfstat(struct thread *td, struct freebsd11_nfstat_args *uap)
{
struct nstat nub;
struct stat ub;
@@ -1369,11 +1395,12 @@ sys_nfstat(struct thread *td, struct nfstat_args *uap)
error = kern_fstat(td, uap->fd, &ub);
if (error == 0) {
- cvtnstat(&ub, &nub);
+ freebsd11_cvtnstat(&ub, &nub);
error = copyout(&nub, uap->sb, sizeof(nub));
}
return (error);
}
+#endif /* COMPAT_FREEBSD11 */
/*
* Return pathconf information about a file descriptor.
@@ -3590,13 +3617,21 @@ kinfo_to_okinfo(struct kinfo_file *kif, struct kinfo_ofile *okif)
KF_FLAG_APPEND | KF_FLAG_ASYNC | KF_FLAG_FSYNC | KF_FLAG_NONBLOCK |
KF_FLAG_DIRECT | KF_FLAG_HASLOCK);
okif->kf_offset = kif->kf_offset;
- okif->kf_vnode_type = kif->kf_vnode_type;
- okif->kf_sock_domain = kif->kf_sock_domain;
- okif->kf_sock_type = kif->kf_sock_type;
- okif->kf_sock_protocol = kif->kf_sock_protocol;
+ if (kif->kf_type == KF_TYPE_VNODE)
+ okif->kf_vnode_type = kif->kf_un.kf_file.kf_file_type;
+ else
+ okif->kf_vnode_type = KF_VTYPE_VNON;
strlcpy(okif->kf_path, kif->kf_path, sizeof(okif->kf_path));
- okif->kf_sa_local = kif->kf_sa_local;
- okif->kf_sa_peer = kif->kf_sa_peer;
+ if (kif->kf_type == KF_TYPE_SOCKET) {
+ okif->kf_sock_domain = kif->kf_un.kf_sock.kf_sock_domain0;
+ okif->kf_sock_type = kif->kf_un.kf_sock.kf_sock_type0;
+ okif->kf_sock_protocol = kif->kf_un.kf_sock.kf_sock_protocol0;
+ okif->kf_sa_local = kif->kf_un.kf_sock.kf_sa_local;
+ okif->kf_sa_peer = kif->kf_un.kf_sock.kf_sa_peer;
+ } else {
+ okif->kf_sa_local.ss_family = AF_UNSPEC;
+ okif->kf_sa_peer.ss_family = AF_UNSPEC;
+ }
}
static int
diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c
index 9b4ed9d88a01..c029567b6c44 100644
--- a/sys/kern/kern_proc.c
+++ b/sys/kern/kern_proc.c
@@ -986,11 +986,14 @@ fill_kinfo_proc_only(struct proc *p, struct kinfo_proc *kp)
}
if ((p->p_flag & P_CONTROLT) && tp != NULL) {
kp->ki_tdev = tty_udev(tp);
+ kp->ki_tdev_freebsd11 = kp->ki_tdev; /* truncate */
kp->ki_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
if (tp->t_session)
kp->ki_tsid = tp->t_session->s_sid;
- } else
+ } else {
kp->ki_tdev = NODEV;
+ kp->ki_tdev_freebsd11 = kp->ki_tdev; /* truncate */
+ }
if (p->p_comm[0] != '\0')
strlcpy(kp->ki_comm, p->p_comm, sizeof(kp->ki_comm));
if (p->p_sysent && p->p_sysent->sv_name != NULL &&
@@ -1232,6 +1235,7 @@ freebsd32_kinfo_proc_out(const struct kinfo_proc *ki, struct kinfo_proc32 *ki32)
CP(*ki, *ki32, ki_tsid);
CP(*ki, *ki32, ki_jobc);
CP(*ki, *ki32, ki_tdev);
+ CP(*ki, *ki32, ki_tdev_freebsd11);
CP(*ki, *ki32, ki_siglist);
CP(*ki, *ki32, ki_sigmask);
CP(*ki, *ki32, ki_sigignore);
@@ -2204,6 +2208,7 @@ sysctl_kern_proc_ovmmap(SYSCTL_HANDLER_ARGS)
vn_lock(vp, LK_SHARED | LK_RETRY);
if (VOP_GETATTR(vp, &va, cred) == 0) {
kve->kve_fileid = va.va_fileid;
+ /* truncate */
kve->kve_fsid = va.va_fsid;
}
vput(vp);
@@ -2443,10 +2448,14 @@ kern_proc_vmmap_out(struct proc *p, struct sbuf *sb, ssize_t maxlen, int flags)
if (VOP_GETATTR(vp, &va, cred) == 0) {
kve->kve_vn_fileid = va.va_fileid;
kve->kve_vn_fsid = va.va_fsid;
+ kve->kve_vn_fsid_freebsd11 =
+ kve->kve_vn_fsid; /* truncate */
kve->kve_vn_mode =
MAKEIMODE(va.va_type, va.va_mode);
kve->kve_vn_size = va.va_size;
kve->kve_vn_rdev = va.va_rdev;
+ kve->kve_vn_rdev_freebsd11 =
+ kve->kve_vn_rdev; /* truncate */
kve->kve_status = KF_ATTR_VALID;
}
vput(vp);
diff --git a/sys/kern/makesyscalls.sh b/sys/kern/makesyscalls.sh
index f220554ab04e..7ea37de6e53c 100644
--- a/sys/kern/makesyscalls.sh
+++ b/sys/kern/makesyscalls.sh
@@ -10,6 +10,7 @@ compat4=COMPAT_FREEBSD4
compat6=COMPAT_FREEBSD6
compat7=COMPAT_FREEBSD7
compat10=COMPAT_FREEBSD10
+compat11=COMPAT_FREEBSD11
# output files:
sysnames="syscalls.c"
@@ -36,6 +37,8 @@ syscompat7="sysent.compat7.$$"
syscompat7dcl="sysent.compat7dcl.$$"
syscompat10="sysent.compat10.$$"
syscompat10dcl="sysent.compat10dcl.$$"
+syscompat11="sysent.compat11.$$"
+syscompat11dcl="sysent.compat11dcl.$$"
sysent="sysent.switch.$$"
sysinc="sysinc.switch.$$"
sysarg="sysarg.switch.$$"
@@ -50,9 +53,9 @@ else
capenabled=""
fi
-trap "rm $sysaue $sysdcl $syscompat $syscompatdcl $syscompat4 $syscompat4dcl $syscompat6 $syscompat6dcl $syscompat7 $syscompat7dcl $syscompat10 $syscompat10dcl $sysent $sysinc $sysarg $sysprotoend $systracetmp $systraceret" 0
+trap "rm $sysaue $sysdcl $syscompat $syscompatdcl $syscompat4 $syscompat4dcl $syscompat6 $syscompat6dcl $syscompat7 $syscompat7dcl $syscompat10 $syscompat10dcl $syscompat11 $syscompat11dcl $sysent $sysinc $sysarg $sysprotoend $systracetmp $systraceret" 0
-touch $sysaue $sysdcl $syscompat $syscompatdcl $syscompat4 $syscompat4dcl $syscompat6 $syscompat6dcl $syscompat7 $syscompat7dcl $syscompat10 $syscompat10dcl $sysent $sysinc $sysarg $sysprotoend $systracetmp $systraceret
+touch $sysaue $sysdcl $syscompat $syscompatdcl $syscompat4 $syscompat4dcl $syscompat6 $syscompat6dcl $syscompat7 $syscompat7dcl $syscompat10 $syscompat10dcl $syscompat11 $syscompat11dcl $sysent $sysinc $sysarg $sysprotoend $systracetmp $systraceret
case $# in
0) echo "usage: $0 input-file <config-file>" 1>&2
@@ -92,6 +95,8 @@ sed -e '
syscompat7dcl = \"$syscompat7dcl\"
syscompat10 = \"$syscompat10\"
syscompat10dcl = \"$syscompat10dcl\"
+ syscompat11 = \"$syscompat11\"
+ syscompat11dcl = \"$syscompat11dcl\"
sysent = \"$sysent\"
syssw = \"$syssw\"
sysinc = \"$sysinc\"
@@ -107,6 +112,7 @@ sed -e '
compat6 = \"$compat6\"
compat7 = \"$compat7\"
compat10 = \"$compat10\"
+ compat11 = \"$compat11\"
syscallprefix = \"$syscallprefix\"
switchname = \"$switchname\"
namesname = \"$namesname\"
@@ -155,6 +161,7 @@ sed -e '
printf "\n#ifdef %s\n\n", compat6 > syscompat6
printf "\n#ifdef %s\n\n", compat7 > syscompat7
printf "\n#ifdef %s\n\n", compat10 > syscompat10
+ printf "\n#ifdef %s\n\n", compat11 > syscompat11
printf "/*\n * System call names.\n *\n" > sysnames
printf " * DO NOT EDIT-- this file is automatically generated.\n" > sysnames
@@ -205,6 +212,7 @@ sed -e '
print > syscompat6
print > syscompat7
print > syscompat10
+ print > syscompat11
print > sysnames
print > systrace
print > systracetmp
@@ -221,6 +229,7 @@ sed -e '
print > syscompat6
print > syscompat7
print > syscompat10
+ print > syscompat11
print > sysnames
print > systrace
print > systracetmp
@@ -237,6 +246,7 @@ sed -e '
print > syscompat6
print > syscompat7
print > syscompat10
+ print > syscompat11
print > sysnames
print > systrace
print > systracetmp
@@ -345,6 +355,8 @@ sed -e '
argalias = "freebsd7_" argalias
if (flag("COMPAT10"))
argalias = "freebsd10_" argalias
+ if (flag("COMPAT11"))
+ argalias = "freebsd11_" argalias
}
f++
@@ -497,7 +509,7 @@ sed -e '
next
}
type("COMPAT") || type("COMPAT4") || type("COMPAT6") || \
- type("COMPAT7") || type("COMPAT10") {
+ type("COMPAT7") || type("COMPAT10") || type("COMPAT11") {
if (flag("COMPAT")) {
ncompat++
out = syscompat
@@ -533,6 +545,13 @@ sed -e '
wrap = "compat10"
prefix = "freebsd10_"
descr = "freebsd10"
+ } else if (flag("COMPAT11")) {
+ ncompat11++
+ out = syscompat11
+ outdcl = syscompat11dcl
+ wrap = "compat11"
+ prefix = "freebsd11_"
+ descr = "freebsd11"
}
parseline()
if (argc != 0 && !flag("NOARGS") && !flag("NOPROTO") && \
@@ -608,7 +627,7 @@ sed -e '
END {
printf "\n#define AS(name) (sizeof(struct name) / sizeof(register_t))\n" > sysinc
- if (ncompat != 0 || ncompat4 != 0 || ncompat6 != 0 || ncompat7 != 0 || ncompat10 != 0)
+ if (ncompat != 0 || ncompat4 != 0 || ncompat6 != 0 || ncompat7 != 0 || ncompat10 != 0 || ncompat11 != 0)
printf "#include \"opt_compat.h\"\n\n" > syssw
if (ncompat != 0) {
@@ -649,11 +668,20 @@ sed -e '
printf "#define compat10(n, name) 0, (sy_call_t *)nosys\n" > sysinc
printf "#endif\n" > sysinc
}
+ if (ncompat11 != 0) {
+ printf "\n#ifdef %s\n", compat11 > sysinc
+ printf "#define compat11(n, name) n, (sy_call_t *)__CONCAT(freebsd11_,name)\n" > sysinc
+ printf "#else\n" > sysinc
+ printf "#define compat11(n, name) 0, (sy_call_t *)nosys\n" > sysinc
+ printf "#endif\n" > sysinc
+ }
+
printf("\n#endif /* %s */\n\n", compat) > syscompatdcl
printf("\n#endif /* %s */\n\n", compat4) > syscompat4dcl
printf("\n#endif /* %s */\n\n", compat6) > syscompat6dcl
printf("\n#endif /* %s */\n\n", compat7) > syscompat7dcl
printf("\n#endif /* %s */\n\n", compat10) > syscompat10dcl
+ printf("\n#endif /* %s */\n\n", compat11) > syscompat11dcl
printf("\n#undef PAD_\n") > sysprotoend
printf("#undef PADL_\n") > sysprotoend
@@ -677,6 +705,7 @@ cat $sysarg $sysdcl \
$syscompat6 $syscompat6dcl \
$syscompat7 $syscompat7dcl \
$syscompat10 $syscompat10dcl \
+ $syscompat11 $syscompat11dcl \
$sysaue $sysprotoend > $sysproto
cat $systracetmp >> $systrace
cat $systraceret >> $systrace
diff --git a/sys/kern/sys_socket.c b/sys/kern/sys_socket.c
index 441a628b7f78..a30260bfeebc 100644
--- a/sys/kern/sys_socket.c
+++ b/sys/kern/sys_socket.c
@@ -346,14 +346,15 @@ soo_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp)
kif->kf_type = KF_TYPE_SOCKET;
so = fp->f_data;
- kif->kf_sock_domain = so->so_proto->pr_domain->dom_family;
- kif->kf_sock_type = so->so_type;
- kif->kf_sock_protocol = so->so_proto->pr_protocol;
+ kif->kf_un.kf_sock.kf_sock_domain0 =
+ so->so_proto->pr_domain->dom_family;
+ kif->kf_un.kf_sock.kf_sock_type0 = so->so_type;
+ kif->kf_un.kf_sock.kf_sock_protocol0 = so->so_proto->pr_protocol;
kif->kf_un.kf_sock.kf_sock_pcb = (uintptr_t)so->so_pcb;
- switch (kif->kf_sock_domain) {
+ switch (kif->kf_un.kf_sock.kf_sock_domain0) {
case AF_INET:
case AF_INET6:
- if (kif->kf_sock_protocol == IPPROTO_TCP) {
+ if (kif->kf_un.kf_sock.kf_sock_protocol0 == IPPROTO_TCP) {
if (so->so_pcb != NULL) {
inpcb = (struct inpcb *)(so->so_pcb);
kif->kf_un.kf_sock.kf_sock_inpcb =
@@ -376,13 +377,15 @@ soo_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp)
break;
}
error = so->so_proto->pr_usrreqs->pru_sockaddr(so, &sa);
- if (error == 0 && sa->sa_len <= sizeof(kif->kf_sa_local)) {
- bcopy(sa, &kif->kf_sa_local, sa->sa_len);
+ if (error == 0 &&
+ sa->sa_len <= sizeof(kif->kf_un.kf_sock.kf_sa_local)) {
+ bcopy(sa, &kif->kf_un.kf_sock.kf_sa_local, sa->sa_len);
free(sa, M_SONAME);
}
error = so->so_proto->pr_usrreqs->pru_peeraddr(so, &sa);
- if (error == 0 && sa->sa_len <= sizeof(kif->kf_sa_peer)) {
- bcopy(sa, &kif->kf_sa_peer, sa->sa_len);
+ if (error == 0 &&
+ sa->sa_len <= sizeof(kif->kf_un.kf_sock.kf_sa_peer)) {
+ bcopy(sa, &kif->kf_un.kf_sock.kf_sa_peer, sa->sa_len);
free(sa, M_SONAME);
}
strncpy(kif->kf_path, so->so_proto->pr_domain->dom_name,
diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master
index 999da9c884ce..ad0fdb27545f 100644
--- a/sys/kern/syscalls.master
+++ b/sys/kern/syscalls.master
@@ -12,7 +12,7 @@
; case where the event exists, but we don't want auditing, the
; event should be #defined to AUE_NULL in audit_kevents.h.
; type one of STD, OBSOL, UNIMPL, COMPAT, COMPAT4, COMPAT6,
-; COMPAT7, NODEF, NOARGS, NOPROTO, NOSTD
+; COMPAT7, COMPAT11, NODEF, NOARGS, NOPROTO, NOSTD
; The COMPAT* options may be combined with one or more NO*
; options separated by '|' with no spaces (e.g. COMPAT|NOARGS)
; name psuedo-prototype of syscall routine
@@ -29,6 +29,7 @@
; COMPAT6 included on COMPAT_FREEBSD6 #ifdef (FreeBSD 6 compat)
; COMPAT7 included on COMPAT_FREEBSD7 #ifdef (FreeBSD 7 compat)
; COMPAT10 included on COMPAT_FREEBSD10 #ifdef (FreeBSD 10 compat)
+; COMPAT11 included on COMPAT11 #ifdef (FreeBSD 11 compat)
; OBSOL obsolete, not included in system, only specifies name
; UNIMPL not implemented, placeholder only
; NOSTD implemented but as a lkm that can be statically
@@ -79,7 +80,7 @@
11 AUE_NULL OBSOL execv
12 AUE_CHDIR STD { int chdir(char *path); }
13 AUE_FCHDIR STD { int fchdir(int fd); }
-14 AUE_MKNOD STD { int mknod(char *path, int mode, int dev); }
+14 AUE_MKNOD COMPAT11 { int mknod(char *path, int mode, int dev); }
15 AUE_CHMOD STD { int chmod(char *path, int mode); }
16 AUE_CHOWN STD { int chown(char *path, int uid, int gid); }
17 AUE_NULL STD { int obreak(char *nsize); } break \
@@ -363,9 +364,12 @@
185 AUE_NULL UNIMPL lfs_markv
186 AUE_NULL UNIMPL lfs_segclean
187 AUE_NULL UNIMPL lfs_segwait
-188 AUE_STAT STD { int stat(char *path, struct stat *ub); }
-189 AUE_FSTAT STD { int fstat(int fd, struct stat *sb); }
-190 AUE_LSTAT STD { int lstat(char *path, struct stat *ub); }
+188 AUE_STAT COMPAT11 { int stat(char *path, \
+ struct freebsd11_stat *ub); }
+189 AUE_FSTAT COMPAT11 { int fstat(int fd, \
+ struct freebsd11_stat *sb); }
+190 AUE_LSTAT COMPAT11 { int lstat(char *path, \
+ struct freebsd11_stat *ub); }
191 AUE_PATHCONF STD { int pathconf(char *path, int name); }
192 AUE_FPATHCONF STD { int fpathconf(int fd, int name); }
193 AUE_NULL UNIMPL nosys
@@ -375,7 +379,7 @@
195 AUE_SETRLIMIT STD { int setrlimit(u_int which, \
struct rlimit *rlp); } setrlimit \
__setrlimit_args int
-196 AUE_GETDIRENTRIES STD { int getdirentries(int fd, char *buf, \
+196 AUE_GETDIRENTRIES COMPAT11 { int getdirentries(int fd, char *buf, \
u_int count, long *basep); }
197 AUE_MMAP COMPAT6 { caddr_t mmap(caddr_t addr, \
size_t len, int prot, int flags, int fd, \
@@ -496,7 +500,7 @@
269 AUE_NULL UNIMPL nosys
270 AUE_NULL UNIMPL nosys
271 AUE_NULL UNIMPL nosys
-272 AUE_O_GETDENTS STD { int getdents(int fd, char *buf, \
+272 AUE_O_GETDENTS COMPAT11 { int getdents(int fd, char *buf, \
size_t count); }
273 AUE_NULL UNIMPL nosys
274 AUE_LCHMOD STD { int lchmod(char *path, mode_t mode); }
@@ -507,9 +511,9 @@
struct timeval *tptr); }
277 AUE_MSYNC NOPROTO { int msync(void *addr, size_t len, \
int flags); } netbsd_msync msync_args int
-278 AUE_STAT STD { int nstat(char *path, struct nstat *ub); }
-279 AUE_FSTAT STD { int nfstat(int fd, struct nstat *sb); }
-280 AUE_LSTAT STD { int nlstat(char *path, struct nstat *ub); }
+278 AUE_STAT COMPAT11 { int nstat(char *path, struct nstat *ub); }
+279 AUE_FSTAT COMPAT11 { int nfstat(int fd, struct nstat *sb); }
+280 AUE_LSTAT COMPAT11 { int nlstat(char *path, struct nstat *ub); }
281 AUE_NULL UNIMPL nosys
282 AUE_NULL UNIMPL nosys
283 AUE_NULL UNIMPL nosys
@@ -535,8 +539,8 @@
struct ostatfs *buf); }
298 AUE_FHOPEN STD { int fhopen(const struct fhandle *u_fhp, \
int flags); }
-299 AUE_FHSTAT STD { int fhstat(const struct fhandle *u_fhp, \
- struct stat *sb); }
+299 AUE_FHSTAT COMPAT11 { int fhstat(const struct fhandle *u_fhp, \
+ struct freebsd11_stat *sb); }
; syscall numbers for FreeBSD
300 AUE_NULL STD { int modnext(int modid); }
301 AUE_NULL STD { int modstat(int modid, \
@@ -707,13 +711,14 @@
off_t *sbytes, int flags); }
394 AUE_NULL STD { int mac_syscall(const char *policy, \
int call, void *arg); }
-395 AUE_GETFSSTAT STD { int getfsstat(struct statfs *buf, \
+395 AUE_GETFSSTAT COMPAT11 { int getfsstat(struct freebsd11_statfs *buf, \
long bufsize, int mode); }
-396 AUE_STATFS STD { int statfs(char *path, \
- struct statfs *buf); }
-397 AUE_FSTATFS STD { int fstatfs(int fd, struct statfs *buf); }
-398 AUE_FHSTATFS STD { int fhstatfs(const struct fhandle *u_fhp, \
- struct statfs *buf); }
+396 AUE_STATFS COMPAT11 { int statfs(char *path, \
+ struct freebsd11_statfs *buf); }
+397 AUE_FSTATFS COMPAT11 { int fstatfs(int fd, \
+ struct freebsd11_statfs *buf); }
+398 AUE_FHSTATFS COMPAT11 { int fhstatfs(const struct fhandle *u_fhp, \
+ struct freebsd11_statfs *buf); }
399 AUE_NULL UNIMPL nosys
400 AUE_SEMCLOSE NOSTD { int ksem_close(semid_t id); }
401 AUE_SEMPOST NOSTD { int ksem_post(semid_t id); }
@@ -883,16 +888,16 @@
gid_t gid, int flag); }
492 AUE_FEXECVE STD { int fexecve(int fd, char **argv, \
char **envv); }
-493 AUE_FSTATAT STD { int fstatat(int fd, char *path, \
- struct stat *buf, int flag); }
+493 AUE_FSTATAT COMPAT11 { int fstatat(int fd, char *path, \
+ struct freebsd11_stat *buf, int flag); }
494 AUE_FUTIMESAT STD { int futimesat(int fd, char *path, \
struct timeval *times); }
495 AUE_LINKAT STD { int linkat(int fd1, char *path1, int fd2, \
char *path2, int flag); }
496 AUE_MKDIRAT STD { int mkdirat(int fd, char *path, mode_t mode); }
497 AUE_MKFIFOAT STD { int mkfifoat(int fd, char *path, mode_t mode); }
-498 AUE_MKNODAT STD { int mknodat(int fd, char *path, mode_t mode, \
- dev_t dev); }
+498 AUE_MKNODAT COMPAT11 { int mknodat(int fd, char *path, mode_t mode, \
+ uint32_t dev); }
; XXX: see the comment for open
499 AUE_OPENAT_RWTC STD { int openat(int fd, char *path, int flag, \
mode_t mode); }
@@ -997,6 +1002,21 @@
id_t id, const struct \
vm_domain_policy_entry *policy); }
550 AUE_FSYNC STD { int fdatasync(int fd); }
+551 AUE_FSTAT STD { int fstat(int fd, struct stat *sb); }
+552 AUE_FSTATAT STD { int fstatat(int fd, char *path, \
+ struct stat *buf, int flag); }
+553 AUE_FHSTAT STD { int fhstat(const struct fhandle *u_fhp, \
+ struct stat *sb); }
+554 AUE_GETDIRENTRIES STD { ssize_t getdirentries(int fd, char *buf, \
+ size_t count, off_t *basep); }
+555 AUE_STATFS STD { int statfs(char *path, struct statfs *buf); }
+556 AUE_FSTATFS STD { int fstatfs(int fd, struct statfs *buf); }
+557 AUE_GETFSSTAT STD { int getfsstat(struct statfs *buf, \
+ long bufsize, int mode); }
+558 AUE_FHSTATFS STD { int fhstatfs(const struct fhandle *u_fhp, \
+ struct statfs *buf); }
+559 AUE_MKNODAT STD { int mknodat(int fd, char *path, mode_t mode, \
+ dev_t dev); }
; Please copy any additions and changes to the following compatability tables:
; sys/compat/freebsd32/syscalls.master
diff --git a/sys/kern/tty.c b/sys/kern/tty.c
index b0a535cb67e3..63e195945d89 100644
--- a/sys/kern/tty.c
+++ b/sys/kern/tty.c
@@ -1205,7 +1205,7 @@ tty_to_xtty(struct tty *tp, struct xtty *xt)
xt->xt_pgid = tp->t_pgrp ? tp->t_pgrp->pg_id : 0;
xt->xt_sid = tp->t_session ? tp->t_session->s_sid : 0;
xt->xt_flags = tp->t_flags;
- xt->xt_dev = tp->t_dev ? dev2udev(tp->t_dev) : NODEV;
+ xt->xt_dev = tp->t_dev ? dev2udev(tp->t_dev) : (uint32_t)NODEV;
}
static int
diff --git a/sys/kern/tty_pts.c b/sys/kern/tty_pts.c
index a4c3dbb3cc22..b9a888c5a124 100644
--- a/sys/kern/tty_pts.c
+++ b/sys/kern/tty_pts.c
@@ -592,6 +592,8 @@ ptsdev_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp)
kif->kf_type = KF_TYPE_PTS;
tp = fp->f_data;
kif->kf_un.kf_pts.kf_pts_dev = tty_udev(tp);
+ kif->kf_un.kf_pts.kf_pts_dev_freebsd11 =
+ kif->kf_un.kf_pts.kf_pts_dev; /* truncate */
strlcpy(kif->kf_path, tty_devname(tp), sizeof(kif->kf_path));
return (0);
}
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index 7671e1b84ac2..27b2635030d3 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -525,7 +525,7 @@ restart:
/*
* Get old format filesystem statistics.
*/
-static void cvtstatfs(struct statfs *, struct ostatfs *);
+static void freebsd4_cvtstatfs(struct statfs *, struct ostatfs *);
#ifndef _SYS_SYSPROTO_H_
struct freebsd4_statfs_args {
@@ -543,7 +543,7 @@ freebsd4_statfs(struct thread *td, struct freebsd4_statfs_args *uap)
sfp = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);
error = kern_statfs(td, uap->path, UIO_USERSPACE, sfp);
if (error == 0) {
- cvtstatfs(sfp, &osb);
+ freebsd4_cvtstatfs(sfp, &osb);
error = copyout(&osb, uap->buf, sizeof(osb));
}
free(sfp, M_STATFS);
@@ -569,7 +569,7 @@ freebsd4_fstatfs(struct thread *td, struct freebsd4_fstatfs_args *uap)
sfp = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);
error = kern_fstatfs(td, uap->fd, sfp);
if (error == 0) {
- cvtstatfs(sfp, &osb);
+ freebsd4_cvtstatfs(sfp, &osb);
error = copyout(&osb, uap->buf, sizeof(osb));
}
free(sfp, M_STATFS);
@@ -602,11 +602,12 @@ freebsd4_getfsstat(struct thread *td, struct freebsd4_getfsstat_args *uap)
size = count * sizeof(struct statfs);
error = kern_getfsstat(td, &buf, size, &count, UIO_SYSSPACE,
uap->mode);
- td->td_retval[0] = count;
+ if (error == 0)
+ td->td_retval[0] = count;
if (size != 0) {
sp = buf;
while (count != 0 && error == 0) {
- cvtstatfs(sp, &osb);
+ freebsd4_cvtstatfs(sp, &osb);
error = copyout(&osb, uap->buf, sizeof(osb));
sp++;
uap->buf++;
@@ -640,7 +641,7 @@ freebsd4_fhstatfs(struct thread *td, struct freebsd4_fhstatfs_args *uap)
sfp = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);
error = kern_fhstatfs(td, fh, sfp);
if (error == 0) {
- cvtstatfs(sfp, &osb);
+ freebsd4_cvtstatfs(sfp, &osb);
error = copyout(&osb, uap->buf, sizeof(osb));
}
free(sfp, M_STATFS);
@@ -651,7 +652,7 @@ freebsd4_fhstatfs(struct thread *td, struct freebsd4_fhstatfs_args *uap)
* Convert a new format statfs structure to an old format statfs structure.
*/
static void
-cvtstatfs(struct statfs *nsp, struct ostatfs *osp)
+freebsd4_cvtstatfs(struct statfs *nsp, struct ostatfs *osp)
{
statfs_scale_blocks(nsp, LONG_MAX);
@@ -680,6 +681,138 @@ cvtstatfs(struct statfs *nsp, struct ostatfs *osp)
}
#endif /* COMPAT_FREEBSD4 */
+#if defined(COMPAT_FREEBSD11)
+/*
+ * Get old format filesystem statistics.
+ */
+static void freebsd11_cvtstatfs(struct statfs *, struct freebsd11_statfs *);
+
+int
+freebsd11_statfs(struct thread *td, struct freebsd11_statfs_args *uap)
+{
+ struct freebsd11_statfs osb;
+ struct statfs *sfp;
+ int error;
+
+ sfp = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);
+ error = kern_statfs(td, uap->path, UIO_USERSPACE, sfp);
+ if (error == 0) {
+ freebsd11_cvtstatfs(sfp, &osb);
+ error = copyout(&osb, uap->buf, sizeof(osb));
+ }
+ free(sfp, M_STATFS);
+ return (error);
+}
+
+/*
+ * Get filesystem statistics.
+ */
+int
+freebsd11_fstatfs(struct thread *td, struct freebsd11_fstatfs_args *uap)
+{
+ struct freebsd11_statfs osb;
+ struct statfs *sfp;
+ int error;
+
+ sfp = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);
+ error = kern_fstatfs(td, uap->fd, sfp);
+ if (error == 0) {
+ freebsd11_cvtstatfs(sfp, &osb);
+ error = copyout(&osb, uap->buf, sizeof(osb));
+ }
+ free(sfp, M_STATFS);
+ return (error);
+}
+
+/*
+ * Get statistics on all filesystems.
+ */
+int
+freebsd11_getfsstat(struct thread *td, struct freebsd11_getfsstat_args *uap)
+{
+ struct freebsd11_statfs osb;
+ struct statfs *buf, *sp;
+ size_t count, size;
+ int error;
+
+ count = uap->bufsize / sizeof(struct ostatfs);
+ size = count * sizeof(struct statfs);
+ error = kern_getfsstat(td, &buf, size, &count, UIO_SYSSPACE,
+ uap->mode);
+ if (error == 0)
+ td->td_retval[0] = count;
+ if (size > 0) {
+ sp = buf;
+ while (count > 0 && error == 0) {
+ freebsd11_cvtstatfs(sp, &osb);
+ error = copyout(&osb, uap->buf, sizeof(osb));
+ sp++;
+ uap->buf++;
+ count--;
+ }
+ free(buf, M_STATFS);
+ }
+ return (error);
+}
+
+/*
+ * Implement fstatfs() for (NFS) file handles.
+ */
+int
+freebsd11_fhstatfs(struct thread *td, struct freebsd11_fhstatfs_args *uap)
+{
+ struct freebsd11_statfs osb;
+ struct statfs *sfp;
+ fhandle_t fh;
+ int error;
+
+ error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t));
+ if (error)
+ return (error);
+ sfp = malloc(sizeof(struct statfs), M_STATFS, M_WAITOK);
+ error = kern_fhstatfs(td, fh, sfp);
+ if (error == 0) {
+ freebsd11_cvtstatfs(sfp, &osb);
+ error = copyout(&osb, uap->buf, sizeof(osb));
+ }
+ free(sfp, M_STATFS);
+ return (error);
+}
+
+/*
+ * Convert a new format statfs structure to an old format statfs structure.
+ */
+static void
+freebsd11_cvtstatfs(struct statfs *nsp, struct freebsd11_statfs *osp)
+{
+
+ bzero(osp, sizeof(*osp));
+ osp->f_version = FREEBSD11_STATFS_VERSION;
+ osp->f_type = nsp->f_type;
+ osp->f_flags = nsp->f_flags;
+ osp->f_bsize = nsp->f_bsize;
+ osp->f_iosize = nsp->f_iosize;
+ osp->f_blocks = nsp->f_blocks;
+ osp->f_bfree = nsp->f_bfree;
+ osp->f_bavail = nsp->f_bavail;
+ osp->f_files = nsp->f_files;
+ osp->f_ffree = nsp->f_ffree;
+ osp->f_syncwrites = nsp->f_syncwrites;
+ osp->f_asyncwrites = nsp->f_asyncwrites;
+ osp->f_syncreads = nsp->f_syncreads;
+ osp->f_asyncreads = nsp->f_asyncreads;
+ osp->f_namemax = nsp->f_namemax;
+ osp->f_owner = nsp->f_owner;
+ osp->f_fsid = nsp->f_fsid;
+ strlcpy(osp->f_fstypename, nsp->f_fstypename,
+ MIN(MFSNAMELEN, sizeof(osp->f_fstypename)));
+ strlcpy(osp->f_mntonname, nsp->f_mntonname,
+ MIN(MNAMELEN, sizeof(osp->f_mntonname)));
+ strlcpy(osp->f_mntfromname, nsp->f_mntfromname,
+ MIN(MNAMELEN, sizeof(osp->f_mntfromname)));
+}
+#endif /* COMPAT_FREEBSD11 */
+
/*
* Change current working directory to a given file descriptor.
*/
@@ -1060,39 +1193,44 @@ ocreat(struct thread *td, struct ocreat_args *uap)
* Create a special file.
*/
#ifndef _SYS_SYSPROTO_H_
-struct mknod_args {
+struct mknodat_args {
+ int fd;
char *path;
- int mode;
- int dev;
+ mode_t mode;
+ dev_t dev;
};
#endif
int
-sys_mknod(struct thread *td, struct mknod_args *uap)
+sys_mknodat(struct thread *td, struct mknodat_args *uap)
+{
+
+ return (kern_mknodat(td, uap->fd, uap->path, UIO_USERSPACE, uap->mode,
+ uap->dev));
+}
+
+#if defined(COMPAT_FREEBSD11)
+int
+freebsd11_mknod(struct thread *td,
+ struct freebsd11_mknod_args *uap)
{
return (kern_mknodat(td, AT_FDCWD, uap->path, UIO_USERSPACE,
uap->mode, uap->dev));
}
-#ifndef _SYS_SYSPROTO_H_
-struct mknodat_args {
- int fd;
- char *path;
- mode_t mode;
- dev_t dev;
-};
-#endif
int
-sys_mknodat(struct thread *td, struct mknodat_args *uap)
+freebsd11_mknodat(struct thread *td,
+ struct freebsd11_mknodat_args *uap)
{
return (kern_mknodat(td, uap->fd, uap->path, UIO_USERSPACE, uap->mode,
uap->dev));
}
+#endif /* COMPAT_FREEBSD11 */
int
kern_mknodat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
- int mode, int dev)
+ int mode, dev_t dev)
{
struct vnode *vp;
struct mount *mp;
@@ -1968,28 +2106,104 @@ cvtstat(struct stat *st, struct ostat *ost)
}
#endif /* COMPAT_43 */
-/*
- * Get file status; this version follows links.
- */
-#ifndef _SYS_SYSPROTO_H_
-struct stat_args {
- char *path;
- struct stat *ub;
-};
-#endif
+#if defined(COMPAT_FREEBSD11)
+void
+freebsd11_cvtstat(struct stat *st, struct freebsd11_stat *ost)
+{
+
+ ost->st_dev = st->st_dev;
+ ost->st_ino = st->st_ino; /* truncate */
+ ost->st_mode = st->st_mode;
+ ost->st_nlink = st->st_nlink; /* truncate */
+ ost->st_uid = st->st_uid;
+ ost->st_gid = st->st_gid;
+ ost->st_rdev = st->st_rdev;
+ ost->st_atim = st->st_atim;
+ ost->st_mtim = st->st_mtim;
+ ost->st_ctim = st->st_ctim;
+ ost->st_size = st->st_size;
+ ost->st_blocks = st->st_blocks;
+ ost->st_blksize = st->st_blksize;
+ ost->st_flags = st->st_flags;
+ ost->st_gen = st->st_gen;
+ ost->st_lspare = 0;
+ ost->st_birthtim = st->st_birthtim;
+ bzero((char *)&ost->st_birthtim + sizeof(ost->st_birthtim),
+ sizeof(*ost) - offsetof(struct freebsd11_stat,
+ st_birthtim) - sizeof(ost->st_birthtim));
+}
+
int
-sys_stat(struct thread *td, struct stat_args *uap)
+freebsd11_stat(struct thread *td, struct freebsd11_stat_args* uap)
{
struct stat sb;
+ struct freebsd11_stat osb;
int error;
error = kern_statat(td, 0, AT_FDCWD, uap->path, UIO_USERSPACE,
&sb, NULL);
- if (error == 0)
- error = copyout(&sb, uap->ub, sizeof (sb));
+ if (error != 0)
+ return (error);
+ freebsd11_cvtstat(&sb, &osb);
+ error = copyout(&osb, uap->ub, sizeof(osb));
return (error);
}
+int
+freebsd11_lstat(struct thread *td, struct freebsd11_lstat_args* uap)
+{
+ struct stat sb;
+ struct freebsd11_stat osb;
+ int error;
+
+ error = kern_statat(td, AT_SYMLINK_NOFOLLOW, AT_FDCWD, uap->path,
+ UIO_USERSPACE, &sb, NULL);
+ if (error != 0)
+ return (error);
+ freebsd11_cvtstat(&sb, &osb);
+ error = copyout(&osb, uap->ub, sizeof(osb));
+ return (error);
+}
+
+int
+freebsd11_fhstat(struct thread *td, struct freebsd11_fhstat_args* uap)
+{
+ struct fhandle fh;
+ struct stat sb;
+ struct freebsd11_stat osb;
+ int error;
+
+ error = copyin(uap->u_fhp, &fh, sizeof(fhandle_t));
+ if (error != 0)
+ return (error);
+ error = kern_fhstat(td, fh, &sb);
+ if (error != 0)
+ return (error);
+ freebsd11_cvtstat(&sb, &osb);
+ error = copyout(&osb, uap->sb, sizeof(osb));
+ return (error);
+}
+
+int
+freebsd11_fstatat(struct thread *td, struct freebsd11_fstatat_args* uap)
+{
+ struct stat sb;
+ struct freebsd11_stat osb;
+ int error;
+
+ error = kern_statat(td, uap->flag, uap->fd, uap->path,
+ UIO_USERSPACE, &sb, NULL);
+ if (error != 0)
+ return (error);
+ freebsd11_cvtstat(&sb, &osb);
+ error = copyout(&osb, uap->buf, sizeof(osb));
+ return (error);
+}
+#endif /* COMPAT_FREEBSD11 */
+
+/*
+ * Get file status
+ */
#ifndef _SYS_SYSPROTO_H_
struct fstatat_args {
int fd;
@@ -2042,6 +2256,12 @@ kern_statat(struct thread *td, int flag, int fd, char *path,
vput(nd.ni_vp);
if (error != 0)
return (error);
+#ifdef __STAT_TIME_T_EXT
+ sb.st_atim_ext = 0;
+ sb.st_mtim_ext = 0;
+ sb.st_ctim_ext = 0;
+ sb.st_btim_ext = 0;
+#endif
*sbp = sb;
#ifdef KTRACE
if (KTRPOINT(td, KTR_STRUCT))
@@ -2050,36 +2270,15 @@ kern_statat(struct thread *td, int flag, int fd, char *path,
return (0);
}
-/*
- * Get file status; this version does not follow links.
- */
-#ifndef _SYS_SYSPROTO_H_
-struct lstat_args {
- char *path;
- struct stat *ub;
-};
-#endif
-int
-sys_lstat(struct thread *td, struct lstat_args *uap)
-{
- struct stat sb;
- int error;
-
- error = kern_statat(td, AT_SYMLINK_NOFOLLOW, AT_FDCWD, uap->path,
- UIO_USERSPACE, &sb, NULL);
- if (error == 0)
- error = copyout(&sb, uap->ub, sizeof (sb));
- return (error);
-}
-
+#if defined(COMPAT_FREEBSD11)
/*
* Implementation of the NetBSD [l]stat() functions.
*/
void
-cvtnstat( struct stat *sb, struct nstat *nsb)
+freebsd11_cvtnstat(struct stat *sb, struct nstat *nsb)
{
- bzero(nsb, sizeof *nsb);
+ bzero(nsb, sizeof(*nsb));
nsb->st_dev = sb->st_dev;
nsb->st_ino = sb->st_ino;
nsb->st_mode = sb->st_mode;
@@ -2099,13 +2298,13 @@ cvtnstat( struct stat *sb, struct nstat *nsb)
}
#ifndef _SYS_SYSPROTO_H_
-struct nstat_args {
+struct freebsd11_nstat_args {
char *path;
struct nstat *ub;
};
#endif
int
-sys_nstat(struct thread *td, struct nstat_args *uap)
+freebsd11_nstat(struct thread *td, struct freebsd11_nstat_args *uap)
{
struct stat sb;
struct nstat nsb;
@@ -2115,7 +2314,7 @@ sys_nstat(struct thread *td, struct nstat_args *uap)
&sb, NULL);
if (error != 0)
return (error);
- cvtnstat(&sb, &nsb);
+ freebsd11_cvtnstat(&sb, &nsb);
return (copyout(&nsb, uap->ub, sizeof (nsb)));
}
@@ -2123,13 +2322,13 @@ sys_nstat(struct thread *td, struct nstat_args *uap)
* NetBSD lstat. Get file status; this version does not follow links.
*/
#ifndef _SYS_SYSPROTO_H_
-struct lstat_args {
+struct freebsd11_nlstat_args {
char *path;
- struct stat *ub;
+ struct nstat *ub;
};
#endif
int
-sys_nlstat(struct thread *td, struct nlstat_args *uap)
+freebsd11_nlstat(struct thread *td, struct freebsd11_nlstat_args *uap)
{
struct stat sb;
struct nstat nsb;
@@ -2139,9 +2338,10 @@ sys_nlstat(struct thread *td, struct nlstat_args *uap)
UIO_USERSPACE, &sb, NULL);
if (error != 0)
return (error);
- cvtnstat(&sb, &nsb);
+ freebsd11_cvtnstat(&sb, &nsb);
return (copyout(&nsb, uap->ub, sizeof (nsb)));
}
+#endif /* COMPAT_FREEBSD11 */
/*
* Get configurable pathname variables.
@@ -3502,7 +3702,87 @@ out:
return (error);
}
+#if defined(COMPAT_43) || defined(COMPAT_FREEBSD11)
+int
+freebsd11_kern_getdirentries(struct thread *td, int fd, char *ubuf, u_int count,
+ long *basep, void (*func)(struct freebsd11_dirent *))
+{
+ struct freebsd11_dirent dstdp;
+ struct dirent *dp, *edp;
+ char *dirbuf;
+ off_t base;
+ ssize_t resid, ucount;
+ int error;
+
+ /* XXX arbitrary sanity limit on `count'. */
+ count = min(count, 64 * 1024);
+
+ dirbuf = malloc(count, M_TEMP, M_WAITOK);
+
+ error = kern_getdirentries(td, fd, dirbuf, count, &base, &resid,
+ UIO_SYSSPACE);
+ if (error != 0)
+ goto done;
+ if (basep != NULL)
+ *basep = base;
+
+ ucount = 0;
+ for (dp = (struct dirent *)dirbuf,
+ edp = (struct dirent *)&dirbuf[count - resid];
+ ucount < count && dp < edp; ) {
+ if (dp->d_reclen == 0)
+ break;
+ MPASS(dp->d_reclen >= _GENERIC_DIRLEN(0));
+ if (dp->d_namlen >= sizeof(dstdp.d_name))
+ continue;
+ dstdp.d_type = dp->d_type;
+ dstdp.d_namlen = dp->d_namlen;
+ dstdp.d_fileno = dp->d_fileno; /* truncate */
+ dstdp.d_reclen = sizeof(dstdp) - sizeof(dstdp.d_name) +
+ ((dp->d_namlen + 1 + 3) &~ 3);
+ bcopy(dp->d_name, dstdp.d_name, dstdp.d_namlen);
+ bzero(dstdp.d_name + dstdp.d_namlen,
+ dstdp.d_reclen - offsetof(struct freebsd11_dirent, d_name) -
+ dstdp.d_namlen);
+ MPASS(dstdp.d_reclen <= dp->d_reclen);
+ MPASS(ucount + dstdp.d_reclen <= count);
+ if (func != NULL)
+ func(&dstdp);
+ error = copyout(&dstdp, ubuf + ucount, dstdp.d_reclen);
+ if (error != 0)
+ break;
+ dp = (struct dirent *)((char *)dp + dp->d_reclen);
+ ucount += dstdp.d_reclen;
+ }
+
+done:
+ free(dirbuf, M_TEMP);
+ if (error == 0)
+ td->td_retval[0] = ucount;
+ return (error);
+}
+#endif /* COMPAT */
+
#ifdef COMPAT_43
+static void
+ogetdirentries_cvt(struct freebsd11_dirent *dp)
+{
+#if (BYTE_ORDER == LITTLE_ENDIAN)
+ /*
+ * The expected low byte of dp->d_namlen is our dp->d_type.
+ * The high MBZ byte of dp->d_namlen is our dp->d_namlen.
+ */
+ dp->d_type = dp->d_namlen;
+ dp->d_namlen = 0;
+#else
+ /*
+ * The dp->d_type is the high byte of the expected dp->d_namlen,
+ * so must be zero'ed.
+ */
+ dp->d_type = 0;
+#endif
+}
+
/*
* Read a block of directory entries in a filesystem independent format.
*/
@@ -3530,138 +3810,26 @@ int
kern_ogetdirentries(struct thread *td, struct ogetdirentries_args *uap,
long *ploff)
{
- struct vnode *vp;
- struct file *fp;
- struct uio auio, kuio;
- struct iovec aiov, kiov;
- struct dirent *dp, *edp;
- cap_rights_t rights;
- caddr_t dirbuf;
- int error, eofflag, readcnt;
- long loff;
- off_t foffset;
+ long base;
+ int error;
/* XXX arbitrary sanity limit on `count'. */
if (uap->count > 64 * 1024)
return (EINVAL);
- error = getvnode(td, uap->fd, cap_rights_init(&rights, CAP_READ), &fp);
- if (error != 0)
- return (error);
- if ((fp->f_flag & FREAD) == 0) {
- fdrop(fp, td);
- return (EBADF);
- }
- vp = fp->f_vnode;
- foffset = foffset_lock(fp, 0);
-unionread:
- if (vp->v_type != VDIR) {
- foffset_unlock(fp, foffset, 0);
- fdrop(fp, td);
- return (EINVAL);
- }
- aiov.iov_base = uap->buf;
- aiov.iov_len = uap->count;
- auio.uio_iov = &aiov;
- auio.uio_iovcnt = 1;
- auio.uio_rw = UIO_READ;
- auio.uio_segflg = UIO_USERSPACE;
- auio.uio_td = td;
- auio.uio_resid = uap->count;
- vn_lock(vp, LK_SHARED | LK_RETRY);
- loff = auio.uio_offset = foffset;
-#ifdef MAC
- error = mac_vnode_check_readdir(td->td_ucred, vp);
- if (error != 0) {
- VOP_UNLOCK(vp, 0);
- foffset_unlock(fp, foffset, FOF_NOUPDATE);
- fdrop(fp, td);
- return (error);
- }
-#endif
-# if (BYTE_ORDER != LITTLE_ENDIAN)
- if (vp->v_mount->mnt_maxsymlinklen <= 0) {
- error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag,
- NULL, NULL);
- foffset = auio.uio_offset;
- } else
-# endif
- {
- kuio = auio;
- kuio.uio_iov = &kiov;
- kuio.uio_segflg = UIO_SYSSPACE;
- kiov.iov_len = uap->count;
- dirbuf = malloc(uap->count, M_TEMP, M_WAITOK);
- kiov.iov_base = dirbuf;
- error = VOP_READDIR(vp, &kuio, fp->f_cred, &eofflag,
- NULL, NULL);
- foffset = kuio.uio_offset;
- if (error == 0) {
- readcnt = uap->count - kuio.uio_resid;
- edp = (struct dirent *)&dirbuf[readcnt];
- for (dp = (struct dirent *)dirbuf; dp < edp; ) {
-# if (BYTE_ORDER == LITTLE_ENDIAN)
- /*
- * The expected low byte of
- * dp->d_namlen is our dp->d_type.
- * The high MBZ byte of dp->d_namlen
- * is our dp->d_namlen.
- */
- dp->d_type = dp->d_namlen;
- dp->d_namlen = 0;
-# else
- /*
- * The dp->d_type is the high byte
- * of the expected dp->d_namlen,
- * so must be zero'ed.
- */
- dp->d_type = 0;
-# endif
- if (dp->d_reclen > 0) {
- dp = (struct dirent *)
- ((char *)dp + dp->d_reclen);
- } else {
- error = EIO;
- break;
- }
- }
- if (dp >= edp)
- error = uiomove(dirbuf, readcnt, &auio);
- }
- free(dirbuf, M_TEMP);
- }
- if (error != 0) {
- VOP_UNLOCK(vp, 0);
- foffset_unlock(fp, foffset, 0);
- fdrop(fp, td);
- return (error);
- }
- if (uap->count == auio.uio_resid &&
- (vp->v_vflag & VV_ROOT) &&
- (vp->v_mount->mnt_flag & MNT_UNION)) {
- struct vnode *tvp = vp;
- vp = vp->v_mount->mnt_vnodecovered;
- VREF(vp);
- fp->f_vnode = vp;
- fp->f_data = vp;
- foffset = 0;
- vput(tvp);
- goto unionread;
- }
- VOP_UNLOCK(vp, 0);
- foffset_unlock(fp, foffset, 0);
- fdrop(fp, td);
- td->td_retval[0] = uap->count - auio.uio_resid;
- if (error == 0)
- *ploff = loff;
+
+ error = freebsd11_kern_getdirentries(td, uap->fd, uap->buf, uap->count,
+ &base, ogetdirentries_cvt);
+
+ if (error == 0 && uap->basep != NULL)
+ error = copyout(&base, uap->basep, sizeof(long));
+
return (error);
}
#endif /* COMPAT_43 */
-/*
- * Read a block of directory entries in a filesystem independent format.
- */
+#if defined(COMPAT_FREEBSD11)
#ifndef _SYS_SYSPROTO_H_
-struct getdirentries_args {
+struct freebsd11_getdirentries_args {
int fd;
char *buf;
u_int count;
@@ -3669,30 +3837,61 @@ struct getdirentries_args {
};
#endif
int
-sys_getdirentries(struct thread *td, struct getdirentries_args *uap)
+freebsd11_getdirentries(struct thread *td,
+ struct freebsd11_getdirentries_args *uap)
{
long base;
int error;
+ error = freebsd11_kern_getdirentries(td, uap->fd, uap->buf, uap->count,
+ &base, NULL);
+
+ if (error == 0 && uap->basep != NULL)
+ error = copyout(&base, uap->basep, sizeof(long));
+ return (error);
+}
+
+int
+freebsd11_getdents(struct thread *td, struct freebsd11_getdents_args *uap)
+{
+ struct freebsd11_getdirentries_args ap;
+
+ ap.fd = uap->fd;
+ ap.buf = uap->buf;
+ ap.count = uap->count;
+ ap.basep = NULL;
+ return (freebsd11_getdirentries(td, &ap));
+}
+#endif /* COMPAT_FREEBSD11 */
+
+/*
+ * Read a block of directory entries in a filesystem independent format.
+ */
+int
+sys_getdirentries(struct thread *td, struct getdirentries_args *uap)
+{
+ off_t base;
+ int error;
+
error = kern_getdirentries(td, uap->fd, uap->buf, uap->count, &base,
NULL, UIO_USERSPACE);
if (error != 0)
return (error);
if (uap->basep != NULL)
- error = copyout(&base, uap->basep, sizeof(long));
+ error = copyout(&base, uap->basep, sizeof(off_t));
return (error);
}
int
-kern_getdirentries(struct thread *td, int fd, char *buf, u_int count,
- long *basep, ssize_t *residp, enum uio_seg bufseg)
+kern_getdirentries(struct thread *td, int fd, char *buf, size_t count,
+ off_t *basep, ssize_t *residp, enum uio_seg bufseg)
{
struct vnode *vp;
struct file *fp;
struct uio auio;
struct iovec aiov;
cap_rights_t rights;
- long loff;
+ off_t loff;
int error, eofflag;
off_t foffset;
@@ -3759,25 +3958,6 @@ fail:
return (error);
}
-#ifndef _SYS_SYSPROTO_H_
-struct getdents_args {
- int fd;
- char *buf;
- size_t count;
-};
-#endif
-int
-sys_getdents(struct thread *td, struct getdents_args *uap)
-{
- struct getdirentries_args ap;
-
- ap.fd = uap->fd;
- ap.buf = uap->buf;
- ap.count = uap->count;
- ap.basep = NULL;
- return (sys_getdirentries(td, &ap));
-}
-
/*
* Set the mode mask for creation of filesystem nodes.
*/
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index d041c07920de..f61531783707 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -2340,7 +2340,7 @@ vn_fill_kinfo_vnode(struct vnode *vp, struct kinfo_file *kif)
char *fullpath, *freepath;
int error;
- kif->kf_vnode_type = vntype_to_kinfo(vp->v_type);
+ kif->kf_un.kf_file.kf_file_type = vntype_to_kinfo(vp->v_type);
freepath = NULL;
fullpath = "-";
error = vn_fullpath(curthread, vp, &fullpath, &freepath);
@@ -2369,10 +2369,14 @@ vn_fill_kinfo_vnode(struct vnode *vp, struct kinfo_file *kif)
else
kif->kf_un.kf_file.kf_file_fsid =
vp->v_mount->mnt_stat.f_fsid.val[0];
+ kif->kf_un.kf_file.kf_file_fsid_freebsd11 =
+ kif->kf_un.kf_file.kf_file_fsid; /* truncate */
kif->kf_un.kf_file.kf_file_fileid = va.va_fileid;
kif->kf_un.kf_file.kf_file_mode = MAKEIMODE(va.va_type, va.va_mode);
kif->kf_un.kf_file.kf_file_size = va.va_size;
kif->kf_un.kf_file.kf_file_rdev = va.va_rdev;
+ kif->kf_un.kf_file.kf_file_rdev_freebsd11 =
+ kif->kf_un.kf_file.kf_file_rdev; /* truncate */
return (0);
}
diff --git a/sys/nlm/nlm_advlock.c b/sys/nlm/nlm_advlock.c
index d6ccd2f8ef08..10b41ab0acff 100644
--- a/sys/nlm/nlm_advlock.c
+++ b/sys/nlm/nlm_advlock.c
@@ -202,7 +202,7 @@ nlm_advlock_internal(struct vnode *vp, void *id, int op, struct flock *fl,
union nfsfh fh;
struct sockaddr *sa;
struct sockaddr_storage ss;
- char servername[MNAMELEN];
+ char *servername;
struct timeval timo;
int retries;
rpcvers_t vers;
@@ -218,6 +218,7 @@ nlm_advlock_internal(struct vnode *vp, void *id, int op, struct flock *fl,
ASSERT_VOP_LOCKED(vp, "nlm_advlock_1");
+ servername = malloc(MNAMELEN, M_TEMP, M_WAITOK); /* XXXKIB vp locked */
nmp = VFSTONFS(vp->v_mount);
/*
* Push any pending writes to the server and flush our cache
@@ -381,7 +382,7 @@ nlm_advlock_internal(struct vnode *vp, void *id, int op, struct flock *fl,
AUTH_DESTROY(auth);
nlm_host_release(host);
-
+ free(servername, M_TEMP);
return (error);
}
diff --git a/sys/security/audit/audit_private.h b/sys/security/audit/audit_private.h
index 64afa87bc45d..3d99635f7de0 100644
--- a/sys/security/audit/audit_private.h
+++ b/sys/security/audit/audit_private.h
@@ -107,9 +107,9 @@ struct vnode_au_info {
mode_t vn_mode;
uid_t vn_uid;
gid_t vn_gid;
- dev_t vn_dev;
- long vn_fsid;
- long vn_fileid;
+ u_int32_t vn_dev; /* XXX dev_t compatibility */
+ long vn_fsid; /* XXX uint64_t compatibility */
+ long vn_fileid; /* XXX ino_t compatibility */
long vn_gen;
};
@@ -210,7 +210,7 @@ struct audit_record {
int ar_arg_atfd2;
int ar_arg_fflags;
mode_t ar_arg_mode;
- int ar_arg_dev;
+ int ar_arg_dev; /* XXX dev_t compatibility */
long ar_arg_value;
void *ar_arg_addr;
int ar_arg_len;
diff --git a/sys/sys/_types.h b/sys/sys/_types.h
index 8736651ba6f0..1dd7c7df4cf7 100644
--- a/sys/sys/_types.h
+++ b/sys/sys/_types.h
@@ -43,13 +43,13 @@ typedef __uint64_t __fsblkcnt_t;
typedef __uint64_t __fsfilcnt_t;
typedef __uint32_t __gid_t;
typedef __int64_t __id_t; /* can hold a gid_t, pid_t, or uid_t */
-typedef __uint32_t __ino_t; /* inode number */
+typedef __uint64_t __ino_t; /* inode number */
typedef long __key_t; /* IPC key (for Sys V IPC) */
typedef __int32_t __lwpid_t; /* Thread ID (a.k.a. LWP) */
typedef __uint16_t __mode_t; /* permissions */
typedef int __accmode_t; /* access permissions */
typedef int __nl_item;
-typedef __uint16_t __nlink_t; /* link count */
+typedef __uint64_t __nlink_t; /* link count */
typedef __int64_t __off_t; /* file offset */
typedef __int64_t __off64_t; /* file offset (alias) */
typedef __int32_t __pid_t; /* process [group] */
@@ -105,7 +105,7 @@ typedef struct {
long double __max_align2 __aligned(_Alignof(long double));
} __max_align_t;
-typedef __uint32_t __dev_t; /* device number */
+typedef __uint64_t __dev_t; /* device number */
typedef __uint32_t __fixpt_t; /* fixed point number */
diff --git a/sys/sys/acct.h b/sys/sys/acct.h
index 759fdc6e0aa7..fc033b588124 100644
--- a/sys/sys/acct.h
+++ b/sys/sys/acct.h
@@ -45,12 +45,12 @@
#define AC_COMM_LEN 16
/*
- * Accounting structure version 2 (current).
+ * Accounting structure version 3 (current).
* The first byte is always zero.
* Time units are microseconds.
*/
-struct acctv2 {
+struct acctv3 {
uint8_t ac_zero; /* zero identifies new version */
uint8_t ac_version; /* record version number */
uint16_t ac_len; /* record length */
@@ -65,10 +65,13 @@ struct acctv2 {
float ac_mem; /* average memory usage */
float ac_io; /* count of IO blocks */
__dev_t ac_tty; /* controlling tty */
-
+ uint32_t ac_pad0;
+#if defined(__powerpc__) && !defined(_LP64)
+ uint32_t ac_pad1;
+#endif
uint16_t ac_len2; /* record length */
union {
- __dev_t ac_align; /* force v1 compatible alignment */
+ uint32_t ac_align; /* force v1 compatible alignment */
#define AFORK 0x01 /* forked but not exec'ed */
/* ASU is no longer supported */
@@ -84,6 +87,28 @@ struct acctv2 {
#define ac_flagx ac_trailer.ac_flag
};
+struct acctv2 {
+ uint8_t ac_zero; /* zero identifies new version */
+ uint8_t ac_version; /* record version number */
+ uint16_t ac_len; /* record length */
+
+ char ac_comm[AC_COMM_LEN]; /* command name */
+ float ac_utime; /* user time */
+ float ac_stime; /* system time */
+ float ac_etime; /* elapsed time */
+ time_t ac_btime; /* starting time */
+ uid_t ac_uid; /* user id */
+ gid_t ac_gid; /* group id */
+ float ac_mem; /* average memory usage */
+ float ac_io; /* count of IO blocks */
+ uint32_t ac_tty; /* controlling tty */
+
+ uint16_t ac_len2; /* record length */
+ union {
+ uint32_t ac_align; /* force v1 compatible alignment */
+ uint8_t ac_flag; /* accounting flags */
+ } ac_trailer;
+};
/*
* Legacy accounting structure (rev. 1.5-1.18).
@@ -105,7 +130,7 @@ struct acctv1 {
gid_t ac_gid; /* group id */
uint16_t ac_mem; /* average memory usage */
comp_t ac_io; /* count of IO blocks */
- __dev_t ac_tty; /* controlling tty */
+ uint32_t ac_tty; /* controlling tty */
uint8_t ac_flag; /* accounting flags */
};
diff --git a/sys/sys/dirent.h b/sys/sys/dirent.h
index ed3f6f5c7746..472142f960b4 100644
--- a/sys/sys/dirent.h
+++ b/sys/sys/dirent.h
@@ -36,22 +36,39 @@
#include <sys/cdefs.h>
#include <sys/_types.h>
+#ifndef _INO_T_DECLARED
+typedef __ino_t ino_t;
+#define _INO_T_DECLARED
+#endif
+
+#ifndef _OFF_T_DECLARED
+typedef __off_t off_t;
+#define _OFF_T_DECLARED
+#endif
+
/*
* The dirent structure defines the format of directory entries returned by
* the getdirentries(2) system call.
*
* A directory entry has a struct dirent at the front of it, containing its
* inode number, the length of the entry, and the length of the name
- * contained in the entry. These are followed by the name padded to a 4
+ * contained in the entry. These are followed by the name padded to an 8
* byte boundary with null bytes. All names are guaranteed null terminated.
* The maximum length of a name in a directory is MAXNAMLEN.
+ *
+ * Explicit padding between the last member of the header (d_namelen) and
+ * d_name avoids ABI padding at the end of dirent on LP64 architectures.
+ * There is code depending on d_name being last.
*/
struct dirent {
- __uint32_t d_fileno; /* file number of entry */
+ ino_t d_fileno; /* file number of entry */
+ off_t d_off; /* directory offset of entry */
__uint16_t d_reclen; /* length of this record */
- __uint8_t d_type; /* file type, see below */
- __uint8_t d_namlen; /* length of string in d_name */
+ __uint8_t d_type; /* file type, see below */
+ __uint8_t d_pad0;
+ __uint16_t d_namlen; /* length of string in d_name */
+ __uint16_t d_pad1;
#if __BSD_VISIBLE
#define MAXNAMLEN 255
char d_name[MAXNAMLEN + 1]; /* name must be no longer than this */
@@ -60,7 +77,18 @@ struct dirent {
#endif
};
+#if defined(_WANT_FREEBSD11_DIRENT) || defined(_KERNEL)
+struct freebsd11_dirent {
+ __uint32_t d_fileno; /* file number of entry */
+ __uint16_t d_reclen; /* length of this record */
+ __uint8_t d_type; /* file type, see below */
+ __uint8_t d_namlen; /* length of string in d_name */
+ char d_name[255 + 1]; /* name must be no longer than this */
+};
+#endif /* _WANT_FREEBSD11_DIRENT || _KERNEL */
+
#if __BSD_VISIBLE
+
/*
* File types
*/
@@ -84,13 +112,14 @@ struct dirent {
* The _GENERIC_DIRSIZ macro gives the minimum record length which will hold
* the directory entry. This returns the amount of space in struct direct
* without the d_name field, plus enough space for the name with a terminating
- * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary.
+ * null byte (dp->d_namlen+1), rounded up to a 8 byte boundary.
*
* XXX although this macro is in the implementation namespace, it requires
* a manifest constant that is not.
*/
-#define _GENERIC_DIRSIZ(dp) \
- ((sizeof (struct dirent) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3))
+#define _GENERIC_DIRLEN(namlen) \
+ ((__offsetof(struct dirent, d_name) + (namlen) + 1 + 7) & ~7)
+#define _GENERIC_DIRSIZ(dp) _GENERIC_DIRLEN((dp)->d_namlen)
#endif /* __BSD_VISIBLE */
#ifdef _KERNEL
diff --git a/sys/sys/mount.h b/sys/sys/mount.h
index 9800d97df27e..519b4cf94f52 100644
--- a/sys/sys/mount.h
+++ b/sys/sys/mount.h
@@ -65,8 +65,8 @@ struct fid {
* filesystem statistics
*/
#define MFSNAMELEN 16 /* length of type name including null */
-#define MNAMELEN 88 /* size of on/from name bufs */
-#define STATFS_VERSION 0x20030518 /* current version number */
+#define MNAMELEN 1024 /* size of on/from name bufs */
+#define STATFS_VERSION 0x20140518 /* current version number */
struct statfs {
uint32_t f_version; /* structure version number */
uint32_t f_type; /* type of filesystem */
@@ -92,6 +92,34 @@ struct statfs {
char f_mntonname[MNAMELEN]; /* directory on which mounted */
};
+#if defined(_WANT_FREEBSD11_STATFS) || defined(_KERNEL)
+#define FREEBSD11_STATFS_VERSION 0x20030518 /* current version number */
+struct freebsd11_statfs {
+ uint32_t f_version; /* structure version number */
+ uint32_t f_type; /* type of filesystem */
+ uint64_t f_flags; /* copy of mount exported flags */
+ uint64_t f_bsize; /* filesystem fragment size */
+ uint64_t f_iosize; /* optimal transfer block size */
+ uint64_t f_blocks; /* total data blocks in filesystem */
+ uint64_t f_bfree; /* free blocks in filesystem */
+ int64_t f_bavail; /* free blocks avail to non-superuser */
+ uint64_t f_files; /* total file nodes in filesystem */
+ int64_t f_ffree; /* free nodes avail to non-superuser */
+ uint64_t f_syncwrites; /* count of sync writes since mount */
+ uint64_t f_asyncwrites; /* count of async writes since mount */
+ uint64_t f_syncreads; /* count of sync reads since mount */
+ uint64_t f_asyncreads; /* count of async reads since mount */
+ uint64_t f_spare[10]; /* unused spare */
+ uint32_t f_namemax; /* maximum filename length */
+ uid_t f_owner; /* user that mounted the filesystem */
+ fsid_t f_fsid; /* filesystem id */
+ char f_charspare[80]; /* spare string space */
+ char f_fstypename[16]; /* filesystem type name */
+ char f_mntfromname[88]; /* mounted filesystem */
+ char f_mntonname[88]; /* directory on which mounted */
+};
+#endif /* _WANT_FREEBSD11_STATFS || _KERNEL */
+
#ifdef _KERNEL
#define OMFSNAMELEN 16 /* length of fs type name, including null */
#define OMNAMELEN (88 - 2 * sizeof(long)) /* size of on/from name bufs */
diff --git a/sys/sys/param.h b/sys/sys/param.h
index db976774c7c0..97d1d379111f 100644
--- a/sys/sys/param.h
+++ b/sys/sys/param.h
@@ -58,7 +58,7 @@
* in the range 5 to 9.
*/
#undef __FreeBSD_version
-#define __FreeBSD_version 1200030 /* Master, propagated to newvers */
+#define __FreeBSD_version 1200031 /* Master, propagated to newvers */
/*
* __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,
diff --git a/sys/sys/stat.h b/sys/sys/stat.h
index 6af909aea7c1..95a42b24716a 100644
--- a/sys/sys/stat.h
+++ b/sys/sys/stat.h
@@ -102,9 +102,9 @@ typedef __uid_t uid_t;
#ifdef _KERNEL
struct ostat {
__uint16_t st_dev; /* inode's device */
- ino_t st_ino; /* inode's number */
+ __uint32_t st_ino; /* inode's number */
mode_t st_mode; /* inode protection mode */
- nlink_t st_nlink; /* number of hard links */
+ __uint16_t st_nlink; /* number of hard links */
__uint16_t st_uid; /* user ID of the file's owner */
__uint16_t st_gid; /* group ID of the file's group */
__uint16_t st_rdev; /* device type */
@@ -119,14 +119,15 @@ struct ostat {
};
#endif
-struct stat {
- __dev_t st_dev; /* inode's device */
- ino_t st_ino; /* inode's number */
+#if defined(_WANT_FREEBSD11_STAT) || defined(_KERNEL)
+struct freebsd11_stat {
+ __uint32_t st_dev; /* inode's device */
+ __uint32_t st_ino; /* inode's number */
mode_t st_mode; /* inode protection mode */
- nlink_t st_nlink; /* number of hard links */
+ __uint16_t st_nlink; /* number of hard links */
uid_t st_uid; /* user ID of the file's owner */
gid_t st_gid; /* group ID of the file's group */
- __dev_t st_rdev; /* device type */
+ __uint32_t st_rdev; /* device type */
struct timespec st_atim; /* time of last access */
struct timespec st_mtim; /* time of last data modification */
struct timespec st_ctim; /* time of last file status change */
@@ -148,16 +149,55 @@ struct stat {
unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec));
unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec));
};
+#endif /* _WANT_FREEBSD11_STAT || _KERNEL */
+
+#if defined(__i386__)
+#define __STAT_TIME_T_EXT 1
+#endif
+
+struct stat {
+ dev_t st_dev; /* inode's device */
+ ino_t st_ino; /* inode's number */
+ nlink_t st_nlink; /* number of hard links */
+ mode_t st_mode; /* inode protection mode */
+ __int16_t st_padding0;
+ uid_t st_uid; /* user ID of the file's owner */
+ gid_t st_gid; /* group ID of the file's group */
+ __int32_t st_padding1;
+ dev_t st_rdev; /* device type */
+#ifdef __STAT_TIME_T_EXT
+ __int32_t st_atim_ext;
+#endif
+ struct timespec st_atim; /* time of last access */
+#ifdef __STAT_TIME_T_EXT
+ __int32_t st_mtim_ext;
+#endif
+ struct timespec st_mtim; /* time of last data modification */
+#ifdef __STAT_TIME_T_EXT
+ __int32_t st_ctim_ext;
+#endif
+ struct timespec st_ctim; /* time of last file status change */
+#ifdef __STAT_TIME_T_EXT
+ __int32_t st_btim_ext;
+#endif
+ struct timespec st_birthtim; /* time of file creation */
+ off_t st_size; /* file size, in bytes */
+ blkcnt_t st_blocks; /* blocks allocated for file */
+ blksize_t st_blksize; /* optimal blocksize for I/O */
+ fflags_t st_flags; /* user defined flags for file */
+ __uint64_t st_gen; /* file generation number */
+ __uint64_t st_spare[10];
+};
#ifdef _KERNEL
struct nstat {
- __dev_t st_dev; /* inode's device */
- ino_t st_ino; /* inode's number */
+ __uint32_t st_dev; /* inode's device */
+ __uint32_t st_ino; /* inode's number */
__uint32_t st_mode; /* inode protection mode */
__uint32_t st_nlink; /* number of hard links */
uid_t st_uid; /* user ID of the file's owner */
gid_t st_gid; /* group ID of the file's group */
- __dev_t st_rdev; /* device type */
+ __uint32_t st_rdev; /* device type */
struct timespec st_atim; /* time of last access */
struct timespec st_mtim; /* time of last data modification */
struct timespec st_ctim; /* time of last file status change */
@@ -168,7 +208,8 @@ struct nstat {
__uint32_t st_gen; /* file generation number */
struct timespec st_birthtim; /* time of file creation */
/*
- * See above about the following padding.
+ * See comment in the definition of struct freebsd11_stat
+ * above about the following padding.
*/
unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec));
unsigned int :(8 / 2) * (16 - (int)sizeof(struct timespec));
diff --git a/sys/sys/syscallsubr.h b/sys/sys/syscallsubr.h
index d4cfa26045e9..c994ee94f829 100644
--- a/sys/sys/syscallsubr.h
+++ b/sys/sys/syscallsubr.h
@@ -117,8 +117,8 @@ int kern_futimes(struct thread *td, int fd, struct timeval *tptr,
enum uio_seg tptrseg);
int kern_futimens(struct thread *td, int fd, struct timespec *tptr,
enum uio_seg tptrseg);
-int kern_getdirentries(struct thread *td, int fd, char *buf, u_int count,
- long *basep, ssize_t *residp, enum uio_seg bufseg);
+int kern_getdirentries(struct thread *td, int fd, char *buf, size_t count,
+ off_t *basep, ssize_t *residp, enum uio_seg bufseg);
int kern_getfsstat(struct thread *td, struct statfs **buf, size_t bufsize,
size_t *countp, enum uio_seg bufseg, int mode);
int kern_getitimer(struct thread *, u_int, struct itimerval *);
@@ -158,7 +158,7 @@ int kern_mkdirat(struct thread *td, int fd, char *path,
int kern_mkfifoat(struct thread *td, int fd, char *path,
enum uio_seg pathseg, int mode);
int kern_mknodat(struct thread *td, int fd, char *path,
- enum uio_seg pathseg, int mode, int dev);
+ enum uio_seg pathseg, int mode, dev_t dev);
int kern_mlock(struct proc *proc, struct ucred *cred, uintptr_t addr,
size_t len);
int kern_mmap(struct thread *td, uintptr_t addr, size_t size, int prot,
@@ -292,4 +292,9 @@ int kern_socketpair(struct thread *td, int domain, int type, int protocol,
#define KSA_OSIGSET 0x0001 /* uses osigact_t */
#define KSA_FREEBSD4 0x0002 /* uses ucontext4 */
+struct freebsd11_dirent;
+
+int freebsd11_kern_getdirentries(struct thread *td, int fd, char *ubuf, u_int
+ count, long *basep, void (*func)(struct freebsd11_dirent *));
+
#endif /* !_SYS_SYSCALLSUBR_H_ */
diff --git a/sys/sys/tty.h b/sys/sys/tty.h
index 09e04195ae55..c37d0bf3d073 100644
--- a/sys/sys/tty.h
+++ b/sys/sys/tty.h
@@ -148,7 +148,7 @@ struct xtty {
pid_t xt_pgid; /* Foreground process group. */
pid_t xt_sid; /* Session. */
unsigned int xt_flags; /* Terminal option flags. */
- dev_t xt_dev; /* Userland device. */
+ uint32_t xt_dev; /* Userland device. XXXKIB truncated */
};
#ifdef _KERNEL
diff --git a/sys/sys/user.h b/sys/sys/user.h
index ab9cee5c8b91..ba5e43a74158 100644
--- a/sys/sys/user.h
+++ b/sys/sys/user.h
@@ -84,7 +84,7 @@
* it in two places: function fill_kinfo_proc in sys/kern/kern_proc.c and
* function kvm_proclist in lib/libkvm/kvm_proc.c .
*/
-#define KI_NSPARE_INT 4
+#define KI_NSPARE_INT 2
#define KI_NSPARE_LONG 12
#define KI_NSPARE_PTR 6
@@ -135,7 +135,7 @@ struct kinfo_proc {
pid_t ki_tsid; /* Terminal session ID */
short ki_jobc; /* job control counter */
short ki_spare_short1; /* unused (just here for alignment) */
- dev_t ki_tdev; /* controlling tty dev */
+ uint32_t ki_tdev_freebsd11; /* controlling tty dev */
sigset_t ki_siglist; /* Signals arrived but not delivered */
sigset_t ki_sigmask; /* Current signal mask */
sigset_t ki_sigignore; /* Signals being ignored */
@@ -188,6 +188,7 @@ struct kinfo_proc {
*/
char ki_sparestrings[46]; /* spare string space */
int ki_spareints[KI_NSPARE_INT]; /* spare room for growth */
+ uint64_t ki_tdev; /* controlling tty dev */
int ki_oncpu; /* Which cpu we are on */
int ki_lastcpu; /* Last cpu we were on */
int ki_tracer; /* Pid of tracing process */
@@ -341,14 +342,19 @@ struct kinfo_file {
int kf_flags; /* Flags. */
int kf_pad0; /* Round to 64 bit alignment. */
int64_t kf_offset; /* Seek location. */
- int kf_vnode_type; /* Vnode type. */
- int kf_sock_domain; /* Socket domain. */
- int kf_sock_type; /* Socket type. */
- int kf_sock_protocol; /* Socket protocol. */
- struct sockaddr_storage kf_sa_local; /* Socket address. */
- struct sockaddr_storage kf_sa_peer; /* Peer address. */
union {
struct {
+ uint32_t kf_spareint;
+ /* Socket domain. */
+ int kf_sock_domain0;
+ /* Socket type. */
+ int kf_sock_type0;
+ /* Socket protocol. */
+ int kf_sock_protocol0;
+ /* Socket address. */
+ struct sockaddr_storage kf_sa_local;
+ /* Peer address. */
+ struct sockaddr_storage kf_sa_peer;
/* Address of so_pcb. */
uint64_t kf_sock_pcb;
/* Address of inp_ppcb. */
@@ -363,14 +369,23 @@ struct kinfo_file {
uint32_t kf_sock_pad0;
} kf_sock;
struct {
+ /* Vnode type. */
+ int kf_file_type;
+ /* Space for future use */
+ int kf_spareint[3];
+ uint64_t kf_spareint64[30];
+ /* Vnode filesystem id. */
+ uint64_t kf_file_fsid;
+ /* File device. */
+ uint64_t kf_file_rdev;
/* Global file id. */
uint64_t kf_file_fileid;
/* File size. */
uint64_t kf_file_size;
- /* Vnode filesystem id. */
- uint32_t kf_file_fsid;
- /* File device. */
- uint32_t kf_file_rdev;
+ /* Vnode filesystem id, FreeBSD 11 compat. */
+ uint32_t kf_file_fsid_freebsd11;
+ /* File device, FreeBSD 11 compat. */
+ uint32_t kf_file_rdev_freebsd11;
/* File mode. */
uint16_t kf_file_mode;
/* Round to 64 bit alignment. */
@@ -378,10 +393,14 @@ struct kinfo_file {
uint32_t kf_file_pad1;
} kf_file;
struct {
+ uint32_t kf_spareint[4];
+ uint64_t kf_spareint64[32];
uint32_t kf_sem_value;
uint16_t kf_sem_mode;
} kf_sem;
struct {
+ uint32_t kf_spareint[4];
+ uint64_t kf_spareint64[32];
uint64_t kf_pipe_addr;
uint64_t kf_pipe_peer;
uint32_t kf_pipe_buffer_cnt;
@@ -389,11 +408,17 @@ struct kinfo_file {
uint32_t kf_pipe_pad0[3];
} kf_pipe;
struct {
- uint32_t kf_pts_dev;
+ uint32_t kf_spareint[4];
+ uint64_t kf_spareint64[32];
+ uint32_t kf_pts_dev_freebsd11;
+ uint32_t kf_pts_pad0;
+ uint64_t kf_pts_dev;
/* Round to 64 bit alignment. */
- uint32_t kf_pts_pad0[7];
+ uint32_t kf_pts_pad1[4];
} kf_pts;
struct {
+ uint32_t kf_spareint[4];
+ uint64_t kf_spareint64[32];
pid_t kf_pid;
} kf_proc;
} kf_un;
@@ -405,6 +430,12 @@ struct kinfo_file {
/* Truncated before copyout in sysctl */
char kf_path[PATH_MAX]; /* Path to file, if any. */
};
+#ifndef _KERNEL
+#define kf_vnode_type kf_un.kf_file.kf_file_type
+#define kf_sock_domain kf_un.kf_sock.kf_sock_domain0
+#define kf_sock_type kf_un.kf_sock.kf_sock_type0
+#define kf_sock_protocol kf_un.kf_sock.kf_sock_protocol0
+#endif
/*
* The KERN_PROC_VMMAP sysctl allows a process to dump the VM layout of
@@ -454,7 +485,7 @@ struct kinfo_ovmentry {
void *_kve_pspare[8]; /* Space for more stuff. */
off_t kve_offset; /* Mapping offset in object */
uint64_t kve_fileid; /* inode number if vnode */
- dev_t kve_fsid; /* dev_t of vnode location */
+ uint32_t kve_fsid; /* dev_t of vnode location */
int _kve_ispare[3]; /* Space for more stuff. */
};
@@ -469,7 +500,7 @@ struct kinfo_vmentry {
uint64_t kve_end; /* Finishing address. */
uint64_t kve_offset; /* Mapping offset in object */
uint64_t kve_vn_fileid; /* inode number if vnode */
- uint32_t kve_vn_fsid; /* dev_t of vnode location */
+ uint32_t kve_vn_fsid_freebsd11; /* dev_t of vnode location */
int kve_flags; /* Flags on map entry. */
int kve_resident; /* Number of resident pages. */
int kve_private_resident; /* Number of private pages. */
@@ -478,10 +509,12 @@ struct kinfo_vmentry {
int kve_shadow_count; /* VM obj shadow count. */
int kve_vn_type; /* Vnode type. */
uint64_t kve_vn_size; /* File size. */
- uint32_t kve_vn_rdev; /* Device id if device. */
+ uint32_t kve_vn_rdev_freebsd11; /* Device id if device. */
uint16_t kve_vn_mode; /* File mode. */
uint16_t kve_status; /* Status flags. */
- int _kve_ispare[12]; /* Space for more stuff. */
+ uint64_t kve_vn_fsid; /* dev_t of vnode location */
+ uint64_t kve_vn_rdev; /* Device id if device. */
+ int _kve_ispare[8]; /* Space for more stuff. */
/* Truncated before copyout in sysctl */
char kve_path[PATH_MAX]; /* Path to VM obj, if any. */
};
@@ -495,14 +528,15 @@ struct kinfo_vmobject {
int kvo_type; /* Object type: KVME_TYPE_*. */
uint64_t kvo_size; /* Object size in pages. */
uint64_t kvo_vn_fileid; /* inode number if vnode. */
- uint32_t kvo_vn_fsid; /* dev_t of vnode location. */
+ uint32_t kvo_vn_fsid_freebsd11; /* dev_t of vnode location. */
int kvo_ref_count; /* Reference count. */
int kvo_shadow_count; /* Shadow count. */
int kvo_memattr; /* Memory attribute. */
uint64_t kvo_resident; /* Number of resident pages. */
uint64_t kvo_active; /* Number of active pages. */
uint64_t kvo_inactive; /* Number of inactive pages. */
- uint64_t _kvo_qspare[8];
+ uint64_t kvo_vn_fsid;
+ uint64_t _kvo_qspare[7];
uint32_t _kvo_ispare[8];
char kvo_path[PATH_MAX]; /* Pathname, if any. */
};
diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h
index b688bfd143d2..8bfe851c55e6 100644
--- a/sys/sys/vnode.h
+++ b/sys/sys/vnode.h
@@ -266,11 +266,12 @@ struct xvnode {
struct vattr {
enum vtype va_type; /* vnode type (for create) */
u_short va_mode; /* files access mode and type */
- short va_nlink; /* number of references to file */
+ u_short va_padding0;
uid_t va_uid; /* owner user id */
gid_t va_gid; /* owner group id */
+ nlink_t va_nlink; /* number of references to file */
dev_t va_fsid; /* filesystem id */
- long va_fileid; /* file id */
+ ino_t va_fileid; /* file id */
u_quad_t va_size; /* file size in bytes */
long va_blocksize; /* blocksize preferred for i/o */
struct timespec va_atime; /* time of last access */
@@ -585,6 +586,7 @@ struct file;
struct mount;
struct nameidata;
struct ostat;
+struct freebsd11_stat;
struct thread;
struct proc;
struct stat;
@@ -613,7 +615,8 @@ void cache_purge_negative(struct vnode *vp);
void cache_purgevfs(struct mount *mp, bool force);
int change_dir(struct vnode *vp, struct thread *td);
void cvtstat(struct stat *st, struct ostat *ost);
-void cvtnstat(struct stat *sb, struct nstat *nsb);
+void freebsd11_cvtnstat(struct stat *sb, struct nstat *nsb);
+void freebsd11_cvtstat(struct stat *st, struct freebsd11_stat *ost);
int getnewvnode(const char *tag, struct mount *mp, struct vop_vector *vops,
struct vnode **vpp);
void getnewvnode_reserve(u_int count);
diff --git a/sys/vm/swap_pager.c b/sys/vm/swap_pager.c
index 76b69e5053e9..2a73acaad666 100644
--- a/sys/vm/swap_pager.c
+++ b/sys/vm/swap_pager.c
@@ -69,6 +69,7 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include "opt_compat.h"
#include "opt_swap.h"
#include "opt_vm.h"
@@ -2417,10 +2418,24 @@ swap_dev_info(int name, struct xswdev *xs, char *devname, size_t len)
return (error);
}
+#if defined(COMPAT_FREEBSD11)
+#define XSWDEV_VERSION_11 1
+struct xswdev11 {
+ u_int xsw_version;
+ uint32_t xsw_dev;
+ int xsw_flags;
+ int xsw_nblks;
+ int xsw_used;
+};
+#endif
+
static int
sysctl_vm_swap_info(SYSCTL_HANDLER_ARGS)
{
struct xswdev xs;
+#if defined(COMPAT_FREEBSD11)
+ struct xswdev11 xs11;
+#endif
int error;
if (arg2 != 1) /* name length */
@@ -2428,7 +2443,17 @@ sysctl_vm_swap_info(SYSCTL_HANDLER_ARGS)
error = swap_dev_info(*(int *)arg1, &xs, NULL, 0);
if (error != 0)
return (error);
- error = SYSCTL_OUT(req, &xs, sizeof(xs));
+#if defined(COMPAT_FREEBSD11)
+ if (req->oldlen == sizeof(xs11)) {
+ xs11.xsw_version = XSWDEV_VERSION_11;
+ xs11.xsw_dev = xs.xsw_dev; /* truncation */
+ xs11.xsw_flags = xs.xsw_flags;
+ xs11.xsw_nblks = xs.xsw_nblks;
+ xs11.xsw_used = xs.xsw_used;
+ error = SYSCTL_OUT(req, &xs11, sizeof(xs11));
+ } else
+#endif
+ error = SYSCTL_OUT(req, &xs, sizeof(xs));
return (error);
}
diff --git a/sys/vm/vm_object.c b/sys/vm/vm_object.c
index 022fbd57c882..a751ac6ea2ff 100644
--- a/sys/vm/vm_object.c
+++ b/sys/vm/vm_object.c
@@ -2342,6 +2342,7 @@ sysctl_vm_object_list(SYSCTL_HANDLER_ARGS)
kvo.kvo_vn_fileid = 0;
kvo.kvo_vn_fsid = 0;
+ kvo.kvo_vn_fsid_freebsd11 = 0;
freepath = NULL;
fullpath = "";
vp = NULL;
@@ -2383,6 +2384,8 @@ sysctl_vm_object_list(SYSCTL_HANDLER_ARGS)
if (VOP_GETATTR(vp, &va, curthread->td_ucred) == 0) {
kvo.kvo_vn_fileid = va.va_fileid;
kvo.kvo_vn_fsid = va.va_fsid;
+ kvo.kvo_vn_fsid_freebsd11 = va.va_fsid;
+ /* truncate */
}
vput(vp);
}
diff --git a/sys/vm/vm_param.h b/sys/vm/vm_param.h
index c4d72237fd40..8ca83bf18ddf 100644
--- a/sys/vm/vm_param.h
+++ b/sys/vm/vm_param.h
@@ -89,7 +89,7 @@
/*
* Structure for swap device statistics
*/
-#define XSWDEV_VERSION 1
+#define XSWDEV_VERSION 2
struct xswdev {
u_int xsw_version;
dev_t xsw_dev;
diff --git a/usr.bin/kdump/kdump.c b/usr.bin/kdump/kdump.c
index 60898fde8772..0432449755bb 100644
--- a/usr.bin/kdump/kdump.c
+++ b/usr.bin/kdump/kdump.c
@@ -932,7 +932,6 @@ ktrsyscall(struct ktr_syscall *ktr, u_int sv_flags)
ip++;
narg--;
break;
- case SYS_mknod:
case SYS_mknodat:
print_number(ip, narg, c);
putchar(',');
diff --git a/usr.bin/lastcomm/lastcomm.c b/usr.bin/lastcomm/lastcomm.c
index 57acfb583bd7..e3b9aea50644 100644
--- a/usr.bin/lastcomm/lastcomm.c
+++ b/usr.bin/lastcomm/lastcomm.c
@@ -61,9 +61,9 @@ __FBSDID("$FreeBSD$");
time_t expand(u_int);
char *flagbits(int);
const char *getdev(dev_t);
-int readrec_forward(FILE *f, struct acctv2 *av2);
-int readrec_backward(FILE *f, struct acctv2 *av2);
-int requested(char *[], struct acctv2 *);
+int readrec_forward(FILE *f, struct acctv3 *av3);
+int readrec_backward(FILE *f, struct acctv3 *av3);
+int requested(char *[], struct acctv3 *);
static void usage(void);
#define AC_UTIME 1 /* user */
@@ -77,10 +77,10 @@ static void usage(void);
int
main(int argc, char *argv[])
{
- struct acctv2 ab;
+ struct acctv3 ab;
char *p;
FILE *fp;
- int (*readrec)(FILE *f, struct acctv2 *av2);
+ int (*readrec)(FILE *f, struct acctv3 *av3);
time_t t;
int ch, rv;
const char *acctfile, *format;
@@ -234,7 +234,7 @@ flagbits(int f)
}
int
-requested(char *argv[], struct acctv2 *acp)
+requested(char *argv[], struct acctv3 *acp)
{
const char *p;
diff --git a/usr.bin/lastcomm/readrec.c b/usr.bin/lastcomm/readrec.c
index 5de7c5c4c808..0a3e9306e063 100644
--- a/usr.bin/lastcomm/readrec.c
+++ b/usr.bin/lastcomm/readrec.c
@@ -38,8 +38,8 @@ __FBSDID("$FreeBSD$");
#include <stdio.h>
#include <string.h>
-int readrec_forward(FILE *f, struct acctv2 *av2);
-int readrec_backward(FILE *f, struct acctv2 *av2);
+int readrec_forward(FILE *f, struct acctv3 *av2);
+int readrec_backward(FILE *f, struct acctv3 *av2);
/*
* Reverse offsetof: return the offset of field f
@@ -90,27 +90,27 @@ decode_comp(comp_t v)
* Return EOF on error or end-of-file.
*/
static int
-readrec_v1(FILE *f, struct acctv2 *av2)
+readrec_v1(FILE *f, struct acctv3 *av3)
{
struct acctv1 av1;
int rv;
if ((rv = fread_record(&av1, sizeof(av1), f)) == EOF)
return (EOF);
- av2->ac_zero = 0;
- av2->ac_version = 2;
- av2->ac_len = av2->ac_len2 = sizeof(*av2);
- memcpy(av2->ac_comm, av1.ac_comm, AC_COMM_LEN);
- av2->ac_utime = decode_comp(av1.ac_utime) * 1000000;
- av2->ac_stime = decode_comp(av1.ac_stime) * 1000000;
- av2->ac_etime = decode_comp(av1.ac_etime) * 1000000;
- av2->ac_btime = av1.ac_btime;
- av2->ac_uid = av1.ac_uid;
- av2->ac_gid = av1.ac_gid;
- av2->ac_mem = av1.ac_mem;
- av2->ac_io = decode_comp(av1.ac_io);
- av2->ac_tty = av1.ac_tty;
- av2->ac_flagx = av1.ac_flag | ANVER;
+ av3->ac_zero = 0;
+ av3->ac_version = 3;
+ av3->ac_len = av3->ac_len2 = sizeof(*av3);
+ memcpy(av3->ac_comm, av1.ac_comm, AC_COMM_LEN);
+ av3->ac_utime = decode_comp(av1.ac_utime) * 1000000;
+ av3->ac_stime = decode_comp(av1.ac_stime) * 1000000;
+ av3->ac_etime = decode_comp(av1.ac_etime) * 1000000;
+ av3->ac_btime = av1.ac_btime;
+ av3->ac_uid = av1.ac_uid;
+ av3->ac_gid = av1.ac_gid;
+ av3->ac_mem = av1.ac_mem;
+ av3->ac_io = decode_comp(av1.ac_io);
+ av3->ac_tty = av1.ac_tty;
+ av3->ac_flagx = av1.ac_flag | ANVER;
return (0);
}
@@ -120,9 +120,40 @@ readrec_v1(FILE *f, struct acctv2 *av2)
* Return EOF on error or end-of-file.
*/
static int
-readrec_v2(FILE *f, struct acctv2 *av2)
+readrec_v2(FILE *f, struct acctv3 *av3)
{
- return (fread_record(av2, sizeof(*av2), f));
+ struct acctv2 av2;
+ int rv;
+
+ if ((rv = fread_record(&av2, sizeof(av2), f)) == EOF)
+ return (EOF);
+ av3->ac_zero = 0;
+ av3->ac_version = 3;
+ av3->ac_len = av3->ac_len2 = sizeof(*av3);
+ memcpy(av3->ac_comm, av2.ac_comm, AC_COMM_LEN);
+ av3->ac_utime = av2.ac_utime;
+ av3->ac_stime = av2.ac_stime;
+ av3->ac_etime = av2.ac_etime;
+ av3->ac_btime = av2.ac_btime;
+ av3->ac_uid = av2.ac_uid;
+ av3->ac_gid = av2.ac_gid;
+ av3->ac_mem = av2.ac_mem;
+ av3->ac_io = av2.ac_io;
+ av3->ac_tty = av2.ac_tty;
+ av3->ac_flagx = av2.ac_flagx;
+ return (0);
+}
+
+/*
+ * Read an v2 accounting record stored at the current
+ * position of stream f.
+ * Return EOF on error or end-of-file.
+ */
+static int
+readrec_v3(FILE *f, struct acctv3 *av3)
+{
+
+ return (fread_record(av3, sizeof(*av3), f));
}
/*
@@ -132,7 +163,7 @@ readrec_v2(FILE *f, struct acctv2 *av2)
* Return EOF on error or end-of-file.
*/
static int
-readrec_vx(FILE *f, struct acctv2 *av2)
+readrec_vx(FILE *f, struct acctv3 *av3)
{
uint8_t magic, version;
@@ -143,7 +174,9 @@ readrec_vx(FILE *f, struct acctv2 *av2)
return (EOF);
switch (version) {
case 2:
- return (readrec_v2(f, av2));
+ return (readrec_v2(f, av3));
+ case 3:
+ return (readrec_v3(f, av3));
/* Add handling for more versions here. */
@@ -162,7 +195,7 @@ readrec_vx(FILE *f, struct acctv2 *av2)
* or EOF on error.
*/
int
-readrec_forward(FILE *f, struct acctv2 *av2)
+readrec_forward(FILE *f, struct acctv3 *av3)
{
int magic, rv;
@@ -172,10 +205,10 @@ readrec_forward(FILE *f, struct acctv2 *av2)
return (EOF);
if (magic != 0)
/* Old record format. */
- rv = readrec_v1(f, av2);
+ rv = readrec_v1(f, av3);
else
/* New record formats. */
- rv = readrec_vx(f, av2);
+ rv = readrec_vx(f, av3);
return (rv == EOF ? EOF : 1);
}
@@ -190,7 +223,7 @@ readrec_forward(FILE *f, struct acctv2 *av2)
* or EOF on error.
*/
int
-readrec_backward(FILE *f, struct acctv2 *av2)
+readrec_backward(FILE *f, struct acctv3 *av3)
{
off_t pos;
int c;
@@ -200,17 +233,20 @@ readrec_backward(FILE *f, struct acctv2 *av2)
return (EOF);
if (pos == 0)
return (0);
- if (fseek(f, -roffsetof(struct acctv2, ac_trailer),
+ if (fseek(f, -roffsetof(struct acctv3, ac_trailer),
SEEK_CUR) == EOF ||
(c = getc(f)) == EOF)
return (EOF);
if (c & ANVER) {
- /* New record formats. */
+ /*
+ * New record formats. For v2 and v3 offset from the
+ * end for ac_len2 should be same.
+ */
if (fseeko(f, pos - roffsetof(struct acctv2, ac_len2),
SEEK_SET) == EOF ||
fread_record(&len, sizeof(len), f) == EOF ||
fseeko(f, pos - len, SEEK_SET) == EOF ||
- readrec_vx(f, av2) == EOF ||
+ readrec_vx(f, av3) == EOF ||
fseeko(f, pos - len, SEEK_SET) == EOF)
return (EOF);
else
@@ -218,7 +254,7 @@ readrec_backward(FILE *f, struct acctv2 *av2)
} else {
/* Old record format. */
if (fseeko(f, pos - sizeof(struct acctv1), SEEK_SET) == EOF ||
- readrec_v1(f, av2) == EOF ||
+ readrec_v1(f, av3) == EOF ||
fseeko(f, pos - sizeof(struct acctv1), SEEK_SET) == EOF)
return (EOF);
else
diff --git a/usr.sbin/pstat/pstat.c b/usr.sbin/pstat/pstat.c
index 700323be8fbc..ec801822fdb2 100644
--- a/usr.sbin/pstat/pstat.c
+++ b/usr.sbin/pstat/pstat.c
@@ -255,7 +255,7 @@ ttymode_kvm(void)
/* xt.xt_pgid = ... */
/* xt.xt_sid = ... */
xt.xt_flags = tty.t_flags;
- xt.xt_dev = NODEV;
+ xt.xt_dev = (uint32_t)NODEV;
ttyprt(&xt);
tp = TAILQ_NEXT(&tty, t_list);
}
diff --git a/usr.sbin/sa/extern.h b/usr.sbin/sa/extern.h
index 70f97a7ff51b..62acf71e263a 100644
--- a/usr.sbin/sa/extern.h
+++ b/usr.sbin/sa/extern.h
@@ -79,7 +79,7 @@ int pacct_update(void);
void pacct_print(void);
/* external functions in readrec.c */
-int readrec_forward(FILE *f, struct acctv2 *av2);
+int readrec_forward(FILE *f, struct acctv3 *av2);
/* external functions in usrdb.c */
int usracct_init(void);
diff --git a/usr.sbin/sa/main.c b/usr.sbin/sa/main.c
index 64736ac340cf..d8ad5f5a912d 100644
--- a/usr.sbin/sa/main.c
+++ b/usr.sbin/sa/main.c
@@ -310,7 +310,7 @@ usage(void)
static FILE *
acct_load(const char *pn, int wr)
{
- struct acctv2 ac;
+ struct acctv3 ac;
struct cmdinfo ci;
ssize_t rv;
FILE *f;