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);
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to