| /* |
| * 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. |
| */ |
| |
| #include "config.h" |
| |
| #include "error.h" |
| |
| #include <errno.h> |
| #include <stdlib.h> |
| #include <string.h> |
| |
| #ifdef HAVE_LIBPTHREAD |
| #include <pthread.h> |
| #endif |
| |
| /* |
| * Error strings |
| */ |
| |
| const char* __GUAC_STATUS_SUCCESS_STR = "Success"; |
| const char* __GUAC_STATUS_NO_MEMORY_STR = "Insufficient memory"; |
| const char* __GUAC_STATUS_CLOSED_STR = "Closed"; |
| const char* __GUAC_STATUS_TIMEOUT_STR = "Timed out"; |
| const char* __GUAC_STATUS_IO_ERROR_STR = "Input/output error"; |
| const char* __GUAC_STATUS_INVALID_ARGUMENT_STR = "Invalid argument"; |
| const char* __GUAC_STATUS_INTERNAL_ERROR_STR = "Internal error"; |
| const char* __GUAC_STATUS_UNKNOWN_STATUS_STR = "UNKNOWN STATUS CODE"; |
| const char* __GUAC_STATUS_NO_SPACE_STR = "Insufficient space"; |
| const char* __GUAC_STATUS_INPUT_TOO_LARGE_STR = "Input too large"; |
| const char* __GUAC_STATUS_RESULT_TOO_LARGE_STR = "Result too large"; |
| const char* __GUAC_STATUS_PERMISSION_DENIED_STR = "Permission denied"; |
| const char* __GUAC_STATUS_BUSY_STR = "Resource busy"; |
| const char* __GUAC_STATUS_NOT_AVAILABLE_STR = "Resource not available"; |
| const char* __GUAC_STATUS_NOT_SUPPORTED_STR = "Not supported"; |
| const char* __GUAC_STATUS_NOT_INPLEMENTED_STR = "Not implemented"; |
| const char* __GUAC_STATUS_TRY_AGAIN_STR = "Temporary failure"; |
| const char* __GUAC_STATUS_PROTOCOL_ERROR_STR = "Protocol violation"; |
| const char* __GUAC_STATUS_NOT_FOUND_STR = "Not found"; |
| const char* __GUAC_STATUS_CANCELED_STR = "Canceled"; |
| const char* __GUAC_STATUS_OUT_OF_RANGE_STR = "Value out of range"; |
| const char* __GUAC_STATUS_REFUSED_STR = "Operation refused"; |
| const char* __GUAC_STATUS_TOO_MANY_STR = "Insufficient resources"; |
| const char* __GUAC_STATUS_WOULD_BLOCK_STR = "Operation would block"; |
| |
| const char* guac_status_string(guac_status status) { |
| |
| switch (status) { |
| |
| /* No error */ |
| case GUAC_STATUS_SUCCESS: |
| return __GUAC_STATUS_SUCCESS_STR; |
| |
| /* Out of memory */ |
| case GUAC_STATUS_NO_MEMORY: |
| return __GUAC_STATUS_NO_MEMORY_STR; |
| |
| /* End of stream */ |
| case GUAC_STATUS_CLOSED: |
| return __GUAC_STATUS_CLOSED_STR; |
| |
| /* Timeout */ |
| case GUAC_STATUS_TIMEOUT: |
| return __GUAC_STATUS_TIMEOUT_STR; |
| |
| /* Further information in errno */ |
| case GUAC_STATUS_SEE_ERRNO: |
| return strerror(errno); |
| |
| /* Input/output error */ |
| case GUAC_STATUS_IO_ERROR: |
| return __GUAC_STATUS_IO_ERROR_STR; |
| |
| /* Invalid argument */ |
| case GUAC_STATUS_INVALID_ARGUMENT: |
| return __GUAC_STATUS_INVALID_ARGUMENT_STR; |
| |
| /* Internal error */ |
| case GUAC_STATUS_INTERNAL_ERROR: |
| return __GUAC_STATUS_INTERNAL_ERROR_STR; |
| |
| /* Out of space */ |
| case GUAC_STATUS_NO_SPACE: |
| return __GUAC_STATUS_NO_SPACE_STR; |
| |
| /* Input too large */ |
| case GUAC_STATUS_INPUT_TOO_LARGE: |
| return __GUAC_STATUS_INPUT_TOO_LARGE_STR; |
| |
| /* Result too large */ |
| case GUAC_STATUS_RESULT_TOO_LARGE: |
| return __GUAC_STATUS_RESULT_TOO_LARGE_STR; |
| |
| /* Permission denied */ |
| case GUAC_STATUS_PERMISSION_DENIED: |
| return __GUAC_STATUS_PERMISSION_DENIED_STR; |
| |
| /* Resource is busy */ |
| case GUAC_STATUS_BUSY: |
| return __GUAC_STATUS_BUSY_STR; |
| |
| /* Resource not available */ |
| case GUAC_STATUS_NOT_AVAILABLE: |
| return __GUAC_STATUS_NOT_AVAILABLE_STR; |
| |
| /* Not supported */ |
| case GUAC_STATUS_NOT_SUPPORTED: |
| return __GUAC_STATUS_NOT_SUPPORTED_STR; |
| |
| /* Not implemented */ |
| case GUAC_STATUS_NOT_INPLEMENTED: |
| return __GUAC_STATUS_NOT_INPLEMENTED_STR; |
| |
| /* Temporary failure */ |
| case GUAC_STATUS_TRY_AGAIN: |
| return __GUAC_STATUS_TRY_AGAIN_STR; |
| |
| /* Guacamole protocol error */ |
| case GUAC_STATUS_PROTOCOL_ERROR: |
| return __GUAC_STATUS_PROTOCOL_ERROR_STR; |
| |
| /* Resource not found */ |
| case GUAC_STATUS_NOT_FOUND: |
| return __GUAC_STATUS_NOT_FOUND_STR; |
| |
| /* Operation canceled */ |
| case GUAC_STATUS_CANCELED: |
| return __GUAC_STATUS_CANCELED_STR; |
| |
| /* Value out of range */ |
| case GUAC_STATUS_OUT_OF_RANGE: |
| return __GUAC_STATUS_OUT_OF_RANGE_STR; |
| |
| /* Operation refused */ |
| case GUAC_STATUS_REFUSED: |
| return __GUAC_STATUS_REFUSED_STR; |
| |
| /* Too many resource in use */ |
| case GUAC_STATUS_TOO_MANY: |
| return __GUAC_STATUS_TOO_MANY_STR; |
| |
| /* Operation would block */ |
| case GUAC_STATUS_WOULD_BLOCK: |
| return __GUAC_STATUS_WOULD_BLOCK_STR; |
| |
| /* Unknown status code */ |
| default: |
| return __GUAC_STATUS_UNKNOWN_STATUS_STR; |
| |
| } |
| |
| } |
| |
| #ifdef HAVE_LIBPTHREAD |
| |
| /* PThread implementation of __guac_error */ |
| |
| static pthread_key_t __guac_error_key; |
| static pthread_once_t __guac_error_key_init = PTHREAD_ONCE_INIT; |
| |
| static pthread_key_t __guac_error_message_key; |
| static pthread_once_t __guac_error_message_key_init = PTHREAD_ONCE_INIT; |
| |
| static void __guac_free_pointer(void* pointer) { |
| |
| /* Free memory allocated to status variable */ |
| free(pointer); |
| |
| } |
| |
| static void __guac_alloc_error_key() { |
| |
| /* Create key, destroy any allocated variable on thread exit */ |
| pthread_key_create(&__guac_error_key, __guac_free_pointer); |
| |
| } |
| |
| static void __guac_alloc_error_message_key() { |
| |
| /* Create key, destroy any allocated variable on thread exit */ |
| pthread_key_create(&__guac_error_message_key, __guac_free_pointer); |
| |
| } |
| |
| guac_status* __guac_error() { |
| |
| /* Pointer for thread-local data */ |
| guac_status* status; |
| |
| /* Init error key, if not already initialized */ |
| pthread_once(&__guac_error_key_init, __guac_alloc_error_key); |
| |
| /* Retrieve thread-local status variable */ |
| status = (guac_status*) pthread_getspecific(__guac_error_key); |
| |
| /* Allocate thread-local status variable if not already allocated */ |
| if (status == NULL) { |
| status = malloc(sizeof(guac_status)); |
| pthread_setspecific(__guac_error_key, status); |
| } |
| |
| return status; |
| |
| } |
| |
| const char** __guac_error_message() { |
| |
| /* Pointer for thread-local data */ |
| const char** message; |
| |
| /* Init error message key, if not already initialized */ |
| pthread_once( |
| &__guac_error_message_key_init, |
| __guac_alloc_error_message_key |
| ); |
| |
| /* Retrieve thread-local message variable */ |
| message = (const char**) pthread_getspecific(__guac_error_message_key); |
| |
| /* Allocate thread-local message variable if not already allocated */ |
| if (message == NULL) { |
| message = malloc(sizeof(const char*)); |
| pthread_setspecific(__guac_error_message_key, message); |
| } |
| |
| return message; |
| |
| } |
| |
| #else |
| |
| /* Default (not-threadsafe) implementation */ |
| static guac_status __guac_error_unsafe_storage; |
| static const char** __guac_error_message_unsafe_storage; |
| |
| guac_status* __guac_error() { |
| return &__guac_error_unsafe_storage; |
| } |
| |
| const char** __guac_error_message() { |
| return &__guac_error_message_unsafe_storage; |
| } |
| |
| /* Warn about threadsafety */ |
| #warn No threadsafe implementation of __guac_error exists for your platform, so a default non-threadsafe implementation has been used instead. This may lead to incorrect status codes being reported for failures. Please consider adding support for your platform, or filing a bug report with the Guacamole project. |
| |
| #endif |
| |