QNX-9—QNX官网文档翻译—Resource Managers—Alphabetical listing of connect and I/O functions

注:本文翻译自
QNX Software Development Platform --> Programming --> Getting Started with QNX Neutrino --> Resource Managers
http://www.qnx.com/developers/docs/7.1/index.html#com.qnx.doc.neutrino.getting_started/topic/s1_resmgr_alphalist.html


一、Alphabetical listing of connect and I/O functions

1. Access control list I/O function handler

Prototype:

int (*acl)( resmgr_context_t *ctp, io_acl_t *msg, RESMGR_OCB_T *ocb ) 

Classification: I/O

Default handler: iofunc_acl_default()

Helper functions: iofunc_acl()

Client functions: acl_*(),如 acl_set_permset()

Messages: _IO_ACL

Data structure:

struct _io_acl {
    uint16_t                        type;
    uint16_t                        combine_len;
    uint32_t                        subtype;
    int32_t                         zero[2];
    /* struct _acl_header           hdr; */
    /* void                         acl_data */
};

enum _io_acl_subtypes {
    _IO_ACL_GET,
    _IO_ACL_SET,
    _IO_ACL_CHK
};

struct _io_acl_reply {
    uint32_t                        zero[4];
    /* struct _acl_header           hdr; */
    /* void                         acl_data */
};

typedef union {
    struct _io_acl                  i;
    struct _io_acl_reply            o;
} io_acl_t;

Description: 获取、设置或检查访问控制列表 (ACL)。

返回:通过辅助宏 _RESMGR_STATUS() 和回复缓冲区(如果需要,带有回复数据)的状态。

引用者:resmgr_io_funcs_t I/O table 

权限检查:默认实现 iofunc_acl_default() 调用辅助函数 iofunc_acl()),该函数不执行任何权限检查,也不需要任何权限检查。


2. Change file mode I/O function handler

Prototype:

int (*chmod) ( resmgr_context_t *ctp, io_chmod_t *msg, RESMGR_OCB_T *ocb ) 

Classification: I/O function

Default handler: iofunc_chmod_default()

Helper functions: iofunc_ability_check(), iofunc_chmod()

Client functions: chmod(), fchmod(), fchmodat()

Messages: _IO_CHMOD

Data structure:

struct _io_chmod {
    uint16_t type;
    uint16_t combine_len;
    mode_t   mode;
};

typedef union {
    struct _io_chmod i;
} io_chmod_t;


Description: 负责将传递的 ocb 标识的资源的模式更改为模式消息成员指定的值。

Returns: 通过辅助宏 _RESMGR_STATUS() 获取状态。

引用者:resmgr_io_funcs_t I/O 表

权限检查:默认实现 iofunc_chmod_default() 调用辅助函数 iofunc_chmod() 来检查客户端是否是文件的所有者(即,它具有相同的用户 ID)并且它不是只读文件系统。 辅助功能还可以防止用户设置粘性位和设置组 ID 位,除非它是 root。


3. Change ownership I/O function handler

Prototype:

int (*chown)( resmgr_context_t *ctp, io_chown_t *msg, RESMGR_OCB_T *ocb ) 

Classification: I/O function

Default handler: iofunc_chown_default()

Helper functions: iofunc_ability_check(), iofunc_chown()

Client functions: chown(), fchown(), fchownat()

Messages: _IO_CHOWN

Data structure:

struct _io_chown {
    uint16_t type;
    uint16_t combine_len;
    int32_t  gid;
    int32_t  uid;
};

typedef union {
    struct _io_chown i;
} io_chown_t;


Description: 负责将传递的 ocb 标识的资源的用户 ID 和组 ID 字段分别更改为 uid 和 gid。 请注意,应检查挂载结构标志 IOFUNC_PC_CHOWN_RESTRICTED 和 OCB 标志字段,以确定文件系统是否允许非 root 用户执行 chown()。

返回:通过辅助宏 _RESMGR_STATUS() 获取状态。

引用者:resmgr_io_funcs_t I/O 表

权限检查:默认实现 iofunc_chown_default() 调用辅助函数 iofunc_chown() 来检查 IOFUNC_PC_CHOWN_RESTRICTED 标志,以确定是否允许用户更改条目上的用户 ID。 帮助器函数还检查客户端是否具有 iofunc/chown (IOFUNC_ABILITY_CHOWN) 动态能力(使用 iofunc_ability_check(),这允许它像 root 一样设置用户 ID。最后,帮助器检查以确保它不是只读文件系统。

当 iofunc_chown() 设置新的用户 ID 或组 ID 时,它会删除设置的用户 ID 和设置的组 ID 位(如果它们已在文件中设置)。 用户或组 ID 的值为 -1 意味着调用者不想更改该 ID。


4. Change timestamps I/O function handler

Prototype:

int (*utime) ( resmgr_context_t *ctp, io_utime_t *msg, RESMGR_OCB_T *ocb ) 

Classification: I/O

Default handler: iofunc_utime_default()

Helper functions: iofunc_utime()

Client function: utime()

Messages: _IO_UTIME or _IO_UTIME64

Data structure:

struct _io_utime {
    uint16_t                    type;
    uint16_t                    combine_len;
    int32_t                     cur_flag;
    struct __utimbuf32          times;
};

struct _io_utime64 {
    uint16_t                    type;
    uint16_t                    combine_len;
    int32_t                     cur_flag;
    int64_t                     atime_s;
    int64_t                     atime_ns;
    int64_t                     mtime_s;
    int64_t                     mtime_ns;
};

typedef union {
    struct _io_utime            i;
    struct _io_utime            i64;
} io_utime_t;


描述:将访问和修改时间更改为“现在”(如果为零)或指定值。 请注意,可能需要此消息处理程序根据 POSIX 规则修改属性结构中的 IOFUNC_ATTR_* 标志。 您自己几乎永远不会使用此呼出,而是使用 POSIX 层帮助函数。

返回:通过辅助宏 _RESMGR_STATUS() 获取状态。

引用者:resmgr_io_funcs_t I/O 表

权限检查:默认实现 iofunc_utime_default() 调用辅助函数 iofunc_utime() 来检查该条目是否由当前用户拥有或当前用户对其具有写访问权限。 该帮助程序还检查只读文件系统。 实体的所有者可以设置任意时间,而只有写权限的用户只能设置当前时间(cur_flag 为 1)。


5. Close duplicate OCB I/O function handler

Prototype:

int (*close_dup) ( resmgr_context_t *ctp, io_close_t *msg, RESMGR_OCB_T *ocb ) 

Classification: I/O function

Default handler: iofunc_close_dup_default()

Helper functions: iofunc_close_dup()

Client functions: close(), fclose()

Messages: _IO_CLOSE

Data structure:

struct _io_close {
    uint16_t type;
    uint16_t combine_len;
};

typedef union {
    struct _io_close i;
} io_close_t;


描述:这是客户端 close() 或 fclose() 函数调用的真正函数处理程序。
如果你接管这个函数,除了你所做的工作之外,你几乎总是会调用 iofunc_close_dup_default() 。 这是因为基础层跟踪为特定 OCB 发出的 open()、dup() 和 close() 消息的数量,然后当 已收到特定 OCB 的最后 close() 消息。

请注意,ctp->rcvid 中存在的接收 ID 不一定与传递给打开连接函数处理程序的接收 ID 匹配。 例如,当客户端在未发送 _IO_CLOSE 的情况下断开连接时,资源管理器框架会处理生成的脉冲并伪造 _IO_CLOSE 消息。 任何通过 ctp->rcvid(应该为 0)直接回复此消息的尝试,或者将其保留为“阻止”并稍后回复的尝试都将失败。


如果您的资源管理器使客户端被阻止(例如,在 read()、write() 或 devctl() 调用时),您将需要接管此函数,以便您可以跟踪哪些客户端被阻止,如果有必要的话并取消阻止。 有关更多信息,请参阅《编写资源管理器》的“解除阻止客户端和处理中断”一章中的 “Unblocking if someone closes the file descriptor”。


与大多数其他 I/O 函数处理程序不同,资源管理器框架运行 close_dup() 而不锁定 OCB 结构 (ocb)。如果您需要修改此结构中的字段并且您的服务器进程是多线程的,则必须序列化对该结构的访问以避免竞争条件。 有关更多信息,请参阅编写资源管理器中的“如果有人关闭文件描述符则解除阻塞”中有关锁定属性结构的注释。


返回:通过辅助宏 _RESMGR_STATUS() 获取状态。

引用者:resmgr_io_funcs_t I/O Table

权限检查:默认实现 iofunc_close_dup_default() 调用辅助函数 iofunc_close_dup(),该函数不执行任何权限检查。


6. Close OCB I/O function handler

Prototype:

int (*close_ocb) ( resmgr_context_t *ctp, void *reserved, RESMGR_OCB_T *ocb ) 

Classification: I/O function (synthesized by library)

Default handler: iofunc_close_ocb_default()

Helper functions: none

Client function: none—synthesized by library

Messages: none—synthesized by library

Data structure:

// synthesized by library
struct _io_close {
    uint16_t type;
    uint16_t combine_len;
};

typedef union {
    struct _io_close i;
} io_close_t;

描述:这是当收到特定 OCB 的最后一个 close() 时由基础层库合成的函数。 您可以在 OCB 被销毁之前执行所需的任何最终清理工作。 请注意,ctp->rcvid 中的接收 ID 为零,因为该函数是由库合成的,不一定对应于任何特定消息。

返回:通过辅助宏 _RESMGR_STATUS() 获取状态。

参考者:resmgr_io_funcs_t I/O table

权限检查:默认实现 iofunc_close_ocb_default() 和辅助函数 iofunc_close_ocb() 不执行权限检查。 无需进行权限检查。 如果您创建了自己的 OCB,则只需实现此函数(另请参阅 iofunc_close_ocb_calloc 和 iofunc_close_ocb_free)。


7. Create file link connect function handler

Prototype:

int (*link) ( resmgr_context_t *ctp, io_link_t *msg, RESMGR_HANDLE_T *handle, io_link_extra_t *extra ) 

Classification: Connect

Default handler: none

Helper functions: iofunc_link()

Client functions: link(), linkat(), symlink(), symlinkat()

Messages: _IO_CONNECT with subtype _IO_CONNECT_LINK

Data structure:

struct _io_connect {
    // internal fields (as described above)
    uint16_t path_len;
    uint8_t  extra_type;
    uint16_t extra_len;
    char     path [1];
};

struct _io_connect_link_reply {
    uint32_t reserved1;
    uint32_t file_type;
    uint8_t  eflag;
    uint8_t  reserved2[1];
    uint16_t chroot_len;
    uint32_t umask;
    uint16_t nentries;
    uint16_t path_len;
};

struct _io_connect_ftype_reply {
    uint16_t status;      /* Typically an errno */
    uint16_t reserved;
    uint32_t file_type;   /* _FTYPE_? in sys/ftype.h */
};

typedef union {
    struct _io_connect             connect;
    struct _io_connect_link_reply  link_reply;
    struct _io_connect_ftype_reply ftype_reply;
} io_link_t;

typedef union _io_link_extra {
    struct _msg_info              info;
    void                          *ocb;
    char                          path [1];
    struct _io_resmgr_link_extra  resmgr;
} io_link_extra_t;

描述:使用 msg 的路径成员中给定的名称创建一个新链接,链接到 extra 的路径成员指定的现有路径名(传递给您的函数)。 为了方便起见,extra 的 ocb 成员包含一个指向现有路径名的 OCB 的指针。

返回:通过辅助宏 _RESMGR_STATUS() 获取状态。

参考者:resmgr_connect_funcs_t 连接表

权限检查:iofunc_link() 函数使用带有 S_ISUID、S_ISGID 和 S_IREAD 标志的 iofunc_check_access() 来检查 OCB 上现有路径名的访问。


8. Device control I/O function handler

Prototype:

int (*devctl) (resmgr_context_t *ctp, io_devctl_t *msg, RESMGR_OCB_T *ocb ) 

Classification: I/O

Default handler: iofunc_devctl_default()

Helper functions: iofunc_devctl(), iofunc_devctl_verify()

Client functions: devctl(), ioctl()

Messages: _IO_DEVCTL

Data structure:

struct _io_devctl {
    uint16_t type;
    uint16_t combine_len;
    int32_t  dcmd;
    uint32_t nbytes;
    int32_t  zero;
};

struct _io_devctl_reply {
    uint32_t zero;
    int32_t  ret_val;
    uint32_t nbytes;
    int32_t  zero2;
};

typedef union {
    struct _io_devctl       i;
    struct _io_devctl_reply o;
} io_devctl_t;

描述:执行从 dcmd 中客户端的 devctl() 传递的设备 I/O 操作。 客户端将方向编码到 dcmd 的前两位中,指示 devctl() 如何传输数据(“to”字段指 _POSIX_DEVDIR_TO 位;“from”字段指 _POSIX_DEVDIR_FROM 位):

--------------------------------------------
to field  from field  Meaning
--------------------------------------------
0         0           无数据传输
0         1           从驱动程序传输到客户端
1         0           从客户端传输到驱动程序
1         1           双向传输
--------------------------------------------

在没有数据传输的情况下,驱动程序应简单地执行 dcmd 中给出的命令。

(1) 访问客户端发送的数据

如果客户端提供数据,它会紧跟在 msg 参数提供的 io_devctl_t 标头之后。 在访问任何数据之前,您需要验证其长度。

由于组合消息会使确定消息的长度变得更加复杂,因此当您禁止使用它们时,验证会更简单。 (允许组合消息没有任何优势。)

为了防止使用组合消息,请检查 ctp->rcvid 是否为零,如果为零则返回错误。

检查消息长度的方式取决于您要处理的消息的长度:

a. 如果处理程序仅处理短消息(小于 1500 字节),则消息长度为 ctp->size。 这种类型的处理程序稍微简单一些。
b. 如果处理程序必须处理大消息,则消息长度为 (ctp->info.srcmsglen – ctp->offset)。 然而,在这种情况下,消息缓冲区中只有 ctp->size 可以直接使用。 您需要使用 resmgr_msgget() 或 resmgr_msgread() 等函数读取其余部分。

如果您的处理程序支持多个设备控制操作,则您可能拥有来自这两个类别的操作。


您需要验证实际消息长度至少与预期长度一样大。 如果您需要访问消息的任何部分以确定预期大小,则需要确保 ctp->size 足够大以包含此数据。

验证消息长度后,您需要访问数据。 如果您的设备控制操作仅处理短消息(上面的类别 1),则消息有效负载完全包含在消息缓冲区中。 如果您的操作必须处理大消息(类别 2),您可能必须使用 resmgr_msgget() 或 resmgr_msggetv() 来读取至少部分有效负载。

(2) 返回数据给客户端

如果可以的话,在执行请求之前,您应该验证将返回的数据量加上 io_devctl_t 标头的大小是否小于或等于 ctp->info.dstmsglen。 否则,客户端将不会收到您发送的所有数据。 如果您的设备控制操作返回的数据量是可变的,则返回的数据最好包括大小或计算方法。

(3) 结构填充

请注意,输入和输出数据结构是用零填充的,以便它们彼此对齐。 这意味着隐式数据区域从输入和输出结构中的相同地址开始。

(4) 无法识别的命令

如果使用辅助例程 iofunc_devctl(),请注意,如果它无法对 devctl() 消息执行任何操作,它将返回常量 _RESMGR_DEFAULT。 该返回值用于将合法的 errno 返回值与“无法识别的命令”返回值分离。 收到 _RESMGR_DEFAULT 后,基础层库将响应 ENOSYS 错误号,客户端的 devctl() 库函数将其转换为 ENOTTY。

(5) 检查打开模式

由您的函数根据操作检查打开模式; 在客户端的 devctl() 库或资源管理器库中的任何地方都不会进行任何检查。 例如,可以“只读”打开资源管理器,然后向其发出 devctl() 告诉它“格式化硬盘”(这在很大程度上是一个“写入”操作)。 在继续操作之前,请先验证打开模式是谨慎的做法。

有关检查消息安全性和有效性的更多信息,请参阅下面“Permission checking.”。

(6) 可用的 dcmd 值

请注意,您可以使用的 dcmd 值的范围是有限的(0x0000 到 0x0FFF(含)为 BlackBerry QNX 保留)。 可能使用其他值; 查看名为 <sys/dcmd_*.h> 的包含文件。


返回:通过辅助宏 _RESMGR_STATUS() 和回复缓冲区(如果需要,带有回复数据)的状态。例如,请查看下面的 “A simple device control I/O function handler example,” 。

引用者:resmgr_io_funcs_t I/O 表


权限检查:

默认实现 iofunc_devctl_default() 处理程序不执行权限检查,因为该处理程序不实现任何需要保护的功能。 实现 devctl() 的资源管理器必须根据要执行的命令应用权限检查。 由于 devctl() 操作的灵活性,这很复杂。 例如,当更改串行设备的波特率时,可以打开该设备进行只读访问,然后执行 devctl() 来更改波特率。 尽管此操作执行修改,但它不需要已打开文件描述符进行写入。 因此,每个单独的 devctl() 命令通常需要进行适当的权限检查。

处理 devctl() 的可能方法包括以下策略:

(1) 根据文件打开模式强制执行全局权限检查。 例如,如果尚未打开 OCB 进行写访问,则资源管理器坚持根本不执行 devctl() 操作可能是可以接受的,如以下代码所示(位于 devctl() 的开头) 处理函数):

if (!(ocb->ioflag & _IO_FLAG_WR)) {
    return EPERM;
}    

(2) 执行特定于命令的权限检查,检查每个 devctl() 操作,以确定必须根据命令的特定功能强制执行的权限。 您还可以实施类似于以下检查的检查,该检查验证文件是否以读取权限打开:

if ( (ocb->ioflag & _IO_FLAG_RD) == 0 ) {
    return EPERM; 
}

QNX 不建议使用 iofunc_devctl_verify() 执行验证。

有关包含权限和长度检查的示例处理程序,请参阅 “A simple device control I/O function handler example” 。


9. Duplicate a file descriptor I/O function handler


10. File descriptor information I/O function handler


11. File locking I/O function handler


12. Flush data I/O function handler


13. Lock OCB I/O function handler

原型:

int (*lock_ocb) ( resmgr_context_t *ctp, void *reserved, RESMGR_OCB_T *ocb )

分类:I/O(由库合成)

默认处理程序:iofunc_lock_ocb_default()

辅助函数:无

客户端函数:全部

消息:无——由库合成

数据结构:没有

描述:

该函数负责锁定 OCB 指向的属性结构。 这样做是为了确保一次只有一个线程可以对 OCB 和相应的属性结构进行操作锁定(和相应的解锁)函数由资源管理器库在消息处理完成之前和之后合成。有关更多详细信息,请参阅上面的 “Combine messages” 部分。 你自己几乎永远不会使用这种调用; 相反,使用 POSIX 层默认函数。

返回:通过辅助宏 _RESMGR_STATUS() 获取状态。

引用者:resmgr_io_funcs_t I/O table

权限检查:默认实现 iofunc_lock_ocb_default() 不执行任何权限检查,并且没有辅助函数。 无需进行权限检查。


14. Make filesystem node connect function handler


15. Map memory I/O function handler


16. Mount connect function handler


17. Open connect function handler

Prototype:

int (*open) (resmgr_context_t *ctp, io_open_t *msg, RESMGR_HANDLE_T *handle, void *extra ) 

Classification: Connect

Default handler: iofunc_open_default()

Helper functions: iofunc_ability_check(), iofunc_ocb_attach(), iofunc_open()

Client functions: open(), openat(), fopen(), sopen() (and others)

Messages: _IO_CONNECT with one of _IO_CONNECT_COMBINE, _IO_CONNECT_COMBINE_CLOSE or _IO_CONNECT_OPEN subtypes.

Data structure:

struct _io_connect {
    // internal fields (as described above)
    uint16_t path_len;
    uint8_t  extra_type;
    uint16_t extra_len;
    char     path [1];
};

struct _io_connect_link_reply {
    uint32_t reserved1;
    uint32_t file_type;
    uint8_t  eflag;
    uint8_t  reserved2[1];
    uint16_t chroot_len;
    uint32_t umask;
    uint16_t nentries;
    uint16_t path_len;
};

struct _io_connect_ftype_reply {
    uint16_t status;      /* Typically an errno */
    uint16_t reserved;
    uint32_t file_type;   /* _FTYPE_? in sys/ftype.h */
};

typedef union {
    struct _io_connect             connect;
    struct _io_connect_link_reply  link_reply;
    struct _io_connect_ftype_reply ftype_reply;
} io_open_t;

描述:这是新文件描述符的处理函数。 它检查客户端是否确实具有打开文件的适当权限,将 OCB 绑定到内部库结构(通过 resmgr_bind_ocb() 或 iofunc_ocb_attach()),并返回 errno。 请注意,并非所有输入和输出结构成员都与此函数相关。

返回:通过辅助宏 _IO_SET_CONNECT_RET() 获取状态。

引用者:resmgr_connect_funcs_t connect table

权限检查:当您覆盖默认函数时,QNX 建议您在实现任何附加功能之前调用 iofunc_open_default()(它根据请求的访问权限实现多项权限检查)。 请注意,由于文件可以在没有读或写权限的情况下打开,因此在实现锁定之类的操作之前检查 iofunc_open_default() (或相关的 iofunc_open())是否返回 EOK 是不够的(例如,对于一次只能由一名客户端打开访问的资源)。


18. Open file descriptor I/O function handler

Prototype:

int (*openfd) ( resmgr_context_t *ctp, io_openfd_t *msg, RESMGR_OCB_T *ocb ) 

Classification: I/O

Default handler: iofunc_openfd_default()

Helper functions: iofunc_ability_check(), iofunc_openfd()

Client function: openfd()

Messages: _IO_OPENFD

Data structure:

struct _io_openfd {
    uint16_t            type;
    uint16_t            combine_len;
    uint32_t            ioflag;
    uint16_t            sflag;
    uint16_t            reserved1;
    struct _msg_info32  info;
    uint32_t            reserved2;
    uint32_t            key;
};

typedef union {
    struct _io_openfd i;
} io_openfd_t;

描述:

此函数类似于为 open connect 函数提供的处理程序,不同之处在于传递的不是路径名,而是已打开的文件描述符(通过在函数调用中传递 ocb)##########。

返回:

通过辅助宏 _RESMGR_STATUS() 获取状态。

引用者:

resmgr_io_funcs_t I/O table

权限检查:

默认实现 iofunc_openfd_default() 检查扩展类型,然后调用辅助函数 iofunc_openfd。 帮助程序功能确保新权限的限制不低于当前打开的访问模式。


19. pathconf I/O function handler


20. Power I/O function handler


21. Read I/O function handler

Prototype:

int (*read) ( resmgr_context_t *ctp, io_read_t *msg, RESMGR_OCB_T *ocb ) 

Classification: I/O

Default handler: iofunc_read_default()

Helper functions: iofunc_read_verify()

Client functions: read(), readdir()

Messages: _IO_READ, _IO_READ64

Data structure:

struct _io_read {
    uint16_t            type;
    uint16_t            combine_len;
    uint32_t            nbytes;
    uint32_t            xtype;
    uint32_t            zero;
};

struct _io_read64 {
    uint16_t            type;
    uint16_t            combine_len;
    uint32_t            nbytes;
    uint32_t            xtype;
    uint32_t            nbytes_hi;
};

typedef union {
    struct _io_read     i;
    struct _io_read     i64;
    /* unsigned char    data[nbytes];    */
    /* nbytes is returned with MsgReply  */
} io_read_t;

描述:

负责从资源中读取数据。 客户端在 nbytes 输入成员中指定准备读取的字节数。 您返回数据,提前 OCB 中的偏移量,并更新相应的时间字段。

请注意以下事项:

(1) 仅当长度大于 4 GB 时,客户端库才使用 _IO_READ64 形式。 您可以使用 _IO_READ_GET_NBYTES() 宏(在 <sys/iofunc.h> 中定义)来确定字节数。

(2) xtype 成员可以指定per-read-message覆盖标志。 应该对此进行检查。 如果您不支持任何扩展覆盖标志,则应返回 EINVAL。 我们将在下面的读 I/O 函数处理程序和写 I/O 函数处理程序示例中看到一个特别重要(且棘手!)的覆盖标志(称为 _IO_XTYPE_OFFSET)的处理。

(3) _IO_READ 或 _IO_READ64 消息的到达不仅用于常规文件,还用于读取目录的内容。 您必须确保在目录情况下返回整数个 struct dirent 成员。 有关返回目录条目的更多信息,请参阅“高级主题”部分中 “Returning directory entries.” 下的示例。

在 QNX Neutrino 7.0 或更高版本中,readdir() 将 xtype 设置为 _IO_XTYPE_READDIR。 如果有人尝试从目录中 read(),则此消息的处理程序可能会给出错误。
您应该调用辅助函数 iofunc_read_verify() 来确定文件是否以与读取兼容的模式打开。 您还应该调用 iofunc_sync_verify() 函数来验证数据是否需要同步到介质。(对于 read(),这意味着返回的数据保证位于介质上。)

返回:

通过辅助宏 _IO_SET_READ_NBYTES() 读取的字节数或状态,以及通过消息回复的数据本身。 有关仅返回数据的示例,请查看下面的“A simple read I/O function handler example”。 有关返回数据和目录条目的更复杂示例,请查看“返回目录条目”下的“高级主题”部分。

引用者:

resmgr_io_funcs_t I/O table

权限检查:

默认实现 iofunc_read_default() 调用 iofunc_read_verify(),然后不返回任何数据。 由于可以在没有读或写权限的情况下打开文件,因此您必须验证 OCB 是否已在每次调用中打开以供读取。 iofunc_read_verify() 函数默认执行此操作。此外,资源管理器应该验证扩展类型(xtype;请参阅编写资源管理器中的 “If you aren't expecting extended types (xtype)” )。


22. Read link connect function handler


23. Rename connect function handler


24. Register for notification I/O function handler

Prototype:

int (*notify) ( resmgr_context_t *ctp, io_notify_t *msg, RESMGR_OCB_T *ocb )

Classification: I/O

Default handler: none

Helper functions: iofunc_notify(), iofunc_notify_remove(), iofunc_notify_remove_strict(), iofunc_notify_trigger(), iofunc_notify_trigger_strict()

Client functions: poll(), select(), ionotify()

Messages: _IO_NOTIFY, _IO_NOTIFY64

Data structure:

struct _io_notify {
    uint16_t                    type;
    uint16_t                    combine_len;
    int32_t                     action;
    int32_t                     flags;
    struct __sigevent32         event;

    /* The fields `mgr` to `timo` are only valid if (flags & _NOTIFY_COND_EXTEN)
     * The full header must be present regardless of the flags.
     */
    int32_t                     mgr[2];    /* For use by manager */
    int32_t                     flags_extra_mask;
    int32_t                     flags_exten;
    int32_t                     nfds;
    int32_t                     fd_first;
    int32_t                     nfds_ready;
    int64_t                     timo;
    /* struct pollfd            fds[nfds]; */
};

struct _io_notify64 {
    uint16_t                    type;
    uint16_t                    combine_len;
    int32_t                     action;
    int32_t                     flags;
    struct __sigevent32         old_event;

    /* The fields `mgr` to `timo` are only valid if (flags & _NOTIFY_COND_EXTEN)
     * The full header must be present regardless of the flags.
     */
    int32_t                     mgr[2];    /* For use by manager */
    int32_t                     flags_extra_mask;
    int32_t                     flags_exten;
    int32_t                     nfds;
    int32_t                     fd_first;
    int32_t                     nfds_ready;
    int64_t                     timo;
    union {
        struct __sigevent32     event32;
        struct __sigevent64     event64;
    };
    /* struct pollfd            fds[nfds]; */
};

struct _io_notify_reply {
    uint32_t                    zero;
    uint32_t                    flags;   /* actions above */
    int32_t                     flags2;  /* flags above */
    struct __sigevent32         event;

    /* Following fields only updated by new managers (if valid) */
    int32_t                     mgr[2];    /* For use by manager */
    int32_t                     flags_extra_mask;
    int32_t                     flags_exten;
    int32_t                     nfds;
    int32_t                     fd_first;
    int32_t                     nfds_ready;
    int64_t                     timo;
    /* struct pollfd            fds[nfds]; */
};

struct _io_notify_reply64 {
    uint32_t                    zero;
    uint32_t                    flags;  /* actions */
    int32_t                     flags2; /* flags above */
    struct __sigevent32         old_event;

    /* Following fields only updated by new managers (if valid) */
    int32_t                     mgr[2];    /* For use by manager */
    int32_t                     flags_extra_mask;
    int32_t                     flags_exten;
    int32_t                     nfds;
    int32_t                     fd_first;
    int32_t                     nfds_ready;
    int64_t                     timo;
    union {
        struct __sigevent32     event32;
        struct __sigevent64     event64;
    };
    /* struct pollfd            fds[nfds]; */
};

typedef union {
    struct _io_notify           i;
    struct _io_notify64         i64;
    struct _io_notify_reply     o;
    struct _io_notify_reply64   o64;
} io_notify_t;

描述:

该处理程序负责安装、轮询或删除通知处理程序。 action 和 flags 决定了通知操作的种类和条件; 该事件是一个 struct sigevent 结构,它定义了客户端希望收到信号的通知事件(如果有)。 您可以使用 MsgDeliverEvent() 或 iofunc_notify_trigger() 函数将事件传递给客户端。

返回:

通过辅助宏 _RESMGR_STATUS() 获取状态; 标志通过消息回复返回。

引用者:

resmgr_io_funcs_t I/O table

权限检查:

iofunc_notify() 辅助函数不执行权限检查。 但是,如果尚未打开 OCB 进行读取,则可能不允许请求该 OCB 上发生的与读取数据相关的条件的通知(例如,设置了 _NOTIFY_CONDE_RDNORM 标志)。 与读取或写入数据无关的通知(例如,_NOTIFY_CONDE_HUP 和 _NOTIFY_CONDE_NVAL)不需要与读取或写入访问绑定。 尽管在这种情况下信息泄漏非常有限(例如,了解文件描述符何时准备好读取或写入或具有可用的带外数据),但它可能被用于各种攻击,例如竞争条件。 QNX 建议您拒绝对尚未打开文件描述符进行读取或写入的调用方进行 notification() 调用。 彻底的权限检查将根据提供给notify()函数的标志来应用适当的决定。

对于处理用户输入(例如键盘)的资源管理器,请注意不要通过通知消息的传递泄漏计时数据。 攻击者可以使用此计时数据来构建用户输入内容的配置文件。 同样,不要提供特定于进程的特征(例如 CPU 使用情况和分配内存的变化)的通知。


25. Resize file I/O function handler


26. Set file position I/O function handler


27. Shutdown I/O function handler


28. stat I/O function handler


29. Unblock connect function handler

原型:

int (*unblock) ( resmgr_context_t *ctp, io_pulse_t *msg, RESMGR_HANDLE_T *handle, void *reserved ) 

分类:Connect(由内核、库进行合成)

默认处理程序:无

辅助函数:iofunc_unblock()

客户端函数:none——这是由于信号或超时而导致的内核操作

消息:无 —— 由库合成

数据结构:(参见解锁功能的I/O版本)

描述:这是解锁呼出的连接消息版本,由库根据客户端在连接消息阶段尝试解锁而产生的内核脉冲而合成。 有关更多详细信息,请参阅解锁 I/O 函数处理程序。

返回:通过辅助宏 _RESMGR_STATUS() 获取状态。

有关解锁策略的详细讨论,请参阅消息传递一章中标题为 “Using the _NTO_MI_UNBLOCK_REQ” 的部分。

引用者:resmgr_connect_funcs_t table

权限检查:iofunc_unblock() 函数不执行任何权限检查。


30. Unblock I/O function handler

原型:

int (*unblock) ( resmgr_context_t *ctp, io_pulse_t *msg, RESMGR_OCB_T *ocb )

分类:I/O(由内核、库合成)

默认处理程序:iofunc_unblock_default()

辅助函数:iofunc_unblock()

客户端函数:none——由于信号或超时而导致的内核操作

消息:无——由库合成

数据结构:指向被中断的消息结构的指针

描述:这是解锁呼出的 I/O 消息版本,由库合成,是由于客户端在 I/O 消息阶段尝试解锁而产生的内核脉冲的结果。 解锁连接函数处理程序基本相同(请参阅上一节)。
两个解锁处理程序(连接和 I/O)的共同点是客户端希望解锁,但受资源管理器的支配。 资源管理器必须回复客户端的消息才能解锁客户端。 (当我们查看 ChannelCreate() 标志,特别是 _NTO_CHF_UNBLOCK 标志时,这在消息传递章节中进行了讨论)。

返回:
通过辅助宏 _RESMGR_STATUS() 获取状态。
有关解锁策略的详细讨论,请参阅消息传递一章中标题为“使用 _NTO_MI_UNBLOCK_REQ”的部分。

引用者:resmgr_io_funcs_t I/O table

权限检查:默认实现 iofunc_unblock_default() 不执行任何权限检查。


31. Unlink connect function handler


32. Unlock OCB I/O function handler

原型:

int (*unlock_ocb) ( resmgr_context_t *ctp, void *reserved, RESMGR_OCB_T *ocb )

分类:I/O(由库合成)

默认处理程序:iofunc_unlock_ocb_default()

辅助函数:无

客户端功能:全部

消息:无 —— 由库合成

数据结构:无


描述:

是上面的“lock OCB I/O function handler”的逆操作。 也就是说,它负责解锁 OCB 指向的属性结构。 此操作释放属性结构,以便资源管理器中的其他线程可以对其进行操作。有关更多详细信息,请参阅上面的 “Combine messages” 部分。

返回:通过辅助宏 _RESMGR_STATUS() 获取状态。

引用者:resmgr_io_funcs_t I/O table

权限检查:默认实现 iofunc_unlock_ocb_default() 不执行任何权限检查,并且没有辅助函数。 无需进行权限检查。


33. User-defined message I/O function handler

原型:

int (*msg) ( resmgr_context_t *ctp, io_msg_t *msg, RESMGR_OCB_T *ocb )

分类:输入/输出

默认处理程序:无

辅助函数:无

客户端函数:无——手动组装并通过 MsgSend() 发送

消息:_IO_MSG

数据结构:

struct _io_msg {
    uint16_t       type;
    uint16_t       combine_len;
    uint16_t       mgrid;
    uint16_t       subtype;
};

typedef union {
    struct _io_msg i;
} io_msg_t;

描述:
与 devctl() 一样,_IO_MSG 接口允许您发送各种请求。 mgrid 用于识别特定的manager - 您不应该对不符合您的manager ID 的请求执行操作。 subtype 实际上是客户端希望执行的命令。 隐式传输的任何数据都遵循输入结构。 返回给客户端的数据自行发送,状态通过 _RESMGR_STATUS() 返回。

验证此处理程序消息的方法与设备控制 I/O 函数处理程序相同,但请注意以下差异:

(1) 与设备控制 I/O 函数处理程序(具有 devctl() 和 devctlv())不同,用户定义的消息处理程序没有 libc 函数来帮助发送消息。
(2) 输入标头的大小是 io_msg_t,而不是 io_devctl_t。
(3) 未定义输出标头。

返回:通过辅助宏 _RESMGR_STATUS() 获取状态。

引用者:resmgr_io_funcs_t I/O table

权限检查:
此函数没有默认处理程序或帮助程序。 它处理通过 MsgSend() 手动发送的消息。 任何权限检查都是特定于正在实现的功能的。 如果消息处理程序支持类似于 devctl() 的各种命令,则可能需要对每个命令进行访问检查。


34. Write I/O function handler

原型:

int (*write) ( resmgr_context_t *ctp, io_write_t *msg, RESMGR_OCB_T *ocb )

分类:输入/输出

默认处理程序:iofunc_write_default()

辅助函数:iofunc_write_verify()

客户端函数:write()、fwrite() 等

引用:_IO_WRITE,_IO_WRITE64

数据结构:

struct _io_write {
    uint16_t            type;
    uint16_t            combine_len;
    uint32_t            nbytes;
    uint32_t            xtype;
    uint32_t            zero;
    /* unsigned char    data[nbytes]; */
};

struct _io_write64 {
    uint16_t            type;
    uint16_t            combine_len;
    uint32_t            nbytes;
    uint32_t            xtype;
    uint32_t            nbytes_hi;
    /* unsigned char    data[nbytes]; */
};

typedef union {
    struct _io_write    i;
    struct _io_write    i64;
    /*  nbytes is returned with MsgReply  */
} io_write_t;

描述:

该消息处理程序负责获取客户端写入资源管理器的数据。它获取客户端尝试在 nbytes 成员中写入的字节数; 数据隐式遵循输入数据结构(除非 xtype 覆盖为 _IO_XTYPE_OFFSET;请参阅下面的 “A simple write I/O function handler example” !)该实现需要使用 resmgr_msggetv( ) 或同等内容。 返回状态是实际写入的字节数或错误号。

请注意以下事项:
(1) 要确保处理程序支持大于 4 GB 的写入(无论形式是 _IO_WRITE 还是 _IO_WRITE64),请使用 _IO_WRITE_GET_NBYTES() 宏(在 <sys/iofunc.h> 中定义)。
(2) 您应该使用辅助函数 iofunc_write_verify() 来确定文件是否以与写入兼容的模式打开。 您还应该调用 iofunc_sync_verify() 函数来验证数据是否需要同步到介质。

返回:

通过辅助宏 _IO_SET_WRITE_NBYTES() 获取状态。有关示例,请查看下面的“A simple write I/O function handler example”。

引用者:

resmgr_io_funcs_t I/O table

权限检查:

默认实现 iofunc_write_default() 调用 iofunc_write_verify(),然后默默地丢弃所有写入的数据。 由于可以在没有读或写权限的情况下打开文件,因此您必须验证 OCB 是否已在每次调用中打开以进行写入。 默认情况下,此验证是使用 iofunc_write_verify() 完成的。 此外,资源管理器应该验证扩展类型(xtype)。

 

posted on 2023-07-09 21:00  Hello-World3  阅读(191)  评论(0编辑  收藏  举报

导航