svn commit: r319734 - in head/sys: compat/freebsd32 kern

Konstantin Belousov kib at FreeBSD.org
Fri Jun 9 11:17:09 UTC 2017


Author: kib
Date: Fri Jun  9 11:17:08 2017
New Revision: 319734
URL: https://svnweb.freebsd.org/changeset/base/319734

Log:
  Enhance vfs.ino64_trunc_error sysctl.
  
  Provide a new mode "2" which returns a special overflow indicator in
  the non-representable field instead of the silent truncation (mode
  "0") or EOVERFLOW (mode "1").
  
  In particular, the typical use of st_ino to detect hard links with
  mode "2" reports false positives, which might be more suitable for
  some uses.
  
  Discussed with:	bde
  Sponsored by:	The FreeBSD Foundation

Modified:
  head/sys/compat/freebsd32/freebsd32_misc.c
  head/sys/kern/vfs_syscalls.c

Modified: head/sys/compat/freebsd32/freebsd32_misc.c
==============================================================================
--- head/sys/compat/freebsd32/freebsd32_misc.c	Fri Jun  9 07:08:58 2017	(r319733)
+++ head/sys/compat/freebsd32/freebsd32_misc.c	Fri Jun  9 11:17:08 2017	(r319734)
@@ -1911,11 +1911,31 @@ freebsd11_cvtstat32(struct stat *in, struct freebsd11_
 {
 
 	CP(*in, *out, st_ino);
-	if (in->st_ino != out->st_ino && ino64_trunc_error)
-		return (EOVERFLOW);
+	if (in->st_ino != out->st_ino) {
+		switch (ino64_trunc_error) {
+		default:
+		case 0:
+			break;
+		case 1:
+			return (EOVERFLOW);
+		case 2:
+			out->st_ino = UINT32_MAX;
+			break;
+		}
+	}
 	CP(*in, *out, st_nlink);
-	if (in->st_nlink != out->st_nlink && ino64_trunc_error)
-		return (EOVERFLOW);
+	if (in->st_nlink != out->st_nlink) {
+		switch (ino64_trunc_error) {
+		default:
+		case 0:
+			break;
+		case 1:
+			return (EOVERFLOW);
+		case 2:
+			out->st_nlink = UINT16_MAX;
+			break;
+		}
+	}
 	CP(*in, *out, st_dev);
 	CP(*in, *out, st_mode);
 	CP(*in, *out, st_uid);

Modified: head/sys/kern/vfs_syscalls.c
==============================================================================
--- head/sys/kern/vfs_syscalls.c	Fri Jun  9 07:08:58 2017	(r319733)
+++ head/sys/kern/vfs_syscalls.c	Fri Jun  9 11:17:08 2017	(r319734)
@@ -2117,12 +2117,32 @@ freebsd11_cvtstat(struct stat *st, struct freebsd11_st
 
 	ost->st_dev = st->st_dev;
 	ost->st_ino = st->st_ino;
-	if (ost->st_ino != st->st_ino && ino64_trunc_error)
-		return (EOVERFLOW);
+	if (ost->st_ino != st->st_ino) {
+		switch (ino64_trunc_error) {
+		default:
+		case 0:
+			break;
+		case 1:
+			return (EOVERFLOW);
+		case 2:
+			ost->st_ino = UINT32_MAX;
+			break;
+		}
+	}
 	ost->st_mode = st->st_mode;
 	ost->st_nlink = st->st_nlink;
-	if (ost->st_nlink != st->st_nlink && ino64_trunc_error)
-		return (EOVERFLOW);
+	if (ost->st_nlink != st->st_nlink) {
+		switch (ino64_trunc_error) {
+		default:
+		case 0:
+			break;
+		case 1:
+			return (EOVERFLOW);
+		case 2:
+			ost->st_nlink = UINT16_MAX;
+			break;
+		}
+	}
 	ost->st_uid = st->st_uid;
 	ost->st_gid = st->st_gid;
 	ost->st_rdev = st->st_rdev;
@@ -3751,8 +3771,19 @@ freebsd11_kern_getdirentries(struct thread *td, int fd
 		dstdp.d_type = dp->d_type;
 		dstdp.d_namlen = dp->d_namlen;
 		dstdp.d_fileno = dp->d_fileno;		/* truncate */
-		if (dstdp.d_fileno != dp->d_fileno && ino64_trunc_error)
-			continue;
+		if (dstdp.d_fileno != dp->d_fileno) {
+			switch (ino64_trunc_error) {
+			default:
+			case 0:
+				break;
+			case 1:
+				error = EOVERFLOW;
+				goto done;
+			case 2:
+				dstdp.d_fileno = UINT32_MAX;
+				break;
+			}
+		}
 		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);


More information about the svn-src-all mailing list