main() and declarations
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:
- file attribute structure
- Marked as a regular file (the S_IFREG constant) with an access mode
of 0444 (meaning everyone has read access, no one has write access).
The size is
1
—the file contains only one byte, namely, the uppercase letter corresponding to the filename. The inodes for these individual files are numbered1
through26
inclusive (it would have been more convenient to number them0
through25,
but0
is reserved). - directory attribute structure
- Marked as a directory file (the S_IFDIR constant) with an access
mode of 0555 (meaning that everyone has read and seek access, no one has
write access).
The size is
26
—this is simply a number picked based on the number of entries in the directory. The inode is27
—a number known not to be in use by any of the other attributes structures.
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);
}