iofunc_open()

Подтвердить способность клиента открыть ресурс

Прототип:

#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 );

Аргументы:

ctp
Указатель на структуру resmgr_context_t, которую библиотека менеджера ресурсов использует для передачи контекстной информации между функциями.
msg
Указатель на структуру io_open_t, содержащую сообщение, полученное менеджером ресурсов.
attr
Указатель на атрибутную запись iofunc_attr_t, описывающую характеристики устройства, связанного с менеджером ресурсов.
dattr
NULL или указатель на структуру iofunc_attr_t, описывающую характеристики родительского каталога.
info
NULL или указатель на структуру struct _client_info с информацией о клиентском подключении.

Библиотека:

libc

Описание:

Функция iofunc_open() проверяет, имеет ли клиент (описываемый необязательной структурой info) доступ для открытия ресурса, имя которого передаётся в msg->connect.path.

Структура attr содержит атрибуты ресурса. Необязательная структура dattr содержит атрибуты родительского каталога; если dattr не равен NULL, ресурс, указанный в attr, создаётся в каталоге, указанном в dattr.

Аргумент info может быть передан как NULL, в этом случае iofunc_open() сама получает информацию о клиенте с помощью вызова iofunc_client_info(). Но, конечно, эффективнее будет получить информацию о клиенте один раз, а не каждый раз вызывать эту функцию с NULL.

Обратите внимание, что если обрабатывается запрос на чтение/запись каталога, необходимо вернуть данные, сформированные в соответствии с типом struct dirent. Вспомогательная функция iofunc_stat() может помочь в этом.

Ответ менеджера ресурсов на запрос open() не всегда является ответом "да" или "нет". Можно вернуть сообщение о подключении, указывающее, что сервер хотел бы предпринять какое-либо другое действие. Например, если открывается символическая ссылка на какой-либо другой путь, сервер может ответить, используя макрос _IO_SET_CONNECT_RET() и значение _IO_CONNECT_RET_LINK.

Например, обработчик открытия только переопределяющий пути, выглядит примерно следующим образом:

io_open( resmgr_context_t *ctp, io_open_t *msg,
iofunc_attr_t *dattr, void *extra )
{
char *newpath;
/* Выполнить все проверки доступа/ошибок ... */
/* Найти и сохранить новый путь в '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 ));
}

В этом примере используется макрос _IO_RET_CONNECT_RET() (определён в <sys/iomsg.h>), чтобы установить в поле ctp->status значение _IO_CONNECT_REMOTE_LINK. Это значение указывает менеджеру ресурсов, что возвращаемое значение на самом деле не является простым кодом возврата, а новым запросом, подлежащим обработке.

Путь для этого нового запроса следует непосредственно за структурой link_reply и имеет длину path_len байт. Последние несколько строк кода просто заполняют IOV ответным сообщением (и новым путём, который нужно запросить) и возвращают управление в фреймворк менеджера ресурсов.

Возвращаемое значение:

EOK
Успешное завершение.
Other
Произошла ошибка, определённая семантикой POSIX для вызова open(). Эта ошибка должна быть возвращена на уровень выше.

Примеры:

Пример псевдокода для типичной файловой системы для шагов, которые необходимо выполнить для обработки запроса на открытие файла:

если запрос открытия пути ( т.е. несколько уровней директорий )
{
вызвать iofunc_client_info() чтобы получить информацию о клиенте;
для каждого компонента директории
{
вызвать iofunc_check_access() чтобы проверить разрешения на выполнение;
/*
* напомним, что разрешение на выполнение в каталоге на самом деле
* является "поиском"
*/
}
далее
/* на этом этапе доступ подтвержден */
}
если O_CREAT установлен и файл не существует
{
вызвать iofunc_open(), передав атрибуты родительской директории как dattr;
если iofunc_open() успешно завершилась
{
выполнить работу по созданию нового inode или чего-либо ещё;
}
} иначе {
вызвать iofunc_open(), передав attr файла и NULL в dattr;
}
/* на этом этапе следует проверить o_trunc, и т.д. -- то, что необходимо сделать для attr */
вызвать iofunc_ocb_attach();
вернуть (EOK);

Для устройства ( resmgr_attach() не указал, что устройство является директорией), выполняются следующие действия:

/* при запуске (т.е. в main() менеджере ресурсов) */
вызвать iofunc_attr_init() чтобы инициализировать структуру атрибутов;
/* в обработчике сообщений io_open: */
вызвать iofunc_open(), передав атрибуты устройства и NULL в dattr;
вызвать iofunc_ocb_attach();
вернуть (EOK);

Классификация:

ЗОСРВ «Нейтрино»

Безопасность использования
Точка остановки потока
Нет
Обработчик прерываний
Нет
Обработчик сигналов
Да
В потоке
Да

Тематические ссылки:

struct _client_info, struct dirent, io_open_t, struct _io_connect, struct _io_connect_link_reply, struct _io_connect_ftype_reply, resmgr_context_t, iofunc_attr_init(), iofunc_check_access(), iofunc_client_info(), iofunc_ocb_attach(), iofunc_stat(), open(), resmgr_attach(), resmgr_open_bind()




Предыдущий раздел: Описание API системной библиотеки