The new-and-improved execute_resmgr()

We need to change the execute_resmgr() function a little. We're no longer registering a pair of file-type resources, but rather just a single directory.

Therefore, we need to allocate and initialize the arrays attr_gif and attr_txt so that they contain the right information for the GIF-encoded and text files:

// initialize the individual attributes structures
for (i = 0; i < optN; i++) {
  iofunc_attr_init (&attr_gif [i].base, S_IFREG | 0666, 0, 0);
  iofunc_attr_init (&attr_txt [i].base, S_IFREG | 0666, 0, 0);

  // even inodes are TXT files
  attr_txt [i].base.inode = (i + 1) * 2;

  // odd inodes are GIF files
  attr_gif [i].base.inode = (i + 1) * 2 + 1;
}

It's important to realize that the attributes structure's inode (or “file serial number”) member plays a key role. First of all, the inode cannot be zero. To QNX Neutrino, this indicates that the file is no longer in use. Therefore, our inodes begin at 2. I've made it so that even-numbered inodes are used with the text files, and odd-numbered inodes are used with the GIF-encoded files. There's nothing saying how you use your inodes; it's completely up to you how you interpret them — so long as all inodes in a particular filesystem are unique.

We're going to use the inode to index into the attr_gif and attr_txt attributes structures. We're also going to make use of the even/odd characteristic when we handle the client's read() function.

Next, we initialize the attributes structure for the directory itself:

iofunc_attr_init (&attr.base, S_IFDIR | 0777, 0, 0);

// our directory has an inode of one.
attr.base.inode = 1;

Notice the S_IFDIR | 0777 — this sets the mode member of the attributes structure to indicate that this is a directory (the S_IFDIR part) and that the permissions are 0777 — readable, writable, and seekable by all.

Finally, we register the pathname with the process manager:

if (resmgr_attach (dpp, &resmgr_attr, optn, _FTYPE_ANY,
    _RESMGR_FLAG_DIR, &connect_func, &io_func, &attr) == -1) {
    perror ("Unable to resmgr_attach()\n");
    exit (EXIT_FAILURE);
}

Notice that this time there is only one resmgr_attach() call—we're registering only one pathname, the directory. All of the files underneath the directory are managed by our resource manager, so they don't need to be registered with the process manager. Also notice that we use the flag _RESMGR_FLAG_DIR. This tells the process manager that it should forward any requests at and below the registered mount point to our resource manager.