* syscall.c (cb_syscall) <case CB_SYS_lstat>: New case.
[deliverable/binutils-gdb.git] / sim / common / callback.c
index 068cea292e9ab44ee9017b0ff9a8c5d9bef85d50..7ba0c06fb0656fde8967e735ca3485762163e6c2 100644 (file)
@@ -1,5 +1,6 @@
 /* Remote target callback routines.
-   Copyright 1995, 1996, 1997 Free Software Foundation, Inc.
+   Copyright 1995, 1996, 1997, 2000, 2002, 2003, 2004
+   Free Software Foundation, Inc.
    Contributed by Cygnus Solutions.
 
    This file is part of GDB.
@@ -22,7 +23,7 @@
    level.  */
 
 #ifdef HAVE_CONFIG_H
-#include "config.h"
+#include "cconfig.h"
 #endif
 #include "ansidecl.h"
 #ifdef ANSI_PROTOTYPES
@@ -46,7 +47,7 @@
 #include <time.h>
 #include <sys/types.h>
 #include <sys/stat.h>
-#include "callback.h"
+#include "gdb/callback.h"
 #include "targ-vals.h"
 
 #ifdef HAVE_UNISTD_H
@@ -89,7 +90,6 @@ static void os_error PARAMS ((host_callback *, const char *, ...));
 static int fdmap PARAMS ((host_callback *, int));
 static int fdbad PARAMS ((host_callback *, int));
 static int wrap PARAMS ((host_callback *, int));
-static int enosys PARAMS ((host_callback *, int));
 
 /* Set the callback copy of errno from what we see now.  */
 
@@ -102,21 +102,6 @@ wrap (p, val)
   return val;
 }
 
-/* Return a value indicating the system call isn't present.  */
-
-static int
-enosys (p, result)
-     host_callback *p;
-     int result;
-{
-#ifdef ENOSYS
-  p->last_errno = ENOSYS;
-#else
-  p->last_errno = EINVAL;
-#endif
-  return result;
-}
-
 /* Make sure the FD provided is ok.  If not, return non-zero
    and set errno. */
 
@@ -125,7 +110,7 @@ fdbad (p, fd)
      host_callback *p;
      int fd;
 {
-  if (fd < 0 || fd > MAX_CALLBACK_FDS || !p->fdopen[fd])
+  if (fd < 0 || fd > MAX_CALLBACK_FDS || p->fd_buddy[fd] < 0)
     {
       p->last_errno = EINVAL;
       return -1;
@@ -147,13 +132,20 @@ os_close (p, fd)
      int fd;
 {
   int result;
+  int i, next;
 
   result = fdbad (p, fd);
   if (result)
     return result;
-  result = wrap (p, close (fdmap (p, fd)));
-  if(result == 0 && !p->alwaysopen[fd])
-    p->fdopen[fd] = 0;
+  /* If this file descripter has one or more buddies (originals /
+     duplicates from a dup), just remove it from the circular list.  */
+  for (i = fd; (next = p->fd_buddy[i]) != fd; )
+    i = next;
+  if (fd != i)
+    p->fd_buddy[i] = p->fd_buddy[fd];
+  else
+    result = wrap (p, close (fdmap (p, fd)));
+  p->fd_buddy[fd] = -1;
 
   return result;
 }
@@ -249,7 +241,7 @@ os_open (p, name, flags)
   int i;
   for (i = 0; i < MAX_CALLBACK_FDS; i++)
     {
-      if (!p->fdopen[i])
+      if (p->fd_buddy[i] < 0)
        {
          int f = open (name, cb_target_to_host_open (p, flags), 0644);
          if (f < 0)
@@ -257,7 +249,7 @@ os_open (p, name, flags)
              p->last_errno = errno;
              return f;
            }
-         p->fdopen[i] = 1;
+         p->fd_buddy[i] = i;
          p->fdmap[i] = f;
          return i;
        }
@@ -322,32 +314,32 @@ os_write (p, fd, buf, len)
 
 static int 
 os_write_stdout (p, buf, len)
-     host_callback *p;
+     host_callback *p ATTRIBUTE_UNUSED;
      const char *buf;
      int len;
 {
-  return fwrite(buf, 1, len, stdout);
+  return fwrite (buf, 1, len, stdout);
 }
 
 static void
 os_flush_stdout (p)
-     host_callback *p;
+     host_callback *p ATTRIBUTE_UNUSED;
 {
   fflush (stdout);
 }
 
 static int 
 os_write_stderr (p, buf, len)
-     host_callback *p;
+     host_callback *p ATTRIBUTE_UNUSED;
      const char *buf;
      int len;
 {
-  return fwrite(buf, 1, len, stderr);
+  return fwrite (buf, 1, len, stderr);
 }
 
 static void
 os_flush_stderr (p)
-     host_callback *p;
+     host_callback *p ATTRIBUTE_UNUSED;
 {
   fflush (stderr);
 }
@@ -391,8 +383,12 @@ static int
 os_stat (p, file, buf)
      host_callback *p;
      const char *file;
-     PTR buf;
+     struct stat *buf;
 {
+  /* ??? There is an issue of when to translate to the target layout.
+     One could do that inside this function, or one could have the
+     caller do it.  It's more flexible to let the caller do it, though
+     I'm not sure the flexibility will ever be useful.  */
   return wrap (p, stat (file, buf));
 }
 
@@ -400,22 +396,81 @@ static int
 os_fstat (p, fd, buf)
      host_callback *p;
      int fd;
-     PTR buf;
+     struct stat *buf;
+{
+  if (fdbad (p, fd))
+    return -1;
+  /* ??? There is an issue of when to translate to the target layout.
+     One could do that inside this function, or one could have the
+     caller do it.  It's more flexible to let the caller do it, though
+     I'm not sure the flexibility will ever be useful.  */
+  return wrap (p, fstat (fdmap (p, fd), buf));
+}
+
+static int
+os_lstat (p, file, buf)
+     host_callback *p;
+     const char *file;
+     struct stat *buf;
+{
+  /* NOTE: hpn/2004-12-12: Same issue here as with os_fstat.  */
+  return wrap (p, lstat (file, buf));
+}
+
+static int 
+os_ftruncate (p, fd, len)
+     host_callback *p;
+     int fd;
+     long len;
+{
+  int result;
+
+  result = fdbad (p, fd);
+  if (result)
+    return result;
+  result = wrap (p, ftruncate (fdmap (p, fd), len));
+  return result;
+}
+
+static int
+os_truncate (p, file, len)
+     host_callback *p;
+     const char *file;
+     long len;
 {
-  return wrap (p, fstat (fd, buf));
+  return wrap (p, truncate (file, len));
 }
 
 static int
 os_shutdown (p)
      host_callback *p;
 {
-  int i;
+  int i, next, j;
   for (i = 0; i < MAX_CALLBACK_FDS; i++)
     {
-      if (p->fdopen[i] && !p->alwaysopen[i]) {
+      int do_close = 1;
+
+      next = p->fd_buddy[i];
+      if (next < 0)
+       continue;
+      do
+       {
+         j = next;
+         if (j == MAX_CALLBACK_FDS)
+           do_close = 0;
+         next = p->fd_buddy[j];
+         p->fd_buddy[j] = -1;
+         /* At the initial call of os_init, we got -1, 0, 0, 0, ...  */
+         if (next < 0)
+           {
+             p->fd_buddy[i] = -1;
+             do_close = 0;
+             break;
+           }
+       }
+      while (j != i);
+      if (do_close)
        close (p->fdmap[i]);
-       p->fdopen[i] = 0;
-      }
     }
   return 1;
 }
@@ -430,9 +485,10 @@ os_init (p)
   for (i = 0; i < 3; i++)
     {
       p->fdmap[i] = i;
-      p->fdopen[i] = 1;
-      p->alwaysopen[i] = 1;
+      p->fd_buddy[i] = i - 1;
     }
+  p->fd_buddy[0] = MAX_CALLBACK_FDS;
+  p->fd_buddy[MAX_CALLBACK_FDS] = 2;
 
   p->syscall_map = cb_init_syscall_map;
   p->errno_map = cb_init_errno_map;
@@ -441,12 +497,12 @@ os_init (p)
   return 1;
 }
 
-/* DEPRECIATED */
+/* DEPRECATED */
 
 /* VARARGS */
 static void
 #ifdef ANSI_PROTOTYPES
-os_printf_filtered (host_callback *p, const char *format, ...)
+os_printf_filtered (host_callback *p ATTRIBUTE_UNUSED, const char *format, ...)
 #else
 os_printf_filtered (p, va_alist)
      host_callback *p;
@@ -470,7 +526,7 @@ os_printf_filtered (p, va_alist)
 /* VARARGS */
 static void
 #ifdef ANSI_PROTOTYPES
-os_vprintf_filtered (host_callback *p, const char *format, va_list args)
+os_vprintf_filtered (host_callback *p ATTRIBUTE_UNUSED, const char *format, va_list args)
 #else
 os_vprintf_filtered (p, format, args)
      host_callback *p;
@@ -484,7 +540,7 @@ os_vprintf_filtered (p, format, args)
 /* VARARGS */
 static void
 #ifdef ANSI_PROTOTYPES
-os_evprintf_filtered (host_callback *p, const char *format, va_list args)
+os_evprintf_filtered (host_callback *p ATTRIBUTE_UNUSED, const char *format, va_list args)
 #else
 os_evprintf_filtered (p, format, args)
      host_callback *p;
@@ -498,7 +554,7 @@ os_evprintf_filtered (p, format, args)
 /* VARARGS */
 static void
 #ifdef ANSI_PROTOTYPES
-os_error (host_callback *p, const char *format, ...)
+os_error (host_callback *p ATTRIBUTE_UNUSED, const char *format, ...)
 #else
 os_error (p, va_alist)
      host_callback *p;
@@ -543,6 +599,10 @@ host_callback default_callback =
 
   os_stat,
   os_fstat,
+  os_lstat,
+
+  os_ftruncate,
+  os_truncate,
 
   os_poll_quit,
 
@@ -558,8 +618,7 @@ host_callback default_callback =
   0,           /* last errno */
 
   { 0, },      /* fdmap */
-  { 0, },      /* fdopen */
-  { 0, },      /* alwaysopen */
+  { -1, },     /* fd_buddy */
 
   0, /* syscall_map */
   0, /* errno_map */
@@ -728,20 +787,25 @@ store (p, size, val, big_p)
 }
 
 /* Translate a host's stat struct into a target's.
+   If HS is NULL, just compute the length of the buffer required,
+   TS is ignored.
 
-   BIG_P is non-zero if the target is big-endian.
    The result is the size of the target's stat struct,
-   or zero if an error occured during the translation.  */
+   or zero if an error occurred during the translation.  */
 
 int
-cb_host_to_target_stat (cb, hs, ts, big_p)
+cb_host_to_target_stat (cb, hs, ts)
      host_callback *cb;
      const struct stat *hs;
      PTR ts;
-     int big_p;
 {
   const char *m = cb->stat_map;
-  char *p = ts;
+  char *p;
+  int big_p = 0;
+
+  if (hs == NULL)
+    ts = NULL;
+  p = ts;
 
   while (m)
     {
@@ -761,13 +825,60 @@ cb_host_to_target_stat (cb, hs, ts, big_p)
          return 0;
        }
 
-      if (strncmp (m, "st_dev", q - m) == 0)
-       store (p, size, hs->st_dev, big_p);
-      else if (strncmp (m, "st_ino", q - m) == 0)
-       store (p, size, hs->st_ino, big_p);
-      /* FIXME:wip */
-      else
-       store (p, size, 0, big_p); /* unsupported field, store 0 */
+      if (hs != NULL)
+       {
+         if (0)
+           ;
+         /* Defined here to avoid emacs indigestion on a lone "else".  */
+#undef ST_x
+#define ST_x(FLD)                                      \
+         else if (strncmp (m, #FLD, q - m) == 0)       \
+           store (p, size, hs->FLD, big_p)
+
+#ifdef HAVE_STRUCT_STAT_ST_DEV
+         ST_x (st_dev);
+#endif
+#ifdef HAVE_STRUCT_STAT_ST_INO
+         ST_x (st_ino);
+#endif
+#ifdef HAVE_STRUCT_STAT_ST_MODE
+         ST_x (st_mode);
+#endif
+#ifdef HAVE_STRUCT_STAT_ST_NLINK
+         ST_x (st_nlink);
+#endif
+#ifdef HAVE_STRUCT_STAT_ST_UID
+         ST_x (st_uid);
+#endif
+#ifdef HAVE_STRUCT_STAT_ST_GID
+         ST_x (st_gid);
+#endif
+#ifdef HAVE_STRUCT_STAT_ST_RDEV
+         ST_x (st_rdev);
+#endif
+#ifdef HAVE_STRUCT_STAT_ST_SIZE
+         ST_x (st_size);
+#endif
+#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
+         ST_x (st_blksize);
+#endif
+#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
+         ST_x (st_blocks);
+#endif
+#ifdef HAVE_STRUCT_STAT_ST_ATIME
+         ST_x (st_atime);
+#endif
+#ifdef HAVE_STRUCT_STAT_ST_MTIME
+         ST_x (st_mtime);
+#endif
+#ifdef HAVE_STRUCT_STAT_ST_CTIME
+         ST_x (st_ctime);
+#endif
+#undef ST_x
+         /* FIXME:wip */
+         else
+           store (p, size, 0, big_p); /* unsupported field, store 0 */
+       }
 
       p += size;
       m = strchr (q, ':');
This page took 0.027328 seconds and 4 git commands to generate.