⛏️ index : haiku.git

/*
 * Copyright 2005-2009, Axel Dörfler, axeld@pinc-software.de.
 * Distributed under the terms of the MIT license.
 *
 * Copyright 2001, Dan Sinclair. All rights reserved.
 * Distributed under the terms of the NewOS License.
 */


#include <string.h>
#include <stdio.h>

#include <SupportDefs.h>


static const struct error_base {
	int			base;
	const char	*name;
} kErrorBases[] = {
	{B_GENERAL_ERROR_BASE, "General "},
	{B_OS_ERROR_BASE, "OS "},
	{B_APP_ERROR_BASE, "Application Kit "},
	{B_INTERFACE_ERROR_BASE, "Interface Kit "},
	{B_MEDIA_ERROR_BASE, "Media Kit "},
	{B_TRANSLATION_ERROR_BASE, "Translation Kit "},
	{B_MIDI_ERROR_BASE, "Midi Kit "},
	{B_STORAGE_ERROR_BASE, "Storage Kit "},
	{B_POSIX_ERROR_BASE, "POSIX "},
	{B_MAIL_ERROR_BASE, "Mail Kit "},
	{B_PRINT_ERROR_BASE, "Print "},
	{B_DEVICE_ERROR_BASE, "Device "},
	{B_ERRORS_END, "Application "},
};
static const uint32 kNumErrorBases = sizeof(kErrorBases)
	/ sizeof(struct error_base);


static char *
error_description(int error)
{
	switch (error) {
		// General Errors

		case B_NO_ERROR:
			return "No error";
		case B_ERROR:
			return "General system error";

		case B_NO_MEMORY:
		case B_POSIX_ENOMEM:
			// ENOMEM
			return "Out of memory";
		case B_IO_ERROR:
			// EIO
			return "I/O error";
		case B_PERMISSION_DENIED:
			// EACCES
			return "Permission denied";
		case B_BAD_INDEX:
			return "Index not in range for the data set";
		case B_BAD_TYPE:
			return "Bad argument type passed to function";
		case B_BAD_VALUE:
			// EINVAL
			return "Invalid Argument";
		case B_MISMATCHED_VALUES:
			return "Mismatched values passed to function";
		case B_NAME_NOT_FOUND:
			return "Name not found";
		case B_NAME_IN_USE:
			return "Name in use";
		case B_TIMED_OUT:
			// ETIMEDOUT
			return "Operation timed out";
		case B_INTERRUPTED:
			// EINTR
			return "Interrupted system call";
		case B_WOULD_BLOCK:
			// EAGAIN
			// EWOULDBLOCK
			return "Operation would block";
		case B_CANCELED:
			return "Operation canceled";
		case B_NO_INIT:
			return "Initialization failed";
		case B_BUSY:
			// EBUSY
			return "Device/File/Resource busy";
		case B_NOT_ALLOWED:
			// EPERM
			return "Operation not allowed";
		case B_BAD_DATA:
			return "Bad data";
		case B_DONT_DO_THAT:
			return "No, really, don't do that";

		// Kernel Kit Errors

		case B_BAD_SEM_ID:
			return "Bad semaphore ID";
		case B_NO_MORE_SEMS:
			return "No more semaphores";

		case B_BAD_THREAD_ID:
			return "Bad thread ID";
		case B_NO_MORE_THREADS:
			return "No more threads";
		case B_BAD_THREAD_STATE:
			return "Thread is inappropriate state";
		case B_BAD_TEAM_ID:
			return "Operation on invalid team";
		case B_NO_MORE_TEAMS:
			return "No more teams";

		case B_BAD_PORT_ID:
			return "Bad port ID";
		case B_NO_MORE_PORTS:
			return "No more ports available";	// "No more ports"

		case B_BAD_IMAGE_ID:
			return "Bad image ID";
		case B_BAD_ADDRESS:
			// EFAULT
			return "Bad address";
		case B_NOT_AN_EXECUTABLE:
			// ENOEXEC
			return "Not an executable";
		case B_MISSING_LIBRARY:
			return "Missing library";
		case B_MISSING_SYMBOL:
			return "Symbol not found";
		case B_UNKNOWN_EXECUTABLE:
			return "Unknown executable format";
		case B_LEGACY_EXECUTABLE:
			return "Unsupported legacy executable";

		case B_DEBUGGER_ALREADY_INSTALLED:
			return "Debugger already installed for this team";

		// Application Kit Errors

		case B_BAD_REPLY:
			return "Invalid or unwanted reply";
		case B_DUPLICATE_REPLY:
			return "Duplicate reply";
		case B_MESSAGE_TO_SELF:
			return "Can't send message to self";
		case B_BAD_HANDLER:
			return "Bad handler";
		case B_ALREADY_RUNNING:
			return "Already running";
		case B_LAUNCH_FAILED:
			return "Launch failed";
		case B_AMBIGUOUS_APP_LAUNCH:
			return "Ambiguous app launch";
		case B_UNKNOWN_MIME_TYPE:
			return "Unknown MIME type";
		case B_BAD_SCRIPT_SYNTAX:
			return "Bad script syntax";
		case B_LAUNCH_FAILED_NO_RESOLVE_LINK:
			return "Could not resolve a link";
		case B_LAUNCH_FAILED_EXECUTABLE:
			return "File is mistakenly marked as executable";
		case B_LAUNCH_FAILED_APP_NOT_FOUND:
			return "Application could not be found";
		case B_LAUNCH_FAILED_APP_IN_TRASH:
			return "Application is in the trash";
		case B_LAUNCH_FAILED_NO_PREFERRED_APP:
			return "There is no preferred application for this type of file";
		case B_LAUNCH_FAILED_FILES_APP_NOT_FOUND:
			return "This file has a preferred app, but it could not be found";
		case B_BAD_MIME_SNIFFER_RULE:
			return "Bad sniffer rule";
		case B_NOT_A_MESSAGE:
			return "Data is not a message";
		case B_SHUTDOWN_CANCELLED:
			return "System shutdown cancelled";
		case B_SHUTTING_DOWN:
			return "System shutting down";

		// Storage Kit Errors

		case B_FILE_ERROR:
			// EBADF
			return "Bad file descriptor";
		case (B_STORAGE_ERROR_BASE + 1): /* B_FILE_NOT_FOUND (deprecated) */
		case B_ENTRY_NOT_FOUND:
			// ENOENT
			return "No such file or directory";
		case B_FILE_EXISTS:
			// EEXIST
			return "File or Directory already exists";
		case B_NAME_TOO_LONG:
			//	ENAMETOOLONG
			return "File name too long";
		case B_NOT_A_DIRECTORY:
			// ENOTDIR
			return "Not a directory";
		case B_DIRECTORY_NOT_EMPTY:
			// ENOTEMPTY
			return "Directory not empty";
		case B_DEVICE_FULL:
			// ENOSPC
			return "No space left on device";
		case B_READ_ONLY_DEVICE:
			// EROFS:
			return "Read-only file system";
		case B_IS_A_DIRECTORY:
			// EISDIR
			return "Is a directory";
		case B_NO_MORE_FDS:
			// EMFILE
			return "Too many open files";
		case B_CROSS_DEVICE_LINK:
			// EXDEV
			return "Cross-device link";
		case B_LINK_LIMIT:
			// ELOOP
			return "Too many symbolic links";
		case B_BUSTED_PIPE:
			// EPIPE
			return "Broken pipe";
		case B_UNSUPPORTED:
			return "Operation not supported";
		case B_PARTITION_TOO_SMALL:
			return "Partition too small to contain filesystem";
		case B_PARTIAL_READ:
			return "Data read partially";
		case B_PARTIAL_WRITE:
			return "Data written partially";

		// Media Kit Errors

		case B_STREAM_NOT_FOUND:
			return "Stream not found";
		case B_SERVER_NOT_FOUND:
			return "Server not found";
		case B_RESOURCE_NOT_FOUND:
			return "Resource not found";
		case B_RESOURCE_UNAVAILABLE:
			return "Resource unavailable";
		case B_BAD_SUBSCRIBER:
			return "Bad subscriber";
		case B_SUBSCRIBER_NOT_ENTERED:
			return "Subscriber not entered";
		case B_BUFFER_NOT_AVAILABLE:
			return "Buffer not available";
		case B_LAST_BUFFER_ERROR:
			return "Last buffer";
		case B_MEDIA_SYSTEM_FAILURE:
			return "System failure";
		case B_MEDIA_BAD_NODE:
			return "Bad media node";
		case B_MEDIA_NODE_BUSY:
			return "Media node busy";
		case B_MEDIA_BAD_FORMAT:
			return "Bad media format";
		case B_MEDIA_BAD_BUFFER:
			return "Bad buffer";
		case B_MEDIA_TOO_MANY_NODES:
			return "Too many nodes";
		case B_MEDIA_TOO_MANY_BUFFERS:
			return "Too many buffers";
		case B_MEDIA_NODE_ALREADY_EXISTS:
			return "Media node already exists";
		case B_MEDIA_BUFFER_ALREADY_EXISTS:
			return "Buffer already exists";
		case B_MEDIA_CANNOT_SEEK:
			return "Cannot seek";
		case B_MEDIA_CANNOT_CHANGE_RUN_MODE:
			return "Cannot change run mode";
		case B_MEDIA_APP_ALREADY_REGISTERED:
			return "Application already registered";
		case B_MEDIA_APP_NOT_REGISTERED:
			return "Application not registered";
		case B_MEDIA_CANNOT_RECLAIM_BUFFERS:
			return "Cannot reclaim buffers";
		case B_MEDIA_BUFFERS_NOT_RECLAIMED:
			return "Buffers not reclaimed";
		case B_MEDIA_TIME_SOURCE_STOPPED:
			return "Time source stopped";
		case B_MEDIA_TIME_SOURCE_BUSY:
			return "Time source busy";
		case B_MEDIA_BAD_SOURCE:
			return "Bad source";
		case B_MEDIA_BAD_DESTINATION:
			return "Bad destination";
		case B_MEDIA_ALREADY_CONNECTED:
			return "Already connected";
		case B_MEDIA_NOT_CONNECTED:
			return "Not connected";
		case B_MEDIA_BAD_CLIP_FORMAT:
			return "Bad clipping format";
		case B_MEDIA_ADDON_FAILED:
			return "Media addon failed";
		case B_MEDIA_ADDON_DISABLED:
			return "Media addon disabled";
		case B_MEDIA_CHANGE_IN_PROGRESS:
			return "Change in progress";
		case B_MEDIA_STALE_CHANGE_COUNT:
			return "Stale change count";
		case B_MEDIA_ADDON_RESTRICTED:
			return "Media addon restricted";
		case B_MEDIA_NO_HANDLER:
			return "No handler";
		case B_MEDIA_DUPLICATE_FORMAT:
			return "Duplicate format";
		case B_MEDIA_REALTIME_DISABLED:
			return "Realtime disabled";
		case B_MEDIA_REALTIME_UNAVAILABLE:
			return "Realtime unavailable";

		// Mail Kit Errors

		case B_MAIL_NO_DAEMON:
			return "No mail daemon";
		case B_MAIL_UNKNOWN_USER:
			return "Unknown mail user";
		case B_MAIL_WRONG_PASSWORD:
			return "Wrong password (mail)";
		case B_MAIL_UNKNOWN_HOST:
			return "Mail unknown host";
		case B_MAIL_ACCESS_ERROR:
			return "Mail access error";
		case B_MAIL_UNKNOWN_FIELD:
			return "Unknown mail field";
		case B_MAIL_NO_RECIPIENT:
			return "No mail recipient";
		case B_MAIL_INVALID_MAIL:
			return "Invalid mail";

		// Printing Errors

		case B_NO_PRINT_SERVER:
			return "No print server";

		// Device Kit Errors

		case B_DEV_INVALID_IOCTL:
			return "Invalid device ioctl";
		case B_DEV_NO_MEMORY:
			return "No device memory";
		case B_DEV_BAD_DRIVE_NUM:
			return "Bad drive number";
		case B_DEV_NO_MEDIA:
			return "No media present";
		case B_DEV_UNREADABLE:
			return "Device unreadable";
		case B_DEV_FORMAT_ERROR:
			return "Device format error";
		case B_DEV_TIMEOUT:
			return "Device timeout";
		case B_DEV_RECALIBRATE_ERROR:
			return "Device recalibrate error";
		case B_DEV_SEEK_ERROR:
			return "Device seek error";
		case B_DEV_ID_ERROR:
			return "Device ID error";
		case B_DEV_READ_ERROR:
			return "Device read error";
		case B_DEV_WRITE_ERROR:
			return "Device write error";
		case B_DEV_NOT_READY:
			return "Device not ready";
		case B_DEV_MEDIA_CHANGED:
			return "Device media changed";
		case B_DEV_MEDIA_CHANGE_REQUESTED:
			return "Device media change requested";
		case B_DEV_RESOURCE_CONFLICT:
			return "Resource conflict";
		case B_DEV_CONFIGURATION_ERROR:
			return "Configuration error";
		case B_DEV_DISABLED_BY_USER:
			return "Disabled by user";
		case B_DEV_DOOR_OPEN:
			return "Drive door open";

		// the commented out ones are really strange error codes...
		//case B_DEV_INVALID_PIPE:

		case B_DEV_CRC_ERROR:
			return "Device check-sum error";
		case B_DEV_STALLED:
			return "Device stalled";

		//case B_DEV_BAD_PID:
		//case B_DEV_UNEXPECTED_PID:

		case B_DEV_DATA_OVERRUN:
			return "Device data overrun";
		case B_DEV_DATA_UNDERRUN:
			return "Device data underrun";
		case B_DEV_FIFO_OVERRUN:
			return "Device FIFO overrun";
		case B_DEV_FIFO_UNDERRUN:
			return "Device FIFO underrun";
		case B_DEV_PENDING:
			return "Device pending";
		case B_DEV_MULTIPLE_ERRORS:
			return "Multiple device errors";
		case B_DEV_TOO_LATE:
			return "Device too late";

		// Translation Kit Errors

		case B_NO_TRANSLATOR:
			return "No translator found";
		case B_ILLEGAL_DATA:
			return "Illegal data";

		// Other POSIX Errors

		case ENFILE:
			return "File table overflow";
		case ENXIO:
			return "Device not accessible";
		case ESPIPE:
			return "Seek not allowed on file descriptor";
		case ENOSYS:
			return "Function not implemented";
		case EDOM:
			return "Numerical argument out of range";	// "Domain Error"
		case ENOBUFS:
			return "No buffer space available";
		case E2BIG:
			return "Argument too big";
		case ECHILD:
			return "No child process";
		case EDEADLK:
			return "Resource deadlock";
		case EFBIG:
			return "File too large";
		case EMLINK:
			return "Too many links";
		case ENODEV:
			return "No such device";
		case ENOLCK:
			return "No record locks available";
		case ENOTTY:
			return "Not a tty";
		case ESRCH:
			return "No such process";
		case EFPOS:
			return "File Position Error";
		case ESIGPARM:
			return "Signal Error";
		case ERANGE:
			return "Range Error";

		case EPROTOTYPE:
			return "Protocol wrong type for socket";
		case EPROTONOSUPPORT:
			return "Protocol not supported";
		case EPFNOSUPPORT:
			return "Protocol family not supported";
		case EAFNOSUPPORT:
			return "Address family not supported by protocol family";
		case EADDRINUSE:
			return "Address already in use";
		case EADDRNOTAVAIL:
			return "Can't assign requested address";
		case ENETDOWN:
			return "Network is down";
		case ENETUNREACH:
			return "Network is unreachable";
		case ENETRESET:
			return "Network dropped connection on reset";
		case ECONNABORTED:
			return "Software caused connection abort";
		case ECONNRESET:
			return "Connection reset by peer";
		case EISCONN:
			return "Socket is already connected";
		case ENOTCONN:
			return "Socket is not connected";
		case ESHUTDOWN:
			return "Can't send after socket shutdown";
		case ECONNREFUSED:
			return "Connection refused";
		case EHOSTUNREACH:
			return "No route to host";
		case ENOPROTOOPT:
			return "Protocol option not available";
		case EINPROGRESS:
			return "Operation now in progress";
		case EALREADY:
			return "Operation already in progress";
		case EILSEQ:
			return "Illegal byte sequence";
		case ENOMSG:
			return "No message of desired type";
		case ESTALE:
			return "Stale file handle";

		case EOVERFLOW:
			return "Value too large for defined type";
		case EMSGSIZE:
			return "Message too long";
		case EOPNOTSUPP:
			return "Operation not supported";
		case ENOTSOCK:
			return "Socket operation on non-socket";
		case EHOSTDOWN:
			return "Host is down";
		case EBADMSG:
			return "Bad message";
		case ECANCELED:
			return "Operation canceled";
		case EDESTADDRREQ:
			return "Destination address required";
		case EDQUOT:
			return "Reserved";
		case EIDRM:
			return "Identifier removed";
		case EMULTIHOP:
			return "Reserved";
		case ENODATA:
			return "No message available";
		case ENOLINK:
			return "Reserved";
		case ENOSR:
			return "No STREAM resources";
		case ENOSTR:
			return "Not a STREAM";
		case ENOTSUP:
			return "Not supported";
		case EPROTO:
			return "Protocol error";
		case ETIME:
			return "STREAM ioctl() timeout";
		case ETXTBSY:
			return "Text file busy";
		case ENOATTR:
			return "No such attribute";
		case ENOTRECOVERABLE:
			return "State not recoverable";
		case EOWNERDEAD:
			return "Previous owner died";

		default:
			return NULL;
	}
}


char *
strerror(int error)
{
	static char unknown[48];
	uint32 i;

	char *description = error_description(error);
	if (description != NULL)
		return description;

	if (error < B_OK) {
		const char *system = "";
		for (i = 0; i < kNumErrorBases; i++) {
			if (kErrorBases[i].base <= error
				&& ((i + 1 < kNumErrorBases && kErrorBases[i + 1].base > error)
					|| i + 1 == kNumErrorBases)) {
				system = kErrorBases[i].name;
				break;
			}
		}
		sprintf(unknown, "Unknown %sError (%d)", system, error);
	} else
		sprintf(unknown, "No Error (%d)", error);

	return unknown;
}


int
strerror_r(int error, char *buffer, size_t bufferSize)
{
	char *description = error_description(error);
	if (description == NULL)
		return EINVAL;

	strlcpy(buffer, description, bufferSize);
	return 0;
		// TODO: could return ERANGE if buffer is too small
}


char *
strerror_l(int error, locale_t locale)
{
	// Don't have error messages in other locales yet.
	(void)locale;
	return strerror(error);
}