The history behind the undocumented NetBSD stat syscalls?

Bruce Evans brde at
Mon Feb 14 07:45:02 UTC 2011

On Sun, 13 Feb 2011, Garrett Cooper wrote:

>    I was poking through vfs_syscalls.c and I noticed that there was a
> syscall called nlstat, and nstat, and a kernel-public only helper
> function called cvtnstat:
>    These aren't used anywhere in our source tree (I trimmed out the
> false positives -- i.e. connstat and instat), minus their declarations
> in kern/vfs_syscalls.c, etc:

I think these are the "new" stat() syscalls in 4.4BSD.  Ones using struct
ostat are normal "old" stat calls.  But normality is reversed in FreeBSD.
FreeBSD was forced to make a clean break with FreeBSD-1, and from
FreeBSD-2 on it didn't have the the "old" stat calls.  Until someone made
a mess by importing anachronous bits from NetBSD.  Both nstat() and ostat()
might be useful for binary compatibilty with NetBSD, but I think there are 
too many other differences for actual usefulness.

NetBSD in 2005 has even more "old" stat structs and corresponding syscalls.
They are named a little differently:

o struct stat43, for 4.3BSD (Net/2, 386BSD, FreeBSD-1?).

   This is under a _KERNEL ifdef as it should be.  This lets the kernel
   support it but prevents current sources from using it.  The corresponding
   ifdef in FreeBSD is wrong -- it is __BSD_VISIBLE.  So we have the
   silly situation that FreeBSD makes visible old NetBSD interfaces
   that NetBSD doesn't make visible.  FreeBSD does better with its own
   "old" structs, e.g., struct ostatfs.

   struct stat43 seems to be compatible with struct ostat.  These are really
   old.  They have 16-bit uids and gids, which are correctly implemented
   by spelling their types as __uint16_t (except in NetBSD there is namespace
   pollution by spelling this as u_int16_t).  Some of the other fields are
   not so carefully handled (using non-fixed-width typedefs which are not
   binary compatible with the future), so it is hard to see if their types
   are actually the same:
   - st_ino has type ino_t in both
   - FreeBSD uses non-fixed-width types for st_mode, st_nlink and st_flags.

o struct stat12, for NetBSD-1.2.

   This is under __LIBC12 || _KERNEL.  It uses non-fixed-width types more.
   It seems to be compatible with FreeBSD struct stat and struct nstat,
   except FreeBSD has st_birthtime and the end where NetBSD has 2 int64_t
   spares, and none of these struct is careful enough about padding to
   ensure binary compatibility on all possible arches.

o struct stat, for NetBSD (2005).

   This uses more non-fixed-width type but is otherwise more careful about
   padding, using methods that I don't like (it restores the old timespec
   ifdefs, which have longs which cause padding problems...).  This now
   has st_birthtime, so FreeBSD struct stat might be fully compatible with
   it, but the wide use of non-fixed-width types and different padding
   methods make this unclear.  This size of struct timespec is
   arch-dependent, so no one has binary compatibility across arches despite
   most of the typedefs reducing to the same fixed-width types (time_t and
   long within struct timespec are the main or only exceptions; `long' there
   is a historical mistake that was unfortunately standardized).

> $ svngrep -Er 'nl?stat\(' /usr/src/
> /usr/src/sys/kern/kern_descrip.c:		cvtnstat(&ub, &nub);
> /usr/src/sys/kern/syscalls.master:278	AUE_STAT	STD	{ int nstat(char
> *path, struct nstat *ub); }
> /usr/src/sys/kern/syscalls.master:280	AUE_LSTAT	STD	{ int nlstat(char
> *path, struct nstat *ub); }

Since they are in syscalls.master...

> /usr/src/sys/kern/vfs_syscalls.c:cvtnstat(sb, nsb)
> /usr/src/sys/kern/vfs_syscalls.c:nstat(td, uap)
> /usr/src/sys/kern/vfs_syscalls.c:	cvtnstat(&sb, &nsb);
> /usr/src/sys/kern/vfs_syscalls.c:nlstat(td, uap)
> /usr/src/sys/kern/vfs_syscalls.c:	cvtnstat(&sb, &nsb);

...and not under any COMPAT* ifdef in vfs_syscalls.c (?), they can be
used by any binary that wants to use them.

>    And seems like it should be superseded by lstat, et all, which
> were introduced a little earlier on [1].
>    Do they serve a real purpose of some kind today? It was introduced
> in the revision seen in SVN here [2], and looking back in time there
> isn't reference to a NetBSD compat layer in sys/conf/options [3], etc,
> so I was a bit curious why there are dangling undocumented (but
> publicly visible via sysproto.h) VFS-related syscalls entries hanging
> around (in particular because the syscalls aren't declared that way in
> NetBSD either).

sysproto.h isn't public (it is kernel-only).  The only publication errors
seem to be the declarations in sys/stat.h discussed above, and the SYS_*
entries in sys/syscall.h (old syscalls are supposed to by marked up in
syscalls.master so that they don't escape).  SYS_nstat is 278, which is
for __stat13 in NetBSD, so it has a chance of working.  SYS_ostat is 38
(except it is intentionally not defined in syscall.h, which is for
compat_43_stat43 in NetBSD, so it too has a chance of working.  Ordinary
SYS_stat is 188 in FreeBSD, but in NetBSD #188 is compat_12_stat12.  These
seem to differe mainly in support for st_birthtime.  FreeBSD didn't change
the syscall for st_birthtime, but this shouldn't cause problems since
stat() is read-only so there is no problem with callers passing garbage
in st_birthtime.


More information about the freebsd-fs mailing list