![]()  | 
![]()  | 
![]()  | 
![]()  | 
Verify a client's ability to open a resource
#include <sys/iofunc.h>
int iofunc_open( resmgr_context_t *ctp,
                 io_open_t *msg,
                 iofunc_attr_t *attr,
                 iofunc_attr_t *dattr,
                 struct _client_info *info );
libc
Use the -l c option to qcc to link against this library. This library is usually included automatically.
The iofunc_open() function checks to see if the client (described by the optional info structure) has access to open the resource whose name is passed in msg->connect.path.
The attr structure describes the resource's attributes. The optional dattr structure defines the attributes of the parent directory; if dattr isn't NULL, the resource identified by attr is being created within the directory specified by dattr.
The info argument can be passed as NULL, in which case iofunc_open() obtains the client information itself via a call to iofunc_client_info(). It is, of course, more efficient to get the client info once, rather than calling this function with NULL every time.
Note that if you're handling a request to read directory entry, you must return data formatted to match the struct dirent type. A helper function, iofunc_stat(), can aid in this.
A resource manager's response to an open() request isn't always a yes-or-no answer. It's possible to return a connect message indicating that the server would like some other action taken. For example, if the open occurs on a path that represents a symbolic link to some other path, the server could respond using the _IO_SET_CONNECT_RET() macro and the _IO_CONNECT_RET_LINK value.
For example, an open handler that only redirects pathnames might look something like:
io_open(resmgr_context_t *ctp, io_open_t *msg, 
        iofunc_attr_t *dattr, void *extra) {
    char *newpath;
    /* Do all the error/access checking ... */
    /* Lookup the redirected path and store 
       the new path in 'newpath' */
    newpath = get_a_new_path(msg->connect.path);
    _IO_SET_CONNECT_RET(ctp, _IO_CONNECT_RET_LINK);
    len = strlen(newpath) + 1;
    msg->link_reply.eflag = msg->connect.eflag;
    msg->link_reply.nentries = 0;
    msg->link_reply.path_len = len;
    strcpy((char *)(msg->link_reply + 1), newpath);
    len += sizeof(msg->link_reply);
    return(_RESMGR_PTR(ctp, &msg->link_reply, len));
}
In this example, we use the macro _IO_SET_CONNECT_RET() (defined in <sys/iomsg.h>) to set the ctp->status field to _IO_CONNECT_RET_LINK. This value indicates to the resource-manager framework that the return value isn't actually a simple return code, but a new request to be processed.
The path for this new request follows directly after the link_reply structure and is path_len bytes long. The final few lines of the code just stuff an IOV with the reply message (and the new path to be queried) and return to the resource-manager framework.
The io_open_t structure holds the _IO_CONNECT message received by the resource manager:
typedef union {
    struct _io_connect                  connect;
    struct _io_connect_link_reply       link_reply;
    struct _io_connect_ftype_reply      ftype_reply;
} io_open_t;
This message structure is a union of an input message (coming to the resource manager), _io_connect, and two possible output or reply messages (going back to the client):
Or:
This is a sample skeleton for a typical filesystem, in pseudo-code, to illustrate the steps that need to be taken to handle an open request for a file:
if the open request is for a path (i.e. multiple 
  directory levels)
    call iofunc_client_info to get information 
      about client
    for each directory component
        call iofunc_check_access to check execute 
          permission for access
        /*
         recall that execute permission on a 
         directory is really the "search" 
         permission for that directory
        */
    next
    /*
     at this point you have verified access 
     to the target
    */
endif
if O_CREAT is set and the file doesn't exist
    call iofunc_open, passing the attribute of the
      parent as dattr
    if the iofunc_open succeeds,
        do the work to create the new inode, 
          or whatever
    endif
else
    call iofunc_open, passing the attr of the file
     and NULL for dattr
endif
/*
 at this point, check for things like o_trunc, 
 etc. -- things that you have to do for the attr
*/
call iofunc_ocb_attach
return EOK
For a device (i.e. resmgr_attach() didn't specify that the managed resource is a directory), the following steps apply:
/* at startup time (i.e.: in the main() of the resource manager) */ call iofunc_attr_init to initialize an attribute structure /* in the io_open message handler: */ call iofunc_open, passing in the attribute of the device and NULL for dattr call iofunc_ocb_attach return EOK
| Safety: | |
|---|---|
| Cancellation point | No | 
| Interrupt handler | No | 
| Signal handler | Yes | 
| Thread | Yes | 
dirent, _io_connect, _io_connect_link_reply, _io_connect_ftype_reply, iofunc_attr_init(), iofunc_check_access(), iofunc_client_info(), iofunc_ocb_attach(), iofunc_stat(), resmgr_open_bind()
Resource Managers chapter of Getting Started with QNX Neutrino
![]()  | 
![]()  | 
![]()  | 
![]()  |