Handling io_read()

This is where things get interesting. Our io_read() function gets called to handle three things:

  1. a read() of the text counter value
  2. a read() of the GIF-encoded counter picture
  3. a readdir() of the directory (e.g., ls /dev/webcounters)

The first two operate on a file, and the last operates on a directory. So that's the first decision point in our new io_read() handler:

static int
io_read (resmgr_context_t *ctp, io_read_t *msg, RESMGR_OCB_T *ocb)
  int     sts;

  // use the helper function to decide if valid
  if ((sts = iofunc_read_verify (ctp, msg, &ocb -> base, NULL)) != EOK) {
    return (sts);

  // decide if we should perform the "file" or "dir" read
  if (S_ISDIR (ocb -> base.attr -> base.mode)) {
    return (io_read_dir (ctp, msg, ocb));
  } else if (S_ISREG (ocb -> base.attr -> base.mode)) {
    return (io_read_file (ctp, msg, ocb));
  } else {
    return (EBADF);

By looking at the attributes structure's mode field, we can tell if the request is for a file or a directory. After all, we set this bit ourselves when we initialized the attributes structures (the S_IFDIR and S_IFREG values).