The first section of code presented is the main() function and some of the declarations. There's a convenience macro, ALIGN(), that's used for alignment by the dirent_fill() and dirent_size() functions.
The atoz_attrs array contains the attributes structures used for the files in this example. We declare NUM_ENTS array members, because we have NUM_ENTS (26) files a through z. The attributes structure used for the directory itself (i.e., the /dev/atoz directory) is declared within main() and is called simply attr. Notice the differences in the way the two types of attributes structures are filled:
Notice how we've overridden only the open member of the connect_func structure and the read member of the io_func structure. We've left all the others to use the POSIX defaults.
Finally, notice how we created the name /dev/atoz using resmgr_attach(). Most importantly, we used the flag _RESMGR_FLAG_DIR, which tells the process manager that it can resolve requests at and below this mountpoint.
/* * atoz.c * * /dev/atoz using the resource manager library */ #include <stdio.h> #include <stddef.h> #include <stdlib.h> #include <errno.h> #include <dirent.h> #include <limits.h> #include <sys/iofunc.h> #include <sys/dispatch.h> #define ALIGN(x) (((x) + 3) & ~3) #define NUM_ENTS 26 static iofunc_attr_t atoz_attrs [NUM_ENTS]; int main (int argc, char **argv) { dispatch_t *dpp; resmgr_attr_t resmgr_attr; dispatch_context_t *ctp; resmgr_connect_funcs_t connect_func; resmgr_io_funcs_t io_func; iofunc_attr_t attr; int i; // create the dispatch structure if ((dpp = dispatch_create ()) == NULL) { perror ("Unable to dispatch_create"); exit (EXIT_FAILURE); } // initialize the various data structures memset (&resmgr_attr, 0, sizeof (resmgr_attr)); resmgr_attr.nparts_max = 1; resmgr_attr.msg_max_size = 2048; // bind default functions into the outcall tables iofunc_func_init (_RESMGR_CONNECT_NFUNCS, &connect_func, _RESMGR_IO_NFUNCS, &io_func); // create and initialize the attributes structure // for the directory. Inodes 1-26 are reserved for the // files 'a' through 'z'. The number of bytes is 26 // because that's how many entries there are. iofunc_attr_init (&attr, S_IFDIR | 0555, 0, 0); attr.inode = NUM_ENTS + 1; attr.nbytes = NUM_ENTS; // and for the "a" through "z" names for (i = 0; i < NUM_ENTS; i++) { iofunc_attr_init (&atoz_attrs [i], S_IFREG | 0444, 0, 0); atoz_attrs [i].inode = i + 1; atoz_attrs [i].nbytes = 1; } // add our functions; we're interested only in // the open connect function handler and read I/O function handlers connect_func.open = my_open; io_func.read = my_read; io_func.read64 = my_read; // establish a name in the pathname space if (resmgr_attach (dpp, &resmgr_attr, "/dev/atoz", _FTYPE_ANY, _RESMGR_FLAG_DIR, &connect_func, &io_func, &attr) == -1) { perror ("Unable to resmgr_attach"); exit (EXIT_FAILURE); } // allocate a context ctp = dispatch_context_alloc (dpp); // wait here forever, handling messages while (1) { if ((ctp = dispatch_block (ctp)) == NULL) { perror ("Unable to dispatch_block"); exit (EXIT_FAILURE); } dispatch_handler (ctp); } // you'll never get here return (EXIT_SUCCESS); }