The io_write() function

Let's look at the io_write() function first, and then we'll discuss the code:

static int
io_write (resmgr_context_t *ctp, io_write_t *msg, RESMGR_OCB_T *ocb)
{
  int     nroom;
  int     nbytes;

  // 1) we don't do any xtypes here...
  if ((msg -> i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE) {
    return (ENOSYS);
  }

  // standard helper function
  if ((sts = iofunc_write_verify (ctp, msg, &ocb -> base, NULL)) != EOK) {
    return (sts);
  }

  // 2) figure out how many bytes we can accept in total
  nroom = sizeof (ocb -> wbuf) - 1 - ocb -> base.offset;

  // 3) and how many we can accept from the client
  nbytes = min (nroom, msg -> i.nbytes);

  if (nbytes) {
    // 4) grab the bytes from the client
    memcpy (ocb -> wbuf + ocb -> base.offset, &msg -> i + 1, nbytes);

    // 5) update flags and offset
    ocb -> base.attr -> base.flags |= 
        IOFUNC_ATTR_MTIME | IOFUNC_ATTR_DIRTY_TIME;
    ocb -> base.offset += nbytes;
  } else {
    // 6) we're full, tell them
    if (!nroom) {
      return (ENOSPC);
    }
  }

  // 7) set the number of returning bytes
  _IO_SET_WRITE_NBYTES (ctp, nbytes);
  return (EOK);
}

The io_write() function performs the following steps:

  1. Just like in the io_read() handler, we fail the attempt to perform any XTYPE operations.
  2. We determine how much room we have available in the buffer by subtracting the current offset from its size.
  3. Next, we determine how many bytes we can accept from the client. This is going to be the smaller of the two numbers representing how much room we have, and how many bytes the client wants to transfer.
  4. If we are transferring any bytes from the client, we do that via memcpy(). (See note after step 7 below!)
  5. POSIX says that the MTIME time field must be updated if transferring more than zero bytes, so we set the "MTIME is dirty" flag.
  6. If we can't transfer any bytes, and it's because we have no room, we give the client an error indication.
  7. Finally, we tell the resource manager framework that we've processed nbytes worth of data, and that the status was EOK.
Note: In step 4, we assume that we have all of the data! Remember that the resource manager framework doesn't necessarily read in all of the bytes from the client—it reads in only as many bytes as you've specified in your resmgr_attr.msg_max_size parameter to the resmgr_attach() function (and in the network case it may read in less than that). However, we are dealing with tiny amounts of data—ten or so bytes at the most, so we are safe in simply assuming that the data is present. For details on how this is done "correctly," take a look at the RAM-disk Filesystem chapter.