[ Moving discussion from wget-patches to wget. ]

"Gisle Vanem" <[EMAIL PROTECTED]> writes:

>> I'm pretty sure that other GNU applications -- that have also been
>> ported to Windows -- use errno.  I wonder how they do it...
>
> Lynx uses this:
>   #define SOCKET_ERRNO errno
>   #ifdef WINDOWS
>   #undef  SOCKET_ERRNO 
>   #define SOCKET_ERRNO    WSAGetLastError()
>   ..
>
> and never errno for network calls directly.  But then again, it
> never *sets* errno as Wget do.

OK.  So the whole thing with errno is only necessary when dealing with
Winsock errors.  For errors from, say, fopen it's fine to use errno?

There is another possible approach.  We already #define read and write
to call Winsock stuff.  We could add some more magic so that they and
other Winsock invocations automatically set errno to last error value,
translating Windows errors to errno errors.  XEmacs has code that
seems to support that kind of translation (Winsock errors might need
to be handled separately, but they could be added) -- please take a
look:

struct errentry {
  unsigned long oscode;  /* Win32 error */
  int errnocode;         /* unix errno */
};

static struct errentry errtable[] = {
  {  ERROR_INVALID_FUNCTION,       EINVAL    },  /* 1 */
  {  ERROR_FILE_NOT_FOUND,         ENOENT    },  /* 2 */
  {  ERROR_PATH_NOT_FOUND,         ENOENT    },  /* 3 */
  {  ERROR_TOO_MANY_OPEN_FILES,    EMFILE    },  /* 4 */
  {  ERROR_ACCESS_DENIED,          EACCES    },  /* 5 */
  {  ERROR_INVALID_HANDLE,         EBADF     },  /* 6 */
  {  ERROR_ARENA_TRASHED,          ENOMEM    },  /* 7 */
  {  ERROR_NOT_ENOUGH_MEMORY,      ENOMEM    },  /* 8 */
  {  ERROR_INVALID_BLOCK,          ENOMEM    },  /* 9 */
  {  ERROR_BAD_ENVIRONMENT,        E2BIG     },  /* 10 */
  {  ERROR_BAD_FORMAT,             ENOEXEC   },  /* 11 */
  {  ERROR_INVALID_ACCESS,         EINVAL    },  /* 12 */
  {  ERROR_INVALID_DATA,           EINVAL    },  /* 13 */
  {  ERROR_INVALID_DRIVE,          ENOENT    },  /* 15 */
  {  ERROR_CURRENT_DIRECTORY,      EACCES    },  /* 16 */
  {  ERROR_NOT_SAME_DEVICE,        EXDEV     },  /* 17 */
  {  ERROR_NO_MORE_FILES,          ENOENT    },  /* 18 */
  {  ERROR_LOCK_VIOLATION,         EACCES    },  /* 33 */
  {  ERROR_BAD_NETPATH,            ENOENT    },  /* 53 */
  {  ERROR_NETWORK_ACCESS_DENIED,  EACCES    },  /* 65 */
  {  ERROR_BAD_NET_NAME,           ENOENT    },  /* 67 */
  {  ERROR_FILE_EXISTS,            EEXIST    },  /* 80 */
  {  ERROR_CANNOT_MAKE,            EACCES    },  /* 82 */
  {  ERROR_FAIL_I24,               EACCES    },  /* 83 */
  {  ERROR_INVALID_PARAMETER,      EINVAL    },  /* 87 */
  {  ERROR_NO_PROC_SLOTS,          EAGAIN    },  /* 89 */
  {  ERROR_DRIVE_LOCKED,           EACCES    },  /* 108 */
  {  ERROR_BROKEN_PIPE,            EPIPE     },  /* 109 */
  {  ERROR_DISK_FULL,              ENOSPC    },  /* 112 */
  {  ERROR_INVALID_TARGET_HANDLE,  EBADF     },  /* 114 */
  {  ERROR_INVALID_HANDLE,         EINVAL    },  /* 124 */
  {  ERROR_WAIT_NO_CHILDREN,       ECHILD    },  /* 128 */
  {  ERROR_CHILD_NOT_COMPLETE,     ECHILD    },  /* 129 */
  {  ERROR_DIRECT_ACCESS_HANDLE,   EBADF     },  /* 130 */
  {  ERROR_NEGATIVE_SEEK,          EINVAL    },  /* 131 */
  {  ERROR_SEEK_ON_DEVICE,         EACCES    },  /* 132 */
  {  ERROR_DIR_NOT_EMPTY,          ENOTEMPTY },  /* 145 */
  {  ERROR_NOT_LOCKED,             EACCES    },  /* 158 */
  {  ERROR_BAD_PATHNAME,           ENOENT    },  /* 161 */
  {  ERROR_MAX_THRDS_REACHED,      EAGAIN    },  /* 164 */
  {  ERROR_LOCK_FAILED,            EACCES    },  /* 167 */
  {  ERROR_ALREADY_EXISTS,         EEXIST    },  /* 183 */
  {  ERROR_FILENAME_EXCED_RANGE,   ENOENT    },  /* 206 */
  {  ERROR_NESTING_NOT_ALLOWED,    EAGAIN    },  /* 215 */
  {  ERROR_NOT_ENOUGH_QUOTA,       ENOMEM    }    /* 1816 */
};

/* The following two constants must be the minimum and maximum
   values in the (contiguous) range of Exec Failure errors. */
#define MIN_EXEC_ERROR ERROR_INVALID_STARTING_CODESEG
#define MAX_EXEC_ERROR ERROR_INFLOOP_IN_RELOC_CHAIN

/* These are the low and high value in the range of errors that are
   access violations */
#define MIN_EACCES_RANGE ERROR_WRITE_PROTECT
#define MAX_EACCES_RANGE ERROR_SHARING_BUFFER_EXCEEDED

void
mswindows_set_errno (unsigned long win32_error)
{
  int i;

  /* check the table for the OS error code */
  for (i = 0; i < countof (errtable); ++i)
    {
      if (win32_error == errtable[i].oscode)
        {
          errno = errtable[i].errnocode;
          return;
        }
    }

  /* The error code wasn't in the table.  We check for a range of
   * EACCES errors or exec failure errors (ENOEXEC).  Otherwise EINVAL is
   * returned. */
  if (win32_error >= MIN_EACCES_RANGE && win32_error <= MAX_EACCES_RANGE)
    errno = EACCES;
  else if (win32_error >= MIN_EXEC_ERROR && win32_error <= MAX_EXEC_ERROR)
    errno = ENOEXEC;
  else
    errno = EINVAL;
}

void
mswindows_set_last_errno (void)
{
  mswindows_set_errno (GetLastError ());
}

Reply via email to