/**************************************************************************** * fs/event/event_open.c * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. The * ASF licenses this file to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance with the * License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations * under the License. * ****************************************************************************/ /**************************************************************************** * Included Files ****************************************************************************/ #include #include #include #include #include #include #include #include #include "inode/inode.h" #include "notify/notify.h" #include "event/event.h" /**************************************************************************** * Public Functions ****************************************************************************/ /**************************************************************************** * Name: nxevent_open * * Description: * This function establishes a connection between named event groups and a * task. the task may reference the event group associated with name using * the address returned by this call. The event group may be used in a * subsequent calls to nxevent_wait(), or nxevent_post(). And the event * group remains usable until the event group is closed by a successful * call to nxevent_close(). * * If a task makes multiple calls to event_open() with the same name, then * the same event group address is returned. * * Input Parameters: * event - Location to return the event group reference. * name - event group name. * oflags - event group creation options. This may either or both of the * following bit settings. * oflags = 0: Connect to the event group only if it already exists. * oflags = O_CREAT: Connect to the event group if it exists, otherwise * create the event group. * oflags = O_CREAT|O_EXCL: Create a new event group unless * already exists. * Optional parameters. When the O_CREAT flag is specified, two optional * parameters are expected: * 1. mode_t mode, is required but not used in the present * implementation. * 2. unsigned events. The event group is created with an initial * value of events. * * Returned Value: * 0 (OK), or negated errno if unsuccessful. * * Assumptions: * ****************************************************************************/ int nxevent_open(FAR nxevent_t **event, FAR const char *name, int oflags, ...) { FAR struct inode *inode; FAR struct nevent_inode_s *nevent; struct inode_search_s desc; char fullpath[MAX_EVENTPATH]; mode_t mode; nxevent_mask_t events = 0; int ret; /* Get the full path to the */ snprintf(fullpath, MAX_EVENTPATH, CONFIG_FS_NAMED_EVENTS_VFS_PATH "/%s", name); /* Get the inode for this event group. This should succeed if the * event group has already been created. In this case, inode_find() * will have incremented the reference count on the inode. */ SETUP_SEARCH(&desc, fullpath, false); ret = inode_find(&desc); if (ret >= 0) { /* Something exists at this path. Get the search results */ inode = desc.node; /* Verify that the inode is a event group */ if (!INODE_IS_NAMEDEVENT(inode)) { ret = -ENXIO; goto errout_with_inode; } /* It exists and is a event group. Check if the caller wanted to * create a new event group with this name. */ if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) { ret = -EEXIST; goto errout_with_inode; } /* Return a reference to the event group, retaining the reference * count on the inode. */ *event = &inode->u.i_nevent->ne_event; } else { va_list ap; /* The event group does not exists. Were we asked to create it? */ if ((oflags & O_CREAT) == 0) { /* The event group does not exist and O_CREAT is not set */ ret = -ENOENT; goto errout_with_search; } /* Create the event group. First we have to extract the additional * parameters from the variable argument list. * REVISIT: Mode parameter is not currently used. */ va_start(ap, oflags); mode = va_arg(ap, mode_t) & ~getumask(); events = va_arg(ap, nxevent_mask_t); va_end(ap); /* Create an inode in the pseudo-filesystem at this path. The new * inode will be created with a reference count of zero. */ inode_lock(); ret = inode_reserve(fullpath, mode, &inode); inode_unlock(); if (ret < 0) { goto errout_with_search; } /* Allocate the event group structure (using the appropriate allocator * for the group) */ nevent = group_malloc(NULL, sizeof(struct nevent_inode_s)); if (!nevent) { ret = -ENOMEM; goto errout_with_inode; } /* Link to the inode */ inode->u.i_nevent = nevent; nevent->ne_inode = inode; /* Initialize the inode */ INODE_SET_NAMEDEVENT(inode); atomic_fetch_add(&inode->i_crefs, 1); /* Initialize the event groups */ nxevent_init(&nevent->ne_event, events); /* Return a reference to the event groups */ *event = &nevent->ne_event; } RELEASE_SEARCH(&desc); #ifdef CONFIG_FS_NOTIFY notify_open(fullpath, oflags); #endif return OK; errout_with_inode: inode_release(inode); errout_with_search: RELEASE_SEARCH(&desc); return ret; }