Blob Blame History Raw
diff --git a/COPYING b/COPYING
index 602bfc9..b23d6b6 100644
--- a/COPYING
+++ b/COPYING
@@ -457,48 +457,10 @@ DAMAGES.
 
 		     END OF TERMS AND CONDITIONS
 
-           How to Apply These Terms to Your New Libraries
-
-  If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change.  You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of the
-ordinary General Public License).
-
-  To apply these terms, attach the following notices to the library.  It is
-safest to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
-
-    <one line to give the library's name and a brief idea of what it does.>
-    Copyright (C) <year>  <name of author>
-
-    This library is free software; you can redistribute it and/or
-    modify it under the terms of the GNU Lesser General Public
-    License as published by the Free Software Foundation; either
-    version 2.1 of the License, or (at your option) any later version.
-
-    This library is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-    Lesser General Public License for more details.
-
-    You should have received a copy of the GNU Lesser General Public
-    License along with this library; if not, write to the Free Software
-    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
-
-Also add information on how to contact you by electronic and paper mail.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the library, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the
-  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
-
-  <signature of Ty Coon>, 1 April 1990
-  Ty Coon, President of Vice
-
-That's all there is to it!
+Note:
+Individual files contain the following tag instead of the full license text.
 
+    SPDX-License-Identifier: LGPL-2.1-only
 
+This enables machine processing of license information based on the SPDX
+License Identifiers that are here available: http://spdx.org/licenses/
diff --git a/ChangeLog.txt b/ChangeLog.txt
index 84c5d5a..f681596 100644
--- a/ChangeLog.txt
+++ b/ChangeLog.txt
@@ -1,3 +1,110 @@
+2019-08-02:
+	* (seebs) Pass flags & O_NOFOLLOW, also use that to influence
+	  stat types. Note. &. Not |.
+
+2019-08-01:
+	* (seebs) Pass flags|O_NOFOLLOW on when resolving paths with openat.
+
+2019-05-15:
+	* (RP) Add SDPX license headers to source files.
+
+2019-04-10:
+	* (seebs) Experimental workaround for special non-blocking open
+	  case.
+	* (seebs) fix warnings in renameat2.
+
+2019-04-09:
+	* (seebs) Partial fix for db corruption issue.
+	* (seebs) Make a glibc renameat2 wrapper that just fails because
+	  implementing renameat2 semantics is Surprisingly Hard.
+
+2018-12-15:
+	* (seebs) Import IPC patch from Rasmus Villemoes.
+	* (seebs) Import (another) IPC patch from Rasmus Villemoes.
+
+2018-11-29:
+	* (seebs) add missing <stdint.h> to pseudo_db.c. Thanks to
+	  Bernhard Hartleb <bernhard.hartleb@gmail.com> for pointing
+	  this out.
+
+2018-09-20:
+	* (seebs) coerce inodes to signed int64_t range when shoving
+	  them into sqlite.
+	* (seebs) add another /*fallthrough*/ comment to make gcc7 happy.
+	* (seebs) also make sure inodes are handled as 64-bit, not
+	  32-bit, which probably matters more. Thanks to <Jack.Fewx@dell.com>
+	  for catching this.
+
+2018-04-13:
+	* (seebs) Reduce spamminess of path mismatches.
+	  Don't log path mismatches with multiple links unless you've
+	  requested path+verbose debugging. Also allow pseudo_debug
+	  to take a 0 to indicate "always debug", because we want that
+	  message unconditionally, and I don't want near-identical
+	  calls to diag() and debug().
+	* (seebs) Fix a lurking stray slash that could happen while
+	  resolving absolute symlinks.
+	* (seebs) fix mishandled flags for symlink following.
+
+2018-04-02:
+	* (seebs) Change default copyright notice in guts to
+	  say "Peter Seebach" rather than "Wind River" as I haven't
+	  worked there in over a year.
+
+2018-03-31:
+	* (seebs) keep pseudo_fix_path from changing errno, because
+	  *some* people think they should check errno to find out
+	  whether an error occurred, even if no call has returned
+	  a status indicating an error, and this is completely wrong
+	  but we can't fix them all.
+	* (seebs) check for wrapper initialization in syscall wrapper,
+	  because what if it was the *first* call someone made. (Thanks
+	  to Joshua Watt <jpewhacker@gmail.com> for diagnosing this
+	  before I got a chance.)
+
+2018-03-30:
+	* (seebs) fix path stuff more thoroughly.
+	* (seebs) Merge suggested README change from Richard Tollerton
+	  <rich.tollerton@ni.com> pointing to oe-core list.
+	* (seebs) Merge suggested setuid/etc bit change from
+	  Richard Tollerton, and associated test case.
+
+2018-03-29:
+	* (seebs) wrap syscall, and if SYS_renameat2 exists, try to
+	  reject it with ENOSYS, because coreutils started using a
+	  new syscall. An actual renameat2 wrapper will be a major
+	  effort ("changing the pseudo_ipc data structure") and is
+	  pointless when glibc hasn't got a wrapper so we have no
+	  viable test cases.
+
+2018-03-06:
+	* (seebs) Update path handling a bit to correctly fail if a path
+	  tries to have a slash after a plain file name, even in cases
+	  like "foo/.", which were previously ignored (or in the case of
+	  "..", resolved as though it had been a directory).
+
+2018-03-01:
+	* (seebs) If you get a CREAT for an existing file, and it matches
+	  both path and inode, don't delete the entry because the inode
+	  matched and then not create it because the path used to match
+	  before you delete it.
+
+2018-02-26:
+	* (seebs) implement mkstemps, mkostemp, and mkostemps. Actually,
+	  move implementation all to mkostemps, then implement the others
+	  in terms of it.
+
+2018-02-19:
+	* (seebs) fix using index of request rather than request's value
+
+2018-02-16:
+	* (seebs) allow closing client #0.
+
+2018-02-15:
+	* (seebs) O_TMPFILE is actually some other flag AND O_DIRECTORYy,
+	  so a test for (flags & O_TMPFILE) does not actually test that
+	  O_TMPFILE is set.
+
 2018-01-20:
 	* (seebs) merge patch from <joshua.g.lock@linux.intel.com> to fix
 	  open/openat flags.
diff --git a/Makefile.in b/Makefile.in
index ad6541b..b43d2d6 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -3,18 +3,7 @@
 #
 # Copyright (c) 2008-2015 Wind River Systems, Inc.
 #
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the Lesser GNU General Public License version 2.1 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the Lesser GNU General Public License for more details.
-#
-# You should have received a copy of the Lesser GNU General Public License
-# version 2.1 along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
+# SPDX-License-Identifier: LGPL-2.1-only
 #
 
 # configuration flags
diff --git a/README b/README
index afe6b27..468cf66 100644
--- a/README
+++ b/README
@@ -85,3 +85,10 @@ consistent support of the whole group for the project.  It's been a great
 deal of fun, and I'm pretty happy that we're finally ready to make it
 available for other people to look at.
 
+
+CONTACT:
+
+Discussions and patches should be directed at the openembedded-core mailing
+list at openembedded-core at lists.openembedded.org. More information at
+https://www.openembedded.org/wiki/Mailing_lists. Bugs should be filed with
+the Yocto project at https://bugzilla.yoctoproject.org/.
diff --git a/configure b/configure
index d7980d7..39b5fbe 100755
--- a/configure
+++ b/configure
@@ -4,18 +4,7 @@
 #
 # Copyright (c) 2008-2014 Wind River Systems, Inc.
 #
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the Lesser GNU General Public License version 2.1 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the Lesser GNU General Public License for more details.
-#
-# You should have received a copy of the Lesser GNU General Public License
-# version 2.1 along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
+# SPDX-License-Identifier: LGPL-2.1-only
 #
 # not a real configure script...
 opt_prefix=
diff --git a/guts/COPYRIGHT b/guts/COPYRIGHT
index 06188b2..1b478d1 100644
--- a/guts/COPYRIGHT
+++ b/guts/COPYRIGHT
@@ -1,17 +1,6 @@
 /*
  * Copyright (c) 2008-2014 Wind River Systems, Inc.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the Lesser GNU General Public License version 2.1 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the Lesser GNU General Public License for more details.
- *
- * You should have received a copy of the Lesser GNU General Public License
- * version 2.1 along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
+ * SPDX-License-Identifier: LGPL-2.1-only
  *
  */
diff --git a/maketables b/maketables
index f74f2b1..a211772 100755
--- a/maketables
+++ b/maketables
@@ -2,18 +2,7 @@
 #
 # Copyright (c) 2008-2010, 2013 Wind River Systems, Inc.
 #
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the Lesser GNU General Public License version 2.1 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the Lesser GNU General Public License for more details.
-#
-# You should have received a copy of the Lesser GNU General Public License
-# version 2.1 along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
+# SPDX-License-Identifier: LGPL-2.1-only
 #
 """convert tables.in files to enums, tables, and support code.
 
diff --git a/makewrappers b/makewrappers
index ff08ba0..e84607d 100755
--- a/makewrappers
+++ b/makewrappers
@@ -2,18 +2,7 @@
 #
 # Copyright (c) 2008-2011,2013 Wind River Systems, Inc.
 #
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the Lesser GNU General Public License version 2.1 as
-# published by the Free Software Foundation.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-# See the Lesser GNU General Public License for more details.
-#
-# You should have received a copy of the Lesser GNU General Public License
-# version 2.1 along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
+# SPDX-License-Identifier: LGPL-2.1-only
 #
 """convert wrapfuncs.in to wrapper function stubs and tables"""
 
@@ -275,7 +264,7 @@ class Function:
                     self.specific_dirfds[arg.name[:-5]] = True
                 self.dirfd = 'dirfd'
             elif arg.name == 'flags':
-                self.flags = 'flags'
+                self.flags = '(flags & AT_SYMLINK_NOFOLLOW)'
             elif arg.name.endswith('path'):
                 self.paths_to_munge.append(arg.name)
     
diff --git a/offsets.c b/offsets.c
index 5e9cddd..b77c7fd 100644
--- a/offsets.c
+++ b/offsets.c
@@ -3,18 +3,7 @@
  *
  * Copyright (c) 2008-2010 Wind River Systems, Inc.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the Lesser GNU General Public License version 2.1 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the Lesser GNU General Public License for more details.
- *
- * You should have received a copy of the Lesser GNU General Public License
- * version 2.1 along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
+ * SPDX-License-Identifier: LGPL-2.1-only
  *
  */
 #ifndef _LARGEFILE64_SOURCE
diff --git a/perftest b/perftest
index 97dced1..2fe0e53 100755
--- a/perftest
+++ b/perftest
@@ -1,4 +1,8 @@
 #!/bin/sh
+#
+# SPDX-License-Identifier: LGPL-2.1-only
+#
+
 # do a quick performance test of pseudo
 opt_f=false
 flag_f=
diff --git a/ports/common/guts/execl.c b/ports/common/guts/execl.c
index be86b49..21a18cc 100644
--- a/ports/common/guts/execl.c
+++ b/ports/common/guts/execl.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2011 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int execl(const char *file, const char *arg, va_list ap)
  *	int rc = -1;
  */
diff --git a/ports/common/guts/execle.c b/ports/common/guts/execle.c
index a3bc3ca..0b15e91 100644
--- a/ports/common/guts/execle.c
+++ b/ports/common/guts/execle.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2011 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int execle(const char *file, const char *arg, va_list ap)
  *	int rc = -1;
  */
diff --git a/ports/common/guts/execlp.c b/ports/common/guts/execlp.c
index 3cf2889..93f85d0 100644
--- a/ports/common/guts/execlp.c
+++ b/ports/common/guts/execlp.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2011 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int execlp(const char *file, const char *arg, va_list ap)
  *	int rc = -1;
  */
diff --git a/ports/common/guts/execv.c b/ports/common/guts/execv.c
index c071626..7819911 100644
--- a/ports/common/guts/execv.c
+++ b/ports/common/guts/execv.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_execv(const char *file, char *const *argv) {
  *	int rc = -1;
diff --git a/ports/common/guts/execve.c b/ports/common/guts/execve.c
index 24cc177..1144f7c 100644
--- a/ports/common/guts/execve.c
+++ b/ports/common/guts/execve.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_execve(const char *file, char *const *argv, char *const *envp) {
  *	int rc = -1;
diff --git a/ports/common/guts/execvp.c b/ports/common/guts/execvp.c
index e6bf09f..acc9fdc 100644
--- a/ports/common/guts/execvp.c
+++ b/ports/common/guts/execvp.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_execvp(const char *file, char *const *argv) {
  *	int rc = -1;
diff --git a/ports/common/guts/fork.c b/ports/common/guts/fork.c
index bebe3b0..4f5f4e4 100644
--- a/ports/common/guts/fork.c
+++ b/ports/common/guts/fork.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_fork(void) {
  *	int rc = -1;
diff --git a/ports/common/pseudo_wrappers.c b/ports/common/pseudo_wrappers.c
index 81be635..92dfaa8 100644
--- a/ports/common/pseudo_wrappers.c
+++ b/ports/common/pseudo_wrappers.c
@@ -1,3 +1,8 @@
+/*
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
 /* these aren't used, but the wrapper table isn't happy unless they
  * exist
  */
diff --git a/ports/common/subports b/ports/common/subports
index e2aac56..4a47252 100755
--- a/ports/common/subports
+++ b/ports/common/subports
@@ -1,4 +1,8 @@
 #!/bin/sh
+#
+# SPDX-License-Identifier: LGPL-2.1-only
+#
+
 case $(uname -s) in
 Linux)	echo "linux";;
 Darwin)	echo "darwin";;
diff --git a/ports/darwin/guts/COPYRIGHT b/ports/darwin/guts/COPYRIGHT
index c96e1b1..b860a36 100644
--- a/ports/darwin/guts/COPYRIGHT
+++ b/ports/darwin/guts/COPYRIGHT
@@ -1,17 +1,6 @@
 /*
  * Copyright (c) 2008-2010 Wind River Systems, Inc.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the Lesser GNU General Public License version 2.1 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the Lesser GNU General Public License for more details.
- *
- * You should have received a copy of the Lesser GNU General Public License
- * version 2.1 along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
+ * SPDX-License-Identifier: LGPL-2.1-only
  *
  */
diff --git a/ports/darwin/guts/fcntl.c b/ports/darwin/guts/fcntl.c
index c0b142b..917d5e2 100644
--- a/ports/darwin/guts/fcntl.c
+++ b/ports/darwin/guts/fcntl.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2011, 2012 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int fcntl(int fd, int cmd, ... { struct flock *lock })
  *	int rc = -1;
  */
diff --git a/ports/darwin/guts/fgetgrent_r.c b/ports/darwin/guts/fgetgrent_r.c
index e760cdd..eec3d3a 100644
--- a/ports/darwin/guts/fgetgrent_r.c
+++ b/ports/darwin/guts/fgetgrent_r.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2011 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int fgetgrent_r(FILE *fp, struct group*gbuf, char *buf, size_t buflen, struct group **gbufp)
  *	int rc = -1;
  */
diff --git a/ports/darwin/guts/fgetpwent_r.c b/ports/darwin/guts/fgetpwent_r.c
index cfea5b8..b935616 100644
--- a/ports/darwin/guts/fgetpwent_r.c
+++ b/ports/darwin/guts/fgetpwent_r.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2011 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int fgetpwent_r(FILE *fp, struct passwd *pbuf, char *buf, size_t buflen, struct passwd **pbufp)
  *	int rc = -1;
  */
diff --git a/ports/darwin/guts/fgetxattr.c b/ports/darwin/guts/fgetxattr.c
index dbb3681..56b09d0 100644
--- a/ports/darwin/guts/fgetxattr.c
+++ b/ports/darwin/guts/fgetxattr.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2014 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * ssize_t fgetxattr(int filedes, const char *name, void *value, size_t size, u_int32_t position, int options)
  *	ssize_t rc = -1;
  */
diff --git a/ports/darwin/guts/flistxattr.c b/ports/darwin/guts/flistxattr.c
index bfaa4e9..de95906 100644
--- a/ports/darwin/guts/flistxattr.c
+++ b/ports/darwin/guts/flistxattr.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2014 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * ssize_t flistxattr(int filedes, char *list, size_t size, int options)
  *	ssize_t rc = -1;
  */
diff --git a/ports/darwin/guts/fremovexattr.c b/ports/darwin/guts/fremovexattr.c
index 4edc38c..125c77c 100644
--- a/ports/darwin/guts/fremovexattr.c
+++ b/ports/darwin/guts/fremovexattr.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2014 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int fremovexattr(int filedes, const char *name, int options)
  *	int rc = -1;
  */
diff --git a/ports/darwin/guts/fsetxattr.c b/ports/darwin/guts/fsetxattr.c
index d707595..8f29ac9 100644
--- a/ports/darwin/guts/fsetxattr.c
+++ b/ports/darwin/guts/fsetxattr.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2014 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int fsetxattr(int filedes, const char *name, const void *value, size_t size, u_int32_t position, int options)
  *	int rc = -1;
  */
diff --git a/ports/darwin/guts/fstat.c b/ports/darwin/guts/fstat.c
index 7695147..12e2233 100644
--- a/ports/darwin/guts/fstat.c
+++ b/ports/darwin/guts/fstat.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2011 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int fstat(int fd, struct stat *buf)
  *	int rc = -1;
  */
diff --git a/ports/darwin/guts/getgrent_r.c b/ports/darwin/guts/getgrent_r.c
index 9d5db5a..ffc4796 100644
--- a/ports/darwin/guts/getgrent_r.c
+++ b/ports/darwin/guts/getgrent_r.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2011 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int getgrent_r(struct group *gbuf, char *buf, size_t buflen, struct group **gbufp)
  *	int rc = -1;
  */
diff --git a/ports/darwin/guts/getgrouplist.c b/ports/darwin/guts/getgrouplist.c
index c5950bd..2988387 100644
--- a/ports/darwin/guts/getgrouplist.c
+++ b/ports/darwin/guts/getgrouplist.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_getgrouplist(const char *name, int basegid, int *groups, int *ngroups) {
  *	int rc = -1;
diff --git a/ports/darwin/guts/getgroups.c b/ports/darwin/guts/getgroups.c
index 3cbeb76..7aba660 100644
--- a/ports/darwin/guts/getgroups.c
+++ b/ports/darwin/guts/getgroups.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_getgroups(int size, gid_t *list) {
  *	int rc = -1;
diff --git a/ports/darwin/guts/getpwent_r.c b/ports/darwin/guts/getpwent_r.c
index 3de41b9..da0f797 100644
--- a/ports/darwin/guts/getpwent_r.c
+++ b/ports/darwin/guts/getpwent_r.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2011 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int getpwent_r(struct passwd *pwbuf, char *buf, size_t buflen, struct passwd **pwbufp)
  *	int rc = -1;
  */
diff --git a/ports/darwin/guts/getxattr.c b/ports/darwin/guts/getxattr.c
index ecef9cf..f67bf2c 100644
--- a/ports/darwin/guts/getxattr.c
+++ b/ports/darwin/guts/getxattr.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2014 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * ssize_t getxattr(const char *path, const char *name, void *value, size_t size, u_int32_t position, int options)
  *	ssize_t rc = -1;
  */
diff --git a/ports/darwin/guts/listxattr.c b/ports/darwin/guts/listxattr.c
index 5a8a7a8..59151b1 100644
--- a/ports/darwin/guts/listxattr.c
+++ b/ports/darwin/guts/listxattr.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2014 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * ssize_t listxattr(const char *path, char *list, size_t size, int options)
  *	ssize_t rc = -1;
  */
diff --git a/ports/darwin/guts/lstat.c b/ports/darwin/guts/lstat.c
index 01e0f30..480dc50 100644
--- a/ports/darwin/guts/lstat.c
+++ b/ports/darwin/guts/lstat.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2011 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int lstat(const char *path, struct stat *buf)
  *	int rc = -1;
  */
diff --git a/ports/darwin/guts/open.c b/ports/darwin/guts/open.c
index 307bcc9..da23316 100644
--- a/ports/darwin/guts/open.c
+++ b/ports/darwin/guts/open.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2011-2013 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int open(const char *path, int flags, ... { int mode })
  *	int rc = -1;
  */
diff --git a/ports/darwin/guts/removexattr.c b/ports/darwin/guts/removexattr.c
index c125b1a..18a1480 100644
--- a/ports/darwin/guts/removexattr.c
+++ b/ports/darwin/guts/removexattr.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2014 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int removexattr(const char *path, const char *name, int options)
  *	int rc = -1;
  */
diff --git a/ports/darwin/guts/scandir.c b/ports/darwin/guts/scandir.c
index 6492b1b..b6a5d8f 100644
--- a/ports/darwin/guts/scandir.c
+++ b/ports/darwin/guts/scandir.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_scandir(const char *path, struct dirent ***namelist, int (*filter)(struct dirent *), int (*compar)(const void *, const void *)) {
  *	int rc = -1;
diff --git a/ports/darwin/guts/setxattr.c b/ports/darwin/guts/setxattr.c
index 10ffba4..3346605 100644
--- a/ports/darwin/guts/setxattr.c
+++ b/ports/darwin/guts/setxattr.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2014 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int setxattr(const char *path, const char *name, const void *value, size_t size, u_int32_t position, int options)
  *	int rc = -1;
  */
diff --git a/ports/darwin/guts/stat.c b/ports/darwin/guts/stat.c
index 8a0742c..4df9670 100644
--- a/ports/darwin/guts/stat.c
+++ b/ports/darwin/guts/stat.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2011 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int stat(const char *path, struct stat *buf)
  *	int rc = -1;
  */
diff --git a/ports/darwin/guts/sync_file_range.c b/ports/darwin/guts/sync_file_range.c
index e0a31a4..229ccaa 100644
--- a/ports/darwin/guts/sync_file_range.c
+++ b/ports/darwin/guts/sync_file_range.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2013 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int sync_file_range(int fd, off_t offset, off_t nbytes, unsigned int flags)
  *	int rc = -1;
  */
diff --git a/ports/darwin/portdefs.h b/ports/darwin/portdefs.h
index 900d98e..07fd39c 100644
--- a/ports/darwin/portdefs.h
+++ b/ports/darwin/portdefs.h
@@ -1,3 +1,7 @@
+/*
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
 #define PRELINK_LIBRARIES "DYLD_INSERT_LIBRARIES"
 #define PRELINK_PATH "DYLD_LIBRARY_PATH"
 #define PSEUDO_STATBUF_64 0
diff --git a/ports/darwin/pseudo_wrappers.c b/ports/darwin/pseudo_wrappers.c
index e33533e..3f05936 100644
--- a/ports/darwin/pseudo_wrappers.c
+++ b/ports/darwin/pseudo_wrappers.c
@@ -3,18 +3,7 @@
  *
  * Copyright (c) 2008-2011 Wind River Systems, Inc.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the Lesser GNU General Public License version 2.1 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the Lesser GNU General Public License for more details.
- *
- * You should have received a copy of the Lesser GNU General Public License
- * version 2.1 along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
+ * SPDX-License-Identifier: LGPL-2.1-only
  *
  */
 /* we need XATTR_NOFOLLOW in scope */
diff --git a/ports/linux/guts/COPYRIGHT b/ports/linux/guts/COPYRIGHT
index c96e1b1..b860a36 100644
--- a/ports/linux/guts/COPYRIGHT
+++ b/ports/linux/guts/COPYRIGHT
@@ -1,17 +1,6 @@
 /*
  * Copyright (c) 2008-2010 Wind River Systems, Inc.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the Lesser GNU General Public License version 2.1 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the Lesser GNU General Public License for more details.
- *
- * You should have received a copy of the Lesser GNU General Public License
- * version 2.1 along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
+ * SPDX-License-Identifier: LGPL-2.1-only
  *
  */
diff --git a/ports/linux/guts/__fxstat.c b/ports/linux/guts/__fxstat.c
index db9716b..0a34320 100644
--- a/ports/linux/guts/__fxstat.c
+++ b/ports/linux/guts/__fxstat.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int
  * wrap___fxstat(int ver, int fd, struct stat *buf) {
  *	int rc = -1;
diff --git a/ports/linux/guts/__fxstat64.c b/ports/linux/guts/__fxstat64.c
index 8601904..aa734b5 100644
--- a/ports/linux/guts/__fxstat64.c
+++ b/ports/linux/guts/__fxstat64.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int
  * wrap___fxstat64(int ver, int fd, struct stat64 *buf) {
  *	int rc = -1;
diff --git a/ports/linux/guts/__fxstatat.c b/ports/linux/guts/__fxstatat.c
index 94c5ff6..23dfa73 100644
--- a/ports/linux/guts/__fxstatat.c
+++ b/ports/linux/guts/__fxstatat.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap___fxstatat(int ver, int dirfd, const char *path, struct stat *buf, int flags) {
  *	int rc = -1;
diff --git a/ports/linux/guts/__fxstatat64.c b/ports/linux/guts/__fxstatat64.c
index 62fc3f1..ecf2952 100644
--- a/ports/linux/guts/__fxstatat64.c
+++ b/ports/linux/guts/__fxstatat64.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap___fxstatat64(int ver, int dirfd, const char *path, struct stat64 *buf, int flags) {
  *	int rc = -1;
diff --git a/ports/linux/guts/__lxstat.c b/ports/linux/guts/__lxstat.c
index 32b0301..1307eb7 100644
--- a/ports/linux/guts/__lxstat.c
+++ b/ports/linux/guts/__lxstat.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap___lxstat(int ver, const char *path, struct stat *buf) {
  *	int rc = -1;
diff --git a/ports/linux/guts/__lxstat64.c b/ports/linux/guts/__lxstat64.c
index ac1f782..1d3cf32 100644
--- a/ports/linux/guts/__lxstat64.c
+++ b/ports/linux/guts/__lxstat64.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap___lxstat64(int ver, const char *path, struct stat64 *buf) {
  *	int rc = -1;
diff --git a/ports/linux/guts/__openat64_2.c b/ports/linux/guts/__openat64_2.c
index e970df7..f9e9cf0 100644
--- a/ports/linux/guts/__openat64_2.c
+++ b/ports/linux/guts/__openat64_2.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010,2012 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap___openat64_2(int dirfd, const char *path, int flags) {
  *	int rc = -1;
diff --git a/ports/linux/guts/__openat_2.c b/ports/linux/guts/__openat_2.c
index 33ed620..e9a1f7e 100644
--- a/ports/linux/guts/__openat_2.c
+++ b/ports/linux/guts/__openat_2.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap___openat_2(int dirfd, const char *path, int flags) {
  *	int rc = -1;
diff --git a/ports/linux/guts/__xmknod.c b/ports/linux/guts/__xmknod.c
index fa31b66..bbf486b 100644
--- a/ports/linux/guts/__xmknod.c
+++ b/ports/linux/guts/__xmknod.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap___xmknod(int ver, const char *path, mode_t mode, dev_t *dev) {
  *	int rc = -1;
diff --git a/ports/linux/guts/__xmknodat.c b/ports/linux/guts/__xmknodat.c
index 4fa021b..8c34427 100644
--- a/ports/linux/guts/__xmknodat.c
+++ b/ports/linux/guts/__xmknodat.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap___xmknodat(int ver, int dirfd, const char *path, mode_t mode, dev_t *dev) {
  *	int rc = -1;
diff --git a/ports/linux/guts/__xstat.c b/ports/linux/guts/__xstat.c
index ec10abb..fed6955 100644
--- a/ports/linux/guts/__xstat.c
+++ b/ports/linux/guts/__xstat.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap___xstat(int ver, const char *path, struct stat *buf) {
  *	int rc = -1;
diff --git a/ports/linux/guts/__xstat64.c b/ports/linux/guts/__xstat64.c
index ed62e7e..ec74c02 100644
--- a/ports/linux/guts/__xstat64.c
+++ b/ports/linux/guts/__xstat64.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap___xstat64(int ver, const char *path, struct stat64 *buf) {
  *	int rc = -1;
diff --git a/ports/linux/guts/canonicalize_file_name.c b/ports/linux/guts/canonicalize_file_name.c
index 9a04f33..a36cfbd 100644
--- a/ports/linux/guts/canonicalize_file_name.c
+++ b/ports/linux/guts/canonicalize_file_name.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static char *
  * wrap_canonicalize_file_name(const char *filename) {
  *	char * rc = NULL;
diff --git a/ports/linux/guts/capset.c b/ports/linux/guts/capset.c
index 51e0cdf..1a4219b 100644
--- a/ports/linux/guts/capset.c
+++ b/ports/linux/guts/capset.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2016 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int capset(cap_user_header_t hdrp, const cap_user_data_t datap)
  *	int rc = -1;
  */
diff --git a/ports/linux/guts/creat64.c b/ports/linux/guts/creat64.c
index 2d2fc27..9ce7e3d 100644
--- a/ports/linux/guts/creat64.c
+++ b/ports/linux/guts/creat64.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_creat64(const char *path, ...mode_t mode) {
  *	int rc = -1;
diff --git a/ports/linux/guts/eaccess.c b/ports/linux/guts/eaccess.c
index e2119cc..66b5b56 100644
--- a/ports/linux/guts/eaccess.c
+++ b/ports/linux/guts/eaccess.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_eaccess(const char *path, int mode) {
  *	int rc = -1;
diff --git a/ports/linux/guts/euidaccess.c b/ports/linux/guts/euidaccess.c
index 85433a8..cf9a8cc 100644
--- a/ports/linux/guts/euidaccess.c
+++ b/ports/linux/guts/euidaccess.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_euidaccess(const char *path, int mode) {
  *	int rc = -1;
diff --git a/ports/linux/guts/fcntl.c b/ports/linux/guts/fcntl.c
index 639fd24..4dd9796 100644
--- a/ports/linux/guts/fcntl.c
+++ b/ports/linux/guts/fcntl.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_fcntl(int fd, int cmd, ...struct flock *lock) {
  *	int rc = -1;
diff --git a/ports/linux/guts/fopen64.c b/ports/linux/guts/fopen64.c
index b243345..e76da69 100644
--- a/ports/linux/guts/fopen64.c
+++ b/ports/linux/guts/fopen64.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static FILE *
  * wrap_fopen64(const char *path, const char *mode) {
  *	FILE * rc = 0;
diff --git a/ports/linux/guts/freopen64.c b/ports/linux/guts/freopen64.c
index 4bad533..5fc9073 100644
--- a/ports/linux/guts/freopen64.c
+++ b/ports/linux/guts/freopen64.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static FILE *
  * wrap_freopen64(const char *path, const char *mode, FILE *stream) {
  *	FILE * rc = NULL;
diff --git a/ports/linux/guts/fstat.c b/ports/linux/guts/fstat.c
index 2cf2787..b089b15 100644
--- a/ports/linux/guts/fstat.c
+++ b/ports/linux/guts/fstat.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2011 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int fstat(int fd, struct stat *buf)
  *	int rc = -1;
  */
diff --git a/ports/linux/guts/fstat64.c b/ports/linux/guts/fstat64.c
index 4a759f7..6dd97da 100644
--- a/ports/linux/guts/fstat64.c
+++ b/ports/linux/guts/fstat64.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2012 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int fstat64(int fd, struct stat *buf)
  *	int rc = -1;
  */
diff --git a/ports/linux/guts/ftw64.c b/ports/linux/guts/ftw64.c
index a375fbf..48adb80 100644
--- a/ports/linux/guts/ftw64.c
+++ b/ports/linux/guts/ftw64.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_ftw64(const char *path, int (*fn)(const char *, const struct stat64 *, int), int nopenfd) {
  *	int rc = -1;
diff --git a/ports/linux/guts/get_current_dir_name.c b/ports/linux/guts/get_current_dir_name.c
index 79f82f9..cd62326 100644
--- a/ports/linux/guts/get_current_dir_name.c
+++ b/ports/linux/guts/get_current_dir_name.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static char *
  * wrap_get_current_dir_name(void) {
  *	char * rc = NULL;
diff --git a/ports/linux/guts/getgrent_r.c b/ports/linux/guts/getgrent_r.c
index b04373d..c94f319 100644
--- a/ports/linux/guts/getgrent_r.c
+++ b/ports/linux/guts/getgrent_r.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010-2011 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_getgrent_r(struct group *gbuf, char *buf, size_t buflen, struct group **gbufp) {
  *	int rc = -1;
diff --git a/ports/linux/guts/getgrouplist.c b/ports/linux/guts/getgrouplist.c
index 8b16e47..5481a38 100644
--- a/ports/linux/guts/getgrouplist.c
+++ b/ports/linux/guts/getgrouplist.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups) {
  *	int rc = -1;
diff --git a/ports/linux/guts/getgroups.c b/ports/linux/guts/getgroups.c
index afb9662..814caaf 100644
--- a/ports/linux/guts/getgroups.c
+++ b/ports/linux/guts/getgroups.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_getgroups(int size, gid_t *list) {
  *	int rc = -1;
diff --git a/ports/linux/guts/getpw.c b/ports/linux/guts/getpw.c
index 62b44da..5aa0bca 100644
--- a/ports/linux/guts/getpw.c
+++ b/ports/linux/guts/getpw.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_getpw(uid_t uid, char *buf) {
  *	int rc = -1;
diff --git a/ports/linux/guts/getpwent_r.c b/ports/linux/guts/getpwent_r.c
index 4fd9cc0..4796edf 100644
--- a/ports/linux/guts/getpwent_r.c
+++ b/ports/linux/guts/getpwent_r.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010-2011 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_getpwent_r(struct passwd *pwbuf, char *buf, size_t buflen, struct passwd **pwbufp) {
  *	int rc = -1;
diff --git a/ports/linux/guts/getresgid.c b/ports/linux/guts/getresgid.c
index 13551a4..f79b9f3 100644
--- a/ports/linux/guts/getresgid.c
+++ b/ports/linux/guts/getresgid.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_getresgid(gid_t *rgid, gid_t *egid, gid_t *sgid) {
  *	int rc = -1;
diff --git a/ports/linux/guts/getresuid.c b/ports/linux/guts/getresuid.c
index 2e47520..59816d4 100644
--- a/ports/linux/guts/getresuid.c
+++ b/ports/linux/guts/getresuid.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_getresuid(uid_t *ruid, uid_t *euid, uid_t *suid) {
  *	int rc = -1;
diff --git a/ports/linux/guts/glob64.c b/ports/linux/guts/glob64.c
index ccac6e4..7e45368 100644
--- a/ports/linux/guts/glob64.c
+++ b/ports/linux/guts/glob64.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_glob64(const char *pattern, int flags, int (*errfunc)(const char *, int), glob64_t *pglob) {
  *	int rc = -1;
diff --git a/ports/linux/guts/lchown.c b/ports/linux/guts/lchown.c
index 4eb1202..b41ccaa 100644
--- a/ports/linux/guts/lchown.c
+++ b/ports/linux/guts/lchown.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_lchown(const char *path, uid_t owner, gid_t group) {
  */
diff --git a/ports/linux/guts/lckpwdf.c b/ports/linux/guts/lckpwdf.c
index b452ec0..f96ab53 100644
--- a/ports/linux/guts/lckpwdf.c
+++ b/ports/linux/guts/lckpwdf.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_lckpwdf(void) {
  *	int rc = -1;
diff --git a/ports/linux/guts/lstat.c b/ports/linux/guts/lstat.c
index 19c202f..d2c4d50 100644
--- a/ports/linux/guts/lstat.c
+++ b/ports/linux/guts/lstat.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2011 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int lstat(const char *path, struct stat *buf)
  *	int rc = -1;
  */
diff --git a/ports/linux/guts/lstat64.c b/ports/linux/guts/lstat64.c
index 94eb60f..43d0ce1 100644
--- a/ports/linux/guts/lstat64.c
+++ b/ports/linux/guts/lstat64.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2012 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int lstat64(const char *path, struct stat *buf)
  *	int rc = -1;
  */
diff --git a/ports/linux/guts/mknod.c b/ports/linux/guts/mknod.c
index eb90e66..61fd320 100644
--- a/ports/linux/guts/mknod.c
+++ b/ports/linux/guts/mknod.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2016 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int mknod(const char *path, mode_t mode, dev_t dev)
  *	int rc = -1;
  */
diff --git a/ports/linux/guts/mknodat.c b/ports/linux/guts/mknodat.c
index 4956a6a..a7e4293 100644
--- a/ports/linux/guts/mknodat.c
+++ b/ports/linux/guts/mknodat.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2016 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int mknodat(int dirfd, const char *path, mode_t mode, dev_t dev)
  *	int rc = -1;
  */
diff --git a/ports/linux/guts/mkstemp64.c b/ports/linux/guts/mkstemp64.c
index 48be612..aa7bb58 100644
--- a/ports/linux/guts/mkstemp64.c
+++ b/ports/linux/guts/mkstemp64.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_mkstemp64(char *template) {
  *	int rc = -1;
diff --git a/ports/linux/guts/nftw64.c b/ports/linux/guts/nftw64.c
index 82571cd..816faba 100644
--- a/ports/linux/guts/nftw64.c
+++ b/ports/linux/guts/nftw64.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_nftw64(const char *path, int (*fn)(const char *, const struct stat64 *, int, struct FTW *), int nopenfd, int flag) {
  *	int rc = -1;
diff --git a/ports/linux/guts/open.c b/ports/linux/guts/open.c
index 0a0596c..ad7fd65 100644
--- a/ports/linux/guts/open.c
+++ b/ports/linux/guts/open.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_open(const char *path, int flags, ...mode_t mode) {
  *	int rc = -1;
diff --git a/ports/linux/guts/open64.c b/ports/linux/guts/open64.c
index 8028ede..b7d9ca3 100644
--- a/ports/linux/guts/open64.c
+++ b/ports/linux/guts/open64.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010,2012 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_open64(const char *path, int flags, ...mode_t mode) {
  *	int rc = -1;
diff --git a/ports/linux/guts/openat.c b/ports/linux/guts/openat.c
index b571c56..656ac2b 100644
--- a/ports/linux/guts/openat.c
+++ b/ports/linux/guts/openat.c
@@ -2,13 +2,17 @@
  * Copyright (c) 2008-2010, 2013 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_openat(int dirfd, const char *path, int flags, ...mode_t mode) {
  *	int rc = -1;
  */
 	struct stat64 buf;
+	int overly_magic_nonblocking = 0;
 	int existed = 1;
 	int save_errno;
+	sigset_t local_saved_sigmask;
 
 	/* mask out mode bits appropriately */
 	mode = mode & ~pseudo_umask;
@@ -42,7 +46,7 @@
 	/* don't handle O_CREAT the same way if O_TMPFILE exists
 	 * and is set.
 	 */
-	if (flags & O_TMPFILE) {
+	if ((flags & O_TMPFILE) == O_TMPFILE) {
 		existed = 0;
 	} else
 #endif
@@ -51,9 +55,13 @@
 	if (flags & O_CREAT) {
 		save_errno = errno;
 #ifdef PSEUDO_NO_REAL_AT_FUNCTIONS
-		rc = real___xstat64(_STAT_VER, path, &buf);
+		if (flags & O_NOFOLLOW) {
+			rc = real___lxstat64(_STAT_VER, path, &buf);
+		} else {
+			rc = real___xstat64(_STAT_VER, path, &buf);
+		}
 #else
-		rc = real___fxstatat64(_STAT_VER, dirfd, path, &buf, 0);
+		rc = real___fxstatat64(_STAT_VER, dirfd, path, &buf, (flags & O_NOFOLLOW) ? AT_SYMLINK_NOFOLLOW : 0);
 #endif
 		existed = (rc != -1);
 		if (!existed)
@@ -61,6 +69,31 @@
 		errno = save_errno;
 	}
 
+	/* if a pipe is opened without O_NONBLOCK, for only reading or
+	 * only writing, it can block forever. We need to do extra magic
+	 * in that case...
+	 */
+	if (!(flags & O_NONBLOCK) && ((flags & (O_WRONLY | O_RDONLY | O_RDWR)) != O_RDWR)) {
+		save_errno = errno;
+#ifdef PSEUDO_NO_REAL_AT_FUNCTIONS
+		if (flags & O_NOFOLLOW) {
+			rc = real___lxstat64(_STAT_VER, path, &buf);
+		} else {
+			rc = real___xstat64(_STAT_VER, path, &buf);
+		}
+#else
+		rc = real___fxstatat64(_STAT_VER, dirfd, path, &buf, (flags & O_NOFOLLOW) ? AT_SYMLINK_NOFOLLOW : 0);
+#endif
+		if (rc != -1 && S_ISFIFO(buf.st_mode)) {
+			overly_magic_nonblocking = 1;
+		}
+	}
+
+	/* this is a horrible special case and i do not know whether it will work */
+	if (overly_magic_nonblocking) {
+		pseudo_droplock();
+		sigprocmask(SIG_SETMASK, &pseudo_saved_sigmask, &local_saved_sigmask);
+	}
 	/* because we are not actually root, secretly mask in 0600 to the
 	 * underlying mode.  The ", 0" is because the only time mode matters
 	 * is if a file is going to be created, in which case it's
@@ -71,6 +104,20 @@
 #else
 	rc = real_openat(dirfd, path, flags, PSEUDO_FS_MODE(mode, 0));
 #endif
+	if (overly_magic_nonblocking) {
+		save_errno = errno;
+		sigprocmask(SIG_SETMASK, &local_saved_sigmask, NULL);
+		/* well this is a problem. we can't NOT proceed; we may have
+		 * already opened the file! we can't even return up the call
+		 * stack to stuff that's going to try to drop the lock.
+		 */
+		if (pseudo_getlock()) {
+			pseudo_diag("PANIC: after opening a readonly/writeonly FIFO (path '%s', fd %d, errno %d, saved errno %d), could not regain lock. unrecoverable. sorry. bye.\n",
+				path, rc, errno, save_errno);
+			abort();
+		}
+		errno = save_errno;
+	}
 
 	if (rc != -1) {
 		save_errno = errno;
@@ -80,18 +127,24 @@
 		 * database, because there's no directory entries for
 		 * the file yet.
 		 */
-		if (flags & O_TMPFILE) {
+		if ((flags & O_TMPFILE) == O_TMPFILE) {
 			real_fchmod(rc, PSEUDO_FS_MODE(mode, 0));
 			errno = save_errno;
 			return rc;
 		}
 #endif
 #ifdef PSEUDO_NO_REAL_AT_FUNCTIONS
-		stat_rc = real___xstat64(_STAT_VER, path, &buf);
+		if (flags & O_NOFOLLOW) {
+			stat_rc = real___lxstat64(_STAT_VER, path, &buf);
+		} else {
+			stat_rc = real___xstat64(_STAT_VER, path, &buf);
+		}
 #else
-		stat_rc = real___fxstatat64(_STAT_VER, dirfd, path, &buf, 0);
+		stat_rc = real___fxstatat64(_STAT_VER, dirfd, path, &buf, (flags & O_NOFOLLOW) ? AT_SYMLINK_NOFOLLOW : 0);
 #endif
 
+		pseudo_debug(PDBGF_FILE, "openat(path %s), flags %o, stat rc %d, stat mode %o\n",
+			path, flags, stat_rc, buf.st_mode);
 		if (stat_rc != -1) {
 			buf.st_mode = PSEUDO_DB_MODE(buf.st_mode, mode);
 			if (!existed) {
diff --git a/ports/linux/guts/openat64.c b/ports/linux/guts/openat64.c
index 8dedcbf..7f9d226 100644
--- a/ports/linux/guts/openat64.c
+++ b/ports/linux/guts/openat64.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010,2012 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_openat64(int dirfd, const char *path, int flags, ...mode_t mode) {
  *	int rc = -1;
diff --git a/ports/linux/guts/renameat2.c b/ports/linux/guts/renameat2.c
new file mode 100644
index 0000000..e2c8cf1
--- /dev/null
+++ b/ports/linux/guts/renameat2.c
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2019 Peter Seebach/Seebs <seebs@seebs.net>; see
+ * guts/COPYRIGHT for information.
+ *
+ * [Note: copyright added by code generator, may be
+ * incorrect. Remove this if you fix it.]
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ * int renameat2(int olddirfd, const char *oldpath, int newdirfd, const char *newpath, unsigned int flags)
+ *	int rc = -1;
+ */
+
+	(void) olddirfd;
+	(void) oldpath;
+	(void) newdirfd;
+	(void) newpath;
+	(void) flags;
+	/* for now, let's try just failing out hard, and hope things retry with a
+	 * different syscall.
+	 */
+	errno = ENOSYS;
+	rc = -1;
+
+/*	return rc;
+ * }
+ */
diff --git a/ports/linux/guts/scandir.c b/ports/linux/guts/scandir.c
index afcebaf..60a275a 100644
--- a/ports/linux/guts/scandir.c
+++ b/ports/linux/guts/scandir.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_scandir(const char *path, struct dirent ***namelist, int (*filter)(const struct dirent *), int (*compar)(const void *, const void *)) {
  *	int rc = -1;
diff --git a/ports/linux/guts/scandir64.c b/ports/linux/guts/scandir64.c
index 1317b73..233602e 100644
--- a/ports/linux/guts/scandir64.c
+++ b/ports/linux/guts/scandir64.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_scandir64(const char *path, struct dirent64 ***namelist, int (*filter)(const struct dirent64 *), int (*compar)(const void *, const void *)) {
  *	int rc = -1;
diff --git a/ports/linux/guts/setfsgid.c b/ports/linux/guts/setfsgid.c
index 0e5a10b..81e916e 100644
--- a/ports/linux/guts/setfsgid.c
+++ b/ports/linux/guts/setfsgid.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_setfsgid(gid_t fsgid) {
  *	int rc = -1;
diff --git a/ports/linux/guts/setfsuid.c b/ports/linux/guts/setfsuid.c
index e52b65e..423ca03 100644
--- a/ports/linux/guts/setfsuid.c
+++ b/ports/linux/guts/setfsuid.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_setfsuid(uid_t fsuid) {
  *	int rc = -1;
diff --git a/ports/linux/guts/setgroups.c b/ports/linux/guts/setgroups.c
index 31b2b57..d26db31 100644
--- a/ports/linux/guts/setgroups.c
+++ b/ports/linux/guts/setgroups.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_setgroups(size_t size, const gid_t *list) {
  *	int rc = -1;
diff --git a/ports/linux/guts/setresgid.c b/ports/linux/guts/setresgid.c
index 2a26405..37739b9 100644
--- a/ports/linux/guts/setresgid.c
+++ b/ports/linux/guts/setresgid.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_setresgid(gid_t rgid, gid_t egid, gid_t sgid) {
  *	int rc = -1;
diff --git a/ports/linux/guts/setresuid.c b/ports/linux/guts/setresuid.c
index a0a367f..3219fc5 100644
--- a/ports/linux/guts/setresuid.c
+++ b/ports/linux/guts/setresuid.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_setresuid(uid_t ruid, uid_t euid, uid_t suid) {
  *	int rc = -1;
diff --git a/ports/linux/guts/stat.c b/ports/linux/guts/stat.c
index 1fe800e..f8c73f7 100644
--- a/ports/linux/guts/stat.c
+++ b/ports/linux/guts/stat.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2011 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int stat(const char *path, struct stat *buf)
  *	int rc = -1;
  */
diff --git a/ports/linux/guts/stat64.c b/ports/linux/guts/stat64.c
index 53dd156..d8b3f36 100644
--- a/ports/linux/guts/stat64.c
+++ b/ports/linux/guts/stat64.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2012 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int stat64(const char *path, struct stat *buf)
  *	int rc = -1;
  */
diff --git a/ports/linux/guts/syscall.c b/ports/linux/guts/syscall.c
new file mode 100644
index 0000000..0fefddc
--- /dev/null
+++ b/ports/linux/guts/syscall.c
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2018 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ * long syscall(long nr)
+ *	long rc = -1;
+ */
+
+	/* we should never get here, syscall is hand-wrapped */
+	rc = -1;
+	errno = ENOTSUPP;
+
+/*	return rc;
+ * }
+ */
diff --git a/ports/linux/guts/truncate64.c b/ports/linux/guts/truncate64.c
index a798984..aaf1797 100644
--- a/ports/linux/guts/truncate64.c
+++ b/ports/linux/guts/truncate64.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_truncate64(const char *path, off64_t length) {
  *	int rc = -1;
diff --git a/ports/linux/guts/ulckpwdf.c b/ports/linux/guts/ulckpwdf.c
index ed6a671..b4a26da 100644
--- a/ports/linux/guts/ulckpwdf.c
+++ b/ports/linux/guts/ulckpwdf.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_ulckpwdf(void) {
  *	int rc = -1;
diff --git a/ports/linux/newclone/guts/clone.c b/ports/linux/newclone/guts/clone.c
index ee6fc09..bc64c5a 100644
--- a/ports/linux/newclone/guts/clone.c
+++ b/ports/linux/newclone/guts/clone.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2011 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * clone(...) {
  *      ....
diff --git a/ports/linux/newclone/pseudo_wrappers.c b/ports/linux/newclone/pseudo_wrappers.c
index 1fc6c59..5b137ee 100644
--- a/ports/linux/newclone/pseudo_wrappers.c
+++ b/ports/linux/newclone/pseudo_wrappers.c
@@ -1,3 +1,8 @@
+/*
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
+
 static int
 wrap_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, va_list
 ap) {
diff --git a/ports/linux/noxattr/guts/fgetxattr.c b/ports/linux/noxattr/guts/fgetxattr.c
index 9d33643..9ab1be2 100644
--- a/ports/linux/noxattr/guts/fgetxattr.c
+++ b/ports/linux/noxattr/guts/fgetxattr.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * ssize_t fgetxattr(int filedes, const char *name, void *value, size_t size)
  *	ssize_t rc = -1;
  */
diff --git a/ports/linux/noxattr/guts/flistxattr.c b/ports/linux/noxattr/guts/flistxattr.c
index 77db021..e9ad277 100644
--- a/ports/linux/noxattr/guts/flistxattr.c
+++ b/ports/linux/noxattr/guts/flistxattr.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * ssize_t flistxattr(int filedes, char *list, size_t size)
  *	ssize_t rc = -1;
  */
diff --git a/ports/linux/noxattr/guts/fremovexattr.c b/ports/linux/noxattr/guts/fremovexattr.c
index 529a9de..99c0906 100644
--- a/ports/linux/noxattr/guts/fremovexattr.c
+++ b/ports/linux/noxattr/guts/fremovexattr.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int fremovexattr(int filedes, const char *name)
  *	int rc = -1;
  */
diff --git a/ports/linux/noxattr/guts/fsetxattr.c b/ports/linux/noxattr/guts/fsetxattr.c
index 3c56ddd..780fa9a 100644
--- a/ports/linux/noxattr/guts/fsetxattr.c
+++ b/ports/linux/noxattr/guts/fsetxattr.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int fsetxattr(int filedes, const char *name, const void *value, size_t size, int flags)
  *	int rc = -1;
  */
diff --git a/ports/linux/noxattr/guts/getxattr.c b/ports/linux/noxattr/guts/getxattr.c
index fe8912d..939060b 100644
--- a/ports/linux/noxattr/guts/getxattr.c
+++ b/ports/linux/noxattr/guts/getxattr.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * ssize_t getxattr(const char *pathname, const char *name, void *value, size_t size)
  *	ssize_t rc = -1;
  */
diff --git a/ports/linux/noxattr/guts/lgetxattr.c b/ports/linux/noxattr/guts/lgetxattr.c
index 404211f..48a0b95 100644
--- a/ports/linux/noxattr/guts/lgetxattr.c
+++ b/ports/linux/noxattr/guts/lgetxattr.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * ssize_t lgetxattr(const char *pathname, const char *name, void *value, size_t size)
  *	ssize_t rc = -1;
  */
diff --git a/ports/linux/noxattr/guts/listxattr.c b/ports/linux/noxattr/guts/listxattr.c
index 1b0b5e7..9c351a5 100644
--- a/ports/linux/noxattr/guts/listxattr.c
+++ b/ports/linux/noxattr/guts/listxattr.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * ssize_t listxattr(const char *pathname, char *list, size_t size)
  *	ssize_t rc = -1;
  */
diff --git a/ports/linux/noxattr/guts/llistxattr.c b/ports/linux/noxattr/guts/llistxattr.c
index a33f970..6fc6bcc 100644
--- a/ports/linux/noxattr/guts/llistxattr.c
+++ b/ports/linux/noxattr/guts/llistxattr.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * ssize_t llistxattr(const char *pathname, char *list, size_t size)
  *	ssize_t rc = -1;
  */
diff --git a/ports/linux/noxattr/guts/lremovexattr.c b/ports/linux/noxattr/guts/lremovexattr.c
index 38429da..e31c46c 100644
--- a/ports/linux/noxattr/guts/lremovexattr.c
+++ b/ports/linux/noxattr/guts/lremovexattr.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int lremovexattr(const char *pathname, const char *name)
  *	int rc = -1;
  */
diff --git a/ports/linux/noxattr/guts/lsetxattr.c b/ports/linux/noxattr/guts/lsetxattr.c
index 140ae8d..096cbf2 100644
--- a/ports/linux/noxattr/guts/lsetxattr.c
+++ b/ports/linux/noxattr/guts/lsetxattr.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int lsetxattr(const char *pathname, const char *name, const void *value, size_t size, int flags)
  *	int rc = -1;
  */
diff --git a/ports/linux/noxattr/guts/removexattr.c b/ports/linux/noxattr/guts/removexattr.c
index cd7f486..4adee0e 100644
--- a/ports/linux/noxattr/guts/removexattr.c
+++ b/ports/linux/noxattr/guts/removexattr.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int removexattr(const char *pathname, const char *name)
  *	int rc = -1;
  */
diff --git a/ports/linux/noxattr/guts/setxattr.c b/ports/linux/noxattr/guts/setxattr.c
index de2de98..3172e6f 100644
--- a/ports/linux/noxattr/guts/setxattr.c
+++ b/ports/linux/noxattr/guts/setxattr.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int setxattr(const char *pathname, const char *name, const void *value, size_t size, int flags)
  *	int rc = -1;
  */
diff --git a/ports/linux/oldclone/guts/clone.c b/ports/linux/oldclone/guts/clone.c
index c6771e5..e0ff768 100644
--- a/ports/linux/oldclone/guts/clone.c
+++ b/ports/linux/oldclone/guts/clone.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2011 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * clone(...) {
  *      ....
diff --git a/ports/linux/oldclone/pseudo_wrappers.c b/ports/linux/oldclone/pseudo_wrappers.c
index 1720dfb..ba9cf42 100644
--- a/ports/linux/oldclone/pseudo_wrappers.c
+++ b/ports/linux/oldclone/pseudo_wrappers.c
@@ -1,3 +1,7 @@
+/*
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
 static int
 wrap_clone(int (*fn)(void *), void *child_stack, int flags, void *arg) {
 	/* unused */
diff --git a/ports/linux/portdefs.h b/ports/linux/portdefs.h
index 942356d..d419365 100644
--- a/ports/linux/portdefs.h
+++ b/ports/linux/portdefs.h
@@ -1,3 +1,7 @@
+/*
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
 #define PRELINK_LIBRARIES "LD_PRELOAD"
 #define PRELINK_PATH "LD_LIBRARY_PATH"
 #define PSEUDO_STATBUF_64 1
@@ -27,3 +31,4 @@ GLIBC_COMPAT_SYMBOL(memcpy,2.0);
 #endif
 
 #include <linux/capability.h>
+#include <sys/syscall.h>
diff --git a/ports/linux/pseudo_wrappers.c b/ports/linux/pseudo_wrappers.c
index e7f79f8..cd7e173 100644
--- a/ports/linux/pseudo_wrappers.c
+++ b/ports/linux/pseudo_wrappers.c
@@ -1,3 +1,7 @@
+/*
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
 /* the unix port wants to know that real_stat() and
  * friends exist.  So they do. And because the Linux
  * port really uses stat64 for those...
@@ -49,3 +53,42 @@ int pseudo_capset(cap_user_header_t hdrp, const cap_user_data_t datap) {
 
 	return 0;
 }
+
+long
+syscall(long number, ...) {
+	long rc = -1;
+
+	if (!pseudo_check_wrappers() || !real_syscall) {
+		/* rc was initialized to the "failure" value */
+		pseudo_enosys("syscall");
+		return rc;
+	}
+
+#ifdef SYS_renameat2
+	/* concerns exist about trying to parse arguments because syscall(2)
+	 * specifies strange ABI behaviors. If we can get better clarity on
+	 * that, it could make sense to redirect to wrap_renameat2().
+	 */
+	if (number == SYS_renameat2) {
+		errno = ENOSYS;
+		return -1;
+	}
+#else
+	(void) number;
+#endif
+
+	/* gcc magic to attempt to just pass these args to syscall. we have to
+	 * guess about the number of args; the docs discuss calling conventions
+	 * up to 7, so let's try that?
+	 */
+	void *res = __builtin_apply((void (*)()) real_syscall, __builtin_apply_args(), sizeof(long) * 7);
+	__builtin_return(res);
+}
+
+/* unused.
+ */
+static long wrap_syscall(long nr, va_list ap) {
+	(void) nr;
+	(void) ap;
+	return -1;
+}
diff --git a/ports/linux/statvfs/guts/statvfs.c b/ports/linux/statvfs/guts/statvfs.c
index c516649..e69ee41 100644
--- a/ports/linux/statvfs/guts/statvfs.c
+++ b/ports/linux/statvfs/guts/statvfs.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2018 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int statvfs(const char *path, struct statvfs *buf)
  *	int rc = -1;
  */
diff --git a/ports/linux/wrapfuncs.in b/ports/linux/wrapfuncs.in
index fca5b50..c5ea7c3 100644
--- a/ports/linux/wrapfuncs.in
+++ b/ports/linux/wrapfuncs.in
@@ -1,12 +1,12 @@
-int open(const char *path, int flags, ...{mode_t mode}); /* flags=0 */
+int open(const char *path, int flags, ...{mode_t mode}); /* flags=flags&O_NOFOLLOW */
 char *get_current_dir_name(void);
 int __xstat(int ver, const char *path, struct stat *buf);
 int __lxstat(int ver, const char *path, struct stat *buf); /* flags=AT_SYMLINK_NOFOLLOW */
 int __fxstat(int ver, int fd, struct stat *buf);
 int lchown(const char *path, uid_t owner, gid_t group); /* flags=AT_SYMLINK_NOFOLLOW */
 int __fxstatat(int ver, int dirfd, const char *path, struct stat *buf, int flags);
-int openat(int dirfd, const char *path, int flags, ...{mode_t mode});
-int __openat_2(int dirfd, const char *path, int flags);
+int openat(int dirfd, const char *path, int flags, ...{mode_t mode}); /* flags=flags&O_NOFOLLOW */
+int __openat_2(int dirfd, const char *path, int flags); /* flags=flags&O_NOFOLLOW */
 int mknod(const char *path, mode_t mode, dev_t dev); /* real_func=pseudo_mknod */
 int mknodat(int dirfd, const char *path, mode_t mode, dev_t dev); /* real_func=pseudo_mknodat */
 int __xmknod(int ver, const char *path, mode_t mode, dev_t *dev); /* flags=AT_SYMLINK_NOFOLLOW */
@@ -15,9 +15,9 @@ int fcntl(int fd, int cmd, ...{struct flock *lock});
 # just so we know the inums of symlinks
 char *canonicalize_file_name(const char *filename);
 int eaccess(const char *path, int mode);
-int open64(const char *path, int flags, ...{mode_t mode}); /* flags=0 */
-int openat64(int dirfd, const char *path, int flags, ...{mode_t mode}); /* flags=0 */
-int __openat64_2(int dirfd, const char *path, int flags); /* flags=0 */
+int open64(const char *path, int flags, ...{mode_t mode}); /* flags=flags&O_NOFOLLOW */
+int openat64(int dirfd, const char *path, int flags, ...{mode_t mode}); /* flags=flags&O_NOFOLLOW */
+int __openat64_2(int dirfd, const char *path, int flags); /* flags=flags&O_NOFOLLOW */
 int creat64(const char *path, mode_t mode);
 int stat(const char *path, struct stat *buf); /* real_func=pseudo_stat */
 int lstat(const char *path, struct stat *buf); /* real_func=pseudo_lstat, flags=AT_SYMLINK_NOFOLLOW */
@@ -54,3 +54,5 @@ int getpw(uid_t uid, char *buf);
 int getpwent_r(struct passwd *pwbuf, char *buf, size_t buflen, struct passwd **pwbufp);
 int getgrent_r(struct group *gbuf, char *buf, size_t buflen, struct group **gbufp);
 int capset(cap_user_header_t hdrp, const cap_user_data_t datap); /* real_func=pseudo_capset */
+long syscall(long nr, ...); /* hand_wrapped=1 */
+int renameat2(int olddirfd, const char *oldpath, int newdirfd, const char *newpath, unsigned int flags); /* flags=AT_SYMLINK_NOFOLLOW */
diff --git a/ports/linux/xattr/guts/fgetxattr.c b/ports/linux/xattr/guts/fgetxattr.c
index ae8c3a3..91a4bd6 100644
--- a/ports/linux/xattr/guts/fgetxattr.c
+++ b/ports/linux/xattr/guts/fgetxattr.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2014 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * ssize_t fgetxattr(int filedes, const char *name, void *value, size_t size)
  *	ssize_t rc = -1;
  */
diff --git a/ports/linux/xattr/guts/flistxattr.c b/ports/linux/xattr/guts/flistxattr.c
index cdd9454..aeb7e4e 100644
--- a/ports/linux/xattr/guts/flistxattr.c
+++ b/ports/linux/xattr/guts/flistxattr.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2014 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * ssize_t flistxattr(int filedes, char *list, size_t size)
  *	ssize_t rc = -1;
  */
diff --git a/ports/linux/xattr/guts/fremovexattr.c b/ports/linux/xattr/guts/fremovexattr.c
index a029d2c..e6c5b0d 100644
--- a/ports/linux/xattr/guts/fremovexattr.c
+++ b/ports/linux/xattr/guts/fremovexattr.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2014 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int fremovexattr(int filedes, const char *name)
  *	int rc = -1;
  */
diff --git a/ports/linux/xattr/guts/fsetxattr.c b/ports/linux/xattr/guts/fsetxattr.c
index 376cf08..679c1f6 100644
--- a/ports/linux/xattr/guts/fsetxattr.c
+++ b/ports/linux/xattr/guts/fsetxattr.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2014 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int fsetxattr(int filedes, const char *name, const void *value, size_t size, int xflags)
  *	int rc = -1;
  */
diff --git a/ports/linux/xattr/guts/getxattr.c b/ports/linux/xattr/guts/getxattr.c
index 7bd2bf5..20e7c72 100644
--- a/ports/linux/xattr/guts/getxattr.c
+++ b/ports/linux/xattr/guts/getxattr.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2014 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * ssize_t getxattr(const char *path, const char *name, void *value, size_t size)
  *	ssize_t rc = -1;
  */
diff --git a/ports/linux/xattr/guts/lgetxattr.c b/ports/linux/xattr/guts/lgetxattr.c
index 675d3da..f24771e 100644
--- a/ports/linux/xattr/guts/lgetxattr.c
+++ b/ports/linux/xattr/guts/lgetxattr.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2014 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * ssize_t lgetxattr(const char *path, const char *name, void *value, size_t size)
  *	ssize_t rc = -1;
  */
diff --git a/ports/linux/xattr/guts/listxattr.c b/ports/linux/xattr/guts/listxattr.c
index 0decf71..ac733b2 100644
--- a/ports/linux/xattr/guts/listxattr.c
+++ b/ports/linux/xattr/guts/listxattr.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2014 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * ssize_t listxattr(const char *path, char *list, size_t size)
  *	ssize_t rc = -1;
  */
diff --git a/ports/linux/xattr/guts/llistxattr.c b/ports/linux/xattr/guts/llistxattr.c
index 9934256..42bbf10 100644
--- a/ports/linux/xattr/guts/llistxattr.c
+++ b/ports/linux/xattr/guts/llistxattr.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2014 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * ssize_t llistxattr(const char *path, char *list, size_t size)
  *	ssize_t rc = -1;
  */
diff --git a/ports/linux/xattr/guts/lremovexattr.c b/ports/linux/xattr/guts/lremovexattr.c
index 1f39788..38c83dc 100644
--- a/ports/linux/xattr/guts/lremovexattr.c
+++ b/ports/linux/xattr/guts/lremovexattr.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2014 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int lremovexattr(const char *path, const char *name)
  *	int rc = -1;
  */
diff --git a/ports/linux/xattr/guts/lsetxattr.c b/ports/linux/xattr/guts/lsetxattr.c
index 9fe35bc..8eeec75 100644
--- a/ports/linux/xattr/guts/lsetxattr.c
+++ b/ports/linux/xattr/guts/lsetxattr.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2014 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int lsetxattr(const char *path, const char *name, const void *value, size_t size, int xflags)
  *	int rc = -1;
  */
diff --git a/ports/linux/xattr/guts/removexattr.c b/ports/linux/xattr/guts/removexattr.c
index 0d4d8e3..2b5719f 100644
--- a/ports/linux/xattr/guts/removexattr.c
+++ b/ports/linux/xattr/guts/removexattr.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2014 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int removexattr(const char *path, const char *name)
  *	int rc = -1;
  */
diff --git a/ports/linux/xattr/guts/setxattr.c b/ports/linux/xattr/guts/setxattr.c
index bace0d8..ba318ee 100644
--- a/ports/linux/xattr/guts/setxattr.c
+++ b/ports/linux/xattr/guts/setxattr.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2014 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int setxattr(const char *path, const char *name, const void *value, size_t size, int xflags)
  *	int rc = -1;
  */
diff --git a/ports/linux/xattr/portdefs.h b/ports/linux/xattr/portdefs.h
index 367ca60..56cd3ca 100644
--- a/ports/linux/xattr/portdefs.h
+++ b/ports/linux/xattr/portdefs.h
@@ -1,2 +1,6 @@
+/*
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
 #include <attr/xattr.h>
 #include <stdint.h>
diff --git a/ports/linux/xattr/pseudo_wrappers.c b/ports/linux/xattr/pseudo_wrappers.c
index d69d53e..590af30 100644
--- a/ports/linux/xattr/pseudo_wrappers.c
+++ b/ports/linux/xattr/pseudo_wrappers.c
@@ -1,3 +1,7 @@
+/*
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
 /* shared functionality for the xattr code */
 /* Each of these functions is expecting to get an optional name, and
  * a populated statbuf to use for sending messages to the server.
@@ -97,6 +101,21 @@ posix_permissions(const acl_header *header, int entries, int *extra, int *mode)
 	return 0;
 }
 
+static int get_special_bits(const char *path, int fd) {
+	int rc;
+	struct stat64 buf;
+	if (path) {
+		rc = lstat64(path, &buf);
+	} else {
+		rc = fstat64(fd, &buf);
+	}
+	if (rc == -1) {
+		return rc;
+	}
+
+	return buf.st_mode & (S_ISUID | S_ISGID | S_ISVTX);
+}
+
 #define RC_AND_BUF \
 	int rc; \
 	PSEUDO_STATBUF buf; \
@@ -172,6 +191,10 @@ static int shared_setxattr(const char *path, int fd, const char *name, const voi
 		int entries = (size - sizeof(acl_header)) / sizeof(acl_entry);
 		int res = posix_permissions(value, entries, &extra, &mode);
 		if (res == 0) {
+			/* POSIX ACLs don't actually include
+			 * setuid/setgid/sticky bit. We need to add those back
+			 * in ourselves. */
+			mode |= get_special_bits(path, fd);
 			pseudo_debug(PDBGF_XATTR, "posix_acl_access translated to mode %04o. Remaining attribute(s): %d.\n",
 				mode, extra);
 			buf.st_mode = mode;
diff --git a/ports/uids_generic/guts/COPYRIGHT b/ports/uids_generic/guts/COPYRIGHT
index c96e1b1..b860a36 100644
--- a/ports/uids_generic/guts/COPYRIGHT
+++ b/ports/uids_generic/guts/COPYRIGHT
@@ -1,17 +1,6 @@
 /*
  * Copyright (c) 2008-2010 Wind River Systems, Inc.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the Lesser GNU General Public License version 2.1 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the Lesser GNU General Public License for more details.
- *
- * You should have received a copy of the Lesser GNU General Public License
- * version 2.1 along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
+ * SPDX-License-Identifier: LGPL-2.1-only
  *
  */
diff --git a/ports/uids_generic/guts/endgrent.c b/ports/uids_generic/guts/endgrent.c
index 843cad0..8ddbb99 100644
--- a/ports/uids_generic/guts/endgrent.c
+++ b/ports/uids_generic/guts/endgrent.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static void
  * wrap_endgrent(void) {
  *	
diff --git a/ports/uids_generic/guts/endpwent.c b/ports/uids_generic/guts/endpwent.c
index f76cf10..92947ea 100644
--- a/ports/uids_generic/guts/endpwent.c
+++ b/ports/uids_generic/guts/endpwent.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static void
  * wrap_endpwent(void) {
  *	
diff --git a/ports/uids_generic/guts/getegid.c b/ports/uids_generic/guts/getegid.c
index 7c14f48..56e9d44 100644
--- a/ports/uids_generic/guts/getegid.c
+++ b/ports/uids_generic/guts/getegid.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static gid_t
  * wrap_getegid(void) {
  *	gid_t rc = 0;
diff --git a/ports/uids_generic/guts/geteuid.c b/ports/uids_generic/guts/geteuid.c
index 1745e13..276a51d 100644
--- a/ports/uids_generic/guts/geteuid.c
+++ b/ports/uids_generic/guts/geteuid.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static uid_t
  * wrap_geteuid(void) {
  *	uid_t rc = 0;
diff --git a/ports/uids_generic/guts/getgid.c b/ports/uids_generic/guts/getgid.c
index ca8bad3..43e18d0 100644
--- a/ports/uids_generic/guts/getgid.c
+++ b/ports/uids_generic/guts/getgid.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static gid_t
  * wrap_getgid(void) {
  *	gid_t rc = 0;
diff --git a/ports/uids_generic/guts/getgrent.c b/ports/uids_generic/guts/getgrent.c
index d6592e6..ff0051b 100644
--- a/ports/uids_generic/guts/getgrent.c
+++ b/ports/uids_generic/guts/getgrent.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static struct group *
  * wrap_getgrent(void) {
  *	struct group * rc = NULL;
diff --git a/ports/uids_generic/guts/getgrgid.c b/ports/uids_generic/guts/getgrgid.c
index 0d3dafb..29af413 100644
--- a/ports/uids_generic/guts/getgrgid.c
+++ b/ports/uids_generic/guts/getgrgid.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static struct group *
  * wrap_getgrgid(gid_t gid) {
  *	struct group * rc = NULL;
diff --git a/ports/uids_generic/guts/getgrgid_r.c b/ports/uids_generic/guts/getgrgid_r.c
index b043995..0c5ae44 100644
--- a/ports/uids_generic/guts/getgrgid_r.c
+++ b/ports/uids_generic/guts/getgrgid_r.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_getgrgid_r(gid_t gid, struct group *gbuf, char *buf, size_t buflen, struct group **gbufp) {
  *	int rc = -1;
diff --git a/ports/uids_generic/guts/getgrnam.c b/ports/uids_generic/guts/getgrnam.c
index 19006ad..7644e3a 100644
--- a/ports/uids_generic/guts/getgrnam.c
+++ b/ports/uids_generic/guts/getgrnam.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static struct group *
  * wrap_getgrnam(const char *name) {
  *	struct group * rc = NULL;
diff --git a/ports/uids_generic/guts/getgrnam_r.c b/ports/uids_generic/guts/getgrnam_r.c
index 39de641..e2196ef 100644
--- a/ports/uids_generic/guts/getgrnam_r.c
+++ b/ports/uids_generic/guts/getgrnam_r.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_getgrnam_r(const char *name, struct group *gbuf, char *buf, size_t buflen, struct group **gbufp) {
  *	int rc = -1;
diff --git a/ports/uids_generic/guts/getpwent.c b/ports/uids_generic/guts/getpwent.c
index 3b1f837..a860e7e 100644
--- a/ports/uids_generic/guts/getpwent.c
+++ b/ports/uids_generic/guts/getpwent.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static struct passwd *
  * wrap_getpwent(void) {
  *	struct passwd * rc = NULL;
diff --git a/ports/uids_generic/guts/getpwnam.c b/ports/uids_generic/guts/getpwnam.c
index 024b3d8..0f99038 100644
--- a/ports/uids_generic/guts/getpwnam.c
+++ b/ports/uids_generic/guts/getpwnam.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static struct passwd *
  * wrap_getpwnam(const char *name) {
  *	struct passwd * rc = NULL;
diff --git a/ports/uids_generic/guts/getpwnam_r.c b/ports/uids_generic/guts/getpwnam_r.c
index 5d7a4ea..cb9f2c6 100644
--- a/ports/uids_generic/guts/getpwnam_r.c
+++ b/ports/uids_generic/guts/getpwnam_r.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_getpwnam_r(const char *name, struct passwd *pwbuf, char *buf, size_t buflen, struct passwd **pwbufp) {
  *	int rc = -1;
diff --git a/ports/uids_generic/guts/getpwuid.c b/ports/uids_generic/guts/getpwuid.c
index 11142de..315647c 100644
--- a/ports/uids_generic/guts/getpwuid.c
+++ b/ports/uids_generic/guts/getpwuid.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static struct passwd *
  * wrap_getpwuid(uid_t uid) {
  *	struct passwd * rc = NULL;
diff --git a/ports/uids_generic/guts/getpwuid_r.c b/ports/uids_generic/guts/getpwuid_r.c
index 06b920e..bfeb649 100644
--- a/ports/uids_generic/guts/getpwuid_r.c
+++ b/ports/uids_generic/guts/getpwuid_r.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_getpwuid_r(uid_t uid, struct passwd *pwbuf, char *buf, size_t buflen, struct passwd **pwbufp) {
  *	int rc = -1;
diff --git a/ports/uids_generic/guts/getuid.c b/ports/uids_generic/guts/getuid.c
index e783cc8..3945836 100644
--- a/ports/uids_generic/guts/getuid.c
+++ b/ports/uids_generic/guts/getuid.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static uid_t
  * wrap_getuid(void) {
  *	uid_t rc = 0;
diff --git a/ports/uids_generic/guts/setegid.c b/ports/uids_generic/guts/setegid.c
index ff777a0..d6ddca7 100644
--- a/ports/uids_generic/guts/setegid.c
+++ b/ports/uids_generic/guts/setegid.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_setegid(gid_t egid) {
  *	int rc = -1;
diff --git a/ports/uids_generic/guts/seteuid.c b/ports/uids_generic/guts/seteuid.c
index 430768f..032e5f1 100644
--- a/ports/uids_generic/guts/seteuid.c
+++ b/ports/uids_generic/guts/seteuid.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_seteuid(uid_t euid) {
  *	int rc = -1;
diff --git a/ports/uids_generic/guts/setgid.c b/ports/uids_generic/guts/setgid.c
index b94db1a..c5746f9 100644
--- a/ports/uids_generic/guts/setgid.c
+++ b/ports/uids_generic/guts/setgid.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_setgid(gid_t gid) {
  *	int rc = -1;
diff --git a/ports/uids_generic/guts/setgrent.c b/ports/uids_generic/guts/setgrent.c
index 75aab61..97faec0 100644
--- a/ports/uids_generic/guts/setgrent.c
+++ b/ports/uids_generic/guts/setgrent.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static void
  * wrap_setgrent(void) {
  *	
diff --git a/ports/uids_generic/guts/setpwent.c b/ports/uids_generic/guts/setpwent.c
index fb35e07..53661fd 100644
--- a/ports/uids_generic/guts/setpwent.c
+++ b/ports/uids_generic/guts/setpwent.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static void
  * wrap_setpwent(void) {
  *	
diff --git a/ports/uids_generic/guts/setregid.c b/ports/uids_generic/guts/setregid.c
index 78b2037..865553f 100644
--- a/ports/uids_generic/guts/setregid.c
+++ b/ports/uids_generic/guts/setregid.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_setregid(gid_t rgid, gid_t egid) {
  *	int rc = -1;
diff --git a/ports/uids_generic/guts/setreuid.c b/ports/uids_generic/guts/setreuid.c
index 3ff82ab..d189d65 100644
--- a/ports/uids_generic/guts/setreuid.c
+++ b/ports/uids_generic/guts/setreuid.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_setreuid(uid_t ruid, uid_t euid) {
  *	int rc = -1;
diff --git a/ports/uids_generic/guts/setuid.c b/ports/uids_generic/guts/setuid.c
index 6bfdf6c..831f8ff 100644
--- a/ports/uids_generic/guts/setuid.c
+++ b/ports/uids_generic/guts/setuid.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_setuid(uid_t uid) {
  *	int rc = -1;
diff --git a/ports/unix/guts/COPYRIGHT b/ports/unix/guts/COPYRIGHT
index c96e1b1..b860a36 100644
--- a/ports/unix/guts/COPYRIGHT
+++ b/ports/unix/guts/COPYRIGHT
@@ -1,17 +1,6 @@
 /*
  * Copyright (c) 2008-2010 Wind River Systems, Inc.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the Lesser GNU General Public License version 2.1 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the Lesser GNU General Public License for more details.
- *
- * You should have received a copy of the Lesser GNU General Public License
- * version 2.1 along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
+ * SPDX-License-Identifier: LGPL-2.1-only
  *
  */
diff --git a/ports/unix/guts/access.c b/ports/unix/guts/access.c
index 0093a3b..1cc8d58 100644
--- a/ports/unix/guts/access.c
+++ b/ports/unix/guts/access.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010, 2012 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_access(const char *path, int mode) {
  *	int rc = -1;
diff --git a/ports/unix/guts/acct.c b/ports/unix/guts/acct.c
index b8dca5d..4acd3fb 100644
--- a/ports/unix/guts/acct.c
+++ b/ports/unix/guts/acct.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_acct(const char *path) {
  *	int rc = -1;
diff --git a/ports/unix/guts/bind.c b/ports/unix/guts/bind.c
index 46164be..6f8a1d2 100644
--- a/ports/unix/guts/bind.c
+++ b/ports/unix/guts/bind.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2016 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
  *	int rc = -1;
  */
diff --git a/ports/unix/guts/chdir.c b/ports/unix/guts/chdir.c
index 9e30348..d796c2e 100644
--- a/ports/unix/guts/chdir.c
+++ b/ports/unix/guts/chdir.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_chdir(const char *path) {
  *	int rc = -1;
diff --git a/ports/unix/guts/chmod.c b/ports/unix/guts/chmod.c
index a157335..77a5c9a 100644
--- a/ports/unix/guts/chmod.c
+++ b/ports/unix/guts/chmod.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_chmod(const char *path, mode_t mode) {
  *	int rc = -1;
diff --git a/ports/unix/guts/chown.c b/ports/unix/guts/chown.c
index 4fcbdda..69bef79 100644
--- a/ports/unix/guts/chown.c
+++ b/ports/unix/guts/chown.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_chown(const char *path, uid_t owner, gid_t group) {
  *	int rc = -1;
diff --git a/ports/unix/guts/chroot.c b/ports/unix/guts/chroot.c
index ac24955..62d5e88 100644
--- a/ports/unix/guts/chroot.c
+++ b/ports/unix/guts/chroot.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_chroot(const char *path) {
  *	int rc = -1;
diff --git a/ports/unix/guts/close.c b/ports/unix/guts/close.c
index 09c73e6..2f1c385 100644
--- a/ports/unix/guts/close.c
+++ b/ports/unix/guts/close.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_close(int fd) {
  *	int rc = -1;
diff --git a/ports/unix/guts/closedir.c b/ports/unix/guts/closedir.c
index 1085361..32c008f 100644
--- a/ports/unix/guts/closedir.c
+++ b/ports/unix/guts/closedir.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2012 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_closedir(DIR *dirp) {
  *	int rc = -1;
diff --git a/ports/unix/guts/creat.c b/ports/unix/guts/creat.c
index 8593cd4..7aaf735 100644
--- a/ports/unix/guts/creat.c
+++ b/ports/unix/guts/creat.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_creat(const char *path, mode_t mode) {
  *	int rc = -1;
diff --git a/ports/unix/guts/dup.c b/ports/unix/guts/dup.c
index 927b264..be8626a 100644
--- a/ports/unix/guts/dup.c
+++ b/ports/unix/guts/dup.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_dup(int fd) {
  *	int rc = -1;
diff --git a/ports/unix/guts/dup2.c b/ports/unix/guts/dup2.c
index 8180039..0b20f01 100644
--- a/ports/unix/guts/dup2.c
+++ b/ports/unix/guts/dup2.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_dup2(int oldfd, int newfd) {
  *	int rc = -1;
diff --git a/ports/unix/guts/fchdir.c b/ports/unix/guts/fchdir.c
index ba77ebf..cace897 100644
--- a/ports/unix/guts/fchdir.c
+++ b/ports/unix/guts/fchdir.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_fchdir(int dirfd) {
  *	int rc = -1;
diff --git a/ports/unix/guts/fchmod.c b/ports/unix/guts/fchmod.c
index e2301e3..4d2d127 100644
--- a/ports/unix/guts/fchmod.c
+++ b/ports/unix/guts/fchmod.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010, 2012, 2013 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_fchmod(int fd, mode_t mode) {
  *	int rc = -1;
diff --git a/ports/unix/guts/fchmodat.c b/ports/unix/guts/fchmodat.c
index 0506794..55dbd35 100644
--- a/ports/unix/guts/fchmodat.c
+++ b/ports/unix/guts/fchmodat.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010, 2012, 2013 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_fchmodat(int dirfd, const char *path, mode_t mode, int flags) {
  *	int rc = -1;
diff --git a/ports/unix/guts/fchown.c b/ports/unix/guts/fchown.c
index 89cabe2..fb3343d 100644
--- a/ports/unix/guts/fchown.c
+++ b/ports/unix/guts/fchown.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010, 2012, 2013 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_fchown(int fd, uid_t owner, gid_t group) {
  *	int rc = -1;
diff --git a/ports/unix/guts/fchownat.c b/ports/unix/guts/fchownat.c
index 2888087..76d276a 100644
--- a/ports/unix/guts/fchownat.c
+++ b/ports/unix/guts/fchownat.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010, 2012, 2013 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_fchownat(int dirfd, const char *path, uid_t owner, gid_t group, int flags) {
  *	int rc = -1;
diff --git a/ports/unix/guts/fclose.c b/ports/unix/guts/fclose.c
index 4469f5b..15d0f85 100644
--- a/ports/unix/guts/fclose.c
+++ b/ports/unix/guts/fclose.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_fclose(FILE *fp) {
  *	int rc = -1;
diff --git a/ports/unix/guts/fdatasync.c b/ports/unix/guts/fdatasync.c
index 4aa77a8..594ad8f 100644
--- a/ports/unix/guts/fdatasync.c
+++ b/ports/unix/guts/fdatasync.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2013 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int fdatasync(int fd)
  *	int rc = -1;
  */
diff --git a/ports/unix/guts/fopen.c b/ports/unix/guts/fopen.c
index 87c7d78..26a6abc 100644
--- a/ports/unix/guts/fopen.c
+++ b/ports/unix/guts/fopen.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010, 2012 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static FILE *
  * wrap_fopen(const char *path, const char *mode) {
  *	FILE * rc = 0;
diff --git a/ports/unix/guts/freopen.c b/ports/unix/guts/freopen.c
index e706d9f..703b6aa 100644
--- a/ports/unix/guts/freopen.c
+++ b/ports/unix/guts/freopen.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static FILE *
  * wrap_freopen(const char *path, const char *mode, FILE *stream) {
  *	FILE * rc = NULL;
diff --git a/ports/unix/guts/fsync.c b/ports/unix/guts/fsync.c
index 6c87a56..c78f43c 100644
--- a/ports/unix/guts/fsync.c
+++ b/ports/unix/guts/fsync.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2013 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int fsync(int fd)
  *	int rc = -1;
  */
diff --git a/ports/unix/guts/fts_open.c b/ports/unix/guts/fts_open.c
index 964314e..e5b27ba 100644
--- a/ports/unix/guts/fts_open.c
+++ b/ports/unix/guts/fts_open.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static FTS *
  * wrap_fts_open(char * const *path_argv, int options, int (*compar)(const FTSENT **, const FTSENT **)) {
  *	FTS * rc = NULL;
diff --git a/ports/unix/guts/ftw.c b/ports/unix/guts/ftw.c
index 0861194..58945a1 100644
--- a/ports/unix/guts/ftw.c
+++ b/ports/unix/guts/ftw.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_ftw(const char *path, int (*fn)(const char *, const struct stat *, int), int nopenfd) {
  *	int rc = -1;
diff --git a/ports/unix/guts/getcwd.c b/ports/unix/guts/getcwd.c
index 2915a18..a5bf2ef 100644
--- a/ports/unix/guts/getcwd.c
+++ b/ports/unix/guts/getcwd.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static char *
  * wrap_getcwd(char *buf, size_t size) {
  *	char * rc = NULL;
diff --git a/ports/unix/guts/getwd.c b/ports/unix/guts/getwd.c
index b1bcf90..bc99f93 100644
--- a/ports/unix/guts/getwd.c
+++ b/ports/unix/guts/getwd.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static char *
  * wrap_getwd(char *buf) {
  *	char * rc = NULL;
diff --git a/ports/unix/guts/glob.c b/ports/unix/guts/glob.c
index 0012179..8c17123 100644
--- a/ports/unix/guts/glob.c
+++ b/ports/unix/guts/glob.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_glob(const char *pattern, int flags, int (*errfunc)(const char *, int), glob_t *pglob) {
  *	int rc = -1;
diff --git a/ports/unix/guts/lchown.c b/ports/unix/guts/lchown.c
index 60727d0..3a14e2f 100644
--- a/ports/unix/guts/lchown.c
+++ b/ports/unix/guts/lchown.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008,2011 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int lchown(const char *path, uid_t owner, gid_t group)
  *	int rc = -1;
  */
diff --git a/ports/unix/guts/link.c b/ports/unix/guts/link.c
index 3b340ee..1e03902 100644
--- a/ports/unix/guts/link.c
+++ b/ports/unix/guts/link.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010, 2012, 2013 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_link(const char *oldname, const char *newname) {
  *	int rc = -1;
diff --git a/ports/unix/guts/linkat.c b/ports/unix/guts/linkat.c
index 279a15b..381f9d0 100644
--- a/ports/unix/guts/linkat.c
+++ b/ports/unix/guts/linkat.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2012, 2013 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int linkat(int olddirfd, const char *oldname, int newdirfd, const char *newname, int flags)
  *	int rc = -1;
  */
diff --git a/ports/unix/guts/lutimes.c b/ports/unix/guts/lutimes.c
index cdadbbd..07cab66 100644
--- a/ports/unix/guts/lutimes.c
+++ b/ports/unix/guts/lutimes.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_lutimes(const char *path, const struct timeval *tv) {
  *	int rc = -1;
diff --git a/ports/unix/guts/mkdir.c b/ports/unix/guts/mkdir.c
index 9f116e2..2eaf81b 100644
--- a/ports/unix/guts/mkdir.c
+++ b/ports/unix/guts/mkdir.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_mkdir(const char *path, mode_t mode) {
  *	int rc = -1;
diff --git a/ports/unix/guts/mkdirat.c b/ports/unix/guts/mkdirat.c
index ef2e3a1..f66e99a 100644
--- a/ports/unix/guts/mkdirat.c
+++ b/ports/unix/guts/mkdirat.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010, 2012 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_mkdirat(int dirfd, const char *path, mode_t mode) {
  *	int rc = -1;
diff --git a/ports/unix/guts/mkdtemp.c b/ports/unix/guts/mkdtemp.c
index 5337661..61cd11c 100644
--- a/ports/unix/guts/mkdtemp.c
+++ b/ports/unix/guts/mkdtemp.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010, 2012 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static char *
  * wrap_mkdtemp(char *template) {
  *	char * rc = NULL;
diff --git a/ports/unix/guts/mkfifo.c b/ports/unix/guts/mkfifo.c
index 32f79fb..81d9c0c 100644
--- a/ports/unix/guts/mkfifo.c
+++ b/ports/unix/guts/mkfifo.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_mkfifo(const char *path, mode_t mode) {
  *	int rc = -1;
diff --git a/ports/unix/guts/mkfifoat.c b/ports/unix/guts/mkfifoat.c
index 6947e70..bc547eb 100644
--- a/ports/unix/guts/mkfifoat.c
+++ b/ports/unix/guts/mkfifoat.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2015 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_mkfifoat(int dirfd, const char *path, mode_t mode) {
  *	int rc = -1;
diff --git a/ports/unix/guts/mknod.c b/ports/unix/guts/mknod.c
index eeca65d..aff3a0b 100644
--- a/ports/unix/guts/mknod.c
+++ b/ports/unix/guts/mknod.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2011,2014 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int mknod(const char *path, mode_t mode, dev_t dev)
  *	int rc = -1;
  */
diff --git a/ports/unix/guts/mknodat.c b/ports/unix/guts/mknodat.c
index afeab46..9e86c93 100644
--- a/ports/unix/guts/mknodat.c
+++ b/ports/unix/guts/mknodat.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2011 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int mknodat(int dirfd, const char *path, mode_t mode, dev_t dev)
  *	int rc = -1;
  */
diff --git a/ports/unix/guts/mkostemp.c b/ports/unix/guts/mkostemp.c
new file mode 100644
index 0000000..199ff20
--- /dev/null
+++ b/ports/unix/guts/mkostemp.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2018 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ * int mkostemp(char *template, int oflags)
+ *	int rc = -1;
+ */
+
+	/* mkostemp = mkostemps() with suffixlen of 0 */
+	rc = wrap_mkostemps(template, 0, oflags);
+
+/*	return rc;
+ * }
+ */
diff --git a/ports/unix/guts/mkostemps.c b/ports/unix/guts/mkostemps.c
new file mode 100644
index 0000000..013757d
--- /dev/null
+++ b/ports/unix/guts/mkostemps.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2008-2010, 2012 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * Copyright (c) 2018 Peter Seebach; see
+ * guts/COPYRIGHT for information.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ * int mkostemps(char *template, int suffixlen, int oflags)
+ *	int rc = -1;
+ */
+
+	PSEUDO_STATBUF buf;
+ 	int save_errno;
+	size_t len;
+	char *tmp_template;
+
+	if (!template) {
+		errno = EFAULT;
+		return 0;
+	}
+
+	len = strlen(template);
+	tmp_template = PSEUDO_ROOT_PATH(AT_FDCWD, template, AT_SYMLINK_NOFOLLOW);
+
+	if (!tmp_template) {
+		errno = ENOENT;
+		return -1;
+	}
+
+	rc = real_mkostemps(tmp_template, suffixlen, oflags);
+
+	if (rc != -1) {
+		save_errno = errno;
+
+		if (base_fstat(rc, &buf) != -1) {
+			real_fchmod(rc, PSEUDO_FS_MODE(0600, 0));
+			pseudo_client_op(OP_CREAT, 0, -1, -1, tmp_template, &buf);
+			pseudo_client_op(OP_OPEN, PSA_READ | PSA_WRITE, rc, -1, tmp_template, &buf);
+		} else {
+			pseudo_debug(PDBGF_CONSISTENCY, "mkstemp (fd %d) succeeded, but fstat failed (%s).\n",
+				rc, strerror(errno));
+			pseudo_client_op(OP_OPEN, PSA_READ | PSA_WRITE, rc, -1, tmp_template, 0);
+		}
+		errno = save_errno;
+	}
+	/* WARNING: At least one system allows the number of Xs to be something
+	 * other than 6. I do not attempt to handle this.
+	 */
+	/* mkstemp only changes the XXXXXX at the end, or suffixlen characters before
+	 * the end if mkostemp/mkostemps.
+	 */
+	memcpy(template + len - 6 - suffixlen, tmp_template + strlen(tmp_template) - 6 - suffixlen, 6);
+/*	return rc;
+ * }
+ */
diff --git a/ports/unix/guts/mkstemp.c b/ports/unix/guts/mkstemp.c
index 1e2b026..0aab6ed 100644
--- a/ports/unix/guts/mkstemp.c
+++ b/ports/unix/guts/mkstemp.c
@@ -2,46 +2,15 @@
  * Copyright (c) 2008-2010, 2012 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_mkstemp(char *template) {
  *	int rc = -1;
  */
-	PSEUDO_STATBUF buf;
- 	int save_errno;
-	size_t len;
-	char *tmp_template;
-
-	if (!template) {
-		errno = EFAULT;
-		return 0;
-	}
-
-	len = strlen(template);
-	tmp_template = PSEUDO_ROOT_PATH(AT_FDCWD, template, AT_SYMLINK_NOFOLLOW);
-
-	if (!tmp_template) {
-		errno = ENOENT;
-		return -1;
-	}
-
-	rc = real_mkstemp(tmp_template);
-
-	if (rc != -1) {
-		save_errno = errno;
+	/* mkstemp() is just like mkostemps() with no flags and no suffix */
+	rc = wrap_mkostemps(template, 0, 0);
 
-		if (base_fstat(rc, &buf) != -1) {
-			real_fchmod(rc, PSEUDO_FS_MODE(0600, 0));
-			pseudo_client_op(OP_CREAT, 0, -1, -1, tmp_template, &buf);
-			pseudo_client_op(OP_OPEN, PSA_READ | PSA_WRITE, rc, -1, tmp_template, &buf);
-		} else {
-			pseudo_debug(PDBGF_CONSISTENCY, "mkstemp (fd %d) succeeded, but fstat failed (%s).\n",
-				rc, strerror(errno));
-			pseudo_client_op(OP_OPEN, PSA_READ | PSA_WRITE, rc, -1, tmp_template, 0);
-		}
-		errno = save_errno;
-	}
-	/* mkstemp only changes the XXXXXX at the end. */
-	memcpy(template + len - 6, tmp_template + strlen(tmp_template) - 6, 6);
 /*	return rc;
  * }
  */
diff --git a/ports/unix/guts/mkstemps.c b/ports/unix/guts/mkstemps.c
new file mode 100644
index 0000000..5b16457
--- /dev/null
+++ b/ports/unix/guts/mkstemps.c
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2018 Wind River Systems; see
+ * guts/COPYRIGHT for information.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ * int mkstemps(char *template, int suffixlen)
+ *	int rc = -1;
+ */
+
+	/* mkstemps() is mkostemps() with no flags */
+	rc = wrap_mkostemps(template, suffixlen, 0);
+
+/*	return rc;
+ * }
+ */
diff --git a/ports/unix/guts/mktemp.c b/ports/unix/guts/mktemp.c
index a39d1b7..9aee829 100644
--- a/ports/unix/guts/mktemp.c
+++ b/ports/unix/guts/mktemp.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static char *
  * wrap_mktemp(char *template) {
  *	char * rc = NULL;
diff --git a/ports/unix/guts/msync.c b/ports/unix/guts/msync.c
index fbc5e26..926ab50 100644
--- a/ports/unix/guts/msync.c
+++ b/ports/unix/guts/msync.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2013 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int msync(void *addr, size_t length, int flags)
  *	int rc = -1;
  */
diff --git a/ports/unix/guts/nftw.c b/ports/unix/guts/nftw.c
index 73daec8..dac3106 100644
--- a/ports/unix/guts/nftw.c
+++ b/ports/unix/guts/nftw.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_nftw(const char *path, int (*fn)(const char *, const struct stat *, int, struct FTW *), int nopenfd, int flag) {
  *	int rc = -1;
diff --git a/ports/unix/guts/opendir.c b/ports/unix/guts/opendir.c
index c8a78f8..5d6f1f2 100644
--- a/ports/unix/guts/opendir.c
+++ b/ports/unix/guts/opendir.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010, 2012 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static DIR *
  * wrap_opendir(const char *path) {
  *	DIR * rc = NULL;
diff --git a/ports/unix/guts/pathconf.c b/ports/unix/guts/pathconf.c
index c6caa34..9300595 100644
--- a/ports/unix/guts/pathconf.c
+++ b/ports/unix/guts/pathconf.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static long
  * wrap_pathconf(const char *path, int name) {
  *	long rc = -1;
diff --git a/ports/unix/guts/popen.c b/ports/unix/guts/popen.c
index 5d44c0e..d19ec7e 100644
--- a/ports/unix/guts/popen.c
+++ b/ports/unix/guts/popen.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2012 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * FILE *popen(const char *command, const char *mode)
  *	FILE *rc = NULL;
  */
diff --git a/ports/unix/guts/readlink.c b/ports/unix/guts/readlink.c
index 18d9dc7..4b3d492 100644
--- a/ports/unix/guts/readlink.c
+++ b/ports/unix/guts/readlink.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static ssize_t
  * wrap_readlink(const char *path, char *buf, size_t bufsiz) {
  *	ssize_t rc = -1;
diff --git a/ports/unix/guts/readlinkat.c b/ports/unix/guts/readlinkat.c
index 5282e2b..86832da 100644
--- a/ports/unix/guts/readlinkat.c
+++ b/ports/unix/guts/readlinkat.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static ssize_t
  * wrap_readlinkat(int dirfd, const char *path, char *buf, size_t bufsiz) {
  *	ssize_t rc = -1;
diff --git a/ports/unix/guts/realpath.c b/ports/unix/guts/realpath.c
index a59808d..085d2cb 100644
--- a/ports/unix/guts/realpath.c
+++ b/ports/unix/guts/realpath.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static char *
  * wrap_realpath(const char *name, char *resolved_name) {
  *	char * rc = NULL;
diff --git a/ports/unix/guts/remove.c b/ports/unix/guts/remove.c
index 4e2cecb..375e648 100644
--- a/ports/unix/guts/remove.c
+++ b/ports/unix/guts/remove.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010, 2012 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_remove(const char *path) {
  *	int rc = -1;
diff --git a/ports/unix/guts/rename.c b/ports/unix/guts/rename.c
index b8ee8b0..5073c71 100644
--- a/ports/unix/guts/rename.c
+++ b/ports/unix/guts/rename.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010, 2012 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_rename(const char *oldpath, const char *newpath) {
  *	int rc = -1;
diff --git a/ports/unix/guts/renameat.c b/ports/unix/guts/renameat.c
index d5e36fa..735a60a 100644
--- a/ports/unix/guts/renameat.c
+++ b/ports/unix/guts/renameat.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2012 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_renameat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath) {
  *	int rc = -1;
diff --git a/ports/unix/guts/rmdir.c b/ports/unix/guts/rmdir.c
index ebc522a..43fcecb 100644
--- a/ports/unix/guts/rmdir.c
+++ b/ports/unix/guts/rmdir.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010, 2012 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_rmdir(const char *path) {
  *	int rc = -1;
diff --git a/ports/unix/guts/symlink.c b/ports/unix/guts/symlink.c
index 487c135..ce9fa1b 100644
--- a/ports/unix/guts/symlink.c
+++ b/ports/unix/guts/symlink.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_symlink(const char *oldname, const char *newpath) {
  *	int rc = -1;
diff --git a/ports/unix/guts/symlinkat.c b/ports/unix/guts/symlinkat.c
index 1346db1..c96ff3e 100644
--- a/ports/unix/guts/symlinkat.c
+++ b/ports/unix/guts/symlinkat.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010, 2012 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_symlinkat(const char *oldname, int dirfd, const char *newpath) {
  *	int rc = -1;
diff --git a/ports/unix/guts/sync.c b/ports/unix/guts/sync.c
index c5d9554..a6eca98 100644
--- a/ports/unix/guts/sync.c
+++ b/ports/unix/guts/sync.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2013 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * void sync(void)
  *	
  */
diff --git a/ports/unix/guts/sync_file_range.c b/ports/unix/guts/sync_file_range.c
index 03cfc6c..7e03b7a 100644
--- a/ports/unix/guts/sync_file_range.c
+++ b/ports/unix/guts/sync_file_range.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2013 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int sync_file_range(int fd, off64_t offset, off64_t nbytes, unsigned int flags)
  *	int rc = -1;
  */
diff --git a/ports/unix/guts/system.c b/ports/unix/guts/system.c
index 6351592..1214314 100644
--- a/ports/unix/guts/system.c
+++ b/ports/unix/guts/system.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2011, 2012 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int system(const char *command)
  *	int rc = -1;
  */
diff --git a/ports/unix/guts/tempnam.c b/ports/unix/guts/tempnam.c
index 9b0257f..26ae3e1 100644
--- a/ports/unix/guts/tempnam.c
+++ b/ports/unix/guts/tempnam.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static char *
  * wrap_tempnam(const char *template, const char *pfx) {
  *	char * rc = NULL;
diff --git a/ports/unix/guts/tmpnam.c b/ports/unix/guts/tmpnam.c
index 3fece57..190d260 100644
--- a/ports/unix/guts/tmpnam.c
+++ b/ports/unix/guts/tmpnam.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static char *
  * wrap_tmpnam(char *s) {
  *	char * rc = NULL;
diff --git a/ports/unix/guts/truncate.c b/ports/unix/guts/truncate.c
index 6a19a50..6a51105 100644
--- a/ports/unix/guts/truncate.c
+++ b/ports/unix/guts/truncate.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_truncate(const char *path, off_t length) {
  *	int rc = -1;
diff --git a/ports/unix/guts/umask.c b/ports/unix/guts/umask.c
index 6b060d3..df1fbb3 100644
--- a/ports/unix/guts/umask.c
+++ b/ports/unix/guts/umask.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2014 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * mode_t umask(mode_t mask)
  *	mode_t rc = 0;
  */
diff --git a/ports/unix/guts/unlink.c b/ports/unix/guts/unlink.c
index d8a5d01..fe96cad 100644
--- a/ports/unix/guts/unlink.c
+++ b/ports/unix/guts/unlink.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_unlink(const char *path) {
  *	int rc = -1;
diff --git a/ports/unix/guts/unlinkat.c b/ports/unix/guts/unlinkat.c
index e723a01..7e4f87c 100644
--- a/ports/unix/guts/unlinkat.c
+++ b/ports/unix/guts/unlinkat.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2008-2010, 2012 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_unlinkat(int dirfd, const char *path, int rflags) {
  *	int rc = -1;
diff --git a/ports/unix/guts/utime.c b/ports/unix/guts/utime.c
index ff65237..c726ff8 100644
--- a/ports/unix/guts/utime.c
+++ b/ports/unix/guts/utime.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_utime(const char *path, const struct utimbuf *buf) {
  *	int rc = -1;
diff --git a/ports/unix/guts/utimes.c b/ports/unix/guts/utimes.c
index 69ad949..ec49f02 100644
--- a/ports/unix/guts/utimes.c
+++ b/ports/unix/guts/utimes.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2010 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * static int
  * wrap_utimes(const char *path, const struct timeval *times) {
  *	int rc = -1;
diff --git a/ports/unix/pseudo_wrappers.c b/ports/unix/pseudo_wrappers.c
index b825d56..bf69aa9 100644
--- a/ports/unix/pseudo_wrappers.c
+++ b/ports/unix/pseudo_wrappers.c
@@ -1,3 +1,7 @@
+/*
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
 FILE *
 popen(const char *command, const char *mode) {
 	sigset_t saved;
diff --git a/ports/unix/syncfs/guts/syncfs.c b/ports/unix/syncfs/guts/syncfs.c
index 2c9a685..76b509e 100644
--- a/ports/unix/syncfs/guts/syncfs.c
+++ b/ports/unix/syncfs/guts/syncfs.c
@@ -2,6 +2,8 @@
  * Copyright (c) 2013 Wind River Systems; see
  * guts/COPYRIGHT for information.
  *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * int syncfs(int fd)
  *	int rc = -1;
  */
diff --git a/ports/unix/wrapfuncs.in b/ports/unix/wrapfuncs.in
index 2addb27..3910fae 100644
--- a/ports/unix/wrapfuncs.in
+++ b/ports/unix/wrapfuncs.in
@@ -46,6 +46,9 @@ int mkfifoat(int dirfd, const char *path, mode_t mode); /* flags=AT_SYMLINK_NOFO
 int mknod(const char *path, mode_t mode, dev_t dev); /* flags=AT_SYMLINK_NOFOLLOW */
 int mknodat(int dirfd, const char *path, mode_t mode, dev_t dev); /* flags=AT_SYMLINK_NOFOLLOW */
 int mkstemp(char *template); /* flags=AT_SYMLINK_NOFOLLOW */
+int mkostemp(char *template, int oflags); /* flags=AT_SYMLINK_NOFOLLOW */
+int mkstemps(char *template, int suffixlen); /* flags=AT_SYMLINK_NOFOLLOW */
+int mkostemps(char *template, int suffixlen, int oflags); /* flags=AT_SYMLINK_NOFOLLOW */
 int rename(const char *oldpath, const char *newpath); /* flags=AT_SYMLINK_NOFOLLOW */
 int renameat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath); /* flags=AT_SYMLINK_NOFOLLOW */
 int rmdir(const char *path); /* flags=AT_SYMLINK_NOFOLLOW */
diff --git a/pseudo.c b/pseudo.c
index a3bc7fa..0f5850e 100644
--- a/pseudo.c
+++ b/pseudo.c
@@ -3,18 +3,7 @@
  *
  * Copyright (c) 2008-2013 Wind River Systems, Inc.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the Lesser GNU General Public License version 2.1 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the Lesser GNU General Public License for more details.
- *
- * You should have received a copy of the Lesser GNU General Public License
- * version 2.1 along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
+ * SPDX-License-Identifier: LGPL-2.1-only
  *
  */
 #include <stdlib.h>
@@ -444,7 +433,7 @@ pseudo_op(pseudo_msg_t *msg, const char *program, const char *tag, char **respon
 	char *path_by_ino = 0;
 	char *oldpath = 0;
 	size_t oldpathlen = 0;
-	int found_path = 0, found_ino = 0;
+	int found_path = 0, found_ino = 0, found_exact = 0;
 	int prefer_ino = 0;
 	int xattr_flags = 0;
 	int trailing_slash = 0;
@@ -543,6 +532,7 @@ pseudo_op(pseudo_msg_t *msg, const char *program, const char *tag, char **respon
 			*msg = msg_header;
 			found_path = 1;
 			found_ino = 1;
+			found_exact = 1;
 			/* note:  we have to avoid freeing this later */
 			path_by_ino = msg->path;
 			if (msg->op == OP_LINK) {
@@ -629,15 +619,15 @@ pseudo_op(pseudo_msg_t *msg, const char *program, const char *tag, char **respon
 			pseudo_diag("dir mismatch: '%s' [%llu] db mode 0%o, header mode 0%o (unlinking db)\n",
 				msg->path, (unsigned long long) by_path.ino,
 				(int) by_path.mode, (int) msg_header.mode);
-			/* unlink everything with this inode */
-			pdb_unlink_file_dev(&by_path);
+			/* unlink this path -- the inode may be in use elsewhere */
+			pdb_unlink_file(msg);
 			found_path = 0;
 		} else if (S_ISLNK(by_path.mode) != S_ISLNK(msg_header.mode)) {
 			pseudo_diag("symlink mismatch: '%s' [%llu] db mode 0%o, header mode 0%o (unlinking db)\n",
 				msg->path, (unsigned long long) by_path.ino,
 				(int) by_path.mode, (int) msg_header.mode);
-			/* unlink everything with this inode */
-			pdb_unlink_file_dev(&by_path);
+			/* unlink this path -- the inode may be in use elsewhere */
+			pdb_unlink_file(msg);
 			found_path = 0;
 		}
 		if (trailing_slash && !S_ISDIR(by_path.mode)) {
@@ -705,7 +695,11 @@ pseudo_op(pseudo_msg_t *msg, const char *program, const char *tag, char **respon
 						msg->path);
 					pdb_did_unlink_file(path_by_ino, &by_ino, by_ino.deleting);
 				} else {
-					pseudo_diag("path mismatch [%d link%s]: ino %llu db '%s' req '%s'.\n",
+					int flags = 0;
+					if (msg->nlink > 1) {
+						flags = PDBGF_FILE | PDBGF_VERBOSE;
+					}
+					pseudo_debug(flags, "path mismatch [%d link%s]: ino %llu db '%s' req '%s'.\n",
 						msg->nlink,
 						msg->nlink == 1 ? "" : "s",
 						(unsigned long long) msg_header.ino,
@@ -768,9 +762,11 @@ pseudo_op(pseudo_msg_t *msg, const char *program, const char *tag, char **respon
 		break;
 	case OP_CREAT:
 		/* implies a new file -- not a link, which would be OP_LINK */
-		if (found_ino) {
+		if (found_ino && !found_exact) {
 			/* CREAT should never be sent if the file existed.
 			 * So, any existing entry is an error.  Nuke it.
+			 * ... But only if it wasn't a match on both inode *and*
+			 * path, because if it were, that would be harmless.
 			 */
 			pseudo_diag("creat for '%s' replaces existing %llu ['%s'].\n",
 				msg->pathlen ? msg->path : "no path",
@@ -1012,6 +1008,7 @@ pseudo_op(pseudo_msg_t *msg, const char *program, const char *tag, char **respon
 		if (msg->op == OP_REPLACE_XATTR) {
 			xattr_flags = XATTR_REPLACE;
 		}
+		/* fallthrough */
 	case OP_SET_XATTR:
 		if (pdb_set_xattr(msg, oldpath, oldpathlen, xattr_flags)) {
 			msg->result = RESULT_FAIL;
diff --git a/pseudo.h b/pseudo.h
index a39b3b3..4b5eaab 100644
--- a/pseudo.h
+++ b/pseudo.h
@@ -3,18 +3,7 @@
  *
  * Copyright (c) 2008-2010, 2013 Wind River Systems, Inc.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the Lesser GNU General Public License version 2.1 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the Lesser GNU General Public License for more details.
- *
- * You should have received a copy of the Lesser GNU General Public License
- * version 2.1 along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
+ * SPDX-License-Identifier: LGPL-2.1-only
  *
  */
 #include <stdlib.h>
@@ -53,7 +42,7 @@ extern void pseudo_evlog_dump(void);
 	if ((x) & PDBGF_VERBOSE) { \
 		if ((pseudo_util_debug_flags & PDBGF_VERBOSE) && (pseudo_util_debug_flags & ((x) & ~PDBGF_VERBOSE))) { pseudo_diag(__VA_ARGS__); } \
 	} else { \
-		if (pseudo_util_debug_flags & (x)) { pseudo_diag(__VA_ARGS__); } \
+		if ((pseudo_util_debug_flags & (x)) || ((x) == 0)) { pseudo_diag(__VA_ARGS__); } \
 	} \
 } while (0) 
 #define pseudo_debug_call(x, fn, ...) do { \
diff --git a/pseudo_client.c b/pseudo_client.c
index ec07c07..478e450 100644
--- a/pseudo_client.c
+++ b/pseudo_client.c
@@ -3,18 +3,7 @@
  *
  * Copyright (c) 2008-2013 Wind River Systems, Inc.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the Lesser GNU General Public License version 2.1 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the Lesser GNU General Public License for more details.
- *
- * You should have received a copy of the Lesser GNU General Public License
- * version 2.1 along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
+ * SPDX-License-Identifier: LGPL-2.1-only
  *
  */
 #define _GNU_SOURCE
@@ -1485,9 +1474,11 @@ base_path(int dirfd, const char *path, int leave_last) {
 	}
 
 	newpath = pseudo_fix_path(basepath, path, minlen, baselen, NULL, leave_last);
-	pseudo_debug(PDBGF_PATH, "base_path: %s</>%s\n",
+	pseudo_debug(PDBGF_PATH, "base_path[%s]: %s</>%s => %s\n",
+		leave_last ? "nofollow" : "follow",
 		basepath ? basepath : "<nil>",
-		path ? path : "<nil>");
+		path ? path : "<nil>",
+		newpath ? newpath : "<nil>");
 	return newpath;
 }
 
diff --git a/pseudo_client.h b/pseudo_client.h
index 28b23dc..457b095 100644
--- a/pseudo_client.h
+++ b/pseudo_client.h
@@ -3,18 +3,7 @@
  *
  * Copyright (c) 2008-2010 Wind River Systems, Inc.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the Lesser GNU General Public License version 2.1 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the Lesser GNU General Public License for more details.
- *
- * You should have received a copy of the Lesser GNU General Public License
- * version 2.1 along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
+ * SPDX-License-Identifier: LGPL-2.1-only
  *
  */
 extern pseudo_msg_t *pseudo_client_op(pseudo_op_t op, int access, int fd, int dirfd, const char *path, const PSEUDO_STATBUF *buf, ...);
diff --git a/pseudo_db.c b/pseudo_db.c
index a9e294b..92e4f50 100644
--- a/pseudo_db.c
+++ b/pseudo_db.c
@@ -3,23 +3,13 @@
  * 
  * Copyright (c) 2008-2010,2013 Wind River Systems, Inc.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the Lesser GNU General Public License version 2.1 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the Lesser GNU General Public License for more details.
- *
- * You should have received a copy of the Lesser GNU General Public License
- * version 2.1 along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
+ * SPDX-License-Identifier: LGPL-2.1-only
  *
  */
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <stdint.h>
 #include <sys/stat.h>
 #include <sys/xattr.h>
 #include <time.h>
@@ -370,6 +360,30 @@ dberr(sqlite3 *db, char *fmt, ...) {
 	}
 }
 
+/* sqlite3 supports only signed integers, thus, the highest positive
+ * value is 2^63-1. some filesystems with 64-bit ino_t will produce
+ * ino_t values in the 2^63..2^64-1 range. we convert those into
+ * the value you'd get treating the 2^63 bit as a sign bit, so sqlite
+ * doesn't convert them into floats, because the float type can't
+ * represent values accurately in this range, which can result in
+ * erroneous matches, etcetera.
+ *
+ * note, when reading the values back out, the conversion does the
+ * right thing. e.g., if the inode number had been 2^63 exactly,
+ * it will convert to -(2^63). that, converted to unsigned, will
+ * convert back to 2^63 exactly, etcetera.
+ *
+ * so far as i know, ino_t is always unsigned. we don't care about
+ * the 32-bit inode case; sqlite can represent those just fine.
+ */
+static int64_t
+signed_ino(ino_t ino) {
+	if (ino > (uint64_t) INT64_MAX) {
+		return (int64_t) (ino + INT64_MIN) + INT64_MIN;
+	}
+	return (int64_t) ino;
+}
+
 #ifdef USE_MEMORY_DB
 
 static void
@@ -782,7 +796,7 @@ pdb_log_traits(pseudo_query_t *traits) {
 			e->gid = trait->data.ivalue;
 			break;
 		case PSQF_INODE:
-			e->ino = trait->data.ivalue;
+			e->ino = (ino_t) trait->data.ivalue;
 			break;
 		case PSQF_MODE:
 			e->mode = trait->data.ivalue;
@@ -875,7 +889,7 @@ pdb_log_entry(log_entry *e) {
 		sqlite3_bind_int(insert, field++, e->client);
 		sqlite3_bind_int(insert, field++, e->dev);
 		sqlite3_bind_int(insert, field++, e->gid);
-		sqlite3_bind_int64(insert, field++, e->ino);
+		sqlite3_bind_int64(insert, field++, signed_ino(e->ino));
 		sqlite3_bind_int(insert, field++, e->mode);
 		if (e->path) {
 			sqlite3_bind_text(insert, field++, e->path, -1, SQLITE_STATIC);
@@ -969,7 +983,7 @@ pdb_log_msg(pseudo_sev_t severity, pseudo_msg_t *msg, const char *program, const
 		sqlite3_bind_int(insert, field++, msg->client);
 		sqlite3_bind_int(insert, field++, msg->dev);
 		sqlite3_bind_int(insert, field++, msg->gid);
-		sqlite3_bind_int64(insert, field++, msg->ino);
+		sqlite3_bind_int64(insert, field++, signed_ino(msg->ino));
 		sqlite3_bind_int(insert, field++, msg->mode);
 		if (msg->pathlen) {
 			sqlite3_bind_text(insert, field++, msg->path, -1, SQLITE_STATIC);
@@ -1376,7 +1390,7 @@ pdb_history_entry(log_history h) {
 			l->gid = sqlite3_column_int64(h->stmt, column++);
 			break;
 		case PSQF_INODE:
-			l->ino = sqlite3_column_int64(h->stmt, column++);
+			l->ino = (ino_t) sqlite3_column_int64(h->stmt, column++);
 			break;
 		case PSQF_MODE:
 			l->mode = sqlite3_column_int64(h->stmt, column++);
@@ -1512,9 +1526,9 @@ pdb_clear_xattrs(pseudo_msg_t *msg) {
 		}
 	}
 	sqlite3_bind_int(delete, 1, msg->dev);
-	sqlite3_bind_int(delete, 2, msg->ino);
+	sqlite3_bind_int64(delete, 2, signed_ino(msg->ino));
 	sqlite3_bind_int(delete, 3, msg->dev);
-	sqlite3_bind_int(delete, 4, msg->ino);
+	sqlite3_bind_int64(delete, 4, signed_ino(msg->ino));
 	rc = sqlite3_step(delete);
 	if (rc != SQLITE_DONE) {
 		dberr(file_db, "delete of unused xattrs may have failed");
@@ -1549,9 +1563,9 @@ pdb_copy_xattrs(pseudo_msg_t *oldmsg, pseudo_msg_t *msg) {
 		}
 	}
 	sqlite3_bind_int(copy, 1, msg->dev);
-	sqlite3_bind_int(copy, 2, msg->ino);
+	sqlite3_bind_int64(copy, 2, signed_ino(msg->ino));
 	sqlite3_bind_int(copy, 3, oldmsg->dev);
-	sqlite3_bind_int(copy, 4, oldmsg->ino);
+	sqlite3_bind_int64(copy, 4, signed_ino(oldmsg->ino));
 	rc = sqlite3_step(copy);
 	if (rc != SQLITE_DONE) {
 		dberr(file_db, "copy of xattrs may have failed");
@@ -1581,7 +1595,7 @@ pdb_check_xattrs(pseudo_msg_t *msg) {
 	}
 	int existing;
 	sqlite3_bind_int(scan, 1, msg->dev);
-	sqlite3_bind_int(scan, 2, msg->ino);
+	sqlite3_bind_int64(scan, 2, signed_ino(msg->ino));
 	rc = sqlite3_step(scan);
 	if (rc == SQLITE_ROW) {
 		existing = (int) sqlite3_column_int64(scan, 0);
@@ -1635,7 +1649,7 @@ pdb_link_file(pseudo_msg_t *msg) {
 		sqlite3_bind_text(insert, 1, "NAMELESS FILE", -1, SQLITE_STATIC);
 	}
 	sqlite3_bind_int(insert, 2, msg->dev);
-	sqlite3_bind_int64(insert, 3, msg->ino);
+	sqlite3_bind_int64(insert, 3, signed_ino(msg->ino));
 	sqlite3_bind_int(insert, 4, msg->uid);
 	sqlite3_bind_int(insert, 5, msg->gid);
 	sqlite3_bind_int(insert, 6, msg->mode);
@@ -1676,7 +1690,7 @@ pdb_unlink_file_dev(pseudo_msg_t *msg) {
 		return 1;
 	}
 	sqlite3_bind_int(sql_delete, 1, msg->dev);
-	sqlite3_bind_int64(sql_delete, 2, msg->ino);
+	sqlite3_bind_int64(sql_delete, 2, signed_ino(msg->ino));
 	file_db_dirty = 1;
 	rc = sqlite3_step(sql_delete);
 	if (rc != SQLITE_DONE) {
@@ -2168,7 +2182,7 @@ pdb_update_inode(pseudo_msg_t *msg) {
 		pdb_copy_xattrs(oldmsg, msg);
 	}
 	sqlite3_bind_int(update, 1, msg->dev);
-	sqlite3_bind_int64(update, 2, msg->ino);
+	sqlite3_bind_int64(update, 2, signed_ino(msg->ino));
 	rc = sqlite3_bind_text(update, 3, msg->path, -1, SQLITE_STATIC);
 	if (rc) {
 		/* msg->path can never be null, and if msg didn't
@@ -2225,7 +2239,7 @@ pdb_update_file(pseudo_msg_t *msg) {
 	sqlite3_bind_int(update, 3, msg->mode);
 	sqlite3_bind_int(update, 4, msg->rdev);
 	sqlite3_bind_int(update, 5, msg->dev);
-	sqlite3_bind_int64(update, 6, msg->ino);
+	sqlite3_bind_int64(update, 6, signed_ino(msg->ino));
 
 	file_db_dirty = 1;
 	rc = sqlite3_step(update);
@@ -2266,7 +2280,7 @@ pdb_find_file_exact(pseudo_msg_t *msg) {
 		dberr(file_db, "error binding %s to select", msg->pathlen ? msg->path : "<nil>");
 	}
 	sqlite3_bind_int(select, 2, msg->dev);
-	sqlite3_bind_int64(select, 3, msg->ino);
+	sqlite3_bind_int64(select, 3, signed_ino(msg->ino));
 	rc = sqlite3_step(select);
 	switch (rc) {
 	case SQLITE_ROW:
@@ -2325,7 +2339,7 @@ pdb_find_file_path(pseudo_msg_t *msg) {
 	switch (rc) {
 	case SQLITE_ROW:
 		msg->dev = sqlite3_column_int64(select, 2);
-		msg->ino = sqlite3_column_int64(select, 3);
+		msg->ino = (ino_t) sqlite3_column_int64(select, 3);
 		msg->uid = sqlite3_column_int64(select, 4);
 		msg->gid = sqlite3_column_int64(select, 5);
 		msg->mode = sqlite3_column_int64(select, 6);
@@ -2370,7 +2384,7 @@ pdb_get_file_path(pseudo_msg_t *msg) {
 		return 0;
 	}
 	sqlite3_bind_int(select, 1, msg->dev);
-	sqlite3_bind_int64(select, 2, msg->ino);
+	sqlite3_bind_int64(select, 2, signed_ino(msg->ino));
 	rc = sqlite3_step(select);
 	switch (rc) {
 	case SQLITE_ROW:
@@ -2419,7 +2433,7 @@ pdb_find_file_dev(pseudo_msg_t *msg, char **path) {
 		return 1;
 	}
 	sqlite3_bind_int(select, 1, msg->dev);
-	sqlite3_bind_int64(select, 2, msg->ino);
+	sqlite3_bind_int64(select, 2, signed_ino(msg->ino));
 	rc = sqlite3_step(select);
 	switch (rc) {
 	case SQLITE_ROW:
@@ -2471,7 +2485,7 @@ pdb_get_xattr(pseudo_msg_t *msg, char **value, size_t *len) {
 	}
 	pseudo_debug(PDBGF_XATTR, "requested xattr named '%s' for ino %lld\n", *value, (long long) msg->ino);
 	sqlite3_bind_int(select, 1, msg->dev);
-	sqlite3_bind_int(select, 2, msg->ino);
+	sqlite3_bind_int64(select, 2, signed_ino(msg->ino));
 	rc = sqlite3_bind_text(select, 3, *value, -1, SQLITE_STATIC);
 	if (rc) {
 		dberr(file_db, "couldn't bind xattr name to SELECT.");
@@ -2533,7 +2547,7 @@ pdb_list_xattr(pseudo_msg_t *msg, char **value, size_t *len) {
 		}
 	}
 	sqlite3_bind_int(select, 1, msg->dev);
-	sqlite3_bind_int(select, 2, msg->ino);
+	sqlite3_bind_int64(select, 2, signed_ino(msg->ino));
 	do {
 		rc = sqlite3_step(select);
 		if (rc == SQLITE_ROW) {
@@ -2587,7 +2601,7 @@ pdb_remove_xattr(pseudo_msg_t *msg, char *value, size_t len) {
 		}
 	}
 	sqlite3_bind_int(delete, 1, msg->dev);
-	sqlite3_bind_int(delete, 2, msg->ino);
+	sqlite3_bind_int64(delete, 2, signed_ino(msg->ino));
 	rc = sqlite3_bind_text(delete, 3, value, len, SQLITE_STATIC);
 	if (rc) {
 		dberr(file_db, "couldn't bind xattr name to DELETE.");
@@ -2628,7 +2642,7 @@ pdb_set_xattr(pseudo_msg_t *msg, char *value, size_t len, int flags) {
 		}
 	}
 	sqlite3_bind_int(select, 1, msg->dev);
-	sqlite3_bind_int(select, 2, msg->ino);
+	sqlite3_bind_int64(select, 2, signed_ino(msg->ino));
 	rc = sqlite3_bind_text(select, 3, value, -1, SQLITE_STATIC);
 	if (rc) {
 		dberr(file_db, "couldn't bind xattr name to SELECT.");
@@ -2697,7 +2711,7 @@ pdb_set_xattr(pseudo_msg_t *msg, char *value, size_t len, int flags) {
 			}
 		}
 		sqlite3_bind_int64(insert, 1, msg->dev);
-		sqlite3_bind_int64(insert, 2, msg->ino);
+		sqlite3_bind_int64(insert, 2, signed_ino(msg->ino));
 		rc = sqlite3_bind_text(insert, 3, vname, -1, SQLITE_STATIC);
 		if (rc) {
 			dberr(file_db, "couldn't bind xattr name to INSERT statement");
@@ -2743,7 +2757,7 @@ pdb_find_file_ino(pseudo_msg_t *msg) {
 	if (!msg) {
 		return 1;
 	}
-	sqlite3_bind_int64(select, 1, msg->ino);
+	sqlite3_bind_int64(select, 1, signed_ino(msg->ino));
 	rc = sqlite3_step(select);
 	switch (rc) {
 	case SQLITE_ROW:
@@ -2818,7 +2832,7 @@ pdb_file(pdb_file_list l) {
 	}
 	pseudo_debug(PDBGF_DB, "pdb_file: '%s'\n", s ? (const char *) s : "<nil>");
 	m->dev = sqlite3_column_int64(l->stmt, column++);
-	m->ino = sqlite3_column_int64(l->stmt, column++);
+	m->ino = (ino_t) sqlite3_column_int64(l->stmt, column++);
 	m->uid = sqlite3_column_int64(l->stmt, column++);
 	m->gid = sqlite3_column_int64(l->stmt, column++);
 	m->mode = sqlite3_column_int64(l->stmt, column++);
diff --git a/pseudo_db.h b/pseudo_db.h
index 1b2599c..5a4aa59 100644
--- a/pseudo_db.h
+++ b/pseudo_db.h
@@ -3,18 +3,7 @@
  *
  * Copyright (c) 2008-2010 Wind River Systems, Inc.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the Lesser GNU General Public License version 2.1 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the Lesser GNU General Public License for more details.
- *
- * You should have received a copy of the Lesser GNU General Public License
- * version 2.1 along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
+ * SPDX-License-Identifier: LGPL-2.1-only
  *
  */
 typedef struct {
diff --git a/pseudo_ipc.c b/pseudo_ipc.c
index 82c6f70..838eba2 100644
--- a/pseudo_ipc.c
+++ b/pseudo_ipc.c
@@ -3,18 +3,7 @@
  *
  * Copyright (c) 2008-2010 Wind River Systems, Inc.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the Lesser GNU General Public License version 2.1 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the Lesser GNU General Public License for more details.
- *
- * You should have received a copy of the Lesser GNU General Public License
- * version 2.1 along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
+ * SPDX-License-Identifier: LGPL-2.1-only
  *
  */
 #include <stddef.h>
@@ -26,13 +15,17 @@
 #include <ctype.h>
 #include <errno.h>
 #include <sys/stat.h>
+#include <sys/socket.h>
 
 #include "pseudo.h"
 #include "pseudo_ipc.h"
 
-/* Short reads or writes can cause a sigpipe, killing the program, so we
- * trap it and report that something happened.
+/* Short reads or writes can cause a sigpipe, killing the program, so
+ * we trap it and report that something happened. We can avoid the
+ * overhead of setting/restoring the SIGPIPE handler if MSG_NOSIGNAL
+ * is available.
  */
+#ifndef MSG_NOSIGNAL
 static sig_atomic_t pipe_error = 0;
 static void (*old_handler)(int) = SIG_DFL;
 
@@ -51,6 +44,9 @@ static void
 allow_sigpipe(void) {
 	signal(SIGPIPE, old_handler);
 }
+#else
+#define pipe_error 0
+#endif
 
 #if 0
 /* useful only when debugging crazy stuff */
@@ -66,6 +62,36 @@ display_msg_header(pseudo_msg_t *msg) {
 }
 #endif
 
+#ifdef MSG_NOSIGNAL
+static int
+do_send(int fd, struct iovec *iov, int iovlen)
+{
+	struct msghdr hdr;
+
+	memset(&hdr, 0, sizeof(hdr));
+	hdr.msg_iov = iov;
+	hdr.msg_iovlen = iovlen;
+
+	return sendmsg(fd, &hdr, MSG_NOSIGNAL);
+}
+#else
+static int
+do_send(int fd, struct iovec *iov, int iovlen)
+{
+	int r, s = 0, i;
+
+	ignore_sigpipe();
+	for (i = 0; i < iovlen; ++i) {
+		r = write(fd, iov[i].iov_base, iov[i].iov_len);
+		s += r;
+		if (r != (int)iov[i].iov_len)
+			break;
+	}
+	allow_sigpipe();
+	return s;
+}
+#endif
+
 /*
  * send message on fd
  * return:
@@ -75,7 +101,8 @@ display_msg_header(pseudo_msg_t *msg) {
  */
 int
 pseudo_msg_send(int fd, pseudo_msg_t *msg, size_t len, const char *path) {
-	int r;
+	struct iovec iov[2];
+	int r, iovc;
 
 	if (!msg)
 		return 1;
@@ -89,30 +116,26 @@ pseudo_msg_send(int fd, pseudo_msg_t *msg, size_t len, const char *path) {
 		if (len == (size_t) -1)
 			len = strlen(path) + 1;
 		msg->pathlen = len;
-		ignore_sigpipe();
-		r = write(fd, msg, PSEUDO_HEADER_SIZE);
-		if (r == PSEUDO_HEADER_SIZE) {
-			r += write(fd, path, len);
-		}
-		allow_sigpipe();
-		pseudo_debug(PDBGF_IPC | PDBGF_VERBOSE, "wrote %d bytes\n", r);
-		if (pipe_error || (r == -1 && errno == EBADF))
-			return -1;
-		return ((size_t) r != PSEUDO_HEADER_SIZE + len);
+		iov[0].iov_base = msg;
+		iov[0].iov_len = PSEUDO_HEADER_SIZE;
+		iov[1].iov_base = (void*)path;
+		iov[1].iov_len = len;
+		iovc = 2;
 	} else {
 		pseudo_debug(PDBGF_IPC, "msg type %d (%s), result %d (%s), path %.*s, mode 0%o\n",
 			msg->type, pseudo_op_name(msg->op),
 			msg->result, pseudo_res_name(msg->result),
 			msg->pathlen, msg->path, (int) msg->mode);
 		// display_msg_header(msg);
-		ignore_sigpipe();
-		r = write(fd, msg, PSEUDO_HEADER_SIZE + msg->pathlen);
-		allow_sigpipe();
-		pseudo_debug(PDBGF_IPC | PDBGF_VERBOSE, "wrote %d bytes\n", r);
-		if (pipe_error || (r == -1 && errno == EBADF))
-			return -1;
-		return ((size_t) r != PSEUDO_HEADER_SIZE + msg->pathlen);
+		iov[0].iov_base = msg;
+		iov[0].iov_len = PSEUDO_HEADER_SIZE + msg->pathlen;
+		iovc = 1;
 	}
+	r = do_send(fd, iov, iovc);
+	pseudo_debug(PDBGF_IPC | PDBGF_VERBOSE, "wrote %d bytes\n", r);
+	if (pipe_error || (r == -1 && (errno == EBADF || errno == EPIPE)))
+		return -1;
+	return ((size_t) r != PSEUDO_HEADER_SIZE + msg->pathlen);
 }
 
 /* attempts to receive a message from fd
diff --git a/pseudo_ipc.h b/pseudo_ipc.h
index 46277bc..caeae5c 100644
--- a/pseudo_ipc.h
+++ b/pseudo_ipc.h
@@ -3,18 +3,7 @@
  *
  * Copyright (c) 2008-2010 Wind River Systems, Inc.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the Lesser GNU General Public License version 2.1 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the Lesser GNU General Public License for more details.
- *
- * You should have received a copy of the Lesser GNU General Public License
- * version 2.1 along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
+ * SPDX-License-Identifier: LGPL-2.1-only
  *
  */
 
diff --git a/pseudo_profile.c b/pseudo_profile.c
index c4af803..c4b16e6 100644
--- a/pseudo_profile.c
+++ b/pseudo_profile.c
@@ -1,3 +1,7 @@
+/*
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
+ */
 #define _GNU_SOURCE
 
 #include <errno.h>
diff --git a/pseudo_server.c b/pseudo_server.c
index dac3258..898aab4 100644
--- a/pseudo_server.c
+++ b/pseudo_server.c
@@ -3,18 +3,7 @@
  *
  * Copyright (c) 2008-2010, 2013 Wind River Systems, Inc.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the Lesser GNU General Public License version 2.1 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the Lesser GNU General Public License for more details.
- *
- * You should have received a copy of the Lesser GNU General Public License
- * version 2.1 along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
+ * SPDX-License-Identifier: LGPL-2.1-only
  *
  */
 #include <stdio.h>
@@ -700,7 +689,8 @@ static void pseudo_server_loop_epoll(void)
 		} else if (rc > 0) {
 			loop_timeout = pseudo_server_timeout;
 			for (i = 0; i < rc; ++i) {
-				if (clients[events[i].data.u64].fd == listen_fd) {
+				int client_id = events[i].data.u64;
+				if (clients[client_id].fd == listen_fd) {
 					if (!die_forcefully) {
 						len = sizeof(client);
 						if ((fd = accept(listen_fd, (struct sockaddr *) &client, &len)) != -1) {
@@ -733,11 +723,11 @@ static void pseudo_server_loop_epoll(void)
 					}
 				} else {
 					int n = 0;
-					ioctl(clients[i].fd, FIONREAD, &n);
+					ioctl(clients[client_id].fd, FIONREAD, &n);
 					if (n == 0) {
-						close_client(i);
+						close_client(client_id);
 					} else {
-						serve_client(i);
+						serve_client(client_id);
 					}
 				}
 				if (die_forcefully)
diff --git a/pseudo_server.h b/pseudo_server.h
index 06598e7..35f5b78 100644
--- a/pseudo_server.h
+++ b/pseudo_server.h
@@ -3,18 +3,7 @@
  *
  * Copyright (c) 2008-2009 Wind River Systems, Inc.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the Lesser GNU General Public License version 2.1 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the Lesser GNU General Public License for more details.
- *
- * You should have received a copy of the Lesser GNU General Public License
- * version 2.1 along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
+ * SPDX-License-Identifier: LGPL-2.1-only
  *
  */
 extern int pseudo_server_start(int);
diff --git a/pseudo_util.c b/pseudo_util.c
index 6a1fac2..c867ed6 100644
--- a/pseudo_util.c
+++ b/pseudo_util.c
@@ -3,18 +3,7 @@
  *
  * Copyright (c) 2008-2013 Wind River Systems, Inc.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the Lesser GNU General Public License version 2.1 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the Lesser GNU General Public License for more details.
- *
- * You should have received a copy of the Lesser GNU General Public License
- * version 2.1 along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
+ * SPDX-License-Identifier: LGPL-2.1-only
  *
  */
 /* we need access to RTLD_NEXT for a horrible workaround */
@@ -265,8 +254,8 @@ int pseudo_util_evlog_fd = 2;
 static int debugged_newline = 1;
 static char pid_text[32];
 static size_t pid_len;
-static int pseudo_append_element(char *newpath, char *root, size_t allocated, char **pcurrent, const char *element, size_t elen, int leave_this);
-static int pseudo_append_elements(char *newpath, char *root, size_t allocated, char **current, const char *elements, size_t elen, int leave_last);
+static int pseudo_append_element(char *newpath, char *root, size_t allocated, char **pcurrent, const char *element, size_t elen, PSEUDO_STATBUF *buf, int leave_this);
+static int pseudo_append_elements(char *newpath, char *root, size_t allocated, char **current, const char *elements, size_t elen, int leave_last, PSEUDO_STATBUF *sbuf);
 extern char **environ;
 static ssize_t pseudo_max_pathlen = -1;
 static ssize_t pseudo_sys_max_pathlen = -1;
@@ -618,11 +607,11 @@ pseudo_new_pid() {
  * the symlink, appending each element in turn the same way.
  */
 static int
-pseudo_append_element(char *newpath, char *root, size_t allocated, char **pcurrent, const char *element, size_t elen, int leave_this) {
+pseudo_append_element(char *newpath, char *root, size_t allocated, char **pcurrent, const char *element, size_t elen, PSEUDO_STATBUF *buf, int leave_this) {
 	static int link_recursion = 0;
 	size_t curlen;
+	int is_dir = S_ISDIR(buf->st_mode);
 	char *current;
-	PSEUDO_STATBUF buf;
 	if (!newpath ||
 	    !pcurrent || !*pcurrent ||
 	    !root || !element) {
@@ -630,25 +619,34 @@ pseudo_append_element(char *newpath, char *root, size_t allocated, char **pcurre
 		return -1;
 	}
 	current = *pcurrent;
-	/* sanity-check:  ignore // or /./ */
-	if (elen == 0 || (elen == 1 && *element == '.')) {
-		return 1;
-	}
-	/* backtrack for .. */
-	if (elen == 2 && element[0] == '.' && element[1] == '.') {
-		/* if newpath's whole contents are '/', do nothing */
-		if (current <= root + 1)
+	pseudo_debug(PDBGF_PATH | PDBGF_VERBOSE, "pae: '%s', + '%.*s', is_dir %d\n",
+		newpath, (int) elen, element, is_dir);
+	/* the special cases here to skip empty paths, or ./.., should apply
+	 * only to directories; plain files, nodes, etcetera should just get
+	 * bogus paths.
+	 */
+	if (is_dir) {
+		/* sanity-check:  ignore // or /./ */
+		if (elen == 0 || (elen == 1 && *element == '.')) {
+			return 0;
+		}
+		/* backtrack for .. */
+		if (elen == 2 && element[0] == '.' && element[1] == '.') {
+			/* if newpath is empty, do nothing. */
+			if (current <= root)
+				return 0;
+			/* now find the previous slash */
+			while (current > root && *current != '/') {
+				--current;
+			}
+			/* either we're at root, or we're at a slash.
+			 * either way, nul that out, leaving us with a
+			 * possibly-empty path which is not slash-terminated.
+			 */
+			*current = '\0';
+			*pcurrent = current;
 			return 1;
-		/* backtrack to the character before the / */
-		current -= 2;
-		/* now find the previous slash */
-		while (current > root && *current != '/') {
-			--current;
 		}
-		/* and point to the nul just past it */
-		*(++current) = '\0';
-		*pcurrent = current;
-		return 1;
 	}
 	curlen = current - newpath;
 	/* current length, plus / <element> / \0 */
@@ -657,15 +655,28 @@ pseudo_append_element(char *newpath, char *root, size_t allocated, char **pcurre
 		pseudo_diag("pseudo_append_element: path too long (wanted %lu bytes).\n", (unsigned long) curlen + elen + 3);
 		return -1;
 	}
+	/* append a slash */
+	*current++ = '/';
 	memcpy(current, element, elen);
 	current += elen;
-	/* nul-terminate, and we now point to the nul after the slash */
+	/* nul-terminate, and we now point to the nul after the element just added. */
 	*current = '\0';
-	/* now, the moment of truth... is that a symlink? */
-	/* if lstat fails, that's fine -- nonexistent files aren't symlinks */
-	if (!leave_this) {
-		int is_link;
-		is_link = (pseudo_real_lstat) && (pseudo_real_lstat(newpath, &buf) != -1) && S_ISLNK(buf.st_mode);
+	/* if we are not on the last element of a path and supposed to leave
+	 * it alone (for SYMLINK_NOFOLLOW type cases), and we are not trying to
+	 * go further under a regular file, we want to know whether this is a symlink.
+	 * either way, we want to update buf to show the correct state of the file.
+	 */
+	if (!pseudo_real_lstat || (pseudo_real_lstat(newpath, buf) == -1)) {
+		// if we can't stat it, zero mode so we don't think it's
+		// known to be a link or a regular file.
+		buf->st_mode = 0;
+	}
+	/* it is intentional that this uses the "stale" is_dir for the file we
+	 * were appending to. we don't want to actually try to do this when
+	 * we're appending names to a regular file.
+	 */
+	if (!leave_this && is_dir) {
+		int is_link = S_ISLNK(buf->st_mode);
 		if (link_recursion >= PSEUDO_MAX_LINK_RECURSION && is_link) {
 			pseudo_diag("link recursion too deep, not expanding path '%s'.\n", newpath);
 			is_link = 0;
@@ -684,65 +695,91 @@ pseudo_append_element(char *newpath, char *root, size_t allocated, char **pcurre
 			linkbuf[linklen] = '\0';
 			/* absolute symlink means start over! */
 			if (*linkbuf == '/') {
-				current = newpath + 1;
+				current = newpath;
 			} else {
 				/* point back at the end of the previous path... */
-				current -= elen;
+				current -= (elen + 1);
 			}
 			/* null terminate at the new pointer */
 			*current = '\0';
-			/* append all the elements in series */
 			*pcurrent = current;
+			/* we know that we're now pointing either at a directory we
+			 * already decided was safe to go into, or root. either way,
+			 * the parent item mode should reflect it being a directory.
+			 * we don't need to call stat for that.
+			 */
+			buf->st_mode = S_IFDIR;
+			/* append all the elements in series */
 			++link_recursion;
-			retval = pseudo_append_elements(newpath, root, allocated, pcurrent, linkbuf, linklen, 0);
+			retval = pseudo_append_elements(newpath, root, allocated, pcurrent, linkbuf, linklen, 0, buf);
 			--link_recursion;
 			return retval;
 		}
 	}
-	/* okay, not a symlink, go ahead and append a slash */
-	*(current++) = '/';
-	*current = '\0';
+	/* we used to always append a slash here. now we don't; append_elements
+	 * handles slashes, so just update the pointer.
+	 */
 	*pcurrent = current;
 	return 1;
 }
 
 static int
-pseudo_append_elements(char *newpath, char *root, size_t allocated, char **current, const char *element, size_t elen, int leave_last) {
+pseudo_append_elements(char *newpath, char *root, size_t allocated, char **current, const char *path, size_t elen, int leave_last, PSEUDO_STATBUF *sbuf) {
 	int retval = 1;
-	const char * start = element;
+	/* a shareable buffer so we can cache stat results while walking the path */
+	PSEUDO_STATBUF buf;
+	buf.st_mode = 0;
+	const char * start = path;
 	if (!newpath || !root ||
 	    !current || !*current ||
-	    !element) {
+	    !path) {
 		pseudo_diag("pseudo_append_elements: invalid arguments.");
 		return -1;
 	}
-	while (element < (start + elen) && *element) {
+	if (!sbuf) {
+		/* we will use this buffer to hold "the current state of newpath".
+		 * append_element will update that whenever it appends an element,
+		 * and any calls back here from there will pass in the same buffer.
+		 * if we didn't get one, we start using this local one, which will
+		 * then get shared by anything we call.
+		 */
+		sbuf = &buf;
+		if (*current > root) {
+			if (!pseudo_real_lstat || (pseudo_real_lstat(newpath, sbuf) == -1)) {
+				sbuf->st_mode = 0;
+			}
+		} else {
+			/* Don't call lstat on an empty path, or at all when we
+			 * know that "root" is always directory-like.
+			 */
+			sbuf->st_mode = S_IFDIR;
+		}
+	}
+	pseudo_debug(PDBGF_PATH | PDBGF_VERBOSE, "paes: newpath %s, element list <%.*s>\n",
+		newpath, (int) elen, path);
+	while (path < (start + elen) && *path) {
 		size_t this_elen;
 		int leave_this = 0;
-		char *next = strchr(element, '/');
+		char *next = strchr(path, '/');
 		if (!next) {
-			next = strchr(element, '\0');
+			next = strchr(path, '\0');
 			leave_this = leave_last;
 		}
-		this_elen = next - element;
-		switch (this_elen) {
-		case 0: /* path => '/' */
-			break;
-		case 1: /* path => '?/' */
-			if (*element != '.') {
-				if (pseudo_append_element(newpath, root, allocated, current, element, this_elen, leave_this) == -1) {
-					retval = -1;
-				}
-			}
-			break;
-		default:
-			if (pseudo_append_element(newpath, root, allocated, current, element, this_elen, leave_this) == -1) {
-				retval = -1;
-			}
+		this_elen = next - path;
+		/* for a directory, we skip the append for empty path or ".";
+		 * regular files get it appended so they can fail properly
+		 * later for being invalid paths.
+		 */
+		pseudo_debug(PDBGF_PATH | PDBGF_VERBOSE, "element to add: '%.*s'\n",
+			(int) this_elen, path);
+		if (pseudo_append_element(newpath, root, allocated, current, path, this_elen, sbuf, leave_this) == -1) {
+			retval = -1;
 			break;
 		}
+		pseudo_debug(PDBGF_FILE | PDBGF_VERBOSE, "paes: append_element gave us '%s', current '%s'\n",
+			newpath, *current);
 		/* and now move past the separator */
-		element += this_elen + 1;
+		path += this_elen + 1;
 	}
 	return retval;
 }
@@ -778,9 +815,12 @@ pseudo_fix_path(const char *base, const char *path, size_t rootlen, size_t basel
 	newpath = pathbufs[pathbuf];
 	pathbuf = (pathbuf + 1) % PATHBUFS;
 	pathlen = strlen(path);
-	/* a trailing slash has special meaning */
-	if (pathlen > 0 && path[pathlen - 1] == '/') {
+	/* a trailing slash has special meaning, but processing
+	 * trailing slashes is expensive.
+	 */
+	while (pathlen > 0 && path[pathlen - 1] == '/') {
 		trailing_slash = 1;
+		--pathlen;
 	}
 	/* allow a bit of slush.  overallocating a bit won't
 	 * hurt.  rounding to 256's in the hopes that it makes life
@@ -800,18 +840,25 @@ pseudo_fix_path(const char *base, const char *path, size_t rootlen, size_t basel
 	 * part of the string; you can't back up over it.
 	 */
 	effective_root = newpath + rootlen;
-	*current++ = '/';
 	*current = '\0';
 	/* at any given point:
-	 * current points to just after the last / of newpath
+	 * path is not slash-terminated
+	 * current points to the null byte immediately after the path
 	 * path points to the next element of path
 	 * newpathlen is the total allocated length of newpath
 	 * (current - newpath) is the used length of newpath
 	 */
-	if (pseudo_append_elements(newpath, effective_root, newpathlen, &current, path, pathlen, leave_last) != -1) {
-		--current;
-		if (*current == '/' && current > effective_root && !trailing_slash) {
-			*current = '\0';
+	int save_errno = errno;
+	if (pseudo_append_elements(newpath, effective_root, newpathlen, &current, path, pathlen, leave_last, 0) != -1) {
+		/* if we are expecting a trailing slash, or the path ended up being completely
+		 * empty (meaning it's pointing at either effective_root or the beginning of
+		 * the path), we need a slash here.
+		 */
+		if ((current == effective_root) || trailing_slash) {
+			if ((current - newpath) < (int) newpathlen) {
+				*current++ = '/';
+				*current = '\0';
+			}
 		}
 		pseudo_debug(PDBGF_PATH, "%s + %s => <%s>\n",
 			base ? base : "<nil>",
@@ -820,8 +867,10 @@ pseudo_fix_path(const char *base, const char *path, size_t rootlen, size_t basel
 		if (lenp) {
 			*lenp = current - newpath;
 		}
+		errno = save_errno;
 		return newpath;
 	} else {
+		errno = save_errno;
 		return 0;
 	}
 }
diff --git a/pseudo_wrappers.c b/pseudo_wrappers.c
index e05f73a..99aabff 100644
--- a/pseudo_wrappers.c
+++ b/pseudo_wrappers.c
@@ -3,18 +3,7 @@
  *
  * Copyright (c) 2008-2012 Wind River Systems, Inc.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the Lesser GNU General Public License version 2.1 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the Lesser GNU General Public License for more details.
- *
- * You should have received a copy of the Lesser GNU General Public License
- * version 2.1 along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
+ * SPDX-License-Identifier: LGPL-2.1-only
  *
  */
 #include <assert.h>
diff --git a/pseudodb.c b/pseudodb.c
index 9203648..f923648 100644
--- a/pseudodb.c
+++ b/pseudodb.c
@@ -3,18 +3,7 @@
  *
  * Copyright (c) 2008-2010 Wind River Systems, Inc.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the Lesser GNU General Public License version 2.1 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the Lesser GNU General Public License for more details.
- *
- * You should have received a copy of the Lesser GNU General Public License
- * version 2.1 along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
+ * SPDX-License-Identifier: LGPL-2.1-only
  *
  */
 #include <stdio.h>
diff --git a/pseudolog.c b/pseudolog.c
index ced421d..1101f28 100644
--- a/pseudolog.c
+++ b/pseudolog.c
@@ -3,18 +3,7 @@
  *
  * Copyright (c) 2008-2010 Wind River Systems, Inc.
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the Lesser GNU General Public License version 2.1 as
- * published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the Lesser GNU General Public License for more details.
- *
- * You should have received a copy of the Lesser GNU General Public License
- * version 2.1 along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
+ * SPDX-License-Identifier: LGPL-2.1-only
  *
  */
 /* We need _XOPEN_SOURCE for strptime(), but if we define that,
diff --git a/run_tests.sh b/run_tests.sh
index 0eced9f..c637c27 100755
--- a/run_tests.sh
+++ b/run_tests.sh
@@ -1,4 +1,8 @@
 #!/bin/bash
+#
+# SPDX-License-Identifier: LGPL-2.1-only
+#
+
 opt_verbose=
 
 usage()
diff --git a/templatefile.py b/templatefile.py
index abf9a2c..be82de3 100644
--- a/templatefile.py
+++ b/templatefile.py
@@ -1,3 +1,7 @@
+#
+# SPDX-License-Identifier: LGPL-2.1-only
+#
+
 from string import Template
 import os
 
diff --git a/templates/guts b/templates/guts
index e2c9880..05605ea 100644
--- a/templates/guts
+++ b/templates/guts
@@ -2,9 +2,14 @@
 @header
 @body
 /* 
- * Copyright (c) ${date} Wind River Systems; see
+ * Copyright (c) ${date} Peter Seebach/Seebs <seebs@seebs.net>; see
  * guts/COPYRIGHT for information.
  *
+ * [Note: copyright added by code generator, may be
+ * incorrect. Remove this if you fix it.]
+ *
+ * SPDX-License-Identifier: LGPL-2.1-only
+ *
  * ${comment}
  *	${rc_decl}
  */
diff --git a/test/test-chroot.sh b/test/test-chroot.sh
index 02c9ff6..faa4ffe 100755
--- a/test/test-chroot.sh
+++ b/test/test-chroot.sh
@@ -1,4 +1,7 @@
 #!/bin/bash
+#
+# SPDX-License-Identifier: LGPL-2.1-only
+#
 
 # Return vals: 2 - invalid arg list
 #              1 - chroot failed
diff --git a/test/test-cp-setuid.sh b/test/test-cp-setuid.sh
new file mode 100755
index 0000000..0759608
--- /dev/null
+++ b/test/test-cp-setuid.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+#
+# SPDX-License-Identifier: LGPL-2.1-only
+#
+set -e
+
+# Verify that special bits (setuid/setgid/sticky) are preserved.
+#
+# Return vals:
+#
+#                 2 - Incorrect permissions
+# All other nonzero - Unexpected command error
+#                 0 - Pass
+
+trap "rm -rf d1 d2" EXIT
+
+mkdir d1
+chmod 7777 d1
+cp -Rp d1 d2
+perms=`ls -od d1 d2 | cut -c 1-10 | uniq`
+if [ "$perms" != drwsrwsrwt ]; then
+	exit 2
+fi
+
+
+exit 0
diff --git a/test/test-dir-move.sh b/test/test-dir-move.sh
index 37182f3..7bb0256 100755
--- a/test/test-dir-move.sh
+++ b/test/test-dir-move.sh
@@ -1,4 +1,7 @@
 #!/bin/bash
+#
+# SPDX-License-Identifier: LGPL-2.1-only
+#
 mkdir d1
 touch d1/f1
 mv d1 d2
diff --git a/test/test-env_i.sh b/test/test-env_i.sh
index c38cf1d..454a7b4 100755
--- a/test/test-env_i.sh
+++ b/test/test-env_i.sh
@@ -1,4 +1,7 @@
 #!/bin/bash
+#
+# SPDX-License-Identifier: LGPL-2.1-only
+#
 
 env -i A=A B=B C=C env | grep -q "PSEUDO_"
 
diff --git a/test/test-execl.sh b/test/test-execl.sh
index 1a1c580..134055b 100755
--- a/test/test-execl.sh
+++ b/test/test-execl.sh
@@ -1,4 +1,7 @@
 #!/bin/bash
+#
+# SPDX-License-Identifier: LGPL-2.1-only
+#
 cat > execl_test.c << EOF
 #include <unistd.h>
 int main() {
diff --git a/test/test-pseudo_disable-fork-env_i.sh b/test/test-pseudo_disable-fork-env_i.sh
index 1e679aa..0bcf797 100755
--- a/test/test-pseudo_disable-fork-env_i.sh
+++ b/test/test-pseudo_disable-fork-env_i.sh
@@ -1,4 +1,7 @@
 #!/bin/bash
+#
+# SPDX-License-Identifier: LGPL-2.1-only
+#
 
 # Verify normal operation...
 uid=`env -i id -u`
diff --git a/test/test-pseudo_disable-fork.sh b/test/test-pseudo_disable-fork.sh
index 13a42a4..e0f5fd3 100755
--- a/test/test-pseudo_disable-fork.sh
+++ b/test/test-pseudo_disable-fork.sh
@@ -1,4 +1,7 @@
 #!/bin/bash
+#
+# SPDX-License-Identifier: LGPL-2.1-only
+#
 
 # Verify normal operation...
 uid=`id -u`
diff --git a/test/test-pseudo_unload-fork-env_i.sh b/test/test-pseudo_unload-fork-env_i.sh
index d6658e0..0e89ba0 100755
--- a/test/test-pseudo_unload-fork-env_i.sh
+++ b/test/test-pseudo_unload-fork-env_i.sh
@@ -1,4 +1,7 @@
 #!/bin/bash
+#
+# SPDX-License-Identifier: LGPL-2.1-only
+#
 
 # Verify normal operation...
 uid=`env -i id -u`
diff --git a/test/test-pseudo_unload-fork.sh b/test/test-pseudo_unload-fork.sh
index 9f79198..822f478 100755
--- a/test/test-pseudo_unload-fork.sh
+++ b/test/test-pseudo_unload-fork.sh
@@ -1,4 +1,7 @@
 #!/bin/bash
+#
+# SPDX-License-Identifier: LGPL-2.1-only
+#
 
 # Verify normal operation...
 uid=`id -u`
diff --git a/test/test-reexec-chroot.sh b/test/test-reexec-chroot.sh
index bde93f1..f6412bc 100755
--- a/test/test-reexec-chroot.sh
+++ b/test/test-reexec-chroot.sh
@@ -1,4 +1,7 @@
 #!/bin/bash
+#
+# SPDX-License-Identifier: LGPL-2.1-only
+#
 
 # Test if we re-invoke pseudo that chroot still works
 
diff --git a/test/test-tclsh-fork.sh b/test/test-tclsh-fork.sh
old mode 100644
new mode 100755
index e9dec66..e06f36b
--- a/test/test-tclsh-fork.sh
+++ b/test/test-tclsh-fork.sh
@@ -1,4 +1,7 @@
 #!/bin/bash
+#
+# SPDX-License-Identifier: LGPL-2.1-only
+#
 
 # Check that tclsh doesn't hang.  Note that the timeout is not needed to
 # reproduce the hang in tclsh, it's only there to ensure that this test script
diff --git a/test/test-umask.sh b/test/test-umask.sh
index 8ca4963..e4e366b 100755
--- a/test/test-umask.sh
+++ b/test/test-umask.sh
@@ -1,4 +1,7 @@
 #!/bin/bash
+#
+# SPDX-License-Identifier: LGPL-2.1-only
+#
 
 mode() {
 	ls -l "$1" | awk '{ print $1 }'
diff --git a/test/test-xattr.sh b/test/test-xattr.sh
index 7d818d2..09cd6b0 100755
--- a/test/test-xattr.sh
+++ b/test/test-xattr.sh
@@ -1,4 +1,7 @@
 #!/bin/bash
+#
+# SPDX-License-Identifier: LGPL-2.1-only
+#
 
 # Return vals: 2 - Unable to run xattr commands
 #              1 - Invalid return value