This is the mail archive of the newlib@sourceware.org mailing list for the newlib project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fixes for libgloss/arm/syscalls.c.


The following patch increases the quality-of-implementation for
libgloss/arm/syscalls.c

1. A rewrite of the file handling cache to support POSIX's requirement
that a lowest possible file handle be returned from open().

In this implementation user file descriptors are represented as indicies
into the openfiles array. This makes the open file lookup O(1) as
opposed to the previous O(n) search.

The function findslot() takes as input a user file descriptor and
returns a pointer to the file descriptor structure. If the user file
descriptor was invalid or not open, findslot() returns NULL. The
caller is responsible for setting errno appropriatly. We centralize fd
checking in findslot().

The open() function uses newslot() to find the lowest numbered unused
file descriptor structure. We cannot use findslot() in open() because
findslot() does error checking.

The function remap_handle() is removed since the values of 0, 1, and 2
for stdin, stdout, and stderr are handled by findslot().

All functions that manipulate fd's must call one of findslot() or
newslot(). 

We call checkerror() or error() on the return of *all* SWI calls, this
ensures that errno is always set correctly. 

The following testcase passes with this patch.
----------
cat >> test.c <<EOF
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <assert.h>
    
int main()
{ 
  int fd;
  int fd2;
  fd = open("test.c", O_RDONLY);
  assert(fd >= 3);
  fd2 = open("test.c", O_RDONLY);
  assert(fd2 > fd);
  close(fd);
  fd2 = open("test.c", O_RDONLY);
  assert(fd == fd2);
  close(STDIN_FILENO);
  close(STDOUT_FILENO); 
  fd = open("test.c", O_RDONLY); 
  assert(fd == 0);
  close(fd);
  fprintf(stderr, "OK\n");
  return 0;
}
EOF

2. Incorrect use of inline assembly, with the assumption that gcc's
epilogue won't modify r0.

Inline assembly code of the form:
---
asm ("mov r0, %1; swi %a0" :: "i" (SWI_Close),"r"(myhan):"r0");
---
has been corrected to:
---
register r0 asm("r0");
r0 = fh;
asm ("swi %a2"
     : "=r"(r0)
     : "0"(r0), "i" (SWI_Close));
return r0;
---
Firstly, this code doesn't return anything. Secondly it assumes that the
epilogue generated by GCC will not clobber r0. Lastly GCC may decide to
save and restore "r0" around the asm block, thereby destroying the
return of the software interrupt. This has been fixed.

3. Robust support of stderr, with redirection to stdout in the case that
the semi-hosting interface does not support ":tt" in append mode.

During the initialization of the monitor handles we detect a failure to
open stderr, and map it to stdout.

  /* If we failed to open stderr, redirect to stdout. */
  if (monitor_stderr == -1)
    monitor_stderr = monitor_stdout;

To avoid a double close of stdout, we add the following logic to
close():

  /* Handle stderr == stdout. */
  if ((fd == 1 || fd == 2)
      && (openfiles[1].handle == openfiles[2].handle))
    {
      openfiles[fd].handle = -1;
      return;
    }

Thus we only close one of the two handles, but track the close for both.

4. Improve _stat and _fstat.

The _stat and _fstat functions now call _swistat to get imformation
about the file, including file length.

Tested on arm-none-eabi without regressions. 

Comments?

If everything looks ok, please apply.

Cheers,
Carlos.
-- 
Carlos O'Donell
CodeSourcery
carlos@codesourcery.com
(650) 331-3385 x716

2007-07-12  Daniel Jacobowitz  <dan@codesourcery.com>

	* arm/syscalls.c (_stat): Use _close

2007-07-12  Carlos O'Donell  <carlos@codesourcery.com>

	* libgloss/arm/syscalls.c (struct poslog): Rename to...
	(struct fdent): ... this.
	(FILE_HANDLE_OFFSET): Remove.
	(findslot): Return a struct fdent* if fd is valid, otherwise
	return NULL.
	(newslot): New function.
	(remap_handle): Remove.
	(initialise_monitor_handles): Use stdout as fallback for
	stderr.
	(wrap): Rename to...
	(checkerror): ... this.
	(_swiread): Use checkerror() for the return of SWI calls.
	Correct the use of r0.
	(_read): Use findslot(). Return EBADF on bad handle.
	(_swilseek): Call findslot(). Check for valid
	whence. Check for negative offset when using SEEK_CUR,
	and check for overflow. Use checkerror(). Check *_Flen
	calls for errors.
	(_swiwrite): Correct the use of r0.
	(_write): Call findslot().
	(_swiopen): Call findslot(). Check for valid flags.
	Use checkerror(). Call newslot(). Handle O_TRUNC,
	and O_WRONLY. Return index into openfiles[] for fd.
	(_swiclose): Correct the use of r0.
	(_close): Handle stderr == stdout case. Only reclaim
	handle if _swiclose succeeded.
	(_getpid): Use __attribute__((unused)).
	(_sbrk): Fix formatting.
	(_swistat): New function.
	(_stat): Call _swistat().
	(_fstat): Call _swistat().
	(_unlink): Correct the use of r0.
	(isatty): Call finslot(). Correct the use of r0.
	(_system): Call checkerror(). Correct the use of r0.
	(_rename): Correct the use of r0.

Index: libgloss/arm/syscalls.c
===================================================================
RCS file: /cvs/src/src/libgloss/arm/syscalls.c,v
retrieving revision 1.15
diff -u -p -r1.15 syscalls.c
--- libgloss/arm/syscalls.c	6 Jul 2007 17:00:12 -0000	1.15
+++ libgloss/arm/syscalls.c	12 Jul 2007 17:33:39 -0000
@@ -27,6 +27,7 @@ int     _unlink		_PARAMS ((const char *)
 int     _link 		_PARAMS ((void));
 int     _stat 		_PARAMS ((const char *, struct stat *));
 int     _fstat 		_PARAMS ((int, struct stat *));
+int	_swistat	_PARAMS ((int fd, struct stat * st));
 caddr_t _sbrk		_PARAMS ((int));
 int     _getpid		_PARAMS ((int));
 int     _close		_PARAMS ((int));
@@ -42,11 +43,39 @@ int     _read		_PARAMS ((int, char *, in
 int     _swiread	_PARAMS ((int, char *, int));
 void    initialise_monitor_handles _PARAMS ((void));
 
-static int	wrap		_PARAMS ((int));
+static int	checkerror	_PARAMS ((int));
 static int	error		_PARAMS ((int));
 static int	get_errno	_PARAMS ((void));
-static int	remap_handle	_PARAMS ((int));
-static int 	findslot	_PARAMS ((int));
+
+/* Struct used to keep track of the file position, just so we
+   can implement fseek(fh,x,SEEK_CUR).  */
+struct fdent
+{
+  int handle;
+  int pos;
+};
+
+#define MAX_OPEN_FILES 20
+
+/* User file descriptors (fd) are integer indexes into 
+   the openfiles[] array. Error checking is done by using
+   findslot(). 
+
+   This openfiles array is manipulated directly by only 
+   these 5 functions:
+
+	findslot() - Translate entry.
+	newslot() - Find empty entry.
+	initilise_monitor_handles() - Initialize entries.
+	_swiopen() - Initialize entry.
+	_close() - Handle stdout == stderr case.
+
+   Every other function must use findslot().  */
+
+static struct fdent openfiles [MAX_OPEN_FILES];
+
+static struct fdent* 	findslot	_PARAMS ((int));
+static int		newslot		_PARAMS ((void));
 
 /* Register name faking - works in collusion with the linker.  */
 register char * stack_ptr asm ("sp");
@@ -62,49 +91,44 @@ extern void   _EXFUN(__sinit,(struct _re
     }						\
   while (0)
 
-/* Adjust our internal handles to stay away from std* handles.  */
-#define FILE_HANDLE_OFFSET (0x20)
-
 static int monitor_stdin;
 static int monitor_stdout;
 static int monitor_stderr;
 
-/* Struct used to keep track of the file position, just so we
-   can implement fseek(fh,x,SEEK_CUR).  */
-typedef struct
+/* Return a pointer to the structure associated with
+   the user file descriptor fd. */ 
+static struct fdent*
+findslot (int fd)
 {
-  int handle;
-  int pos;
-}
-poslog;
+  CHECK_INIT(_REENT);
 
-#define MAX_OPEN_FILES 20
-static poslog openfiles [MAX_OPEN_FILES];
+  /* User file descriptor is out of range. */
+  if ((unsigned int)fd >= MAX_OPEN_FILES)
+    return NULL;
 
-static int
-findslot (int fh)
-{
-  int i;
-  for (i = 0; i < MAX_OPEN_FILES; i ++)
-    if (openfiles[i].handle == fh)
-      break;
-  return i;
+  /* User file descriptor is open? */
+  if (openfiles[fd].handle == -1)
+    return NULL;
+
+  /* Valid. */
+  return &openfiles[fd];
 }
 
-/* Function to convert std(in|out|err) handles to internal versions.  */
+/* Return the next lowest numbered free file 
+   structure, or -1 if we can't find one. */ 
 static int
-remap_handle (int fh)
+newslot (void)
 {
-  CHECK_INIT(_REENT);
+  int i;
+
+  for (i = 0; i < MAX_OPEN_FILES; i++)
+    if (openfiles[i].handle == -1)
+      break;
 
-  if (fh == STDIN_FILENO)
-    return monitor_stdin;
-  if (fh == STDOUT_FILENO)
-    return monitor_stdout;
-  if (fh == STDERR_FILENO)
-    return monitor_stderr;
+  if (i == MAX_OPEN_FILES)
+    return -1;
 
-  return fh - FILE_HANDLE_OFFSET;
+  return i;
 }
 
 void
@@ -165,6 +189,10 @@ initialise_monitor_handles (void)
   monitor_stderr = fh;
 #endif
 
+  /* If we failed to open stderr, redirect to stdout. */
+  if (monitor_stderr == -1)
+    monitor_stderr = monitor_stdout;
+
   for (i = 0; i < MAX_OPEN_FILES; i ++)
     openfiles[i].handle = -1;
 
@@ -188,6 +216,7 @@ get_errno (void)
 #endif
 }
 
+/* Set errno and return result. */
 static int
 error (int result)
 {
@@ -195,21 +224,24 @@ error (int result)
   return result;
 }
 
+/* Check the return and set errno appropriately. */
 static int
-wrap (int result)
+checkerror (int result)
 {
   if (result == -1)
     return error (-1);
   return result;
 }
 
-/* Returns # chars not! written.  */
+/* fh, is a valid internal file handle.
+   ptr, is a null terminated string.
+   len, is the length in bytes to read. 
+   Returns the number of bytes *not* written. */
 int
-_swiread (int file,
+_swiread (int fh,
 	  char * ptr,
 	  int len)
 {
-  int fh = remap_handle (file);
 #ifdef ARM_RDI_MONITOR
   int block[3];
   
@@ -217,104 +249,152 @@ _swiread (int file,
   block[1] = (int) ptr;
   block[2] = len;
   
-  return do_AngelSWI (AngelSWI_Reason_Read, block);
+  return checkerror (do_AngelSWI (AngelSWI_Reason_Read, block));
 #else
-  asm ("mov r0, %1; mov r1, %2;mov r2, %3; swi %a0"
-       : /* No outputs */
-       : "i"(SWI_Read), "r"(fh), "r"(ptr), "r"(len)
-       : "r0","r1","r2");
+  register r0 asm("r0");
+  register r1 asm("r1");
+  register r2 asm("r2");
+  r0 = fh;
+  r1 = (int)ptr;
+  r2 = len;
+  asm ("swi %a4"
+       : "=r" (r0)
+       : "0"(r0), "r"(r1), "r"(r2), "i"(SWI_Read));
+  return checkerror (r0);
 #endif
 }
 
+/* fd, is a valid user file handle. 
+   Translates the return of _swiread into
+   bytes read. */
 int
-_read (int file,
+_read (int fd,
        char * ptr,
        int len)
 {
-  int slot = findslot (remap_handle (file));
-  int x = _swiread (file, ptr, len);
+  int res;
+  struct fdent *pfd;
 
-  if (x < 0)
-    return error (-1);
+  pfd = findslot (fd);
+  if (pfd == NULL)
+    {
+      errno = EBADF;
+      return -1;
+    }
 
-  if (slot != MAX_OPEN_FILES)
-    openfiles [slot].pos += len - x;
+  res = _swiread (pfd->handle, ptr, len);
 
-  /* x == len is not an error, at least if we want feof() to work.  */
-  return len - x;
+  if (res == -1)
+    return res;
+
+  pfd->pos += len - res;
+
+  /* res == len is not an error, 
+     at least if we want feof() to work.  */
+  return len - res;
 }
 
+/* fd, is a user file descriptor. */
 int
-_swilseek (int file,
-	   int ptr,
-	   int dir)
+_swilseek (int fd,
+	int ptr,
+	int dir)
 {
   int res;
-  int fh = remap_handle (file);
-  int slot = findslot (fh);
-#ifdef ARM_RDI_MONITOR
-  int block[2];
-#endif
+  struct fdent *pfd;
+
+  /* Valid file descriptor? */
+  pfd = findslot (fd);
+  if (pfd == NULL)
+    {
+      errno = EBADF;
+      return -1;
+    }
+
+  /* Valid whence? */
+  if ((dir != SEEK_CUR)
+      && (dir != SEEK_SET)
+      && (dir != SEEK_END))
+    {
+      errno = EINVAL;
+      return -1;
+    }
 
+  /* Convert SEEK_CUR to SEEK_SET */
   if (dir == SEEK_CUR)
     {
-      if (slot == MAX_OPEN_FILES)
-	return -1;
-      ptr = openfiles[slot].pos + ptr;
+      ptr = pfd->pos + ptr;
+      /* The resulting file offset would be negative. */
+      if (ptr < 0)
+        {
+          errno = EINVAL;
+          if ((pfd->pos > 0) && (ptr > 0))
+            errno = EOVERFLOW;
+          return -1;
+        }
       dir = SEEK_SET;
     }
-  
+ 
 #ifdef ARM_RDI_MONITOR
+  int block[2];
   if (dir == SEEK_END)
     {
-      block[0] = fh;
-      ptr += do_AngelSWI (AngelSWI_Reason_FLen, block);
+      block[0] = pfd->handle;
+      res = checkerror (do_AngelSWI (AngelSWI_Reason_FLen, block));
+      if (res == -1)
+        return -1;
+      ptr += res;
     }
   
   /* This code only does absolute seeks.  */
-  block[0] = remap_handle (file);
+  block[0] = pfd->handle;
   block[1] = ptr;
-  res = do_AngelSWI (AngelSWI_Reason_Seek, block);
+  res = checkerror (do_AngelSWI (AngelSWI_Reason_Seek, block));
 #else
   if (dir == SEEK_END)
     {
       asm ("mov r0, %2; swi %a1; mov %0, r0"
 	   : "=r" (res)
-	   : "i" (SWI_Flen), "r" (fh)
+	   : "i" (SWI_Flen), "r" (pfd->handle)
 	   : "r0");
+      checkerror (res);
+      if (res == -1)
+        return -1;
       ptr += res;
     }
 
   /* This code only does absolute seeks.  */
   asm ("mov r0, %2; mov r1, %3; swi %a1; mov %0, r0"
        : "=r" (res)
-       : "i" (SWI_Seek), "r" (fh), "r" (ptr)
+       : "i" (SWI_Seek), "r" (pfd->handle), "r" (ptr)
        : "r0", "r1");
+  checkerror (res);
 #endif
-
-  if (slot != MAX_OPEN_FILES && res == 0)
-    openfiles[slot].pos = ptr;
-
-  /* This is expected to return the position in the file.  */
-  return res == 0 ? ptr : -1;
+  /* At this point ptr is the current file position. */
+  if (res >= 0)
+    {
+      pfd->pos = ptr;
+      return ptr;
+    }
+  else
+    return -1;
 }
 
-int
-_lseek (int file,
+_lseek (int fd,
 	int ptr,
 	int dir)
 {
-  return wrap (_swilseek (file, ptr, dir));
+  return _swilseek (fd, ptr, dir);
 }
 
-/* Returns #chars not! written.  */
+/* fh, is a valid internal file handle.
+   Returns the number of bytes *not* written. */
 int
 _swiwrite (
-	   int    file,
+	   int    fh,
 	   char * ptr,
 	   int    len)
 {
-  int fh = remap_handle (file);
 #ifdef ARM_RDI_MONITOR
   int block[3];
   
@@ -322,64 +402,103 @@ _swiwrite (
   block[1] = (int) ptr;
   block[2] = len;
   
-  return do_AngelSWI (AngelSWI_Reason_Write, block);
+  return checkerror (do_AngelSWI (AngelSWI_Reason_Write, block));
 #else
-  asm ("mov r0, %1; mov r1, %2;mov r2, %3; swi %a0"
-       : /* No outputs */
-       : "i"(SWI_Write), "r"(fh), "r"(ptr), "r"(len)
-       : "r0","r1","r2");
+  register r0 asm("r0");
+  register r1 asm("r1");
+  register r2 asm("r2");
+  r0 = fh;
+  r1 = (int)ptr;
+  r2 = len;
+  asm ("swi %a4"
+       : "=r" (r0)
+       : "0"(r0), "r"(r1), "r"(r2), "i"(SWI_Write));
+  return checkerror (r0);
 #endif
 }
 
+/* fd, is a user file descriptor. */
 int
-_write (int    file,
+_write (int    fd,
 	char * ptr,
 	int    len)
 {
-  int slot = findslot (remap_handle (file));
-  int x = _swiwrite (file, ptr,len);
+  int res;
+  struct fdent *pfd;
 
-  if (x == -1 || x == len)
-    return error (-1);
-  
-  if (slot != MAX_OPEN_FILES)
-    openfiles[slot].pos += len - x;
+  pfd = findslot (fd);
+  if (pfd == NULL)
+    {
+      errno = EBADF;
+      return -1;
+    }
+
+  res = _swiwrite (pfd->handle, ptr,len);
+
+  /* Clearly an error. */
+  if (res < 0)
+    return -1;
+
+  pfd->pos += len - res;
+
+  /* We wrote 0 bytes? 
+     Retrieve errno just in case. */
+  if ((len - res) == 0)
+    return error (0);
   
-  return len - x;
+  return (len - res);
 }
 
 int
-_swiopen (const char * path,
-	  int          flags)
+_swiopen (const char * path, int flags)
 {
   int aflags = 0, fh;
 #ifdef ARM_RDI_MONITOR
   int block[3];
 #endif
   
-  int i = findslot (-1);
+  int fd = newslot ();
+
+  if (fd == -1)
+    {
+      errno = EMFILE;
+      return -1;
+    }
   
-  if (i == MAX_OPEN_FILES)
-    return -1;
+  /* It is an error to open a file that already exists. */
+  if ((flags & O_CREAT) 
+      && (flags & O_EXCL))
+    {
+      struct stat st;
+      int res;
+      res = _stat (path, &st);
+      if (res != -1)
+        {
+	  errno = EEXIST;
+	  return -1;
+        }
+    }
 
-  /* The flags are Unix-style, so we need to convert them.  */
+  /* The flags are Unix-style, so we need to convert them. */ 
 #ifdef O_BINARY
   if (flags & O_BINARY)
     aflags |= 1;
 #endif
+  
+  /* In O_RDONLY we expect aflags == 0. */
 
-  if (flags & O_RDWR)
+  if (flags & O_RDWR) 
     aflags |= 2;
 
-  if (flags & O_CREAT)
-    aflags |= 4;
-
-  if (flags & O_TRUNC)
+  if ((flags & O_CREAT)
+      || (flags & O_TRUNC)
+      || (flags & O_WRONLY))
     aflags |= 4;
 
   if (flags & O_APPEND)
     {
-      aflags &= ~4;     /* Can't ask for w AND a; means just 'a'.  */
+      /* Can't ask for w AND a; means just 'a'.  */
+      aflags &= ~4;
       aflags |= 8;
     }
   
@@ -397,58 +516,83 @@ _swiopen (const char * path,
        : "r0","r1");
 #endif
   
+  /* Return a user file descriptor or an error. */
   if (fh >= 0)
     {
-      openfiles[i].handle = fh;
-      openfiles[i].pos = 0;
+      openfiles[fd].handle = fh;
+      openfiles[fd].pos = 0;
+      return fd;
     }
-
-  return fh >= 0 ? fh + FILE_HANDLE_OFFSET : error (fh);
+  else
+    return error (fh);
 }
 
 int
-_open (const char * path,
-       int          flags,
-       ...)
+_open (const char * path, int flags, ...)
 {
-  return wrap (_swiopen (path, flags));
+  return _swiopen (path, flags);
 }
 
+/* fh, is a valid internal file handle. */
 int
-_swiclose (int file)
+_swiclose (int fh)
 {
-  int myhan = remap_handle (file);
-  int slot = findslot (myhan);
-  
-  if (slot != MAX_OPEN_FILES)
-    openfiles[slot].handle = -1;
-
 #ifdef ARM_RDI_MONITOR
-  return do_AngelSWI (AngelSWI_Reason_Close, & myhan);
+  return checkerror (do_AngelSWI (AngelSWI_Reason_Close, &fh));
 #else
-  asm ("mov r0, %1; swi %a0" :: "i" (SWI_Close),"r"(myhan):"r0");
+  register r0 asm("r0");
+  r0 = fh;
+  asm ("swi %a2" 
+       : "=r"(r0) 
+       : "0"(r0), "i" (SWI_Close));
+  return checkerror (r0);
 #endif
 }
 
+/* fd, is a user file descriptor. */
 int
-_close (int file)
+_close (int fd)
 {
-  return wrap (_swiclose (file));
+  int res;
+  struct fdent *pfd;
+
+  pfd = findslot (fd);
+  if (pfd == NULL)
+    {
+      errno = EBADF;
+      return -1;
+    }
+
+  /* Handle stderr == stdout. */
+  if ((fd == 1 || fd == 2)
+      && (openfiles[1].handle == openfiles[2].handle))
+    {
+      pfd->handle = -1;
+      return 0;
+    }
+
+  /* Attempt to close the handle. */
+  res = _swiclose (pfd->handle);
+
+  /* Reclaim handle? */
+  if (res == 0)
+    pfd->handle = -1;
+
+  return res;
 }
 
 int __attribute__((weak))
-_getpid (int n)
+_getpid (int n __attribute__ ((unused)))
 {
   return 1;
-  n = n;
 }
 
 caddr_t
 _sbrk (int incr)
 {
-  extern char   end asm ("end");	/* Defined by the linker.  */
+  extern char end asm ("end"); /* Defined by the linker.  */
   static char * heap_end;
-  char *        prev_heap_end;
+  char * prev_heap_end;
 
   if (heap_end == NULL)
     heap_end = & end;
@@ -476,31 +620,60 @@ _sbrk (int incr)
   return (caddr_t) prev_heap_end;
 }
 
-int __attribute__((weak))
-_fstat (int file, struct stat * st)
+int 
+_swistat (int fd, struct stat * st)
 {
-  memset (st, 0, sizeof (* st));
-  st->st_mode = S_IFCHR;
+  struct fdent *pfd;
+  int res;
+
+  pfd = findslot (fd);
+  if (pfd == NULL)
+    {
+      errno = EBADF;
+      return -1;
+    }
+
+  /* Always assume a character device,
+     with 1024 byte blocks. */
+  st->st_mode |= S_IFCHR;
   st->st_blksize = 1024;
+#ifdef ARM_RDI_MONITOR
+  res = checkerror (do_AngelSWI (AngelSWI_Reason_FLen, &pfd->handle));
+#else
+  asm ("mov r0, %2; swi %a1; mov %0, r0"
+       : "=r" (res)
+       : "i" (SWI_Flen), "r" (pfd->handle)
+       : "r0");
+  checkerror (res);
+#endif
+  if (res == -1)
+    return -1;
+  /* Return the file size. */
+  st->st_size = res;
   return 0;
-  file = file;
 }
 
 int __attribute__((weak))
-_stat (const char *fname, struct stat *st)
+_fstat (int fd, struct stat * st)
 {
-  int file;
-
-  /* The best we can do is try to open the file readonly.  If it exists,
-     then we can guess a few things about it.  */
-  if ((file = _open (fname, O_RDONLY)) < 0)
-    return -1;
+  memset (st, 0, sizeof (* st));
+  return _swistat (fd, st);
+}
 
+int __attribute__((weak))
+_stat (const char *fname, struct stat *st)
+{
+  int fd, res;
   memset (st, 0, sizeof (* st));
-  st->st_mode = S_IFREG | S_IREAD;
-  st->st_blksize = 1024;
-  _swiclose (file); /* Not interested in the error.  */
-  return 0;
+  /* The best we can do is try to open the file readonly.  
+     If it exists, then we can guess a few things about it. */
+  if ((fd = _open (fname, O_RDONLY)) == -1)
+    return -1;
+  st->st_mode |= S_IFREG | S_IREAD;
+  res = _swistat (fd, st);
+  /* Not interested in the error. */
+  _close (fd); 
+  return res;
 }
 
 int __attribute__((weak))
@@ -513,15 +686,23 @@ _link (void)
 int
 _unlink (const char *path)
 {
+  int res;
 #ifdef ARM_RDI_MONITOR
   int block[2];
   block[0] = (int)path;
   block[1] = strlen(path);
-  return wrap (do_AngelSWI (AngelSWI_Reason_Remove, block)) ? -1 : 0;
+  res = do_AngelSWI (AngelSWI_Reason_Remove, block);
 #else
-  (void)path;
-  asm ("swi %a0" :: "i" (SWI_Remove));
+  register r0 asm("r0");
+  r0 = (int)path;
+  asm ("swi %a2" 
+       : "=r"(r0)
+       : "0"(r0), "i" (SWI_Remove));
+  res = r0;
 #endif
+  if (res == -1) 
+    return error (res);
+  return 0;
 }
 
 int
@@ -588,14 +769,24 @@ _times (struct tms * tp)
 int
 _isatty (int fd)
 {
-  int fh = remap_handle (fd);
+  struct fdent *pfd;
+
+  pfd = findslot (fd);
+  if (pfd == NULL)
+    {
+      errno = EBADF;
+      return -1;
+    }
+
 #ifdef ARM_RDI_MONITOR
-  return wrap (do_AngelSWI (AngelSWI_Reason_IsTTY, &fh));
+  return checkerror (do_AngelSWI (AngelSWI_Reason_IsTTY, &pfd->handle));
 #else
-  asm ("mov r0, %1; swi %a0"
-       : /* No outputs */
-       : "i" (SWI_IsTTY), "r"(fh)
-       : "r0");
+  register r0 asm("r0");
+  r0 = pfd->handle;
+  asm ("swi %a2"
+       : "=r" (r0)
+       : "0"(r0), "i" (SWI_IsTTY));
+  return checkerror (r0);
 #endif
 }
 
@@ -613,7 +804,7 @@ _system (const char *s)
     return 1;  /* maybe there is a shell available? we can hope. :-P */
   block[0] = (int)s;
   block[1] = strlen (s);
-  e = wrap (do_AngelSWI (AngelSWI_Reason_System, block));
+  e = checkerror (do_AngelSWI (AngelSWI_Reason_System, block));
   if ((e >= 0) && (e < 256))
     {
       /* We have to convert e, an exit status to the encoded status of
@@ -626,8 +817,12 @@ _system (const char *s)
     }
   return e;
 #else
-  (void)s;
-  asm ("swi %a0" :: "i" (SWI_CLI));
+  register r0 asm("r0");
+  r0 = (int)s;
+  asm ("swi %a2" 
+       : "=r" (r0)
+       : "0"(r0), "i" (SWI_CLI));
+  return checkerror (r0);
 #endif
 }
 
@@ -640,9 +835,15 @@ _rename (const char * oldpath, const cha
   block[1] = strlen(oldpath);
   block[2] = (int)newpath;
   block[3] = strlen(newpath);
-  return wrap (do_AngelSWI (AngelSWI_Reason_Rename, block)) ? -1 : 0;
+  return checkerror (do_AngelSWI (AngelSWI_Reason_Rename, block)) ? -1 : 0;
 #else
-  (void)oldpath; (void)newpath;
-  asm ("swi %a0" :: "i" (SWI_Rename));
+  register r0 asm("r0");
+  register r1 asm("r1");
+  r0 = (int)oldpath;
+  r1 = (int)newpath;
+  asm ("swi %a3" 
+       : "=r" (r0)
+       : "0" (r0), "r" (r1), "i" (SWI_Rename));
+  return checkerror (r0);
 #endif
 }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]