| Updated: October 28, 2024 | 
Attach a path to the pathname space
#include <sys/iofunc.h>
#include <sys/resmgr.h>
#include <sys/dispatch.h>
int resmgr_attach (
       dispatch_t *dpp,
       resmgr_attr_t *attr,
       const char *path, 
       enum _file_type file_type,
       unsigned flags, 
       const resmgr_connect_funcs_t *connect_funcs,
       const resmgr_io_funcs_t *io_funcs,
       RESMGR_HANDLE_T *handle );
For more information, see The flags argument, below.
libc
Use the -l c option to qcc to link against this library. This library is usually included automatically.
The resmgr_attach() function puts the path into the general pathname space and binds requests on this path to the dispatch handle dpp. You usually provide an absolute path; if you provide a path that doesn't start with a slash, it's considered to be relative to the current working directory.
For more information, see procmgr_ability().
File types are used with the _RESMGR_FLAG_FTYPEONLY flag for special services that have their own associated open function to ensure they receive only those open requests targeted for them. For example, the mqueue manager sets file_type to _FTYPE_MQUEUE, and mq_open() requests a pathname match of the same type.
When matching an open request to a registered path's file type, an exact match will always reach the server. If the server sets _RESMGR_FLAG_FTYPEONLY, then only an exact match will reach it. Otherwise, a request of _FTYPE_ANY will reach the server if it has registered any file type. If the server registers a file type of _FTYPE_ALL, which is done by setting the _RESMGR_FLAG_FTYPEALL flag, then requests of all file types will reach the server.
The following table shows some of the different client-request function types and the types of pathnames they will match if the server has not set _RESMGR_FLAG_FTYPEALL:
| Function: | file_type: | Matches pathname of type: | 
|---|---|---|
| mq_open() | _FTYPE_MQ | _FTYPE_ALL or _FTYPE_MQ | 
| mq_open() | _FTYPE_MQUEUE | _FTYPE_ALL or _FTYPE_MQUEUE | 
| mount() | _FTYPE_MOUNT | _FTYPE_ALL or _FTYPE_MOUNT | 
| open() | _FTYPE_ANY | All types | 
| pipe() | _FTYPE_PIPE | _FTYPE_ALL or _FTYPE_PIPE | 
| sem_open() | _FTYPE_SEM | _FTYPE_ALL or _FTYPE_SEM | 
| shm_open() | _FTYPE_SHMEM | _FTYPE_ALL or _FTYPE_SHMEM | 
| socket() | _FTYPE_SOCKET | _FTYPE_ALL or _FTYPE_SOCKET | 
If you want to use the POSIX functions, we've provided you with the POSIX layer; to fill your connect and I/O functions tables with the default handler functions supplied by the POSIX layer library, call iofunc_func_init(). You can then override the defaults placed in the structures with your own handlers.
In the most general case, the last argument, handle is an arbitrary structure that you wish to have associated with the pathname you're attaching. Practically, however, we recommend that it contain the POSIX layer's well defined attributes structure, iofunc_attr_t, because this lets you use the POSIX-layer default library. You can extend the data that's contained in the attributes structure to contain any device-specific data that you may require. This is commonly done, and is described in the POSIX-Layer Data Structures chapter of Writing a Resource Manager.
In order to use the POSIX layer default library, the attributes structure must be bound into the Open Control Block, and you must use the POSIX layer's iofunc_ocb_t OCB. This is described in the documentation for resmgr_open_bind(), as well as in the above reference.
You can specify attributes such as the maximum message size, number of parts (number of IOVs in context), and flags in the attr structure. The resmgr_attr_t structure looks like this:
typedef struct _resmgr_attr {
   unsigned      flags;
   unsigned      nparts_max;
   size_t        msg_max_size;
   int           (*other_func) ( resmgr_context_t *, void *msg );
   unsigned      reserved[4];
} resmgr_attr_t;
The members include:
The flags argument to resmgr_attach() specifies additional information to control the pathname resolution.
The flags (defined in <sys/resmgr.h>) include at least the following bits:
| Attached path | Opened path | _RESMGR_FLAG_DIR set | _RESMGR_FLAG_DIR clear | 
|---|---|---|---|
| /a/b | /a/b | Match "" | Match "" | 
| /a/b | /a/b/c | Match c | No match | 
| /a/b | /a/b/c/d | Match c/d | No match | 
| /a/b | /a/bc | No match | No match | 
You can't attach a directory pathname that contains, as a subset, an existing file pathname. Likewise, you can't attach a file pathname that's a subset of an existing directory pathname.
| Existing path | New path | New path allowed? | 
|---|---|---|
| Directory /a/b | Directory /a | Yes | 
| Directory /a/b | Directory /a/b/c | Yes | 
| File /a/b | Directory /a | Yes | 
| File /a/b | Directory /a/b/c | No; the directory is beneath a file | 
| Directory /a/b | File /a | No; the directory is beneath a file | 
| Directory /a/b | File /a/b/c | Yes | 
| File /a/b | File /a | Yes | 
| File /a/b | File /a/b/c | Yes | 
A unique link ID associated with this attach, or -1 on failure (errno is set).
The returned ID is needed to detach the pathname at a later time using resmgr_detach(). The ID is also passed to all connect and I/O message handlers in the resource-manager context structure (ctp) created by resmgr_context_alloc().
Here's an example of a simple single-threaded resource manager:
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <sys/iofunc.h>
#include <sys/dispatch.h>
static resmgr_connect_funcs_t    connect_funcs;
static resmgr_io_funcs_t         io_funcs;
static iofunc_attr_t             attr;
int main(int argc, char **argv)
{
    dispatch_t           *dpp;
    resmgr_attr_t        resmgr_attr;
    resmgr_context_t     *ctp;
    int                  id;
    /* initialize dispatch interface */
    if ( (dpp = dispatch_create()) == NULL ) {
       fprintf( stderr, "%s: Unable to allocate \
                dispatch handle.\n", argv[0] );
       return EXIT_FAILURE;
    }
    /* initialize resource manager attributes */
    memset( &resmgr_attr, 0, sizeof resmgr_attr );
    resmgr_attr.nparts_max = 1;
    resmgr_attr.msg_max_size = 2048;
    /* initialize functions for handling messages */
    iofunc_func_init( _RESMGR_CONNECT_NFUNCS, &connect_funcs,
                      _RESMGR_IO_NFUNCS, &io_funcs );
    /* initialize attribute structure */
    iofunc_attr_init( &attr, S_IFNAM | 0666, 0, 0 );
    /* attach our device name (passing in the POSIX defaults 
       from the iofunc_func_init and iofunc_attr_init functions) 
     */
    if ( (id = resmgr_attach
          ( dpp, &resmgr_attr, "/dev/mynull", _FTYPE_ANY, 0,
          &connect_funcs, &io_funcs, &attr)) == -1 ) {
        fprintf( stderr, "%s: Unable to attach name.\n", \
                 argv[0] );
        return EXIT_FAILURE;
    }
    /* allocate a context structure */
    ctp = resmgr_context_alloc( dpp );
    /* start the resource manager message loop */
    while (1) {
        if ( (ctp = resmgr_block( ctp )) == NULL ) {
           fprintf(stderr, "block error\n");
           return EXIT_FAILURE;
        }
        resmgr_handler(ctp);
    }
}
For more examples using the dispatch interface, see dispatch_create(), message_attach(), and thread_pool_create(). For more information on writing a resource manager, see Writing a Resource Manager
| Safety: | |
|---|---|
| Cancellation point | Yes | 
| Interrupt handler | No | 
| Signal handler | No | 
| Thread | Yes |