#include "lib.h"
#include "sys9.h"
#include <string.h>
#include <errno.h>
/* make this global, so programs can look at it if errno is unilluminating */
/* see also: ../stdio/strerror.c, with errno-> string mapping */
char _plan9err[ERRMAX];
static struct errmap {
int errno;
char *ename;
} map[] = {
/* from /sys/src/9/port/errstr.h */
{EINVAL, "inconsistent mount"},
{EINVAL, "not mounted"},
{EINVAL, "not in union"},
{EIO, "mount rpc error"},
{EIO, "mounted device shut down"},
{EPERM, "mounted directory forbids creation"},
{ENOENT, "does not exist"},
{ENXIO, "unknown device in # filename"},
{ENOTDIR, "not a directory"},
{EISDIR, "file is a directory"},
{EINVAL, "bad character in file name"},
{EINVAL, "file name syntax"},
{EPERM, "permission denied"},
{EPERM, "inappropriate use of fd"},
{EINVAL, "bad arg in system call"},
{EBUSY, "device or object already in use"},
{EIO, "i/o error"},
{EIO, "read or write too large"},
{EIO, "read or write too small"},
{EADDRINUSE, "network port not available"},
{ESHUTDOWN, "write to hungup stream"},
{ESHUTDOWN, "i/o on hungup channel"},
{EINVAL, "bad process or channel control request"},
{EBUSY, "no free devices"},
{ESRCH, "process exited"},
{ECHILD, "no living children"},
{EIO, "i/o error in demand load"},
{ENOMEM, "virtual memory allocation failed"},
{EBADF, "fd out of range or not open"},
{EMFILE, "no free file descriptors"},
{ESPIPE, "seek on a stream"},
{ENOEXEC, "exec header invalid"},
{ETIMEDOUT, "connection timed out"},
{ECONNREFUSED, "connection refused"},
{ECONNREFUSED, "connection in use"},
{EINTR, "interrupted"},
{ENOMEM, "kernel allocate failed"},
{EINVAL, "segments overlap"},
{EIO, "i/o count too small"},
{EGREG, "ken has left the building"},
{EINVAL, "bad attach specifier"},
/* from exhausted() calls in kernel */
{ENFILE, "no free file descriptors"},
{EBUSY, "no free mount devices"},
{EBUSY, "no free mount rpc buffer"},
{EBUSY, "no free segments"},
{ENOMEM, "no free memory"},
{ENOBUFS, "no free Blocks"},
{EBUSY, "no free routes"},
/* from ken */
{EINVAL, "attach -- bad specifier"},
{EBADF, "unknown fid"},
{EINVAL, "bad character in directory name"},
{EBADF, "read/write -- on non open fid"},
{EIO, "read/write -- count too big"},
{EIO, "phase error -- directory entry not allocated"},
{EIO, "phase error -- qid does not match"},
{EACCES, "access permission denied"},
{ENOENT, "directory entry not found"},
{EINVAL, "open/create -- unknown mode"},
{ENOTDIR, "walk -- in a non-directory"},
{ENOTDIR, "create -- in a non-directory"},
{EIO, "phase error -- cannot happen"},
{EEXIST, "create -- file exists"},
{EINVAL, "create -- . and .. illegal names"},
{ENOTEMPTY, "directory not empty"},
{EINVAL, "attach -- privileged user"},
{EPERM, "wstat -- not owner"},
{EPERM, "wstat -- not in group"},
{EINVAL, "create/wstat -- bad character in file name"},
{EBUSY, "walk -- too many (system wide)"},
{EROFS, "file system read only"},
{ENOSPC, "file system full"},
{EINVAL, "read/write -- offset negative"},
{EBUSY, "open/create -- file is locked"},
{EBUSY, "close/read/write -- lock is broken"},
/* from sockets */
{ENOTSOCK, "not a socket"},
{EPROTONOSUPPORT, "protocol not supported"},
{ECONNREFUSED, "connection refused"},
{EAFNOSUPPORT, "address family not supported"},
{ENOBUFS, "insufficient buffer space"},
{EOPNOTSUPP, "operation not supported"},
{EADDRINUSE, "address in use"},
{EGREG, "unnamed error message"},
};
#define NERRMAP (sizeof(map)/sizeof(struct errmap))
/* convert last system call error to an errno */
void
_syserrno(void)
{
int i;
if(_ERRSTR(_plan9err, sizeof _plan9err) < 0)
errno = EINVAL;
else{
for(i = 0; i < NERRMAP; i++)
if(strstr(_plan9err, map[i].ename) != 0)
break;
_ERRSTR(_plan9err, sizeof _plan9err);
errno = (i < NERRMAP)? map[i].errno : EINVAL;
}
}
|