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

Corinna Vinschen via Newlib <[email protected]>
Newsgroups gmane.comp.lib.newlib
Message-ID <[email protected]>
CC'ing Richard.

On Jun 23 10:30, Joe Ramsay wrote:
> Hi!
> 
> Previously, the implementation of _swistat() for ARM assumed all files
> to be of type character device. This change adds support for stat-ing
> regular files. Tested with arm-none-eabi
> ---
> libgloss/arm/syscalls.c        | 44 +++++++++++++++++++-----------
> newlib/libc/sys/arm/syscalls.c | 61 ++++++++++++++++++++++++++++++++++++------
> 2 files changed, 82 insertions(+), 23 deletions(-)
> 
> 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))
> --
> 2.7.4
> 

-- 
Corinna Vinschen
Cygwin Maintainer
Red Hat
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.