Index: c/src/exec/libcsupport/include/rtems/libio.h
===================================================================
--- c/src/exec/libcsupport/include/rtems/libio.h	(revision b64b1ed387bb9fa18e33bc9d7c24aa7fcce38da6)
+++ c/src/exec/libcsupport/include/rtems/libio.h	(revision af0200363e8d0a69648bd78fd5ee2d0ee5f40624)
@@ -116,4 +116,9 @@
 );
 
+typedef int (*rtems_filesystem_fcntl_t)(
+  int cmd,
+  rtems_libio_t *iop
+);
+
 typedef struct {
     rtems_filesystem_open_t         open;
@@ -129,4 +134,5 @@
     rtems_filesystem_fsync_t        fsync;
     rtems_filesystem_fdatasync_t    fdatasync;
+    rtems_filesystem_fcntl_t        fcntl;
 } rtems_filesystem_file_handlers_r;
 
Index: c/src/exec/libcsupport/src/fcntl.c
===================================================================
--- c/src/exec/libcsupport/src/fcntl.c	(revision b64b1ed387bb9fa18e33bc9d7c24aa7fcce38da6)
+++ c/src/exec/libcsupport/src/fcntl.c	(revision af0200363e8d0a69648bd78fd5ee2d0ee5f40624)
@@ -31,4 +31,5 @@
   int            fd2;
   int            flags;
+  int            ret = 0;
   
   va_start( ap, cmd );
@@ -54,6 +55,8 @@
         /* allocate a file control block */
         diop = rtems_libio_allocate();
-        if ( diop == 0 )
-          return -1;
+        if ( diop == 0 ) {
+          ret = -1;
+          break;
+        }
       }
 
@@ -63,10 +66,9 @@
       diop->pathinfo   = iop->pathinfo;
       
-      return 0;
+      break;
 
     case F_GETFD:        /* get f_flags */
-      if ( iop->flags & LIBIO_FLAGS_CLOSE_ON_EXEC )
-        return 1;
-      return 0;
+      ret = ((iop->flags & LIBIO_FLAGS_CLOSE_ON_EXEC) != 0);
+      break;
 
     case F_SETFD:        /* set f_flags */
@@ -83,8 +85,8 @@
       else
         iop->flags &= ~LIBIO_FLAGS_CLOSE_ON_EXEC;
-      return 0;
+      break;
 
     case F_GETFL:        /* more flags (cloexec) */
-      return rtems_libio_to_fcntl_flags( iop->flags );
+      ret = rtems_libio_to_fcntl_flags( iop->flags );
 
     case F_SETFL:
@@ -92,36 +94,46 @@
 
       /*
-       *  XXX Double check this in the POSIX spec.  According to the Linux
-       *  XXX man page, only these flags can be added.
-       */
-
-      flags = (iop->flags & ~(O_APPEND|O_NONBLOCK)) |
-                   (flags & (O_APPEND|O_NONBLOCK));
-
-      /*
        *  XXX If we are turning on append, should we seek to the end?
        */
 
-      iop->flags = flags;
-      return 0;
+      iop->flags = (iop->flags & ~(O_APPEND | O_NONBLOCK)) |
+                   (flags & (O_APPEND | O_NONBLOCK));
+      break;
 
     case F_GETLK:
-      return -1;
+      errno = ENOTSUP;
+      ret = -1;
+      break;
 
     case F_SETLK:
-      return -1;
+      errno = ENOTSUP;
+      ret = -1;
+      break;
 
     case F_SETLKW:
-      return -1;
+      errno = ENOTSUP;
+      ret = -1;
+      break;
 
     case F_SETOWN:       /*  for sockets. */
-      return -1;
+      errno = ENOTSUP;
+      ret = -1;
+      break;
 
     case F_GETOWN:       /*  for sockets. */
-      return -1;
+      errno = ENOTSUP;
+      ret = -1;
+      break;
 
     default:
       break;
   }
-  return -1;
+  if ((ret >= 0) && iop->handlers->fcntl) {
+    int err = (*iop->handlers->fcntl)( cmd, iop );
+    if (err) {
+      errno = err;
+      ret = -1;
+    }
+  }
+  return ret;
 }
Index: c/src/exec/libnetworking/rtems/rtems_syscall.c
===================================================================
--- c/src/exec/libnetworking/rtems/rtems_syscall.c	(revision b64b1ed387bb9fa18e33bc9d7c24aa7fcce38da6)
+++ c/src/exec/libnetworking/rtems/rtems_syscall.c	(revision af0200363e8d0a69648bd78fd5ee2d0ee5f40624)
@@ -21,4 +21,5 @@
 #include <sys/protosw.h>
 #include <sys/proc.h>
+#include <sys/fcntl.h>
 #include <sys/filio.h>
 
@@ -645,12 +646,16 @@
 
 static int
-so_ioctl (struct socket *so, unsigned32 command, void *buffer)
+so_ioctl (rtems_libio_t *iop, struct socket *so, unsigned32 command, void *buffer)
 {
 	switch (command) {
 	case FIONBIO:
-		if (*(int *)buffer)
+		if (*(int *)buffer) {
+			iop->flags |= O_NONBLOCK;
 			so->so_state |= SS_NBIO;
-		else
+		}
+		else {
+			iop->flags &= ~O_NONBLOCK;
 			so->so_state &= ~SS_NBIO;
+		}
 		return 0;
 
@@ -679,5 +684,5 @@
 		return -1;
 	}
-	error = so_ioctl (so, command, buffer);
+	error = so_ioctl (iop, so, command, buffer);
 	rtems_bsdnet_semaphore_release ();
 	if (error) {
@@ -686,4 +691,24 @@
 	}
 	return 0;
+}
+
+static int
+rtems_bsdnet_fcntl (int cmd, rtems_libio_t *iop)
+{
+	struct socket *so;
+
+	if (cmd == F_SETFL) {
+		rtems_bsdnet_semaphore_obtain ();
+		if ((so = iop->data1) == NULL) {
+			rtems_bsdnet_semaphore_release ();
+			return EBADF;
+		}
+		if (iop->flags & O_NONBLOCK)
+			so->so_state |= SS_NBIO;
+		else
+			so->so_state &= ~SS_NBIO;
+		rtems_bsdnet_semaphore_release ();
+	}
+        return 0;
 }
 
@@ -708,3 +733,4 @@
 	NULL,			/* fsync */
 	NULL,			/* fdatasync */
+	rtems_bsdnet_fcntl,	/* fcntl */
 };
Index: c/src/lib/include/rtems/libio.h
===================================================================
--- c/src/lib/include/rtems/libio.h	(revision b64b1ed387bb9fa18e33bc9d7c24aa7fcce38da6)
+++ c/src/lib/include/rtems/libio.h	(revision af0200363e8d0a69648bd78fd5ee2d0ee5f40624)
@@ -116,4 +116,9 @@
 );
 
+typedef int (*rtems_filesystem_fcntl_t)(
+  int cmd,
+  rtems_libio_t *iop
+);
+
 typedef struct {
     rtems_filesystem_open_t         open;
@@ -129,4 +134,5 @@
     rtems_filesystem_fsync_t        fsync;
     rtems_filesystem_fdatasync_t    fdatasync;
+    rtems_filesystem_fcntl_t        fcntl;
 } rtems_filesystem_file_handlers_r;
 
Index: c/src/lib/libc/fcntl.c
===================================================================
--- c/src/lib/libc/fcntl.c	(revision b64b1ed387bb9fa18e33bc9d7c24aa7fcce38da6)
+++ c/src/lib/libc/fcntl.c	(revision af0200363e8d0a69648bd78fd5ee2d0ee5f40624)
@@ -31,4 +31,5 @@
   int            fd2;
   int            flags;
+  int            ret = 0;
   
   va_start( ap, cmd );
@@ -54,6 +55,8 @@
         /* allocate a file control block */
         diop = rtems_libio_allocate();
-        if ( diop == 0 )
-          return -1;
+        if ( diop == 0 ) {
+          ret = -1;
+          break;
+        }
       }
 
@@ -63,10 +66,9 @@
       diop->pathinfo   = iop->pathinfo;
       
-      return 0;
+      break;
 
     case F_GETFD:        /* get f_flags */
-      if ( iop->flags & LIBIO_FLAGS_CLOSE_ON_EXEC )
-        return 1;
-      return 0;
+      ret = ((iop->flags & LIBIO_FLAGS_CLOSE_ON_EXEC) != 0);
+      break;
 
     case F_SETFD:        /* set f_flags */
@@ -83,8 +85,8 @@
       else
         iop->flags &= ~LIBIO_FLAGS_CLOSE_ON_EXEC;
-      return 0;
+      break;
 
     case F_GETFL:        /* more flags (cloexec) */
-      return rtems_libio_to_fcntl_flags( iop->flags );
+      ret = rtems_libio_to_fcntl_flags( iop->flags );
 
     case F_SETFL:
@@ -92,36 +94,46 @@
 
       /*
-       *  XXX Double check this in the POSIX spec.  According to the Linux
-       *  XXX man page, only these flags can be added.
-       */
-
-      flags = (iop->flags & ~(O_APPEND|O_NONBLOCK)) |
-                   (flags & (O_APPEND|O_NONBLOCK));
-
-      /*
        *  XXX If we are turning on append, should we seek to the end?
        */
 
-      iop->flags = flags;
-      return 0;
+      iop->flags = (iop->flags & ~(O_APPEND | O_NONBLOCK)) |
+                   (flags & (O_APPEND | O_NONBLOCK));
+      break;
 
     case F_GETLK:
-      return -1;
+      errno = ENOTSUP;
+      ret = -1;
+      break;
 
     case F_SETLK:
-      return -1;
+      errno = ENOTSUP;
+      ret = -1;
+      break;
 
     case F_SETLKW:
-      return -1;
+      errno = ENOTSUP;
+      ret = -1;
+      break;
 
     case F_SETOWN:       /*  for sockets. */
-      return -1;
+      errno = ENOTSUP;
+      ret = -1;
+      break;
 
     case F_GETOWN:       /*  for sockets. */
-      return -1;
+      errno = ENOTSUP;
+      ret = -1;
+      break;
 
     default:
       break;
   }
-  return -1;
+  if ((ret >= 0) && iop->handlers->fcntl) {
+    int err = (*iop->handlers->fcntl)( cmd, iop );
+    if (err) {
+      errno = err;
+      ret = -1;
+    }
+  }
+  return ret;
 }
Index: c/src/lib/libc/libio.h
===================================================================
--- c/src/lib/libc/libio.h	(revision b64b1ed387bb9fa18e33bc9d7c24aa7fcce38da6)
+++ c/src/lib/libc/libio.h	(revision af0200363e8d0a69648bd78fd5ee2d0ee5f40624)
@@ -116,4 +116,9 @@
 );
 
+typedef int (*rtems_filesystem_fcntl_t)(
+  int cmd,
+  rtems_libio_t *iop
+);
+
 typedef struct {
     rtems_filesystem_open_t         open;
@@ -129,4 +134,5 @@
     rtems_filesystem_fsync_t        fsync;
     rtems_filesystem_fdatasync_t    fdatasync;
+    rtems_filesystem_fcntl_t        fcntl;
 } rtems_filesystem_file_handlers_r;
 
Index: c/src/lib/libnetworking/rtems/rtems_syscall.c
===================================================================
--- c/src/lib/libnetworking/rtems/rtems_syscall.c	(revision b64b1ed387bb9fa18e33bc9d7c24aa7fcce38da6)
+++ c/src/lib/libnetworking/rtems/rtems_syscall.c	(revision af0200363e8d0a69648bd78fd5ee2d0ee5f40624)
@@ -21,4 +21,5 @@
 #include <sys/protosw.h>
 #include <sys/proc.h>
+#include <sys/fcntl.h>
 #include <sys/filio.h>
 
@@ -645,12 +646,16 @@
 
 static int
-so_ioctl (struct socket *so, unsigned32 command, void *buffer)
+so_ioctl (rtems_libio_t *iop, struct socket *so, unsigned32 command, void *buffer)
 {
 	switch (command) {
 	case FIONBIO:
-		if (*(int *)buffer)
+		if (*(int *)buffer) {
+			iop->flags |= O_NONBLOCK;
 			so->so_state |= SS_NBIO;
-		else
+		}
+		else {
+			iop->flags &= ~O_NONBLOCK;
 			so->so_state &= ~SS_NBIO;
+		}
 		return 0;
 
@@ -679,5 +684,5 @@
 		return -1;
 	}
-	error = so_ioctl (so, command, buffer);
+	error = so_ioctl (iop, so, command, buffer);
 	rtems_bsdnet_semaphore_release ();
 	if (error) {
@@ -686,4 +691,24 @@
 	}
 	return 0;
+}
+
+static int
+rtems_bsdnet_fcntl (int cmd, rtems_libio_t *iop)
+{
+	struct socket *so;
+
+	if (cmd == F_SETFL) {
+		rtems_bsdnet_semaphore_obtain ();
+		if ((so = iop->data1) == NULL) {
+			rtems_bsdnet_semaphore_release ();
+			return EBADF;
+		}
+		if (iop->flags & O_NONBLOCK)
+			so->so_state |= SS_NBIO;
+		else
+			so->so_state &= ~SS_NBIO;
+		rtems_bsdnet_semaphore_release ();
+	}
+        return 0;
 }
 
@@ -708,3 +733,4 @@
 	NULL,			/* fsync */
 	NULL,			/* fdatasync */
+	rtems_bsdnet_fcntl,	/* fcntl */
 };
Index: c/src/libnetworking/rtems/rtems_syscall.c
===================================================================
--- c/src/libnetworking/rtems/rtems_syscall.c	(revision b64b1ed387bb9fa18e33bc9d7c24aa7fcce38da6)
+++ c/src/libnetworking/rtems/rtems_syscall.c	(revision af0200363e8d0a69648bd78fd5ee2d0ee5f40624)
@@ -21,4 +21,5 @@
 #include <sys/protosw.h>
 #include <sys/proc.h>
+#include <sys/fcntl.h>
 #include <sys/filio.h>
 
@@ -645,12 +646,16 @@
 
 static int
-so_ioctl (struct socket *so, unsigned32 command, void *buffer)
+so_ioctl (rtems_libio_t *iop, struct socket *so, unsigned32 command, void *buffer)
 {
 	switch (command) {
 	case FIONBIO:
-		if (*(int *)buffer)
+		if (*(int *)buffer) {
+			iop->flags |= O_NONBLOCK;
 			so->so_state |= SS_NBIO;
-		else
+		}
+		else {
+			iop->flags &= ~O_NONBLOCK;
 			so->so_state &= ~SS_NBIO;
+		}
 		return 0;
 
@@ -679,5 +684,5 @@
 		return -1;
 	}
-	error = so_ioctl (so, command, buffer);
+	error = so_ioctl (iop, so, command, buffer);
 	rtems_bsdnet_semaphore_release ();
 	if (error) {
@@ -686,4 +691,24 @@
 	}
 	return 0;
+}
+
+static int
+rtems_bsdnet_fcntl (int cmd, rtems_libio_t *iop)
+{
+	struct socket *so;
+
+	if (cmd == F_SETFL) {
+		rtems_bsdnet_semaphore_obtain ();
+		if ((so = iop->data1) == NULL) {
+			rtems_bsdnet_semaphore_release ();
+			return EBADF;
+		}
+		if (iop->flags & O_NONBLOCK)
+			so->so_state |= SS_NBIO;
+		else
+			so->so_state &= ~SS_NBIO;
+		rtems_bsdnet_semaphore_release ();
+	}
+        return 0;
 }
 
@@ -708,3 +733,4 @@
 	NULL,			/* fsync */
 	NULL,			/* fdatasync */
+	rtems_bsdnet_fcntl,	/* fcntl */
 };
Index: cpukit/libcsupport/include/rtems/libio.h
===================================================================
--- cpukit/libcsupport/include/rtems/libio.h	(revision b64b1ed387bb9fa18e33bc9d7c24aa7fcce38da6)
+++ cpukit/libcsupport/include/rtems/libio.h	(revision af0200363e8d0a69648bd78fd5ee2d0ee5f40624)
@@ -116,4 +116,9 @@
 );
 
+typedef int (*rtems_filesystem_fcntl_t)(
+  int cmd,
+  rtems_libio_t *iop
+);
+
 typedef struct {
     rtems_filesystem_open_t         open;
@@ -129,4 +134,5 @@
     rtems_filesystem_fsync_t        fsync;
     rtems_filesystem_fdatasync_t    fdatasync;
+    rtems_filesystem_fcntl_t        fcntl;
 } rtems_filesystem_file_handlers_r;
 
Index: cpukit/libcsupport/src/fcntl.c
===================================================================
--- cpukit/libcsupport/src/fcntl.c	(revision b64b1ed387bb9fa18e33bc9d7c24aa7fcce38da6)
+++ cpukit/libcsupport/src/fcntl.c	(revision af0200363e8d0a69648bd78fd5ee2d0ee5f40624)
@@ -31,4 +31,5 @@
   int            fd2;
   int            flags;
+  int            ret = 0;
   
   va_start( ap, cmd );
@@ -54,6 +55,8 @@
         /* allocate a file control block */
         diop = rtems_libio_allocate();
-        if ( diop == 0 )
-          return -1;
+        if ( diop == 0 ) {
+          ret = -1;
+          break;
+        }
       }
 
@@ -63,10 +66,9 @@
       diop->pathinfo   = iop->pathinfo;
       
-      return 0;
+      break;
 
     case F_GETFD:        /* get f_flags */
-      if ( iop->flags & LIBIO_FLAGS_CLOSE_ON_EXEC )
-        return 1;
-      return 0;
+      ret = ((iop->flags & LIBIO_FLAGS_CLOSE_ON_EXEC) != 0);
+      break;
 
     case F_SETFD:        /* set f_flags */
@@ -83,8 +85,8 @@
       else
         iop->flags &= ~LIBIO_FLAGS_CLOSE_ON_EXEC;
-      return 0;
+      break;
 
     case F_GETFL:        /* more flags (cloexec) */
-      return rtems_libio_to_fcntl_flags( iop->flags );
+      ret = rtems_libio_to_fcntl_flags( iop->flags );
 
     case F_SETFL:
@@ -92,36 +94,46 @@
 
       /*
-       *  XXX Double check this in the POSIX spec.  According to the Linux
-       *  XXX man page, only these flags can be added.
-       */
-
-      flags = (iop->flags & ~(O_APPEND|O_NONBLOCK)) |
-                   (flags & (O_APPEND|O_NONBLOCK));
-
-      /*
        *  XXX If we are turning on append, should we seek to the end?
        */
 
-      iop->flags = flags;
-      return 0;
+      iop->flags = (iop->flags & ~(O_APPEND | O_NONBLOCK)) |
+                   (flags & (O_APPEND | O_NONBLOCK));
+      break;
 
     case F_GETLK:
-      return -1;
+      errno = ENOTSUP;
+      ret = -1;
+      break;
 
     case F_SETLK:
-      return -1;
+      errno = ENOTSUP;
+      ret = -1;
+      break;
 
     case F_SETLKW:
-      return -1;
+      errno = ENOTSUP;
+      ret = -1;
+      break;
 
     case F_SETOWN:       /*  for sockets. */
-      return -1;
+      errno = ENOTSUP;
+      ret = -1;
+      break;
 
     case F_GETOWN:       /*  for sockets. */
-      return -1;
+      errno = ENOTSUP;
+      ret = -1;
+      break;
 
     default:
       break;
   }
-  return -1;
+  if ((ret >= 0) && iop->handlers->fcntl) {
+    int err = (*iop->handlers->fcntl)( cmd, iop );
+    if (err) {
+      errno = err;
+      ret = -1;
+    }
+  }
+  return ret;
 }
Index: cpukit/libnetworking/rtems/rtems_syscall.c
===================================================================
--- cpukit/libnetworking/rtems/rtems_syscall.c	(revision b64b1ed387bb9fa18e33bc9d7c24aa7fcce38da6)
+++ cpukit/libnetworking/rtems/rtems_syscall.c	(revision af0200363e8d0a69648bd78fd5ee2d0ee5f40624)
@@ -21,4 +21,5 @@
 #include <sys/protosw.h>
 #include <sys/proc.h>
+#include <sys/fcntl.h>
 #include <sys/filio.h>
 
@@ -645,12 +646,16 @@
 
 static int
-so_ioctl (struct socket *so, unsigned32 command, void *buffer)
+so_ioctl (rtems_libio_t *iop, struct socket *so, unsigned32 command, void *buffer)
 {
 	switch (command) {
 	case FIONBIO:
-		if (*(int *)buffer)
+		if (*(int *)buffer) {
+			iop->flags |= O_NONBLOCK;
 			so->so_state |= SS_NBIO;
-		else
+		}
+		else {
+			iop->flags &= ~O_NONBLOCK;
 			so->so_state &= ~SS_NBIO;
+		}
 		return 0;
 
@@ -679,5 +684,5 @@
 		return -1;
 	}
-	error = so_ioctl (so, command, buffer);
+	error = so_ioctl (iop, so, command, buffer);
 	rtems_bsdnet_semaphore_release ();
 	if (error) {
@@ -686,4 +691,24 @@
 	}
 	return 0;
+}
+
+static int
+rtems_bsdnet_fcntl (int cmd, rtems_libio_t *iop)
+{
+	struct socket *so;
+
+	if (cmd == F_SETFL) {
+		rtems_bsdnet_semaphore_obtain ();
+		if ((so = iop->data1) == NULL) {
+			rtems_bsdnet_semaphore_release ();
+			return EBADF;
+		}
+		if (iop->flags & O_NONBLOCK)
+			so->so_state |= SS_NBIO;
+		else
+			so->so_state &= ~SS_NBIO;
+		rtems_bsdnet_semaphore_release ();
+	}
+        return 0;
 }
 
@@ -708,3 +733,4 @@
 	NULL,			/* fsync */
 	NULL,			/* fdatasync */
+	rtems_bsdnet_fcntl,	/* fcntl */
 };
