예제 #1
0
파일: _READ.C 프로젝트: lubing521/protocols
int read(int fid, void *buf, unsigned int nbytes)
{
  int hchar = 0, read = 0;
  FILE *file;

  /*-------------------------------------------------------------------*/
  /* If number of requested bytes is zero, return zero.                */
  /*-------------------------------------------------------------------*/
  if (nbytes == 0)
    return 0;

#if OS_PARM_CHECK
  /*-------------------------------------------------------------------*/
  /* Ensure file descriptor is valid.                                  */
  /*-------------------------------------------------------------------*/
  if (fid < 0 || fid >= FOPEN_MAX)
  {
    set_errno(EBADF);
    return -1;
  }

  /*-------------------------------------------------------------------*/
  /* Return error if buffer pointer is invalid.                        */
  /*-------------------------------------------------------------------*/
  if (buf == NULL)
  {
    Files[fid].errcode = EFAULT;
    set_errno(EFAULT);
    return -1;
  }
#endif

  /*-------------------------------------------------------------------*/
  /* Acquire exclusive read access to file.                            */
  /*-------------------------------------------------------------------*/
  file = &Files[fid];
  file->acquire(file, F_READ);

  /*-------------------------------------------------------------------*/
  /* Return error if file is closed.                                   */
  /*-------------------------------------------------------------------*/
  if (file->ioctl == NULL)
  {
    set_errno(EBADF);
    file->release(file, F_READ);
    return -1;
  }

  /*-------------------------------------------------------------------*/
  /* If available, read pushed-back character first.                   */
  /*-------------------------------------------------------------------*/
  if (file->hold_char)
  {
    ui8 *cp = buf;

    *cp = (ui8)file->hold_char;
    buf = cp + 1;
    file->hold_char = 0;
    hchar = 1;
    --nbytes;
  }

  /*-------------------------------------------------------------------*/
  /* Check if there are more characters to read.                       */
  /*-------------------------------------------------------------------*/
  if (nbytes)
  {
    /*-----------------------------------------------------------------*/
    /* Pass read request to file system or device driver.              */
    /*-----------------------------------------------------------------*/
    read = file->read(file, buf, nbytes);

    /*-----------------------------------------------------------------*/
    /* Read error is disregarded iff pushed-back character was read.   */
    /*-----------------------------------------------------------------*/
    if (read == -1)
    {
      if (hchar)
        read = 0;
      else
        file->errcode = get_errno();
    }
  }

  /*-------------------------------------------------------------------*/
  /* Release exclusive read access to file.                            */
  /*-------------------------------------------------------------------*/
  file->release(file, F_READ);

  /*-------------------------------------------------------------------*/
  /* Return number of bytes successfully read or -1.                   */
  /*-------------------------------------------------------------------*/
  return read + hchar;
}