[PATCH v2] Support regular file type in _swistat for ARM

Joe Ramsay <[email protected]>
Newsgroups gmane.comp.lib.newlib
Message-ID <[email protected]>
Hi all,

Just pinging this patch (original at https://sourceware.org/pipermail/newlib/2020/017719.html), as it looks to have fallen through the cracks somewhat. I’ve attached the patch file directly, as I think it may have been corrupted in my original email. If anyone is interested in this then a review would be really appreciated – if it’s OK for master then please commit on my behalf as I don’t have write access.

Thanks,
Joe
p.diff (application/octet-stream, 4.3 KB)
diff --git a/libgloss/arm/syscalls.c b/libgloss/arm/syscalls.c
index fc394f9..652301c 100644
--- a/libgloss/arm/syscalls.c
+++ b/libgloss/arm/syscalls.c
@@ -59,6 +59,7 @@ struct fdent
 };
 
 #define MAX_OPEN_FILES 20
+#define DEFAULT_BLOCK_SIZE 1024
 
 /* User file descriptors (fd) are integer indexes into 
    the openfiles[] array. Error checking is done by using
@@ -728,33 +729,46 @@ _sbrk (ptrdiff_t incr)
 int 
 _swistat (int fd, struct stat * st)
 {
-  struct fdent *pfd;
-  int res;
-
-  pfd = findslot (fd);
+  struct fdent *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;
+  int isCharDevice;
 #ifdef ARM_RDI_MONITOR
-  res = checkerror (do_AngelSWI (AngelSWI_Reason_FLen, &pfd->handle));
+  isCharDevice = checkerror (do_AngelSWI (AngelSWI_Reason_IsTTY, &pfd->handle));
 #else
   asm ("mov r0, %2; swi %a1; mov %0, r0"
-       : "=r" (res)
+       : "=r" (isCharDevice)
+       : "i" (SWI_IsTTY), "r" (pfd->handle)
+       : "r0");
+  checkerror(isCharDevice);
+#endif
+
+  int flen;
+#ifdef ARM_RDI_MONITOR
+  flen = checkerror (do_AngelSWI (AngelSWI_Reason_FLen, &pfd->handle));
+#else
+  asm ("mov r0, %2; swi %a1; mov %0, r0"
+       : "=r" (flen)
        : "i" (SWI_Flen), "r" (pfd->handle)
        : "r0");
-  checkerror (res);
+  checkerror(flen);
 #endif
-  if (res == -1)
-    return -1;
-  /* Return the file size. */
-  st->st_size = res;
+
+  st->st_size = flen;
+  st->st_blksize = DEFAULT_BLOCK_SIZE;
+
+  if (isCharDevice)
+    st->st_mode |= S_IFCHR;
+  else
+    {
+      st->st_mode |= S_IFREG;
+      st->st_blocks = (flen + DEFAULT_BLOCK_SIZE - 1) / DEFAULT_BLOCK_SIZE;
+    }
+
   return 0;
 }
 
diff --git a/newlib/libc/sys/arm/syscalls.c b/newlib/libc/sys/arm/syscalls.c
index 1f72229..5156f1a 100644
--- a/newlib/libc/sys/arm/syscalls.c
+++ b/newlib/libc/sys/arm/syscalls.c
@@ -28,6 +28,7 @@ int	_unlink		(const char *);
 int	_link		(const char *, const char *);
 int	_stat		(const char *, struct stat *);
 int	_fstat		(int, struct stat *);
+int     _swistat        (int fd, struct stat * st);
 void *	_sbrk		(ptrdiff_t);
 pid_t	_getpid		(void);
 int	_kill		(int, int);
@@ -84,6 +85,8 @@ poslog;
 #define MAX_OPEN_FILES 20
 static poslog openfiles [MAX_OPEN_FILES];
 
+#define DEFAULT_BLOCK_SIZE 1024
+
 static int
 findslot (int fh)
 {
@@ -543,33 +546,75 @@ _sbrk (ptrdiff_t incr)
   return (void *) prev_heap_end;
 }
 
+int 
+_swistat (int fd, struct stat * st)
+{
+  struct fdent *pfd = findslot (fd);
+  if (pfd == NULL)
+    {
+      errno = EBADF;
+      return -1;
+    }
+
+  int isCharDevice;
+#ifdef ARM_RDI_MONITOR
+  isCharDevice = checkerror (do_AngelSWI (AngelSWI_Reason_IsTTY, &pfd->handle));
+#else
+  asm ("mov r0, %2; swi %a1; mov %0, r0"
+       : "=r" (isCharDevice)
+       : "i" (SWI_IsTTY), "r" (pfd->handle)
+       : "r0");
+  checkerror(isCharDevice);
+#endif
+
+  int flen;
+#ifdef ARM_RDI_MONITOR
+  flen = checkerror (do_AngelSWI (AngelSWI_Reason_FLen, &pfd->handle));
+#else
+  asm ("mov r0, %2; swi %a1; mov %0, r0"
+       : "=r" (flen)
+       : "i" (SWI_Flen), "r" (pfd->handle)
+       : "r0");
+  checkerror(flen);
+#endif
+
+  st->st_size = flen;
+  st->st_blksize = DEFAULT_BLOCK_SIZE;
+
+  if (isCharDevice)
+    st->st_mode |= S_IFCHR;
+  else
+    {
+      st->st_mode |= S_IFREG;
+      st->st_blocks = (flen + DEFAULT_BLOCK_SIZE - 1) / DEFAULT_BLOCK_SIZE;
+    }
+
+  return 0;
+}
+
 extern void memset (struct stat *, int, unsigned int);
 
 int __attribute__((weak))
 _fstat (int file, struct stat * st)
 {
   memset (st, 0, sizeof (* st));
-  st->st_mode = S_IFCHR;
-  st->st_blksize = 1024;
-  return 0;
-  file = file;
+  return _swistat (file, st);
 }
 
 int __attribute__((weak))
 _stat (const char *fname, struct stat *st)
 {
   int file;
-
+  memset (st, 0, sizeof (* st));
   /* 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));
   st->st_mode = S_IFREG | S_IREAD;
-  st->st_blksize = 1024;
+  res = _swistat (file, st);
   _swiclose (file); /* Not interested in the error.  */
-  return 0;
+  return res;
 }
 
 int __attribute__((weak))
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.