Beispiel #1
0
//--------------------------------------------------------------------------------------------------
static tu_UserRef_t GetUserInfo
(
    le_msg_SessionRef_t currentSession,  ///< [IN]  Get the user information for this message
                                         ///<       session.
    bool* wasCreated                     ///< [OUT] Was the user info created for this request?
                                         ///<       Pass NULL if you don't need this.
)
//--------------------------------------------------------------------------------------------------
{
    LE_FATAL_IF(currentSession == NULL, "Bad user message session reference.");

    // Look up the user id of the requesting connection...
    uid_t userId;

    LE_FATAL_IF(le_msg_GetClientUserId(currentSession, &userId) == LE_CLOSED,
                "tu_GetUserInfo must be called within an active connection.");

    // Now that we have a user ID, let's see if we can look them up.
    tu_UserRef_t userRef = GetUser(userId, wasCreated);
    LE_ASSERT(userRef != NULL);

    LE_DEBUG("** Found user <%p>: '%s', %u with default tree, '%s'.",
             userRef,
             userRef->userName,
             userRef->userId,
             userRef->treeName);

    return userRef;
}
Beispiel #2
0
//--------------------------------------------------------------------------------------------------
void cgrp_Init
(
    void
)
{
    // Setup the cgroup root directory if it does not already exist.
    if (!fs_IsMounted(ROOT_NAME, ROOT_PATH))
    {
        LE_FATAL_IF(mount(ROOT_NAME, ROOT_PATH, "tmpfs", 0, NULL) != 0,
                    "Could not mount cgroup root file system.  %m.");
    }

    // Setup a separate cgroup hierarch for each supported subsystem.
    cgrp_SubSys_t subSys = 0;
    for (; subSys < CGRP_NUM_SUBSYSTEMS; subSys++)
    {
        char dir[LIMIT_MAX_PATH_BYTES] = ROOT_PATH;

        LE_ASSERT(le_path_Concat("/", dir, sizeof(dir), SubSysName[subSys], (char*)NULL) == LE_OK);

        LE_ASSERT(le_dir_Make(dir, S_IRWXU) != LE_FAULT);

        if (!fs_IsMounted(SubSysName[subSys], dir))
        {
            LE_FATAL_IF(mount(SubSysName[subSys], dir, "cgroup", 0, SubSysName[subSys]) != 0,
                        "Could not mount cgroup subsystem '%s'.  %m.", SubSysName[subSys]);

            LE_INFO("Mounted cgroup hiearchy for subsystem '%s'.", SubSysName[subSys]);
        }
    }
}
Beispiel #3
0
//--------------------------------------------------------------------------------------------------
void smack_RevokeSubject
(
    const char* subjectLabelPtr     ///< [IN] Subject label.
)
{
    // Open the SMACK revoke file.
    int fd;

    do
    {
        fd = open(SMACK_REVOKE_FILE, O_WRONLY);
    }
    while ( (fd == -1) && (errno == EINTR) );

    LE_FATAL_IF(fd == -1, "Could not open %s.  %m.\n", SMACK_REVOKE_FILE);

    // Write the label to the SMACK revoke file.
    int numBytes = 0;

    do
    {
        numBytes = write(fd, subjectLabelPtr, strlen(subjectLabelPtr));
    }
    while ( (numBytes == -1) && (errno == EINTR) );

    LE_FATAL_IF(numBytes < 0, "Could not revoke SMACK label '%s'.  %m.", subjectLabelPtr);

    fd_Close(fd);

    LE_DEBUG("Revoked SMACK label '%s'.", subjectLabelPtr);
}
Beispiel #4
0
//--------------------------------------------------------------------------------------------------
LE_SHARED void cfgInstall_Add
(
    const char* appName
)
//--------------------------------------------------------------------------------------------------
{
    le_result_t result;

    char filePath[256] = "/opt/legato/apps/";

    result = le_utf8_Append(filePath, appName, sizeof(filePath), NULL);
    LE_FATAL_IF(result != LE_OK, "App name '%s' is too long.", appName);

    result = le_utf8_Append(filePath, "/root.cfg", sizeof(filePath), NULL);
    LE_FATAL_IF(result != LE_OK, "App name '%s' is too long.", appName);

    LE_INFO("Importing configuration for application '%s' from '%s'.", appName, filePath);

    le_cfg_IteratorRef_t i = le_cfg_CreateWriteTxn("/apps");

    result = le_cfgAdmin_ImportTree(i, filePath, appName);

    LE_FATAL_IF(result != LE_OK,
                "Failed to import configuration from '%s' to 'root:/apps/%s' (%s)",
                filePath,
                appName,
                LE_RESULT_TXT(result));

    le_cfg_CommitTxn(i);
}
Beispiel #5
0
//--------------------------------------------------------------------------------------------------
static void CheckLabel
(
    const char* labelPtr            ///< [IN] Label to check.
)
{
    // Check lengths.
    size_t labelSize = strlen(labelPtr);

    LE_FATAL_IF(labelSize == 0, "SMACK label cannot be empty.");

    LE_FATAL_IF(labelSize > LIMIT_MAX_SMACK_LABEL_LEN,
                "SMACK label length, %zd chars, is too long.  Labels must be less than %d chars",
                labelSize, LIMIT_MAX_SMACK_LABEL_LEN);

    // Check for invalid characters.
    LE_FATAL_IF(labelPtr[0] == '-',
                "SMACK label '%s' is invalid because it begins with '-'.", labelPtr);

    int i;
    for (i = 0; i < labelSize; i++)
    {
        char c = labelPtr[i];

        if ( !isprint(c) || !isascii(c) || (c == '/') || (c == '\\') || (c == '\'') || (c == '"') )
        {
            LE_FATAL("SMACK label '%s' contain invalid character(s).", labelPtr);
        }
    }
}
Beispiel #6
0
//--------------------------------------------------------------------------------------------------
event_PerThreadRec_t* fa_event_CreatePerThreadInfo
(
    void
)
{
    event_LinuxPerThreadRec_t* recPtr = le_mem_ForceAlloc(PerThreadPool);

    // Create the epoll file descriptor for this thread.  This will be used to monitor for
    // events on various file descriptors.
    recPtr->epollFd = epoll_create1(0);
    LE_FATAL_IF(recPtr->epollFd < 0, "epoll_create1(0) failed with errno %d.", errno);

    // Open an eventfd for this thread.  This will be uses to signal to the epoll fd that there
    // are Event Reports on the Event Queue.
    recPtr->eventQueueFd = eventfd(0, 0);
    LE_FATAL_IF(recPtr->eventQueueFd < 0, "eventfd() failed with errno %d.", errno);

    // Add the eventfd to the list of file descriptors to wait for using epoll_wait().
    struct epoll_event ev;
    memset(&ev, 0, sizeof(ev));
    ev.events = EPOLLIN | EPOLLWAKEUP;
    ev.data.ptr = NULL;     // This being set to NULL is what tells the main event loop that this
                            // is the Event Queue FD, rather than another FD that is being
                            // monitored.
    if (epoll_ctl(recPtr->epollFd, EPOLL_CTL_ADD, recPtr->eventQueueFd, &ev) == -1)
    {
        LE_FATAL(   "epoll_ctl(ADD) failed for fd %d. errno = %d",
                    recPtr->eventQueueFd,
                    errno);
    }

    return &recPtr->portablePerThreadRec;
}
Beispiel #7
0
//--------------------------------------------------------------------------------------------------
void le_fdMonitor_Enable
(
    le_fdMonitor_Ref_t  monitorRef, ///< [in] Reference to the File Descriptor Monitor object.
    short               events      ///< [in] Bit map of events.
)
//--------------------------------------------------------------------------------------------------
{
    // Look up the File Descriptor Monitor object using the safe reference provided.
    // Note that the safe reference map is shared by all threads in the process, so it
    // must be protected using the mutex.  The File Descriptor Monitor objects, on the other
    // hand, are only allowed to be accessed by the one thread that created them, so it is
    // safe to unlock the mutex after doing the safe reference lookup.
    LOCK
    FdMonitor_t* monitorPtr = le_ref_Lookup(FdMonitorRefMap, monitorRef);
    UNLOCK

    LE_FATAL_IF(monitorPtr == NULL, "File Descriptor Monitor %p doesn't exist!", monitorRef);
    LE_FATAL_IF(thread_GetEventRecPtr() != monitorPtr->threadRecPtr,
                "FD Monitor '%s' (fd %d) is owned by another thread.",
                monitorPtr->name,
                monitorPtr->fd);

    short filteredEvents = events & (POLLIN | POLLOUT | POLLPRI);

    if (filteredEvents != events)
    {
        char textBuff[64];

        LE_WARN("Attempt to enable events that can't be disabled (%s).",
                GetPollEventsText(textBuff, sizeof(textBuff), events & ~filteredEvents));
    }

    uint32_t epollEvents = PollToEPoll(filteredEvents);

    // If the fd doesn't support epoll, we assume it is always ready for read and write.
    // As long as EPOLLIN or EPOLLOUT (or both) is enabled for one of these fds, DispatchToHandler()
    // keeps re-queueing itself to the thread's event queue.  But it will stop doing that if
    // EPOLLIN and EPOLLOUT are both disabled.  So, here is where we get things going again when
    // EPOLLIN or EPOLLOUT is enabled outside DispatchToHandler() for that fd.
    if ( (monitorPtr->isAlwaysReady)
        && (epollEvents & (EPOLLIN | EPOLLOUT))
        && ((monitorPtr->epollEvents & (EPOLLIN | EPOLLOUT)) == 0) )
    {
        // Fetch the pointer to the FD Monitor from thread-specific data.
        // This will be NULL if we are not inside an FD Monitor handler.
        FdMonitor_t* handlerMonitorPtr = pthread_getspecific(FDMonitorPtrKey);

        // If no handler is running or some other fd's handler is running,
        if ((handlerMonitorPtr == NULL) || (handlerMonitorPtr->safeRef == monitorRef))
        {
            // Queue up DispatchToHandler() for this fd.
            fdMon_Report(monitorRef, epollEvents & (EPOLLIN | EPOLLOUT));
        }
    }

    // Bit-wise OR the newly enabled event flags into the FD Monitor's epoll(7) flags set.
    monitorPtr->epollEvents |= epollEvents;

    UpdateEpollFd(monitorPtr);
}
//--------------------------------------------------------------------------------------------------
le_msg_SessionEventHandlerRef_t le_msg_AddServiceCloseHandler
(
    le_msg_ServiceRef_t             serviceRef, ///< [in] Reference to the service.
    le_msg_SessionEventHandler_t    handlerFunc,///< [in] Handler function.
    void*                           contextPtr  ///< [in] Opaque pointer value to pass to handler.
)
//--------------------------------------------------------------------------------------------------
{
    LE_FATAL_IF(serviceRef == NULL,
                "Service doesn't exist. Make sure service is started before setting handlers");
    LE_FATAL_IF(serviceRef->serverThread != le_thread_GetCurrent(),
                "Service (%s:%s) not owned by calling thread.",
                serviceRef->id.name,
                le_msg_GetProtocolIdStr(serviceRef->id.protocolRef));

    // Create the node.
    SessionEventHandler_t* closeEventPtr = le_mem_ForceAlloc(HandlerEventPoolRef);

    // Initialize the node.
    closeEventPtr->handler = handlerFunc;
    closeEventPtr->contextPtr = contextPtr;
    closeEventPtr->link = LE_DLS_LINK_INIT;
    closeEventPtr->listPtr = &serviceRef->closeListPtr;

    // Add the node to the head of the list by passing in the node's link.
    le_dls_Stack(&serviceRef->closeListPtr, &closeEventPtr->link);

    // Need to return a unique reference that will be used by the remove function.
    closeEventPtr->ref = le_ref_CreateRef(HandlersRefMap, &closeEventPtr->link);

    return closeEventPtr->ref;
}
Beispiel #9
0
//--------------------------------------------------------------------------------------------------
void le_fdMonitor_SetDeferrable
(
    le_fdMonitor_Ref_t monitorRef,  ///< [in] Reference to the File Descriptor Monitor object.
    bool               isDeferrable ///< [in] true (deferrable) or false (urgent).
)
//--------------------------------------------------------------------------------------------------
{
    // Look up the File Descriptor Monitor object using the safe reference provided.
    // Note that the safe reference map is shared by all threads in the process, so it
    // must be protected using the mutex.  The File Descriptor Monitor objects, on the other
    // hand, are only allowed to be accessed by the one thread that created them, so it is
    // safe to unlock the mutex after doing the safe reference lookup.
    LOCK
    FdMonitor_t* monitorPtr = le_ref_Lookup(FdMonitorRefMap, monitorRef);
    UNLOCK

    LE_FATAL_IF(monitorPtr == NULL, "File Descriptor Monitor %p doesn't exist!", monitorRef);
    LE_FATAL_IF(thread_GetEventRecPtr() != monitorPtr->threadRecPtr,
                "FD Monitor '%s' (fd %d) is owned by another thread.",
                monitorPtr->name,
                monitorPtr->fd);

    // Set/clear the EPOLLWAKEUP flag in the FD Monitor's epoll(7) flags set.
    if (isDeferrable)
    {
        monitorPtr->epollEvents &= ~EPOLLWAKEUP;
    }
    else
    {
        monitorPtr->epollEvents |= EPOLLWAKEUP;
    }

    UpdateEpollFd(monitorPtr);
}
//--------------------------------------------------------------------------------------------------
void le_msg_AdvertiseService
(
    le_msg_ServiceRef_t serviceRef  ///< [in] Reference to the service.
)
//--------------------------------------------------------------------------------------------------
{
    LE_FATAL_IF(serviceRef->state != LE_MSG_SERVICE_HIDDEN,
                "Re-advertising before hiding service '%s:%s'.",
                serviceRef->id.name,
                le_msg_GetProtocolIdStr(serviceRef->id.protocolRef));

    serviceRef->state = LE_MSG_SERVICE_CONNECTING;

    // Open a socket.
    int fd = unixSocket_CreateSeqPacketUnnamed();
    serviceRef->directorySocketFd = fd;

    // Check for failure.
    LE_FATAL_IF(fd == LE_NOT_PERMITTED, "Permission to open socket denied.");
    LE_FATAL_IF(fd == LE_FAULT, "Failed to open socket.");

    // Warn if one of the three standard I/O streams have been somehow connected to the
    // Service Directory.
    if (fd < 3)
    {
        const char* streamNameStr;
        switch (fd)
        {
            case 0:
                streamNameStr = "stdin";
                break;
            case 1:
                streamNameStr = "stdout";
                break;
            case 2:
                streamNameStr = "stderr";
                break;
        }
        LE_WARN("Service Directory connection mapped to %s.", streamNameStr);
    }

    // Set the socket non-blocking.
    fd_SetNonBlocking(fd);

    // Start monitoring the socket for events.
    StartMonitoringDirectorySocket(serviceRef);

    // Connect the socket to the Service Directory.
    le_result_t result = unixSocket_Connect(fd, LE_SVCDIR_SERVER_SOCKET_NAME);
    LE_FATAL_IF((result != LE_OK) && (result != LE_WOULD_BLOCK),
                "Failed to connect to Service Directory. Result = %d (%s).",
                result,
                LE_RESULT_TXT(result));

    // Wait for writeability notification on the socket.  See DirectorySocketWriteable().
}
Beispiel #11
0
//--------------------------------------------------------------------------------------------------
void le_msg_AdvertiseService
(
    le_msg_ServiceRef_t serviceRef  ///< [in] Reference to the service.
)
//--------------------------------------------------------------------------------------------------
{
    // Open a socket and connect it to the Service Directory.
    int fd = unixSocket_CreateSeqPacketUnnamed();

    // Check for failure.
    LE_FATAL_IF(fd == LE_NOT_PERMITTED, "Permission to open socket denied.");
    LE_FATAL_IF(fd == LE_FAULT, "Failed to open socket.");

    // Warn if one of the three standard I/O streams have been somehow connected to the
    // Service Directory.
    if (fd < 3)
    {
        const char* streamNameStr;
        switch (fd)
        {
            case 0:
                streamNameStr = "stdin";
                break;
            case 1:
                streamNameStr = "stdout";
                break;
            case 2:
                streamNameStr = "stderr";
                break;
        }
        LE_WARN("Service Directory connection mapped to %s.", streamNameStr);
    }

    le_result_t result = unixSocket_Connect(fd, LE_SVCDIR_SERVER_SOCKET_NAME);
    LE_FATAL_IF(result != LE_OK,
                "Failed to connect to Service Directory. Result = %d (%s).",
                result,
                LE_RESULT_TXT(result));

    serviceRef->directorySocketFd = fd;

    // Set the socket non-blocking.
    fd_SetNonBlocking(fd);

    // Start monitoring the socket for events.
    StartMonitoringDirectorySocket(serviceRef);

    // Send the Service ID to the Service Directory.
    msgService_SendServiceId(serviceRef, fd);

    // Wait for the Service Directory to respond by either dropping the connection
    // (meaning that we have been denied permission to offer this service) or by
    // forwarding us file descriptors for authenticated client connections.
}
Beispiel #12
0
//--------------------------------------------------------------------------------------------------
static void CheckFor
(
    appCfg_Iter_t iterRef,
    IterType_t type
)
{
    LE_FATAL_IF(iterRef == NULL, "Iterator reference can not be NULL.");
    LE_FATAL_IF(iterRef->type != type,
                "Expected %s, but received %s instead.",
                TypeToStr(type),
                TypeToStr(iterRef->type));
}
Beispiel #13
0
//--------------------------------------------------------------------------------------------------
bool smack_HasAccess
(
    const char* subjectLabelPtr,    ///< [IN] Subject label.
    const char* accessModePtr,      ///< [IN] Access mode.
    const char* objectLabelPtr      ///< [IN] Object label.
)
{
    CheckLabel(subjectLabelPtr);
    CheckLabel(objectLabelPtr);

    // Create the SMACK rule.
    char rule[SMACK_RULE_STR_BYTES];
    MakeRuleStr(subjectLabelPtr, accessModePtr, objectLabelPtr, rule, sizeof(rule));

    // Open the SMACK access file.
    int fd;

    do
    {
        fd = open(SMACK_ACCESS_FILE, O_RDWR);
    }
    while ( (fd == -1) && (errno == EINTR) );

    LE_FATAL_IF(fd == -1, "Could not open %s.  %m.\n", SMACK_ACCESS_FILE);

    // Write the rule to the SMACK access file.
    int numBytes = 0;

    do
    {
        numBytes = write(fd, rule, sizeof(rule)-1);
    }
    while ( (numBytes == -1) && (errno == EINTR) );

    LE_FATAL_IF(numBytes < 0, "Could not write SMACK rule '%s'.  %m.", rule);

    // Read the SMACK access file to see if access would be granted.
    char a;
    do
    {
        numBytes = read(fd, &a, 1);
    }
    while ( (numBytes == -1) && (errno == EINTR) );

    LE_FATAL_IF(numBytes <= 0, "Could not read '%s'.  %m.", SMACK_ACCESS_FILE);

    fd_Close(fd);

    return (a == '1');
}
Beispiel #14
0
//--------------------------------------------------------------------------------------------------
le_event_FdHandlerRef_t le_event_SetFdHandler
(
    le_event_FdMonitorRef_t  monitorRef, ///< [in] Reference to the File Descriptor Monitor object.
    le_event_FdEventType_t   eventType,  ///< [in] The type of event to be reported to this handler.
    le_event_FdHandlerFunc_t handlerFunc ///< [in] The handler function.
)
//--------------------------------------------------------------------------------------------------
{
    LE_ASSERT(handlerFunc != NULL);

    // Look up the File Descriptor Monitor object using the safe reference provided.
    // Note that the safe reference map is shared by all threads in the process, so it
    // must be protected using the mutex.  The File Descriptor Monitor objects, on the other
    // hand, are only allowed to be accessed by the one thread that created them, so it is
    // safe to unlock the mutex after doing the safe reference lookup.
    LOCK
    FdMonitor_t* monitorPtr = le_ref_Lookup(FdMonitorRefMap, monitorRef);
    UNLOCK

    LE_FATAL_IF(monitorPtr == NULL, "File Descriptor Monitor %p doesn't exist!", monitorRef);
    LE_FATAL_IF(thread_GetEventRecPtr() != monitorPtr->threadRecPtr,
                "FD Monitor '%s' (fd %d) is owned by another thread.",
                monitorPtr->name,
                monitorPtr->fd);

    // Get a pointer to the Handler object in the appropriate spot for this type of event in the
    // FD Monitor's array of handlers.
    Handler_t* handlerPtr = &(monitorPtr->handlerArray[eventType]);

    // Double check that no one has tried setting this handler yet.
    LE_FATAL_IF(handlerPtr->handlerFunc != NULL,
                "FD handler already set for event '%s' on FD Monitor '%s' (fd %d).",
                GetFdEventTypeName(eventType),
                monitorPtr->name,
                monitorPtr->fd);

    // Initialize the Handler object.
    handlerPtr->handlerFunc = handlerFunc;
    handlerPtr->contextPtr = NULL;
    handlerPtr->monitorPtr = monitorPtr;
    LOCK
    handlerPtr->safeRef = le_ref_CreateRef(HandlerRefMap, handlerPtr);
    UNLOCK

    // Enable the monitoring of this event.
    EnableFdMonitoring(monitorPtr, eventType);

    return handlerPtr->safeRef;
}
//--------------------------------------------------------------------------------------------------
void le_msg_DeleteService
(
    le_msg_ServiceRef_t             serviceRef  ///< [in] Reference to the service.
)
//--------------------------------------------------------------------------------------------------
{
    LE_FATAL_IF(serviceRef->serverThread != le_thread_GetCurrent(),
                "Attempted to delete service (%s:%s) not owned by thread.",
                serviceRef->id.name,
                le_msg_GetProtocolIdStr(serviceRef->id.protocolRef));

    // If the service is still advertised, hide it.
    le_msg_HideService(serviceRef);

    // Close any remaining open sessions.
    CloseAllSessions(serviceRef);

    // NOTE: Lock the mutex here to prevent a race between this thread dropping ownership
    // of the service and another thread trying to offer the same service.  This is very
    // unlikely to ever happen, but just in case, make sure it fails with a sensible
    // ("duplicate") log message, instead of just quietly messing up the hashmap or something.
    LOCK

    // Clear out the server thread reference.
    serviceRef->serverThread = NULL;

    // Release the server's hold on the object.
    le_mem_Release(serviceRef);

    UNLOCK
}
Beispiel #16
0
//--------------------------------------------------------------------------------------------------
void TriggerCallbackTestRespond
(
    ServerCmdRef_t _cmdRef
)
{
    LE_ASSERT(_cmdRef != NULL);

    // Get the message related data
    le_msg_MessageRef_t _msgRef = (le_msg_MessageRef_t)_cmdRef;
    _Message_t* _msgPtr = le_msg_GetPayloadPtr(_msgRef);
    __attribute__((unused)) uint8_t* _msgBufPtr = _msgPtr->buffer;

    // Ensure the passed in msgRef is for the correct message
    LE_ASSERT(_msgPtr->id == _MSGID_TriggerCallbackTest);

    // Ensure that this Respond function has not already been called
    LE_FATAL_IF( !le_msg_NeedsResponse(_msgRef), "Response has already been sent");


    // Pack any "out" parameters


    // Return the response
    LE_DEBUG("Sending response to client session %p", le_msg_GetSession(_msgRef));
    le_msg_Respond(_msgRef);
}
Beispiel #17
0
//--------------------------------------------------------------------------------------------------
void atmachinestring_AddInList
(
    le_dls_List_t *list,          ///< List of atmachinestring_t
    const char   **patternListPtr ///< List of pattern
)
{
    uint32_t i = 0;

    if (!patternListPtr) {
        return;
    }

    while(patternListPtr[i] != NULL) {
        atmachinestring_t* newStringPtr = le_mem_ForceAlloc(AtStringPool);

        LE_FATAL_IF(
            (strlen(patternListPtr[i])>ATSTRING_SIZE),
                    "%s is too long (%zd): Max size %d",
                    patternListPtr[i],strlen(patternListPtr[i]),ATSTRING_SIZE);

        strncpy(newStringPtr->line,patternListPtr[i],ATSTRING_SIZE);
        newStringPtr->line[ATSTRING_SIZE-1]='\0';

        newStringPtr->link = LE_DLS_LINK_INIT;
        le_dls_Queue(list,&(newStringPtr->link));
        i++;
    }
}
Beispiel #18
0
//--------------------------------------------------------------------------------------------------
void le_sem_Wait
(
    le_sem_Ref_t    semaphorePtr   ///< [IN] Pointer to the semaphore
)
{
//     TODO: Implement this:
//     if (semaphorePtr->isTraceable)
//     {
//     }
//     else
    {
        int result;

        sem_ThreadRec_t* perThreadRecPtr = thread_GetSemaphoreRecPtr();

        ListOfSemaphoresChgCnt++;
        perThreadRecPtr->waitingOnSemaphore = semaphorePtr;
        AddToWaitingList(semaphorePtr, perThreadRecPtr);

        result = sem_wait(&semaphorePtr->semaphore);

        RemoveFromWaitingList(semaphorePtr, perThreadRecPtr);
        ListOfSemaphoresChgCnt++;
        perThreadRecPtr->waitingOnSemaphore = NULL;

        LE_FATAL_IF( (result!=0), "Thread '%s' failed to wait on semaphore '%s'. Error code %d (%m).",
                    le_thread_GetMyName(),
                    semaphorePtr->nameStr,
                    result);
    }
}
Beispiel #19
0
//--------------------------------------------------------------------------------------------------
static pid_t GetTasksId
(
    int fd                      ///< [IN] File descriptor to an opened procs or tasks file.
)
{
    // Read a pid from the file.
    pid_t pid;
    char pidStr[100];
    le_result_t result = fd_ReadLine(fd, pidStr, sizeof(pidStr));

    LE_FATAL_IF(result == LE_OVERFLOW, "Buffer to read PID is too small.");

    if (result == LE_OK)
    {
        // Convert the string to a pid and store it in the caller's buffer.
        le_result_t r = le_utf8_ParseInt(&pid, pidStr);

        if (r == LE_OK)
        {
            return pid;
        }

        LE_ERROR("Could not convert '%s' to a PID.  %s.", pidStr, LE_RESULT_TXT(r));
        result = LE_FAULT;
    }

    return result;
}
Beispiel #20
0
//--------------------------------------------------------------------------------------------------
void allParametersRespond
(
    ServerCmdRef_t _cmdRef,
    uint32_t b,
    size_t outputNumElements,
    uint32_t* outputPtr,
    char* response,
    char* more
)
{
    LE_ASSERT(_cmdRef != NULL);

    // Get the message related data
    le_msg_MessageRef_t _msgRef = (le_msg_MessageRef_t)_cmdRef;
    _Message_t* _msgPtr = le_msg_GetPayloadPtr(_msgRef);
    __attribute__((unused)) uint8_t* _msgBufPtr = _msgPtr->buffer;

    // Ensure the passed in msgRef is for the correct message
    LE_ASSERT(_msgPtr->id == _MSGID_allParameters);

    // Ensure that this Respond function has not already been called
    LE_FATAL_IF( !le_msg_NeedsResponse(_msgRef), "Response has already been sent");


    // Pack any "out" parameters
    _msgBufPtr = PackData( _msgBufPtr, &b, sizeof(uint32_t) );
    _msgBufPtr = PackData( _msgBufPtr, &outputNumElements, sizeof(size_t) );
    _msgBufPtr = PackData( _msgBufPtr, outputPtr, outputNumElements*sizeof(uint32_t) );
    _msgBufPtr = PackString( _msgBufPtr, response );
    _msgBufPtr = PackString( _msgBufPtr, more );

    // Return the response
    LE_DEBUG("Sending response to client session %p", le_msg_GetSession(_msgRef));
    le_msg_Respond(_msgRef);
}
//--------------------------------------------------------------------------------------------------
le_msg_ServiceRef_t le_msg_CreateService
(
    le_msg_ProtocolRef_t    protocolRef,    ///< [in] Reference to the protocol to be used.
    const char*             serviceName     ///< [in] The service instance name.
)
//--------------------------------------------------------------------------------------------------
{
    // Must lock the mutex to prevent races between different threads trying to offer the
    // same service at the same time, or one thread trying to delete a service while another
    // tries to create it, or accessing the Service List hashmap while another thread
    // is updating it.

    LOCK

    // Get a Service object.
    Service_t* servicePtr = GetService(protocolRef, serviceName);

    // If the Service object already has a server thread, then it means that this service
    // is already being offered by someone else in this very process.
    LE_FATAL_IF(servicePtr->serverThread != NULL,
                "Duplicate service (%s:%s) offered in same process.",
                serviceName,
                le_msg_GetProtocolIdStr(protocolRef));

    servicePtr->serverThread = le_thread_GetCurrent();

    UNLOCK

    return servicePtr;
}
//--------------------------------------------------------------------------------------------------
static Service_t* GetService
(
    le_msg_ProtocolRef_t    protocolRef,
    const char*             serviceName
)
//--------------------------------------------------------------------------------------------------
{
    ServiceId_t id;

    id.protocolRef = protocolRef;
    LE_FATAL_IF(le_utf8_Copy(id.name, serviceName, sizeof(id.name), NULL) == LE_OVERFLOW,
                "Service ID '%s' too long (should only be %zu bytes total).",
                serviceName,
                sizeof(id.name));

    Service_t* servicePtr = le_hashmap_Get(ServiceMapRef, &id);
    if (servicePtr == NULL)
    {
        servicePtr = CreateService(protocolRef, serviceName);
    }
    else
    {
        le_mem_AddRef(servicePtr);
    }

    return servicePtr;
}
//--------------------------------------------------------------------------------------------------
void userAddRemove_Add
(
    const char* appName
)
//--------------------------------------------------------------------------------------------------
{
    le_result_t result;
    uid_t uid;
    gid_t gid;

    char userName[256] = "app";

    result = le_utf8_Append(userName, appName, sizeof(userName), NULL);
    LE_FATAL_IF(result != LE_OK, "App name '%s' is too long.", appName);

    LE_INFO("Creating user '%s' for application '%s'.", userName, appName);

    // Start a read transaction and go to node /apps/app-name
    le_cfg_ConnectService();
    le_cfg_IteratorRef_t i = le_cfg_CreateReadTxn("/apps");
    le_cfg_GoToNode(i, appName);

    // If the node doesn't exist, bail out.
    if (!le_cfg_NodeExists(i, ""))
    {
        fprintf(stderr, "** ERROR: App '%s' doesn't exist in the system configuration.\n", appName);
    }
    else
    {
        result = user_Create(userName, &uid, &gid);

        if (result == LE_OK)
        {
            printf("Created user '%s' (uid %u, gid %u).\n", userName, uid, gid);

            // TODO: Groups configuration.

            le_cfg_CancelTxn(i);

            exit(EXIT_SUCCESS);
        }
        else if (result == LE_DUPLICATE)
        {
            // TODO: Verify correct groups configuration.

            printf("User '%s' already exists (uid %u, gid %u).\n", userName, uid, gid);

            le_cfg_CancelTxn(i);

            exit(EXIT_SUCCESS);
        }
        else
        {
            fprintf(stderr, "** ERROR: user_Create() failed for user '%s'.\n", userName);
        }
    }

    le_cfg_CancelTxn(i);
    exit(EXIT_FAILURE);
}
Beispiel #24
0
//--------------------------------------------------------------------------------------------------
void le_mem_DeleteSubPool
(
    le_mem_PoolRef_t    subPool     ///< [IN] The sub-pool to be deleted.
)
{
    LE_ASSERT(subPool != NULL);

    Lock();

    // Make sure all sub-pool objects are free.
    le_mem_PoolRef_t superPool = subPool->superPoolPtr;

    LE_FATAL_IF(subPool->numBlocksInUse != 0,
                "Subpool '%s' deleted while %zu blocks remain allocated.",
                subPool->name,
                subPool->numBlocksInUse);

    size_t numBlocks = subPool->totalBlocks;

    // Move the blocks from the subPool back to the superpool.
    MoveBlocks(superPool, subPool, numBlocks);

    // Update the superPool's block use count.
    superPool->numBlocksInUse -= numBlocks;

    // Remove the sub-pool from the list of sub-pools.
    ListOfPoolsChgCnt++;
    le_dls_Remove(&ListOfPools, &(subPool->poolLink));

    Unlock();

    // Release the sub-pool.
    le_mem_Release(subPool);
}
Beispiel #25
0
//--------------------------------------------------------------------------------------------------
le_avdata_AssetInstanceRef_t le_avdata_Create
(
    const char* assetName
        ///< [IN]
)
{
    // Get the client's credentials.
    pid_t pid;
    uid_t uid;

    if (le_msg_GetClientUserCreds(le_avdata_GetClientSessionRef(), &uid, &pid) != LE_OK)
    {
        LE_KILL_CLIENT("Could not get credentials for the client.");
        return NULL;
    }


    // Look up the process's application name.
    char appName[LE_LIMIT_APP_NAME_LEN+1];

    le_result_t result = le_appInfo_GetName(pid, appName, sizeof(appName));
    LE_FATAL_IF(result == LE_OVERFLOW, "Buffer too small to contain the application name.");

    // TODO: Should this be LE_KILL_CLIENT instead?
    LE_FATAL_IF(result != LE_OK, "Could not get app name");


    // Create an instance of the asset
    assetData_InstanceDataRef_t instRef;
    int instanceId;

    LE_ASSERT( assetData_CreateInstanceByName(appName, assetName, -1, &instRef) == LE_OK );
    LE_ASSERT( instRef != NULL );
    LE_ASSERT( assetData_GetInstanceId(instRef, &instanceId) == LE_OK );
    LE_PRINT_VALUE("%i", instanceId);

    // Return a safe reference for the instance
    InstanceRefData_t* instRefDataPtr = le_mem_ForceAlloc(InstanceRefDataPoolRef);

    instRefDataPtr->clientSessionRef = le_avdata_GetClientSessionRef();
    instRefDataPtr->instRef = instRef;

    instRef = le_ref_CreateRef(InstanceRefMap, instRefDataPtr);

    return instRef;
}
Beispiel #26
0
//--------------------------------------------------------------------------------------------------
void aus_RegisterFieldEventHandlers
(
    const char* appNamePtr,                              ///< Namespace for the object.
    int objectId,                                        ///< The Id of the object.
    assetData_AssetActionHandlerFunc_t assetHandlerPtr,  ///< Handler for object level events.
    const int* monitorFields,                            ///< List of fields to monitor.
    size_t monFieldCount,                                ///< Size of the field list.
    assetData_FieldActionHandlerFunc_t fieldHandlerPtr   ///< Handler to be called for field
                                                         ///<   activity.
)
//--------------------------------------------------------------------------------------------------
{
    assetData_AssetDataRef_t assetRef = NULL;

    LE_DEBUG("Registering on %s/%d.", appNamePtr, objectId);

    LE_FATAL_IF(assetData_GetAssetRefById(appNamePtr, objectId, &assetRef) != LE_OK,
                "Could not reference object %s/%d data.",
                appNamePtr,
                objectId);

    if (assetHandlerPtr != NULL)
    {
        LE_DEBUG("Registering AssetActionHandler");

        LE_FATAL_IF(assetData_client_AddAssetActionHandler(assetRef,
                                                           assetHandlerPtr,
                                                           NULL) == NULL,
                    "Could not register for instance activity on %s/%d.",
                    appNamePtr,
                    objectId);
    }

    for (size_t i = 0; i < monFieldCount; i++)
    {
        LE_DEBUG("Registering %s/%d/%d field handler.", appNamePtr, objectId, monitorFields[i]);

        LE_FATAL_IF(assetData_client_AddFieldActionHandler(assetRef,
                                                           monitorFields[i],
                                                           fieldHandlerPtr,
                                                           NULL) == NULL,
                    "Could not register for object %s/%d field activity.",
                    appNamePtr,
                    objectId);
    }
}
Beispiel #27
0
//--------------------------------------------------------------------------------------------------
static void LoadIpcBindingConfig
(
    void
)
{

    // Fork a process.
    pid_t pid = fork();
    LE_FATAL_IF(pid < 0, "Failed to fork child process.  %m.");

    if (pid == 0)
    {
        // Launch the child program.  This should not return unless there was an error.
        execlp("sdir", "sdir", "load", (char*)NULL);
        // The program could not be started.
        LE_FATAL("'sdir' could not be started: %m");
    }

    int status;
    pid_t p;

    do
    {
        p = waitpid(pid, &status, 0);
    }
    while((p == -1) && (errno == EINTR));

    if (p != pid)
    {
        if (p == -1)
        {
            LE_FATAL("waitpid() failed: %m");
        }
        else
        {
            LE_FATAL("waitpid() returned unexpected result %d", p);
        }
    }

    if (WIFSIGNALED(status))
    {
        LE_FATAL("Couldn't load IPC binding config. `sdir load` received signal: %d.",
            WTERMSIG(status));
    }
    else if (WIFEXITED(status))
    {
        if (WEXITSTATUS(status) != EXIT_SUCCESS)
        {
            LE_FATAL("Couldn't load IPC binding config. `sdir load` exited with code: %d.",
                WEXITSTATUS(status));
        }
    }
    else
    {
        LE_FATAL("Couldn't load IPC binding config. `sdir load` failed for an unknown reason (status = %d).",
            status);
    }
}
Beispiel #28
0
//--------------------------------------------------------------------------------------------------
void le_event_ClearFdHandlerByEventType
(
    le_event_FdMonitorRef_t  monitorRef, ///< [in] Reference to the File Descriptor Monitor object.
    le_event_FdEventType_t   eventType   ///< [in] The type of event to clear the handler for.
)
//--------------------------------------------------------------------------------------------------
{
    LE_ASSERT(eventType < LE_EVENT_NUM_FD_EVENT_TYPES);

    // Look up the File Descriptor Monitor object using the safe reference provided.
    // Note that the safe reference map is shared by all threads in the process, so it
    // must be protected using the mutex.  The File Descriptor Monitor objects, on the other
    // hand, are only allowed to be accessed by the one thread that created them, so it is
    // safe to unlock the mutex after doing the safe reference lookup.
    LOCK
    FdMonitor_t* monitorPtr = le_ref_Lookup(FdMonitorRefMap, monitorRef);
    UNLOCK

    LE_FATAL_IF(monitorPtr == NULL, "File Descriptor Monitor %p doesn't exist!", monitorRef);
    LE_FATAL_IF(thread_GetEventRecPtr() != monitorPtr->threadRecPtr,
                "FD Monitor '%s' (fd %d) is owned by another thread.",
                monitorPtr->name,
                monitorPtr->fd);

    // Get a pointer to the Handler object in the appropriate spot for this type of event in the
    // FD Monitor's array of handlers.
    Handler_t* handlerPtr = &(monitorPtr->handlerArray[eventType]);

    LE_CRIT_IF(handlerPtr->handlerFunc == NULL,
               "Handler cleared when not set for FD Monitor '%s' (fd %d), event type %d.",
               monitorPtr->name,
               monitorPtr->fd,
               eventType);

    // Clear the Handler object.
    handlerPtr->handlerFunc = NULL;
    handlerPtr->contextPtr = NULL;
    LOCK
    le_ref_DeleteRef(HandlerRefMap, handlerPtr->safeRef);
    UNLOCK
    handlerPtr->safeRef = NULL;

    // Disable the monitoring of this event.
    DisableFdMonitoring(monitorPtr, eventType);
}
Beispiel #29
0
//--------------------------------------------------------------------------------------------------
const char* properties_GetValue
(
    properties_Iter_Ref_t iteratorRef       ///< [IN] Reference to the iterator.
)
{
    LE_FATAL_IF(!HasValidKeyValue(iteratorRef), "Iterator does not contain a valid key-value.");

    return (const char*)iteratorRef->valuePtr;
}
Beispiel #30
0
//--------------------------------------------------------------------------------------------------
static void ConfigureSensorGpio
(
    void
)
{
    // Configure IoT1_GPIO1 as input and set its initial value as high
    LE_FATAL_IF(le_sensorGpio_SetInput(LE_SENSORGPIO_ACTIVE_HIGH) != LE_OK,
                "Couldn't configure cf3 gpio as default input high");
}