diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 7bd0cc4f95..b937f029e3 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,19 @@
+2018-07-05  Julio Guerra  <julio@farjump.io>
+
+	* remote-fileio.c (remote_fileio_func_open, remote_fileio_func_stat):
+	Allow using File I/O functions open(), stat() and fstat() on special
+	files.
+	* common/fileio.c (fileio_to_host_mode, fileio_mode_pack): Add new
+	special file types in fst_mode's definition.
+	(host_to_fileio_stat): Define fst_dev using the new macro definitions
+	and according to the file's type.
+	* testsuite/gdb.base/fileio.c: Add test cases to cover some special
+	files and file descriptors.
+	* testsuite/gdb.base/fileio.exp: Likewise.
+	* doc/gdb.texinfo: Document the changes.
+	* NEWS: Briefly describe the changes of File I/O operations open, stat,
+	fstat.
+
 2018-07-04  Tom Tromey  <tom@tromey.com>
 
 	* darwin-nat.c (darwin_attach_pid): Use exit_inferior.
diff --git a/gdb/NEWS b/gdb/NEWS
index 2d1d161233..4a0ab4ac52 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -36,6 +36,10 @@
 * C expressions can now use _Alignof, and C++ expressions can now use
   alignof.
 
+* The File I/O remote protocole extension now allows opening special files such
+  as FIFOs or character devices. Common file types are now be returned by stat
+  and fstat.
+
 * New commands
 
 set debug fbsd-nat
diff --git a/gdb/common/fileio.c b/gdb/common/fileio.c
index 912a7ede3c..754bc4b4f6 100644
--- a/gdb/common/fileio.c
+++ b/gdb/common/fileio.c
@@ -119,12 +119,40 @@ fileio_to_host_mode (int fileio_mode, mode_t *mode_p)
   if (fileio_mode & ~FILEIO_S_SUPPORTED)
     return -1;
 
-  if (fileio_mode & FILEIO_S_IFREG)
-    mode |= S_IFREG;
-  if (fileio_mode & FILEIO_S_IFDIR)
-    mode |= S_IFDIR;
-  if (fileio_mode & FILEIO_S_IFCHR)
-    mode |= S_IFCHR;
+  switch (fileio_mode & FILEIO_S_IFMT)
+    {
+#ifdef S_IFSOCK
+    case FILEIO_S_IFSOCK:
+      *mode_p |= S_IFSOCK;
+      break;
+#endif
+#ifdef S_IFREG
+    case FILEIO_S_IFREG:
+      mode |= S_IFREG;
+      break;
+#endif
+#ifdef S_IFBLK
+    case FILEIO_S_IFBLK:
+      mode |= S_IFBLK;
+      break;
+#endif
+#ifdef S_IFDIR
+    case FILEIO_S_IFDIR:
+      mode |= S_IFDIR;
+      break;
+#endif
+#ifdef S_IFCHR
+    case FILEIO_S_IFCHR:
+      mode |= S_IFCHR;
+      break;
+#endif
+#ifdef S_IFIFO
+    case FILEIO_S_IFIFO:
+      mode |= S_IFIFO;
+      break;
+#endif
+    }
+
   if (fileio_mode & FILEIO_S_IRUSR)
     mode |= S_IRUSR;
   if (fileio_mode & FILEIO_S_IWUSR)
@@ -167,10 +195,17 @@ fileio_mode_pack (mode_t mode)
 
   if (S_ISREG (mode))
     tmode |= FILEIO_S_IFREG;
-  if (S_ISDIR (mode))
+  else if (S_ISDIR (mode))
     tmode |= FILEIO_S_IFDIR;
-  if (S_ISCHR (mode))
+  else if (S_ISCHR (mode))
     tmode |= FILEIO_S_IFCHR;
+  else if (S_ISSOCK (mode))
+    tmode |= FILEIO_S_IFSOCK;
+  else if (S_ISBLK (mode))
+    tmode |= FILEIO_S_IFBLK;
+  else if (S_ISFIFO (mode))
+    tmode |= FILEIO_S_IFIFO;
+
   if (mode & S_IRUSR)
     tmode |= FILEIO_S_IRUSR;
   if (mode & S_IWUSR)
@@ -224,8 +259,10 @@ void
 host_to_fileio_stat (struct stat *st, struct fio_stat *fst)
 {
   LONGEST blksize;
+  long fst_dev;
 
-  host_to_fileio_uint ((long) st->st_dev, fst->fst_dev);
+  fst_dev = S_ISREG (st->st_mode) ? FILEIO_STDEV_FILE : FILEIO_STDEV_SPECIAL;
+  host_to_fileio_uint (fst_dev, fst->fst_dev);
   host_to_fileio_uint ((long) st->st_ino, fst->fst_ino);
   host_to_fileio_mode (st->st_mode, fst->fst_mode);
   host_to_fileio_uint ((long) st->st_nlink, fst->fst_nlink);
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 91ec219958..54b9ff6253 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -40986,7 +40986,8 @@ range of values.
 @table @code
 
 @item st_dev
-A value of 0 represents a file, 1 the console.
+A value of 0 represents a file, 1 GDB's console and 2 a special file
+(@code{st_mode} gives further details on the file type).
 
 @item st_ino
 No valid meaning for the target.  Transmitted unchanged.
@@ -41073,8 +41074,12 @@ All values are given in hexadecimal representation.
 All values are given in octal representation.
 
 @smallexample
+  S_IFSOCK      0140000
   S_IFREG       0100000
+  S_IFBLK        060000
   S_IFDIR        040000
+  S_IFCHR        020000
+  S_IFIFO        010000
   S_IRUSR          0400
   S_IWUSR          0200
   S_IXUSR          0100
diff --git a/gdb/remote-fileio.c b/gdb/remote-fileio.c
index 313da642ea..168590245e 100644
--- a/gdb/remote-fileio.c
+++ b/gdb/remote-fileio.c
@@ -885,16 +885,9 @@ remote_fileio_func_stat (remote_target *remote, char *buf)
       remote_fileio_return_errno (remote, -1);
       return;
     }
-  /* Only operate on regular files and directories.  */
-  if (!ret && !S_ISREG (st.st_mode) && !S_ISDIR (st.st_mode))
-    {
-      remote_fileio_reply (remote, -1, FILEIO_EACCES);
-      return;
-    }
   if (statptr)
     {
       host_to_fileio_stat (&st, &fst);
-      host_to_fileio_uint (0, fst.fst_dev);
 
       errno = target_write_memory (statptr, (gdb_byte *) &fst, sizeof fst);
       if (errno != 0)
@@ -939,7 +932,6 @@ remote_fileio_func_fstat (remote_target *remote, char *buf)
 
   if (fd == FIO_FD_CONSOLE_IN || fd == FIO_FD_CONSOLE_OUT)
     {
-      host_to_fileio_uint (1, fst.fst_dev);
       memset (&st, 0, sizeof (st));
       st.st_mode = S_IFCHR | (fd == FIO_FD_CONSOLE_IN ? S_IRUSR : S_IWUSR);
       st.st_nlink = 1;
@@ -972,6 +964,8 @@ remote_fileio_func_fstat (remote_target *remote, char *buf)
   if (ptrval)
     {
       host_to_fileio_stat (&st, &fst);
+      if (fd == FIO_FD_CONSOLE_IN || fd == FIO_FD_CONSOLE_OUT)
+	host_to_fileio_uint (FILEIO_STDEV_CONSOLE, fst.fst_dev);
 
       errno = target_write_memory (ptrval, (gdb_byte *) &fst, sizeof fst);
       if (errno != 0)
diff --git a/gdb/testsuite/gdb.base/fileio.c b/gdb/testsuite/gdb.base/fileio.c
index 7f482a34d3..c1902f5cc8 100644
--- a/gdb/testsuite/gdb.base/fileio.c
+++ b/gdb/testsuite/gdb.base/fileio.c
@@ -32,11 +32,19 @@ close(int fd);
 1) Attempt to close an invalid file descriptor - EBADF
 
 stat(const char *file_name, struct stat *buf);
-1) Pathname is a null string -  ENOENT
-2) Pathname does not exist - ENOENT
+1) Regular file
+2) Pathname is a null string -  ENOENT
+3) Pathname is an empty string -  ENOENT or EFAULT
+4) Pathname does not exist - ENOENT
+5) Directory
 
 fstat(int filedes, struct stat *buf);
-1) Attempt to stat using an invalid file descriptor - EBADF
+1) Regular file
+2) Attempt to stat using an invalid file descriptor - EBADF
+3) Directory
+4) Standard input
+5) Standard output
+6) Standard error
 
 isatty (int desc);
 Not applicable. We will test that it returns 1 when expected and a case
@@ -68,9 +76,10 @@ static const char *strerrno (int err);
 #define RENAMED     "bar.fileio.test"
 #define NONEXISTANT "nofoo.fileio.test"
 #define NOWRITE     "nowrt.fileio.test"
-#define TESTDIR1     "dir1.fileio.test"
-#define TESTDIR2     "dir2.fileio.test"
-#define TESTSUBDIR   "dir1.fileio.test/subdir.fileio.test"
+#define TESTDIR1    "dir1.fileio.test"
+#define TESTDIR2    "dir2.fileio.test"
+#define TESTSUBDIR  "dir1.fileio.test/subdir.fileio.test"
+#define DIRECTORY   "directory.fileio.test"
 
 #define STRING      "Hello World"
 
@@ -292,7 +301,8 @@ test_stat (void)
   ret = stat (OUTDIR FILENAME, &st);
   if (!ret)
     printf ("stat 1: ret = %d, errno = %d %s\n", ret, errno,
-	    st.st_size == 11 ? "OK" : "");
+	    st.st_dev == 0 && S_ISREG (st.st_mode) && st.st_size == 11 ?
+	    "OK" : "");
   else
     printf ("stat 1: ret = %d, errno = %d\n", ret, errno);
   stop ();
@@ -311,8 +321,20 @@ test_stat (void)
   /* Nonexistant file */
   errno = 0;
   ret = stat (NONEXISTANT, &st);
-  printf ("stat 4: ret = %d, errno = %d %s\n", ret, errno,
-  	  strerrno (errno));
+  if (!ret)
+    printf ("stat 4: ret = %d, errno = %d %s\n", ret, errno,
+	    strerrno (errno));
+  else
+    printf ("stat 1: ret = %d, errno = %d\n", ret, errno);
+  stop ();
+  /* Special file: directory */
+  errno = 0;
+  ret = stat (OUTDIR DIRECTORY, &st);
+  if (!ret)
+    printf ("stat 5: ret = %d, errno = %d %s\n", ret, errno,
+	    st.st_dev == 2 && S_ISDIR (st.st_mode) ? "OK" : "");
+  else
+    printf ("stat 1: ret = %d, errno = %d\n", ret, errno);
   stop ();
 }
 
@@ -331,7 +353,8 @@ test_fstat (void)
       ret = fstat (fd, &st);
       if (!ret)
 	printf ("fstat 1: ret = %d, errno = %d %s\n", ret, errno,
-		st.st_size == 11 ? "OK" : "");
+		st.st_dev == 0 && S_ISREG (st.st_mode) && st.st_size == 11 ?
+		"OK" : "");
       else
 	printf ("fstat 1: ret = %d, errno = %d\n", ret, errno);
       close (fd);
@@ -345,6 +368,50 @@ test_fstat (void)
   printf ("fstat 2: ret = %d, errno = %d %s\n", ret, errno,
   	  strerrno (errno));
   stop ();
+  /* Special file: directory */
+  errno = 0;
+  fd = open (OUTDIR DIRECTORY, O_RDONLY);
+  if (fd >= 0)
+    {
+      errno = 0;
+      ret = fstat (fd, &st);
+      if (!ret)
+	printf ("fstat 3: ret = %d, errno = %d %s\n", ret, errno,
+		st.st_dev == 2 && S_ISDIR (st.st_mode) ? "OK" : "");
+      else
+	printf ("fstat 3: ret = %d, errno = %d\n", ret, errno);
+      close (fd);
+    }
+  else
+    printf ("fstat 3: errno = %d\n", errno);
+  stop ();
+  /* Standard input */
+  errno = 0;
+  ret = fstat (STDIN_FILENO, &st);
+  if (!ret)
+    printf ("fstat 4: ret = %d, errno = %d %s\n", ret, errno,
+	    st.st_dev == 1 ? "OK" : "");
+  else
+    printf ("fstat 4: ret = %d, errno = %d\n", ret, errno);
+  stop ();
+  /* Standard output */
+  errno = 0;
+  ret = fstat (STDOUT_FILENO, &st);
+  if (!ret)
+    printf ("fstat 5: ret = %d, errno = %d %s\n", ret, errno,
+	    st.st_dev == 1 ? "OK" : "");
+  else
+    printf ("fstat 5: ret = %d, errno = %d\n", ret, errno);
+  stop ();
+  /* Standard error */
+  errno = 0;
+  ret = fstat (STDERR_FILENO, &st);
+  if (!ret)
+    printf ("fstat 6: ret = %d, errno = %d %s\n", ret, errno,
+	    st.st_dev == 1 ? "OK" : "");
+  else
+    printf ("fstat 6: ret = %d, errno = %d\n", ret, errno);
+  stop ();
 }
 
 void
diff --git a/gdb/testsuite/gdb.base/fileio.exp b/gdb/testsuite/gdb.base/fileio.exp
index bc409c26aa..234f304ac7 100644
--- a/gdb/testsuite/gdb.base/fileio.exp
+++ b/gdb/testsuite/gdb.base/fileio.exp
@@ -31,7 +31,7 @@ if {[is_remote host]} {
 
 if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" \
 	   executable \
-	   [list debug "additional_flags=-DOUTDIR=\"$outdir/\""]] != "" } {
+					 [list debug "additional_flags=-DOUTDIR=\"$outdir/\" [target_info fileio,cflags]" "ldflags=[target_info fileio,ldflags]"]] != "" } {
     untested "failed to compile"
     return -1
 }
@@ -136,6 +136,10 @@ gdb_test continue \
 "Continuing\\..*close 2:.*EBADF$stop_msg" \
 "Closing an invalid file descriptor returns EBADF"
 
+# Prepare some different file types for stat and fstat.
+set filetype_directory [file join $outdir "directory.fileio.test"]
+file mkdir $filetype_directory
+
 gdb_test continue \
 "Continuing\\..*stat 1:.*OK$stop_msg" \
 "Stat a file"
@@ -152,6 +156,10 @@ gdb_test continue \
 "Continuing\\..*stat 4:.*ENOENT$stop_msg" \
 "Stat a nonexistant file returns ENOENT"
 
+gdb_test continue \
+"Continuing\\..*stat 5:.*OK$stop_msg" \
+"Stat a directory"
+
 gdb_test continue \
 "Continuing\\..*fstat 1:.*OK$stop_msg" \
 "Fstat an open file"
@@ -160,6 +168,22 @@ gdb_test continue \
 "Continuing\\..*fstat 2:.*EBADF$stop_msg" \
 "Fstat an invalid file descriptor returns EBADF"
 
+gdb_test continue \
+"Continuing\\..*fstat 3:.*OK$stop_msg" \
+"Fstat a directory"
+
+gdb_test continue \
+"Continuing\\..*fstat 4:.*OK$stop_msg" \
+"Fstat standard output"
+
+gdb_test continue \
+"Continuing\\..*fstat 5:.*OK$stop_msg" \
+"Fstat standard input"
+
+gdb_test continue \
+"Continuing\\..*fstat 6:.*OK$stop_msg" \
+"Fstat standard error"
+
 gdb_test continue \
 "Continuing\\..*isatty 1:.*OK$stop_msg" \
 "Isatty (stdin)"
diff --git a/include/ChangeLog b/include/ChangeLog
index de808014ac..64c41b912b 100644
--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -1,3 +1,8 @@
+2018-07-05  Julio Guerra  <julio@farjump.io>
+
+	* gdb/fileio.h: Add macro definitions for special files,
+	both for fst_dev and fst_mode fields of struct fst_stat.
+
 2018-07-02  Maciej W. Rozycki  <macro@mips.com>
 
 	PR tdep/8282
diff --git a/include/gdb/fileio.h b/include/gdb/fileio.h
index 7bb55f579f..8ae1da4c68 100644
--- a/include/gdb/fileio.h
+++ b/include/gdb/fileio.h
@@ -37,10 +37,24 @@
 				 FILEIO_O_CREAT  | FILEIO_O_TRUNC| \
 				 FILEIO_O_EXCL)
 
+/* Device id values of fst_dev field */
+/* Regular file */
+#define FILEIO_STDEV_FILE           0
+/* GDB's console */
+#define FILEIO_STDEV_CONSOLE        1
+/* Not a regular file nor the console.
+   Bits FILEIO_S_IFMT of fst_mode give the exact file type. */
+#define FILEIO_STDEV_SPECIAL        2
+
 /* mode_t bits */
+#define FILEIO_S_IFSOCK       0140000
 #define FILEIO_S_IFREG        0100000
+#define FILEIO_S_IFBLK         060000
 #define FILEIO_S_IFDIR         040000
 #define FILEIO_S_IFCHR         020000
+#define FILEIO_S_IFIFO         010000
+#define FILEIO_S_IFMT         (FILEIO_S_IFIFO | FILEIO_S_IFCHR| \
+         FILEIO_S_IFDIR | FILEIO_S_IFBLK | FILEIO_S_IFREG | FILEIO_S_IFSOCK)
 #define FILEIO_S_IRUSR           0400
 #define FILEIO_S_IWUSR           0200
 #define FILEIO_S_IXUSR           0100
@@ -53,9 +67,8 @@
 #define FILEIO_S_IWOTH             02
 #define FILEIO_S_IXOTH             01
 #define FILEIO_S_IRWXO             07
-#define FILEIO_S_SUPPORTED         (FILEIO_S_IFREG|FILEIO_S_IFDIR|  \
-				    FILEIO_S_IRWXU|FILEIO_S_IRWXG|  \
-                                    FILEIO_S_IRWXO)
+#define FILEIO_S_SUPPORTED         (FILEIO_S_IFMT | FILEIO_S_IRWXU| \
+         FILEIO_S_IRWXG | FILEIO_S_IRWXO)
 
 /* lseek(2) flags */
 #define FILEIO_SEEK_SET             0
