FreeBSD Bugzilla – Attachment 182332 Details for
Bug 218320
[exp-run] ino64
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
ino64: enlarge ino_t to 64bit and several other ABI forward changes, v2
1.patch (text/plain), 285.05 KB, created by
Konstantin Belousov
on 2017-05-06 12:02:13 UTC
(
hide
)
Description:
ino64: enlarge ino_t to 64bit and several other ABI forward changes, v2
Filename:
MIME Type:
Creator:
Konstantin Belousov
Created:
2017-05-06 12:02:13 UTC
Size:
285.05 KB
patch
obsolete
>diff --git a/TODO.ino64 b/TODO.ino64 >new file mode 100644 >index 00000000000..891847ae72b >--- /dev/null >+++ b/TODO.ino64 >@@ -0,0 +1,4 @@ >+Commit checklist: see /preapply.sh >+ >+After commit checklist: >+1. Regen and commit sys/kern and sys/compat/freebsd32 sysents. >diff --git a/abi.sh b/abi.sh >new file mode 100755 >index 00000000000..81c71af2f1a >--- /dev/null >+++ b/abi.sh >@@ -0,0 +1,50 @@ >+#!/bin/sh >+ >+set -e >+PATH=$HOME/bin:$PATH >+ >+PRISTINE_BASE=/scratch/tmp/kib/obj/scratch/tmp/kib/ino64_master/ >+CHANGED_BASE=/scratch/tmp/kib/obj/scratch/tmp/kib/ino64/ >+objs=$(find $CHANGED_BASE \! -regex '.*test.*' \! -regex '.*private.*' \ >+ -type f -name '*.so.*.full' | sed 's@^'${CHANGED_BASE}'@@' ) >+ >+exclude_list="libhx509.so.11 libgssapi_ntlm.so.10" >+subs_list="libarchive.so.6@libarchive.so.7 libmilter.so.5@libmilter.so.6 libzfs.so.2@libzfs.so.3" >+ >+mkdir -p tmp >+rm -rf compat_reports tmp/* >+troubles= >+for obj in $objs; do >+# -public-headers ${PRISTINE_BASE}/tmp/usr/include >+ if echo $obj | grep world32 ; then >+ suffix=-32 >+ else >+ suffix="" >+ fi >+ libname1=$(basename ${obj} | sed 's/\.full//') >+ libname=${libname1}${suffix} >+ for x in $exclude_list; do >+ if [ ${x}${suffix} \= $libname ] ; then >+ continue 2 >+ fi >+ done >+ changed_obj=${CHANGED_BASE}/${obj} >+ pristine_obj=$(echo ${changed_obj} | sed s/ino64/ino64_master/g) >+ for x in ${subs_list} ; do >+ name1=$(echo ${x} | sed 's/@.*$//') >+ name2=$(echo ${x} | sed 's/^.*@//') >+ if [ ${name2} \= ${libname1} ] >+ $pristine_obj=$(echo ${pristine_obj} | sed s/${name2}/${name1}/) >+ fi >+ abi-dumper.pl ${pristine_obj} \ >+ -lver pristine -o tmp/${libname}-pristine.dump >+ abi-dumper.pl ${changed_obj} \ >+ -lver ino64 -o tmp/${libname}-ino64.dump >+ if abi-compliance-checker.pl -l ${libname} \ >+ -old tmp/${libname}-pristine.dump \ >+ -new tmp/${libname}-ino64.dump ; then : ; else >+ troubles="${troubles} ${libname}" >+ fi >+done >+ >+echo "Troublesome libraries: " ${troubles} >diff --git a/cddl/lib/libzfs/Makefile b/cddl/lib/libzfs/Makefile >index a13c50281cd..e8de72f1827 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 7328a5c0ac1..4b59a39ee27 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 5cbd78d3c1b..d7ce7b501f7 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 ca367c95783..cd40a6555a5 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 1ab949ccb37..1cb7cf86b2f 100644 >--- a/include/dirent.h >+++ b/include/dirent.h >@@ -41,6 +41,21 @@ > #include <sys/_types.h> > #include <sys/dirent.h> > >+#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 >+ > #if __XSI_VISIBLE > > #ifndef _INO_T_DECLARED >@@ -89,8 +104,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 53d4cc99418..646ee28f6c9 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 ac6e077207a..b8a969276c5 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 0984febf9c7..5d6a8450540 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 afdab45f6c4..098bc1959eb 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 00000000000..70cb6f0d641 >--- /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 64a73e9ea28..0415a59ec21 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 d8fe6895f11..4c661e5cf7c 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 00000000000..7653d32752f >--- /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 00000000000..52c0637395f >--- /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 00000000000..cad536d2dcd >--- /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 00000000000..728a15a51b1 >--- /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 d1fab5f3146..0366cbfad8b 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 00000000000..05ffb74dc8c >--- /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 00000000000..2bdf99a0bf6 >--- /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 00000000000..d43086f819c >--- /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 00000000000..5293f9ed6ad >--- /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 f828b8d7598..927e08b8fcc 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 00000000000..1c52f563c75 >--- /dev/null >+++ b/lib/libc/gen/readdir-compat11.c >@@ -0,0 +1,112 @@ >+/* >+ * 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 <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 void >+freebsd11_cvtdirent(struct freebsd11_dirent *dstdp, struct dirent *srcdp) >+{ >+ >+ 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); >+} >+ >+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, 1); >+ if (dp != NULL) { >+ if (dirp->dd_compat_de == NULL) >+ dirp->dd_compat_de = malloc(sizeof(struct >+ freebsd11_dirent)); >+ freebsd11_cvtdirent(dirp->dd_compat_de, dp); >+ dstdp = dirp->dd_compat_de; >+ } 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) { >+ freebsd11_cvtdirent(entry, &xentry); >+ *result = entry; >+ } 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 a547f47857b..dc7b0df18b2 100644 >--- a/lib/libc/gen/readdir.c >+++ b/lib/libc/gen/readdir.c >@@ -104,7 +104,7 @@ readdir(DIR *dirp) > } > > 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; >@@ -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 00000000000..28120c0bc13 >--- /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 00183b61de7..b7ec171764c 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 bccabb1aea5..96ff669a312 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 */ > }; > >diff --git a/lib/libc/include/compat.h b/lib/libc/include/compat.h >index d0abfdf70fd..559c8502fb9 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 384f61fb223..6409ff33175 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 76eeebd9d71..b641125096d 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 6a5c838a762..feccda6f6bf 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 00000000000..c8a2878c972 >--- /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 ace8faa7521..d3f2129d400 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 00000000000..ccc73e3d3d0 >--- /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 00000000000..3bb3853b584 >--- /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 00000000000..6b58daa9e51 >--- /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 7a95871125c..a7383c4ce12 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 ac14ef61399..a7886ab556a 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 a8efe9cec7b..17bb09857fc 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 8d4fae0dffe..9d80d17e16a 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 75a8916aca6..a78a4691fe5 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 7d42acce420..d674adc4f9e 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 00b6f1c1c11..7584878252d 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 00000000000..52d80c7afab >--- /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 a16d82b604a..ddc5c9b6b05 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/ports.patch b/ports.patch >new file mode 100644 >index 00000000000..bf018f03e77 >--- /dev/null >+++ b/ports.patch >@@ -0,0 +1,873 @@ >+Index: devel/libgtop/files/patch-ino64 >+=================================================================== >+--- devel/libgtop/files/patch-ino64 (nonexistent) >++++ devel/libgtop/files/patch-ino64 (working copy) >+@@ -0,0 +1,41 @@ >++--- sysdeps/freebsd/procopenfiles.c.orig 2014-10-12 07:17:26.000000000 +0000 >+++++ sysdeps/freebsd/procopenfiles.c 2017-04-22 17:17:54.862169000 +0000 >++@@ -322,12 +322,12 @@ >++ struct sockaddr_un *sun; >++ >++ entry.type = GLIBTOP_FILE_TYPE_LOCALSOCKET; >++- sun = (struct sockaddr_un *)&kif->kf_sa_local; >+++ sun = (struct sockaddr_un *)&kif->kf_un.kf_sock.kf_sa_local; >++ >++ if (sun->sun_path[0]) { >++ char *addrstr; >++ >++- addrstr = addr_to_string(&kif->kf_sa_local); >+++ addrstr = addr_to_string(&kif->kf_un.kf_sock.kf_sa_local); >++ g_strlcpy(entry.info.localsock.name, >++ addrstr, >++ sizeof(entry.info.localsock.name)); >++@@ -335,7 +335,7 @@ >++ } else { >++ char *addrstr; >++ >++- addrstr = addr_to_string(&kif->kf_sa_peer); >+++ addrstr = addr_to_string(&kif->kf_un.kf_sock.kf_sa_peer); >++ g_strlcpy(entry.info.localsock.name, >++ addrstr, >++ sizeof(entry.info.localsock.name)); >++@@ -349,12 +349,12 @@ >++ entry.type = GLIBTOP_FILE_TYPE_INETSOCKET; >++ else >++ entry.type = GLIBTOP_FILE_TYPE_INET6SOCKET; >++- addrstr = addr_to_string(&kif->kf_sa_peer); >+++ addrstr = addr_to_string(&kif->kf_un.kf_sock.kf_sa_peer); >++ g_strlcpy(entry.info.sock.dest_host, >++ addrstr, >++ sizeof(entry.info.sock.dest_host)); >++ g_free(addrstr); >++- entry.info.sock.dest_port = addr_to_port(&kif->kf_sa_peer); >+++ entry.info.sock.dest_port = addr_to_port(&kif->kf_un.kf_sock.kf_sa_peer); >++ } >++ } else if (kif->kf_type == KF_TYPE_PIPE) { >++ entry.type = GLIBTOP_FILE_TYPE_PIPE; >+ >+Property changes on: devel/libgtop/files/patch-ino64 >+___________________________________________________________________ >+Added: fbsd:nokeywords >+## -0,0 +1 ## >++yes >+\ No newline at end of property >+Added: svn:eol-style >+## -0,0 +1 ## >++native >+\ No newline at end of property >+Added: svn:mime-type >+## -0,0 +1 ## >++text/plain >+\ No newline at end of property >+Index: devel/llvm39/Makefile >+=================================================================== >+--- devel/llvm39/Makefile (revision 440145) >++++ devel/llvm39/Makefile (working copy) >+@@ -339,6 +339,7 @@ >+ >+ post-patch-COMPILER_RT-on: >+ cd ${WRKSRC_compiler_rt} && patch < ${PATCHDIR}/compiler-rt-patch-svn-294806 >++ cd ${WRKSRC_compiler_rt} && patch < ${PATCHDIR}/compiler-rt-patch-ino64 >+ >+ post-build-COMPILER_RT-on: >+ ${MKDIR} ${WRKDIR}/compiler-rt-build >+Index: devel/llvm39/files/compiler-rt-patch-ino64 >+=================================================================== >+--- devel/llvm39/files/compiler-rt-patch-ino64 (nonexistent) >++++ devel/llvm39/files/compiler-rt-patch-ino64 (working copy) >+@@ -0,0 +1,49 @@ >++diff --git lib/sanitizer_common/sanitizer_linux.cc lib/sanitizer_common/sanitizer_linux.cc >++index 7328a5c0ac1..4b59a39ee27 100644 >++--- lib/sanitizer_common/sanitizer_linux.cc >+++++ 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 lib/sanitizer_common/sanitizer_platform_limits_posix.h lib/sanitizer_common/sanitizer_platform_limits_posix.h >++index 5cbd78d3c1b..d7ce7b501f7 100644 >++--- lib/sanitizer_common/sanitizer_platform_limits_posix.h >+++++ 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 >++ }; >+ >+Property changes on: devel/llvm39/files/compiler-rt-patch-ino64 >+___________________________________________________________________ >+Added: svn:eol-style >+## -0,0 +1 ## >++native >+\ No newline at end of property >+Added: svn:mime-type >+## -0,0 +1 ## >++text/plain >+\ No newline at end of property >+Index: devel/llvm40/Makefile >+=================================================================== >+--- devel/llvm40/Makefile (revision 440145) >++++ devel/llvm40/Makefile (working copy) >+@@ -338,6 +338,9 @@ >+ post-extract-OPENMP-on: >+ ${MV} ${WRKSRC_openmp} ${PATCH_WRKSRC}/tools/openmp >+ >++post-patch-COMPILER_RT-on: >++ cd ${WRKSRC_compiler_rt} && patch < ${PATCHDIR}/compiler-rt-patch-ino64 >++ >+ post-patch: >+ ${REINPLACE_CMD} -e 's|import lit|import lit${LLVM_SUFFIX}|' \ >+ -e 's|from lit|from lit${LLVM_SUFFIX}|' \ >+Index: devel/llvm40/files/compiler-rt-patch-ino64 >+=================================================================== >+--- devel/llvm40/files/compiler-rt-patch-ino64 (nonexistent) >++++ devel/llvm40/files/compiler-rt-patch-ino64 (working copy) >+@@ -0,0 +1,49 @@ >++diff --git lib/sanitizer_common/sanitizer_linux.cc lib/sanitizer_common/sanitizer_linux.cc >++index 7328a5c0ac1..4b59a39ee27 100644 >++--- lib/sanitizer_common/sanitizer_linux.cc >+++++ 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 lib/sanitizer_common/sanitizer_platform_limits_posix.h lib/sanitizer_common/sanitizer_platform_limits_posix.h >++index 5cbd78d3c1b..d7ce7b501f7 100644 >++--- lib/sanitizer_common/sanitizer_platform_limits_posix.h >+++++ 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 >++ }; >+ >+Property changes on: devel/llvm40/files/compiler-rt-patch-ino64 >+___________________________________________________________________ >+Added: svn:eol-style >+## -0,0 +1 ## >++native >+\ No newline at end of property >+Added: svn:mime-type >+## -0,0 +1 ## >++text/plain >+\ No newline at end of property >+Index: lang/ghc/Makefile >+=================================================================== >+--- lang/ghc/Makefile (revision 440145) >++++ lang/ghc/Makefile (working copy) >+@@ -239,6 +239,9 @@ >+ @${REINPLACE_CMD} -e 's|@SettingsCCompilerFlags@|& -Qunused-arguments|' ${BOOT_DIR}/settings.in >+ .endif >+ .endif >++.if empty(PORT_OPTIONS:MBOOT) >++ @${REINPLACE_CMD} -e 's|@SettingsCCompilerLinkFlags@|& -Wl,--wrap=readdir_r,--wrap=stat,--wrap=lstat,--wrap=fstat,--wrap=mknod|' ${BOOT_DIR}/settings.in >++.endif >+ >+ post-install-script: >+ @${FIND} -ds ${GHC_LIBDIR} -type f -print | ${SED} -E -e \ >+@@ -266,6 +269,13 @@ >+ s|%%AR%%|${AR}|; \ >+ s|%%LD%%|${LD}|' \ >+ ${WRKSRC}/libraries/Cabal/Cabal/Distribution/Simple/Program/Builtin.hs >++.if empty(PORT_OPTIONS:MBOOTH) >++ ${CC} ${CFLAGS} -c -o ${BOOT_DIR}/wrap.o ${PATCHDIR}/wrap.c >++ for x in ${BOOT_DIR}/rts/dist/build/libCffi*.a; do \ >++ ${AR} q $$x ${BOOT_DIR}/wrap.o; ${RANLIB} $$x; \ >++ done >++ rm ${BOOT_DIR}/wrap.o >++.endif >+ >+ pre-configure: >+ @${MKDIR} ${TMPDIR} >+Index: lang/ghc/files/wrap.c >+=================================================================== >+--- lang/ghc/files/wrap.c (nonexistent) >++++ lang/ghc/files/wrap.c (working copy) >+@@ -0,0 +1,54 @@ >++/* -*- ugly-hack-mode -*- */ >++ >++#include <sys/stat.h> >++ >++struct old_dirent; >++struct old_stat; >++ >++__asm(".symver old_readdir_r, readdir_r@FBSD_1.0"); >++int old_readdir_r(void *dirp, struct old_dirent *entry, >++ struct old_dirent **result); >++__asm(".symver old_stat, stat@FBSD_1.0"); >++int old_stat(const char * restrict path, struct old_stat * restrict sb); >++__asm(".symver old_lstat, lstat@FBSD_1.0"); >++int old_lstat(const char * restrict path, struct old_stat * restrict sb); >++__asm(".symver old_fstat, fstat@FBSD_1.0"); >++int old_fstat(int fd, struct old_stat *sb); >++__asm(".symver old_mknod, mknod@FBSD_1.0"); >++int old_mknod(const char *path, mode_t mode, uint32_t dev); >++ >++int >++__wrap_readdir_r(void *dirp, struct old_dirent *entry, >++ struct old_dirent **result) >++{ >++ >++ return (old_readdir_r(dirp, entry, result)); >++} >++ >++int >++__wrap_stat(const char * restrict path, struct old_stat * restrict sb) >++{ >++ >++ return (old_stat(path, sb)); >++} >++ >++int >++__wrap_lstat(const char * restrict path, struct old_stat * restrict sb) >++{ >++ >++ return (old_lstat(path, sb)); >++} >++ >++int >++__wrap_fstat(int fd, struct old_stat *sb) >++{ >++ >++ return (old_fstat(fd, sb)); >++} >++ >++int >++__wrap_mknod(const char *path, mode_t mode, uint32_t dev) >++{ >++ >++ return (old_mknod(path, mode, dev)); >++} >+ >+Property changes on: lang/ghc/files/wrap.c >+___________________________________________________________________ >+Added: svn:eol-style >+## -0,0 +1 ## >++native >+\ No newline at end of property >+Added: svn:mime-type >+## -0,0 +1 ## >++text/plain >+\ No newline at end of property >+Index: lang/rust/Makefile >+=================================================================== >+--- lang/rust/Makefile (revision 440145) >++++ lang/rust/Makefile (working copy) >+@@ -129,6 +129,9 @@ >+ exit 1;\ >+ fi >+ >++LIBSTD= rust-std-1.15.1-x86_64-unknown-freebsd/rust-std-x86_64-unknown-freebsd/lib/rustlib/x86_64-unknown-freebsd/lib/libstd-2057375968b67ddb.rlib >++STDF= std-2057375968b67ddb.0.o >++ >+ post-extract: >+ @${MKDIR} \ >+ ${WRKSRC}/build/cache/${RUST_BOOTSTRAP_DIR} \ >+@@ -135,10 +138,16 @@ >+ ${WRKSRC}/build/cache/${CARGO_BOOTSTRAP_DIR} >+ ${LN} -sf ${DISTDIR}/${DIST_SUBDIR}/${RUSTC_BOOTSTRAP} \ >+ ${WRKSRC}/build/cache/${RUST_BOOTSTRAP_DIR} >+- ${LN} -sf ${DISTDIR}/${DIST_SUBDIR}/${RUST_STD_BOOTSTRAP} \ >+- ${WRKSRC}/build/cache/${RUST_BOOTSTRAP_DIR} >+ ${LN} -sf ${DISTDIR}/${DIST_SUBDIR}/${CARGO_BOOTSTRAP} \ >+ ${WRKSRC}/build/cache/${CARGO_BOOTSTRAP_DIR} >++ ${TAR} -x -C ${WRKSRC} -f ${DISTDIR}/${DIST_SUBDIR}/${RUST_STD_BOOTSTRAP} >++ ${CC} ${CFLAGS} -fPIC -c -o ${WRKSRC}/old_fstat.o ${FILESDIR}/old_fstat.c >++ (cd ${WRKSRC} && ${AR} x ${WRKSRC}/${LIBSTD} ${STDF}) >++ ${LD} -r -o ${WRKSRC}/std.xx.o ${WRKSRC}/${STDF} ${WRKSRC}/old_fstat.o >++ ${MV} ${WRKSRC}/std.xx.o ${WRKSRC}/${STDF} >++ (cd ${WRKSRC} && ${AR} r ${WRKSRC}/${LIBSTD} ${STDF}) >++ ${TAR} -cy -C ${WRKSRC} -f ${WRKSRC}/rustc.tbz rust-std-1.15.1-x86_64-unknown-freebsd >++ ${MV} ${WRKSRC}/rustc.tbz ${WRKSRC}/build/cache/${RUST_STD_BOOTSTRAP} >+ >+ post-patch: >+ @test ! -f ${WRKSRC}/mk/main.mk || \ >+Index: lang/rust/files/old_fstat.c >+=================================================================== >+--- lang/rust/files/old_fstat.c (nonexistent) >++++ lang/rust/files/old_fstat.c (working copy) >+@@ -0,0 +1,101 @@ >++#include <sys/syscall.h> >++#include <dlfcn.h> >++#include <stdio.h> >++#include <stdlib.h> >++#include <unistd.h> >++ >++struct stat; >++ >++int >++fstat(int fd, struct stat *sb) >++{ >++ >++ return (syscall(SYS_freebsd11_fstat, fd, sb)); >++} >++ >++int >++stat(const char *path, struct stat *sb) >++{ >++ >++ return (syscall(SYS_freebsd11_stat, path, sb)); >++} >++ >++int >++lstat(const char *path, struct stat *sb) >++{ >++ >++ return (syscall(SYS_freebsd11_lstat, path, sb)); >++} >++ >++int >++fstatat(int fd, const char *path, struct stat *sb, int flag) >++{ >++ >++ return (syscall(SYS_freebsd11_fstatat, fd, path, sb, flag)); >++} >++ >++struct ODIR; >++struct freebsd11_dirent; >++ >++/* >++__asm(".symver old_readdir, readdir@FBSD_1.0"); >++int old_readdir(struct ODIR *); >++int >++readdir(struct ODIR *dirp) >++{ >++ >++ return (old_readdir(dirp)); >++} >++*/ >++ >++__asm(".symver old_readdir_r, readdir_r@FBSD_1.0"); >++int old_readdir_r(struct ODIR *, struct freebsd11_dirent *, >++ struct freebsd11_dirent **); >++int >++readdir_r(struct ODIR *dirp, struct freebsd11_dirent *entry, >++ struct freebsd11_dirent **result) >++{ >++ void *libc; >++ void *fptr; >++ int error; >++ >++ libc = dlopen("libc.so.7", RTLD_LAZY | RTLD_GLOBAL); >++ if (libc == NULL) { >++ fprintf(stderr, "libc open: %s\n", dlerror()); >++ abort(); >++ } >++ fptr = dlvsym(libc, "readdir_r", "FBSD_1.0"); >++ if (fptr == NULL) { >++ fprintf(stderr, "readdir_r: %s\n", dlerror()); >++ abort(); >++ } >++ error = ((int (*)(struct ODIR *, struct freebsd11_dirent *, >++ struct freebsd11_dirent **))fptr)(dirp, entry, result); >++ dlclose(libc); >++ return (error); >++} >++ >++/* >++__asm(".symver old_scandir, scandir@FBSD_1.0"); >++int old_scandir(const char *, struct freebsd11_dirent ***, >++ int (*)(const struct freebsd11_dirent *), >++ int (*)(const struct freebsd11_dirent **, >++ const struct freebsd11_dirent **)); >++int >++scandir(const char *dirname, struct freebsd11_dirent ***namelist, >++ int (*select)(const struct freebsd11_dirent *), >++ int (*dcomp)(const struct freebsd11_dirent **, >++ const struct freebsd11_dirent **)) >++{ >++ >++ return (old_scandir(dirname, namelist, select, dcomp)); >++} >++*/ >++ >++struct old_statfs; >++int >++fstatfs(int fd, struct old_statfs *buf) >++{ >++ >++ return (syscall(SYS_freebsd11_fstatfs, fd, buf)); >++} >+ >+Property changes on: lang/rust/files/old_fstat.c >+___________________________________________________________________ >+Added: svn:eol-style >+## -0,0 +1 ## >++native >+\ No newline at end of property >+Added: svn:mime-type >+## -0,0 +1 ## >++text/plain >+\ No newline at end of property >+Index: lang/rust/files/patch-ino64 >+=================================================================== >+--- lang/rust/files/patch-ino64 (nonexistent) >++++ lang/rust/files/patch-ino64 (working copy) >+@@ -0,0 +1,308 @@ >++--- ./src/liblibc/src/unix/bsd/freebsdlike/freebsd/mod.rs.orig 2017-03-10 22:56:40.000000000 +0000 >+++++ ./src/liblibc/src/unix/bsd/freebsdlike/freebsd/mod.rs 2017-05-05 10:03:39.644990000 +0000 >++@@ -1,8 +1,8 @@ >++ pub type fflags_t = u32; >++ pub type clock_t = i32; >++-pub type ino_t = u32; >+++pub type ino_t = u64; >++ pub type lwpid_t = i32; >++-pub type nlink_t = u16; >+++pub type nlink_t = u64; >++ pub type blksize_t = u32; >++ pub type clockid_t = ::c_int; >++ pub type sem_t = _sem; >++@@ -39,10 +39,12 @@ >++ } >++ >++ pub struct dirent { >++- pub d_fileno: u32, >+++ pub d_fileno: u64, >+++ pub d_off: u64, >++ pub d_reclen: u16, >++ pub d_type: u8, >++ pub d_namlen: u8, >+++ pub d_pad0: u32, >++ pub d_name: [::c_char; 256], >++ } >++ >++--- ./src/liblibc/src/unix/bsd/freebsdlike/freebsd/x86.rs.orig 2017-03-10 22:56:40.000000000 +0000 >+++++ ./src/liblibc/src/unix/bsd/freebsdlike/freebsd/x86.rs 2017-05-05 10:13:49.091702000 +0000 >++@@ -7,25 +7,30 @@ >++ pub struct stat { >++ pub st_dev: ::dev_t, >++ pub st_ino: ::ino_t, >++- pub st_mode: ::mode_t, >++ pub st_nlink: ::nlink_t, >+++ pub st_mode: ::mode_t, >+++ pub st_pad0: ::uint16_t, >++ pub st_uid: ::uid_t, >++ pub st_gid: ::gid_t, >+++ pub st_pad1: ::uint32_t, >++ pub st_rdev: ::dev_t, >+++ pub st_atime_ext ::i32, >++ pub st_atime: ::time_t, >++ pub st_atime_nsec: ::c_long, >+++ pub st_mtime_ext ::i32, >++ pub st_mtime: ::time_t, >++ pub st_mtime_nsec: ::c_long, >+++ pub st_ctime_ext ::i32, >++ pub st_ctime: ::time_t, >++ pub st_ctime_nsec: ::c_long, >+++ pub st_birthtime_ext ::i32, >+++ pub st_birthtime: ::time_t, >+++ pub st_birthtime_nsec: ::c_long, >++ pub st_size: ::off_t, >++ pub st_blocks: ::blkcnt_t, >++ pub st_blksize: ::blksize_t, >++ pub st_flags: ::fflags_t, >++- pub st_gen: ::uint32_t, >++- pub st_lspare: ::int32_t, >++- pub st_birthtime: ::time_t, >++- pub st_birthtime_nsec: ::c_long, >++- __unused: [u8; 8], >+++ pub st_gen: ::uint64_t, >+++ pub st_lspare: [::uint64_t; 10], >++ } >++ } >++--- ./src/liblibc/src/unix/bsd/freebsdlike/freebsd/x86_64.rs.orig 2017-03-10 22:56:40.000000000 +0000 >+++++ ./src/liblibc/src/unix/bsd/freebsdlike/freebsd/x86_64.rs 2017-05-05 10:03:39.645576000 +0000 >++@@ -7,10 +7,12 @@ >++ pub struct stat { >++ pub st_dev: ::dev_t, >++ pub st_ino: ::ino_t, >++- pub st_mode: ::mode_t, >++ pub st_nlink: ::nlink_t, >+++ pub st_mode: ::mode_t, >+++ pub st_pad0: ::uint16_t, >++ pub st_uid: ::uid_t, >++ pub st_gid: ::gid_t, >+++ pub st_pad1: ::uint32_t, >++ pub st_rdev: ::dev_t, >++ pub st_atime: ::time_t, >++ pub st_atime_nsec: ::c_long, >++@@ -18,13 +20,13 @@ >++ pub st_mtime_nsec: ::c_long, >++ pub st_ctime: ::time_t, >++ pub st_ctime_nsec: ::c_long, >+++ pub st_birthtime: ::time_t, >+++ pub st_birthtime_nsec: ::c_long, >++ pub st_size: ::off_t, >++ pub st_blocks: ::blkcnt_t, >++ pub st_blksize: ::blksize_t, >++ pub st_flags: ::fflags_t, >++- pub st_gen: ::uint32_t, >++- pub st_lspare: ::int32_t, >++- pub st_birthtime: ::time_t, >++- pub st_birthtime_nsec: ::c_long, >+++ pub st_gen: ::uint64_t, >+++ pub st_spare: [::int64_t; 10], >++ } >++ } >++--- ./src/liblibc/src/unix/bsd/freebsdlike/mod.rs.orig 2017-03-10 22:56:40.000000000 +0000 >+++++ ./src/liblibc/src/unix/bsd/freebsdlike/mod.rs 2017-05-05 10:03:39.646020000 +0000 >++@@ -1,4 +1,4 @@ >++-pub type dev_t = u32; >+++pub type dev_t = u64; >++ pub type mode_t = u16; >++ pub type pthread_attr_t = *mut ::c_void; >++ pub type rlim_t = i64; >++--- ./src/vendor/libc/src/unix/bsd/freebsdlike/freebsd/x86_64.rs.orig 2017-03-10 22:55:22.000000000 +0000 >+++++ ./src/vendor/libc/src/unix/bsd/freebsdlike/freebsd/x86_64.rs 2017-05-05 10:03:39.646330000 +0000 >++@@ -7,10 +7,12 @@ >++ pub struct stat { >++ pub st_dev: ::dev_t, >++ pub st_ino: ::ino_t, >++- pub st_mode: ::mode_t, >++ pub st_nlink: ::nlink_t, >+++ pub st_mode: ::mode_t, >+++ pub st_pad0: u16, >++ pub st_uid: ::uid_t, >++ pub st_gid: ::gid_t, >+++ pub st_pad1: ::u32, >++ pub st_rdev: ::dev_t, >++ pub st_atime: ::time_t, >++ pub st_atime_nsec: ::c_long, >++@@ -18,13 +20,13 @@ >++ pub st_mtime_nsec: ::c_long, >++ pub st_ctime: ::time_t, >++ pub st_ctime_nsec: ::c_long, >+++ pub st_birthtime: ::time_t, >+++ pub st_birthtime_nsec: ::c_long, >++ pub st_size: ::off_t, >++ pub st_blocks: ::blkcnt_t, >++ pub st_blksize: ::blksize_t, >++ pub st_flags: ::fflags_t, >++- pub st_gen: ::uint32_t, >++- pub st_lspare: ::int32_t, >++- pub st_birthtime: ::time_t, >++- pub st_birthtime_nsec: ::c_long, >+++ pub st_gen: ::uint64_t, >+++ pub st_spare: [u64; 10], >++ } >++ } >++--- ./src/vendor/libc/src/unix/bsd/freebsdlike/freebsd/mod.rs.orig 2017-03-10 22:55:22.000000000 +0000 >+++++ ./src/vendor/libc/src/unix/bsd/freebsdlike/freebsd/mod.rs 2017-05-05 10:03:39.646697000 +0000 >++@@ -1,7 +1,7 @@ >++ pub type fflags_t = u32; >++ pub type clock_t = i32; >++-pub type ino_t = u32; >++-pub type nlink_t = u16; >+++pub type ino_t = u64; >+++pub type nlink_t = u64; >++ pub type blksize_t = u32; >++ pub type clockid_t = ::c_int; >++ >++@@ -10,10 +10,12 @@ >++ >++ s! { >++ pub struct dirent { >++- pub d_fileno: u32, >+++ pub d_fileno: u64, >+++ pub d_off: u64, >++ pub d_reclen: u16, >++ pub d_type: u8, >++ pub d_namlen: u8, >+++ pub d_pad0: u32, >++ pub d_name: [::c_char; 256], >++ } >++ >++--- ./src/vendor/libc/src/unix/bsd/freebsdlike/freebsd/x86.rs.orig 2017-03-10 22:55:22.000000000 +0000 >+++++ ./src/vendor/libc/src/unix/bsd/freebsdlike/freebsd/x86.rs 2017-05-05 10:13:34.699604000 +0000 >++@@ -7,25 +7,30 @@ >++ pub struct stat { >++ pub st_dev: ::dev_t, >++ pub st_ino: ::ino_t, >++- pub st_mode: ::mode_t, >++ pub st_nlink: ::nlink_t, >+++ pub st_mode: ::mode_t, >+++ pub st_pad0: u16, >++ pub st_uid: ::uid_t, >++ pub st_gid: ::gid_t, >+++ pub st_pad1: u32, >++ pub st_rdev: ::dev_t, >+++ pub st_atime_ext: ::i32, >++ pub st_atime: ::time_t, >++ pub st_atime_nsec: ::c_long, >+++ pub st_mtime_ext: ::i32, >++ pub st_mtime: ::time_t, >++ pub st_mtime_nsec: ::c_long, >+++ pub st_ctime_ext: ::i32, >++ pub st_ctime: ::time_t, >++ pub st_ctime_nsec: ::c_long, >+++ pub st_birthtime_ext: ::i32, >+++ pub st_birthtime: ::time_t, >+++ pub st_birthtime_nsec: ::c_long, >++ pub st_size: ::off_t, >++ pub st_blocks: ::blkcnt_t, >++ pub st_blksize: ::blksize_t, >++ pub st_flags: ::fflags_t, >++- pub st_gen: ::uint32_t, >++- pub st_lspare: ::int32_t, >++- pub st_birthtime: ::time_t, >++- pub st_birthtime_nsec: ::c_long, >++- __unused: [u8; 8], >+++ pub st_gen: ::uint64_t, >+++ pub st_spare: [u64; 10], >++ } >++ } >++--- ./src/vendor/libc/src/unix/bsd/freebsdlike/mod.rs.orig 2017-03-10 22:55:22.000000000 +0000 >+++++ ./src/vendor/libc/src/unix/bsd/freebsdlike/mod.rs 2017-05-05 10:03:39.647404000 +0000 >++@@ -1,4 +1,4 @@ >++-pub type dev_t = u32; >+++pub type dev_t = u64; >++ pub type mode_t = u16; >++ pub type pthread_attr_t = *mut ::c_void; >++ pub type rlim_t = i64; >++--- ./src/libstd/os/freebsd/raw.rs.orig 2017-03-10 22:55:21.000000000 +0000 >+++++ ./src/libstd/os/freebsd/raw.rs 2017-05-05 10:24:00.391639000 +0000 >++@@ -38,32 +38,48 @@ >++ #[stable(feature = "raw_ext", since = "1.1.0")] >++ pub struct stat { >++ #[stable(feature = "raw_ext", since = "1.1.0")] >++- pub st_dev: u32, >+++ pub st_dev: u64, >++ #[stable(feature = "raw_ext", since = "1.1.0")] >++- pub st_ino: u32, >+++ pub st_ino: u64, >++ #[stable(feature = "raw_ext", since = "1.1.0")] >+++ pub st_nlink: u64, >+++ #[stable(feature = "raw_ext", since = "1.1.0")] >++ pub st_mode: u16, >++ #[stable(feature = "raw_ext", since = "1.1.0")] >++- pub st_nlink: u16, >+++ pub st_pad0: u16, >++ #[stable(feature = "raw_ext", since = "1.1.0")] >++ pub st_uid: u32, >++ #[stable(feature = "raw_ext", since = "1.1.0")] >++ pub st_gid: u32, >++ #[stable(feature = "raw_ext", since = "1.1.0")] >++- pub st_rdev: u32, >+++ pub st_pad1: u32, >++ #[stable(feature = "raw_ext", since = "1.1.0")] >+++ pub st_rdev: u64, >+++ #[cfg(target_arch = "x86")] >+++ pub st_atime_ext: c_long, >+++ #[stable(feature = "raw_ext", since = "1.1.0")] >++ pub st_atime: c_long, >++ #[stable(feature = "raw_ext", since = "1.1.0")] >++ pub st_atime_nsec: c_long, >+++ #[cfg(target_arch = "x86")] >+++ pub st_mtime_ext: c_long, >++ #[stable(feature = "raw_ext", since = "1.1.0")] >++ pub st_mtime: c_long, >++ #[stable(feature = "raw_ext", since = "1.1.0")] >++ pub st_mtime_nsec: c_long, >+++ #[cfg(target_arch = "x86")] >+++ pub st_ctime_ext: c_long, >++ #[stable(feature = "raw_ext", since = "1.1.0")] >++ pub st_ctime: c_long, >++ #[stable(feature = "raw_ext", since = "1.1.0")] >++ pub st_ctime_nsec: c_long, >+++ #[cfg(target_arch = "x86")] >+++ pub st_birthtime_ext: c_long, >++ #[stable(feature = "raw_ext", since = "1.1.0")] >+++ pub st_birthtime: c_long, >+++ #[stable(feature = "raw_ext", since = "1.1.0")] >+++ pub st_birthtime_nsec: c_long, >+++ #[stable(feature = "raw_ext", since = "1.1.0")] >++ pub st_size: i64, >++ #[stable(feature = "raw_ext", since = "1.1.0")] >++ pub st_blocks: i64, >++@@ -72,14 +88,7 @@ >++ #[stable(feature = "raw_ext", since = "1.1.0")] >++ pub st_flags: u32, >++ #[stable(feature = "raw_ext", since = "1.1.0")] >++- pub st_gen: u32, >+++ pub st_gen: u64, >++ #[stable(feature = "raw_ext", since = "1.1.0")] >++- pub st_lspare: i32, >++- #[stable(feature = "raw_ext", since = "1.1.0")] >++- pub st_birthtime: c_long, >++- #[stable(feature = "raw_ext", since = "1.1.0")] >++- pub st_birthtime_nsec: c_long, >++- #[cfg(target_arch = "x86")] >++- #[stable(feature = "raw_ext", since = "1.1.0")] >++- pub __unused: [u8; 8], >+++ pub st_spare: [u64; 10], >++ } >++--- ./src/libstd/os/freebsd/fs.rs.orig 2017-03-10 22:55:21.000000000 +0000 >+++++ ./src/libstd/os/freebsd/fs.rs 2017-05-05 10:03:39.647976000 +0000 >++@@ -74,8 +74,6 @@ >++ fn st_flags(&self) -> u32; >++ #[stable(feature = "metadata_ext2", since = "1.8.0")] >++ fn st_gen(&self) -> u32; >++- #[stable(feature = "metadata_ext2", since = "1.8.0")] >++- fn st_lspare(&self) -> u32; >++ } >++ >++ #[stable(feature = "metadata_ext", since = "1.1.0")] >++@@ -146,9 +144,6 @@ >++ } >++ fn st_flags(&self) -> u32 { >++ self.as_inner().as_inner().st_flags as u32 >++- } >++- fn st_lspare(&self) -> u32 { >++- self.as_inner().as_inner().st_lspare as u32 >++ } >++ } >++ >+ >+Property changes on: lang/rust/files/patch-ino64 >+___________________________________________________________________ >+Added: fbsd:nokeywords >+## -0,0 +1 ## >++yes >+\ No newline at end of property >+Added: svn:eol-style >+## -0,0 +1 ## >++native >+\ No newline at end of property >+Added: svn:mime-type >+## -0,0 +1 ## >++text/plain >+\ No newline at end of property >+Index: sysutils/py-psutil/files/patch-ino64 >+=================================================================== >+--- sysutils/py-psutil/files/patch-ino64 (nonexistent) >++++ sysutils/py-psutil/files/patch-ino64 (working copy) >+@@ -0,0 +1,60 @@ >++--- psutil/arch/bsd/freebsd_socks.c.orig 2017-04-22 17:20:07.041427000 +0000 >+++++ psutil/arch/bsd/freebsd_socks.c 2017-04-22 17:22:50.547756000 +0000 >++@@ -148,20 +148,20 @@ >++ if (kif->kf_sock_domain == AF_INET) { >++ if (!psutil_sockaddr_matches( >++ AF_INET, inp->inp_lport, &inp->inp_laddr, >++- &kif->kf_sa_local)) >+++ &kif->kf_un.kf_sock.kf_sa_local)) >++ continue; >++ if (!psutil_sockaddr_matches( >++ AF_INET, inp->inp_fport, &inp->inp_faddr, >++- &kif->kf_sa_peer)) >+++ &kif->kf_un.kf_sock.kf_sa_peer)) >++ continue; >++ } else { >++ if (!psutil_sockaddr_matches( >++ AF_INET6, inp->inp_lport, &inp->in6p_laddr, >++- &kif->kf_sa_local)) >+++ &kif->kf_un.kf_sock.kf_sa_local)) >++ continue; >++ if (!psutil_sockaddr_matches( >++ AF_INET6, inp->inp_fport, &inp->in6p_faddr, >++- &kif->kf_sa_peer)) >+++ &kif->kf_un.kf_sock.kf_sa_peer)) >++ continue; >++ } >++ >++@@ -577,19 +577,19 @@ >++ inet_ntop( >++ kif->kf_sock_domain, >++ psutil_sockaddr_addr(kif->kf_sock_domain, >++- &kif->kf_sa_local), >+++ &kif->kf_un.kf_sock.kf_sa_local), >++ lip, >++ sizeof(lip)); >++ inet_ntop( >++ kif->kf_sock_domain, >++ psutil_sockaddr_addr(kif->kf_sock_domain, >++- &kif->kf_sa_peer), >+++ &kif->kf_un.kf_sock.kf_sa_peer), >++ rip, >++ sizeof(rip)); >++ lport = htons(psutil_sockaddr_port(kif->kf_sock_domain, >++- &kif->kf_sa_local)); >+++ &kif->kf_un.kf_sock.kf_sa_local)); >++ rport = htons(psutil_sockaddr_port(kif->kf_sock_domain, >++- &kif->kf_sa_peer)); >+++ &kif->kf_un.kf_sock.kf_sa_peer)); >++ >++ // construct python tuple/list >++ py_laddr = Py_BuildValue("(si)", lip, lport); >++@@ -620,7 +620,7 @@ >++ else if (kif->kf_sock_domain == AF_UNIX) { >++ struct sockaddr_un *sun; >++ >++- sun = (struct sockaddr_un *)&kif->kf_sa_local; >+++ sun = (struct sockaddr_un *)&kif->kf_un.kf_sock.kf_sa_local; >++ snprintf( >++ path, sizeof(path), "%.*s", >++ (int)(sun->sun_len - (sizeof(*sun) - sizeof(sun->sun_path))), >+ >+Property changes on: sysutils/py-psutil/files/patch-ino64 >+___________________________________________________________________ >+Added: fbsd:nokeywords >+## -0,0 +1 ## >++yes >+\ No newline at end of property >+Added: svn:eol-style >+## -0,0 +1 ## >++native >+\ No newline at end of property >+Added: svn:mime-type >+## -0,0 +1 ## >++text/plain >+\ No newline at end of property >diff --git a/preapply.sh b/preapply.sh >new file mode 100644 >index 00000000000..6ab69c31c6d >--- /dev/null >+++ b/preapply.sh >@@ -0,0 +1,43 @@ >+#!/bin/sh >+if [ x"$INO64GIT" = x ]; then >+ echo "set INO64GIT env var to point to the git mirror of ino64" >+ exit 1 >+fi >+xxx=$(svn st 2>&1) >+if [ x"$xxx" \!= x ]; then >+ echo "working directory is not clean, check with svn status" >+ exit 1 >+fi >+set -e >+svn cp include/fts.h lib/libc/gen/fts-compat11.h >+rm lib/libc/gen/fts-compat11.h >+svn cp include/glob.h lib/libc/gen/glob-compat11.h >+rm lib/libc/gen/glob-compat11.h >+svn cp lib/libc/gen/fts.c lib/libc/gen/fts-compat11.c >+rm lib/libc/gen/fts-compat11.c >+svn cp lib/libc/gen/ftw.c lib/libc/gen/ftw-compat11.c >+rm lib/libc/gen/ftw-compat11.c >+svn cp lib/libc/gen/nftw.c lib/libc/gen/nftw-compat11.c >+rm lib/libc/gen/nftw-compat11.c >+svn cp lib/libc/gen/glob.c lib/libc/gen/glob-compat11.c >+rm lib/libc/gen/glob-compat11.c >+svn cp lib/libc/gen/getmntinfo.c lib/libc/gen/getmntinfo-compat11.c >+rm lib/libc/gen/getmntinfo-compat11.c >+svn cp lib/libc/gen/readdir.c lib/libc/gen/readdir-compat11.c >+rm lib/libc/gen/readdir-compat11.c >+svn cp lib/libc/gen/scandir.c lib/libc/gen/scandir-compat11.c >+rm lib/libc/gen/scandir-compat11.c >+(cd $INO64GIT && git diff origin/master ino64) | gpatch -p1 >+add_files="lib/libc/sys/getdents.c lib/libc/sys/lstat.c" >+add_files="$add_files lib/libc/sys/mknod.c lib/libc/sys/stat.c" >+add_files="$add_files lib/libc/gen/gen-compat.h lib/libc/gen/devname-compat11.c" >+add_files="$add_files lib/libprocstat/libprocstat_compat.c" >+svn add $add_files >+svn propset svn:keywords 'FreeBSD=%H' $add_files >+rm -f TODO.ino64 preapply.sh abi.sh ports.patch >+xxx=$(svn st | awk '$1 ~ /^\?$/ {print $2}') >+if [ x"$xxx" \!= x ]; then >+ echo "unmanaged files were found after patching, check" >+ exit 1 >+fi >+echo "Looks good" >diff --git a/sbin/badsect/badsect.c b/sbin/badsect/badsect.c >index f9d2a1afe72..097e3b112f6 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 f0c6524e3ff..72bf83cdb2f 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 06c72b2af72..549eef2c70b 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 19dfc56705c..01b7d850a3b 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 af9622af314..57edb5e4e83 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 d273f8a0fce..81ea4fa3a97 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 e14ff2db637..a955c93ae38 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 39213aec94d..05447da3696 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 a8e69b731fe..8d338572dd7 100644 >--- a/sys/compat/freebsd32/freebsd32_misc.c >+++ b/sys/compat/freebsd32/freebsd32_misc.c >@@ -123,7 +123,8 @@ CTASSERT(sizeof(struct kevent32) == 20); > CTASSERT(sizeof(struct iovec32) == 8); > CTASSERT(sizeof(struct msghdr32) == 28); > #ifndef __mips__ >-CTASSERT(sizeof(struct stat32) == 96); >+CTASSERT(sizeof(struct stat32) == 208); >+CTASSERT(sizeof(struct freebsd11_stat32) == 96); > #endif > CTASSERT(sizeof(struct sigaction32) == 24); > >@@ -448,6 +449,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 +1540,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 +1764,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 +1798,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 +1864,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 ac624e4f7df..fce75fe3488 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 6480fc823a5..380269140d0 100644 >--- a/sys/compat/linux/linux_file.c >+++ b/sys/compat/linux/linux_file.c >@@ -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 1c02660bec1..84260182265 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 e600ff1cea4..695d3315cca 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 49435608e2d..18b962eadff 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 65b8a54657b..885cc35b038 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 3e23d772999..d010830a904 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 0bdd26b1f8c..67849e1543d 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 c5c6592b84c..c93ab0865b9 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 fae2551e123..e00c25130b0 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 b0fd83e086b..e6380238d1e 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 97fb88144b8..b7c1b76c320 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 622a6a49ea1..c13baa5d389 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 bb54f9d8acb..4b9b32c151b 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. > */ >@@ -1347,21 +1364,30 @@ kern_fstat(struct thread *td, int fd, struct stat *sbp) > if (error == 0 && KTRPOINT(td, KTR_STRUCT)) > ktrstat(sbp); > #endif >+#ifdef __STAT_TIME_T_EXT >+ if (error == 0) { >+ sb.st_atim_ext = 0; >+ sb.st_mtim_ext = 0; >+ sb.st_ctim_ext = 0; >+ sb.st_btim_ext = 0; >+ } >+#endif > 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 9b4ed9d88a0..c029567b6c4 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 f220554ab04..7ea37de6e53 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 441a628b7f7..a30260bfeeb 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 999da9c884c..ad0fdb27545 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 b0a535cb67e..63e195945d8 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 a4c3dbb3cc2..b9a888c5a12 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 7bb9e378576..dc2bd93387d 100644 >--- a/sys/kern/vfs_syscalls.c >+++ b/sys/kern/vfs_syscalls.c >@@ -550,7 +550,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 { >@@ -573,7 +573,7 @@ freebsd4_statfs(td, 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); >@@ -604,7 +604,7 @@ freebsd4_fstatfs(td, 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); >@@ -643,11 +643,12 @@ freebsd4_getfsstat(td, 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++; >@@ -686,7 +687,7 @@ freebsd4_fhstatfs(td, 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); >@@ -697,7 +698,7 @@ freebsd4_fhstatfs(td, uap) > * Convert a new format statfs structure to an old format statfs structure. > */ > static void >-cvtstatfs(nsp, osp) >+freebsd4_cvtstatfs(nsp, osp) > struct statfs *nsp; > struct ostatfs *osp; > { >@@ -728,6 +729,139 @@ cvtstatfs(nsp, 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(nsp, osp) >+ 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. > */ >@@ -1133,45 +1267,44 @@ ocreat(td, 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(td, uap) >- struct thread *td; >- register struct mknod_args /* { >- char *path; >- int mode; >- int dev; >- } */ *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; >@@ -2090,33 +2223,104 @@ cvtstat(st, 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(td, uap) >- struct thread *td; >- register struct stat_args /* { >- char *path; >- struct stat *ub; >- } */ *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; >@@ -2169,6 +2373,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)) >@@ -2177,43 +2387,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(td, uap) >- struct thread *td; >- register struct lstat_args /* { >- char *path; >- struct stat *ub; >- } */ *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(sb, nsb) >- 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; >@@ -2233,15 +2415,15 @@ cvtnstat(sb, nsb) > } > > #ifndef _SYS_SYSPROTO_H_ >-struct nstat_args { >+struct freebsd11_nstat_args { > char *path; > struct nstat *ub; > }; > #endif > int >-sys_nstat(td, uap) >+freebsd11_nstat(td, uap) > struct thread *td; >- register struct nstat_args /* { >+ register struct freebsd11_nstat_args /* { > char *path; > struct nstat *ub; > } */ *uap; >@@ -2254,7 +2436,7 @@ sys_nstat(td, uap) > &sb, NULL); > if (error != 0) > return (error); >- cvtnstat(&sb, &nsb); >+ freebsd11_cvtnstat(&sb, &nsb); > return (copyout(&nsb, uap->ub, sizeof (nsb))); > } > >@@ -2262,15 +2444,15 @@ sys_nstat(td, 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; > }; > #endif > int >-sys_nlstat(td, uap) >+freebsd11_nlstat(td, uap) > struct thread *td; >- register struct nlstat_args /* { >+ register struct freebsd11_nlstat_args /* { > char *path; > struct nstat *ub; > } */ *uap; >@@ -2283,9 +2465,10 @@ sys_nlstat(td, 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. >@@ -3751,7 +3934,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) - 1) >+ 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. > */ >@@ -3779,138 +4042,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; >@@ -3918,37 +4069,61 @@ struct getdirentries_args { > }; > #endif > int >-sys_getdirentries(td, uap) >- struct thread *td; >- register struct getdirentries_args /* { >- int fd; >- char *buf; >- u_int count; >- long *basep; >- } */ *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; > >@@ -4015,31 +4190,6 @@ fail: > return (error); > } > >-#ifndef _SYS_SYSPROTO_H_ >-struct getdents_args { >- int fd; >- char *buf; >- size_t count; >-}; >-#endif >-int >-sys_getdents(td, uap) >- struct thread *td; >- register struct getdents_args /* { >- int fd; >- char *buf; >- u_int count; >- } */ *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 1329dc32fa0..ebab59004bd 100644 >--- a/sys/kern/vfs_vnops.c >+++ b/sys/kern/vfs_vnops.c >@@ -2354,7 +2354,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); >@@ -2383,10 +2383,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 d6ccd2f8ef0..10b41ab0acf 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 64afa87bc45..3d99635f7de 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 8736651ba6f..1dd7c7df4cf 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 759fdc6e0aa..9bf6800a4eb 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,10 @@ 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; > 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 +84,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 +127,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 ed3f6f5c774..341855d0530 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. Also, retaining this >+ * padding on ILP32 architectures simplifies the 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 */ >+ __uint32_t d_pad0; > #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 9800d97df27..519b4cf94f5 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/stat.h b/sys/sys/stat.h >index 6af909aea7c..95a42b24716 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 d4cfa26045e..c994ee94f82 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 09e04195ae5..c37d0bf3d07 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 ab9cee5c8b9..ba5e43a7415 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 b688bfd143d..8bfe851c55e 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 76b69e5053e..2a73acaad66 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 022fbd57c88..a751ac6ea2f 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 c4d72237fd4..8ca83bf18dd 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/testing.txt b/testing.txt >new file mode 100644 >index 00000000000..f769e22a528 >--- /dev/null >+++ b/testing.txt >@@ -0,0 +1,236 @@ >+To: freebsd-current, freebsd-fs, freebsd-ports >+Subject: 64-bit inodes (ino64) Status Update and Call for Testing >+ >+Inodes are data structures corresponding to objects in a file system, >+such as files and directories. FreeBSD has historically used 32-bit >+values to identify inodes, which limits file systems to somewhat under >+2^32 objects. Many modern file systems internally use 64-bit identifiers >+and FreeBSD needs to follow suit to properly and fully support these >+file systems. >+ >+The 64-bit inode project, also known as ino64, started life many years >+ago as a project by Gleb Kurtsou (gleb@). After that time several >+people have had a hand in updating it and addressing regressions, after >+mckusick@ picked up and updated the patch, and acted as a flag-waver. >+ >+Sponsored by the FreeBSD Foundation I have spent a significant effort >+on outstanding issues and integration -- fixing compat32 ABI, NFS and >+ZFS, addressing ABI compat issues and investigating and fixing ports >+failures. rmacklem@ provided feedback on NFS changes, emaste@ and >+jhb@ provided feedback and review on the ABI transition support. pho@ >+performed extensive testing and identified a number of issues that >+have now been fixed. kris@ performed an initial ports investigation >+followed by an exp-run by antoine@. emaste@ helped with organization >+of the process. >+ >+This note explains how to perform useful testing of the ino64 branch, >+beyond typical smoke tests. >+ >+1. Overview. >+ >+The ino64 branch extends the basic system types ino_t and dev_t from >+32-bit to 64-bit, and nlink_t from 16-bit to 64-bit. The struct dirent >+layout is modified due to the larger size of ino_t, and also gains a >+d_off (directory offset) member. As ino64 implies an ABI change anyway >+the struct statfs f_mntfromname[] and f_mntonname[] array length >+MNAMELEN is increased from 88 to 1024, to allow for longer mount path >+names. >+ >+ABI breakage is mitigated by providing compatibility using versioned >+symbols, ingenious use of the existing padding in structures, and by >+employing other tricks. Unfortunately, not everything can be fixed, >+especially outside the base system. For instance, third-party APIs >+which pass struct stat around are broken in backward and forward- >+incompatible way. >+ >+2. Motivation. >+ >+The main risk of the ino64 change is the uncontrolled ABI breakage. >+Due to expansion of the basic types dev_t, ino_t and struct dirent, >+the impact is not limited to one part of the system, but affects: >+- kernel/userspace interface (syscalls ABI, mostly stat(2), kinfo >+ and more) >+- libc interface (mostly related to the readdir(3), FTS(3)) >+- collateral damage in other libraries that happens to use changed types >+ in the interfaces. See, for instance, libprocstat, for which compat >+ was provided using symbol versioning, and libutil, which shlib version >+ was bumped. >+ >+3. Quirks. >+ >+We handled kinfo sysctl MIBs, but there is no general mechanism to >+handle other sysctl MIBS which return structures where the layout has >+changed. It was considered that the breakage is either in the management >+interfaces, where we usually allow ABI slip, or is not important. >+ >+Struct xvnode changed layout, no compat shims are provided. >+ >+For struct xtty, dev_t tty device member was reduced to uint32_t. It >+was decided that keeping ABI compat in this case is more useful than >+reporting 64bit dev_t, for the sake of pstat. >+ >+4. Testing procedure. >+ >+The ino64 project can be tested by cloning the project branch from >+GitHub or by applying the patch <from the Phabricator review | located >+at URL | attached> to a working tree. The authorative source is the >+GitHub, I do not promise to update the review for each update. >+ >+To clone from GitHub: >+% git clone -b ino64 https://github.com/FreeBSDFoundation/freebsd.git ino64 >+ >+To fetch the patch from Phabricator: >+- Visit https://reviews.freebsd.org/D10439 >+- Click "Download Raw Diff" at the upper right of the page >+ >+Or >+% arc patch D10439 >+ >+After that, in the checkout directory do >+% (cd sys/kern && touch syscalls.master && make sysent) >+% (cd sys/compat/freebsd32 && touch syscalls.master && make sysent) >+If you use custom kernel configuration, ensure that >+ options COMPAT_FREEBSD11 >+is included into the config. Then build world and kernel in the >+usual way, install kernel, reboot, install new world. Do not make >+shortcuts in the update procedure. >+ >+4.1 New kernel, old world. >+ >+Build and install pristine HEAD world, apply patch and only build and >+install updated kernel. The system must work same as with the pristine >+kernel. >+ >+4.2 New kernel, new world, old third-party applications. >+ >+Build and install patched kernel and world. Applications compiled on the >+pristine HEAD (e.g. installed by pkg from the regular portmgr builds) must >+work without a regression. >+ >+4.3 32bit compat. >+ >+Same as 4.1 and 4.2, but for 32bit (i386) binaries on the amd64 host. >+Note that big-endian host, like powerpc, might expose additional >+bugs in the 32bit compat with the patch, but the testing is too cumbersome >+to arrange. >+ >+4.4 Targeted tests. >+ >+Useful programs to check items 4.1, 4.2 and 4.3 are versions of the >+following programs, taken from the pristine system: >+ >+ stat(8). Use it on regular file, file in /dev, socket, pipe and so >+ on. For both native and 32bit compat, stat(8) must print reasonable >+ information. >+ >+ procstat(1). Use it with the -f option to examine processes files. >+ kinfo(9) data must be returned in the format acceptable for older >+ apps. >+ >+ Use pristine find(1) binary with many arbitrary options on a system with >+ installed patched world, in particular, libc. Find examines FTS(3), >+ and compat shims in libc are non-trivial. >+ >+4.5 NFS server and client test. >+ >+Check that the NFS server in the patched kernel operates correctly and without >+performance regressions. Same for client. >+NFS should be checked for all four combination of patched/unpatched >+kernel server/client, because the filehandle format includes inode number. >+ >+4.6 Other filesystems >+ >+Generally, filesystems should see no change in the system behaviour, >+since patch goal is to provide space to grow in the ABI. In >+particular, local filesystem layout must stay same. Of course, it is >+possible that some reliance on the exact sizes of the changed types >+was left unnoticed during the patch review, in which case e.g. on-disk >+format would be broken. We do not expect this to slip in, but it is >+possible and should be watched for. >+ >+4.7 Test accounting >+ >+The process accounting, as documented in acct(5), changed format of >+the records due to dev_t increase. Verify that the programs like >+sa(8) and accton(8) correctly work with both old and new accounting >+records. >+ >+5. Ports Status with ino64 >+ >+A ports exp-run for ino64 is open in PR 218320. The failing ports each >+responsible for more than 1 skipped port are: >+ >+lang/ghc 497 >+multimedia/webcamd 62 >+lang/gcc6-aux 54 >+devel/libgtop 39 >+sysutils/py-psutil 13 >+devel/llvm38 6 >+lang/rust 4 >+sysutils/py-psutil121 3 >+ >+Patches are available for lang/llvm39, lang/llvm40, lang/ghc, and >+lang/rust in the topic branch as ports.patch, and llvm38 can be fixed >+in the same way as llvm39 and llvm40. Assistance with investigating >+and fixing the port failures will be greatly appreciated. >+ >+Below is an overview of the problems and proposed solutions, probably >+mostly relevant to the ports maintainers. >+ >+5.1. LLVM >+ >+LLVM includes a component called Address Sanitizer or ASAN, which tries >+to intercept syscalls, and contains knowledge of the layout of many >+system structures. Since stat and lstat syscalls were removed and >+several types and structures changed, this has to be reflected in the >+ASAN hacks. >+ >+5.2. lang/ghc >+ >+The ghc compiler and parts of the runtime are written in Haskell, >+which means that to compile ghc, you need a working Haskell compiler >+for bootstrap. By default for ghc, the runtime is provided in the form >+of static libraries. Static libraries reference default versions of >+libc symbols, which are assigned the ELF symbol version at the final >+linking stage. As result, using such libraries results in using the >+updated syscall, but internally the code still uses old system types. >+The end result is the random memory corruption because both libc and >+kernel assume new types. >+ >+This situation cannot be fixed by symbol versioning, because versioning >+acts too late. Instead, we hacked the bootstrap compiler by providing >+symbols for modified syscalls in the shipped static libraries, which >+symbols direct execution to the compat variants of the syscalls. This >+allows the bootstrap compiler to generate working code. After the >+stage0, compiler operates on new structures and things stabilize. >+ >+The real solution is, of course, to re-package the bootstrap compiler, >+but for some time we need to support pre-ino64 HEAD in ports. Also, >+learning full scope of GHC maintainance duties, required for that, >+is too much for the ino64 task. >+ >+5.3. lang/rust >+ >+Rustc has a similar structure to GHC, and same issue. The same solution >+of patching the bootstrap was done. >+ >+Also rust libstd and liblibc provide rustified definitions of the >+system structures, which were updated to reflect the updated layout. >+I failed to understand why e.g. struct stat has to be defined in 3 >+places at least, but all found locations were patched. >+ >+6. Next Steps >+ >+The tentative schedule for the ino64 project: >+ >+2017-04-20 Post wide call for testing >+ >+ Investigate and address port failures with maintainer support >+ >+2017-05-05 Request second exp-run with initial patches applied >+ >+ Investigate and address port failures with maintainer support >+ >+2017-05-19 Commit to HEAD >+ >+ Address post-commit failures where feasible >diff --git a/usr.bin/kdump/kdump.c b/usr.bin/kdump/kdump.c >index 60898fde877..0432449755b 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 57acfb583bd..e3b9aea5064 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 5de7c5c4c80..0a3e9306e06 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 700323be8fb..ec801822fdb 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 70f97a7ff51..62acf71e263 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 64736ac340c..d8ad5f5a912 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;
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 218320
:
181419
|
181420
| 182332 |
182333
|
182355
|
182641