Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: "Julio Guerra" <julio@farjump.io>
To: "gdb-patches@sourceware.org" <gdb-patches@sourceware.org>
Cc: "Pedro Alves" <palves@redhat.com>, "Julio Guerra" <julio@farjump.io>
Subject: [PATCH v4] Allow using special files with File I/O functions
Date: Thu, 05 Jul 2018 09:16:00 -0000	[thread overview]
Message-ID: <0102016469ba9beb-e8338b53-74bd-46ea-91c7-eea909052532-000000@eu-west-1.amazonses.com> (raw)
In-Reply-To: <20180705091618.33743-1-julio@farjump.io>

Remove the restriction in remote_fileio_func_open() to regular files only and
add support for special file types in the File IO stat structure.
The link file type is not part of the new definitions as stat() and fstat()
called by remote_fileio_func_stat() and remote_fileio_func_fstat() follow links,
it is thus not possible to obtain this file type in the File IO stat structure.

Add tests to cover as much cases as possible, limited by the fact that some
types such as FIFOs or character devices cannot be created on non-unix operating
systems. This limits the test cases to a regular file, a directory and the
standard output/input/error descriptors.

The major goal is to be able to write advanced embedded testing functions, like:
- using a FIFO between the embedded program and the host, instead of being
  restricted to the GDB console only.
- mocking features based on host's by using some host device.

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.

Signed-off-by: Julio Guerra <julio@farjump.io>
---
 gdb/ChangeLog                     | 16 ++++++
 gdb/NEWS                          |  4 ++
 gdb/common/fileio.c               | 55 +++++++++++++++----
 gdb/doc/gdb.texinfo               |  7 ++-
 gdb/remote-fileio.c               | 10 +---
 gdb/testsuite/gdb.base/fileio.c   | 87 +++++++++++++++++++++++++++----
 gdb/testsuite/gdb.base/fileio.exp | 26 ++++++++-
 include/ChangeLog                 |  5 ++
 include/gdb/fileio.h              | 19 +++++--
 9 files changed, 197 insertions(+), 32 deletions(-)

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
-- 
2.18.0



       reply	other threads:[~2018-07-05  9:16 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20180705091618.33743-1-julio@farjump.io>
2018-07-05  9:16 ` Julio Guerra [this message]
2018-07-09 12:47   ` Pedro Alves
     [not found]     ` <a74d27a4-64c9-adcd-deaf-f36e0c03e73d@farjump.io>
2018-07-09 13:16       ` Julio Guerra
2018-07-09 14:37         ` Pedro Alves
     [not found]           ` <28e7d8d4-7a1a-8fe0-a868-bed711cdb417@farjump.io>
2018-07-09 15:22             ` Julio Guerra
2018-07-09 15:37               ` Pedro Alves

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=0102016469ba9beb-e8338b53-74bd-46ea-91c7-eea909052532-000000@eu-west-1.amazonses.com \
    --to=julio@farjump.io \
    --cc=gdb-patches@sourceware.org \
    --cc=palves@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox