[Date Prev][Date Next] [Chronological] [Thread] [Top]

Re: (ITS#6041) opendir() and closedir() bugs on Windows



test.007@seznam.cz wrote:
> Full_Name: Test Seven
> Version: 2.4.15
> OS: Windows
> URL:
> Submission from: (NULL) (195.113.184.20)

Thanks for the patch. The Windows code is known to work fine using gcc. Use of 
MSVC is discouraged since there have been so many incompatible CRT version 
changes in such a short span of time. (Actually, use of Microsoft-anything is 
generally discouraged; the same OpenLDAP code is at least 2-3x faster on the 
same hardware when using Linux instead of Windows.)

> Two problems solved in the patch:
> 1. closedir()'s retval is used, thus it must not be void. Windows uses implicit
> declaration ``int closedir(int)'' because the function is not declared in
> headers, thus the call in ldif.c compiles, but uses random value in EAX.
>
> 2. opendir() must set errno, because ldif_readdir() reads it. The patch converts
> the most common Windows error codes to errno codes after FindFirstFile() WinAPI
> call.
>
> The bugs prevent me from loading cn=config configuration.
>
> --- utils.c.orig	2009-01-22 01:00:58.000000000 +0100
> +++ utils.c	2009-03-27 14:28:33.500000000 +0100
> @@ -466,6 +466,40 @@ int mkstemp( char * template )
>   #endif
>
>   #ifdef _MSC_VER
> +/* Equivalent of MS CRT's _dosmaperr().
> + * @param lastError[in] Result of GetLastError().
> + */
> +static errno_t win2errno(DWORD lastError)
> +{
> +    const struct {
> +        DWORD   windows_code;
> +        errno_t errno_code;
> +    } WIN2ERRNO_TABLE[] = {
> +        { ERROR_SUCCESS, 0 },
> +        { ERROR_FILE_NOT_FOUND, ENOENT },
> +        { ERROR_PATH_NOT_FOUND, ENOENT },
> +        { ERROR_TOO_MANY_OPEN_FILES, EMFILE },
> +        { ERROR_ACCESS_DENIED, EACCES },
> +        { ERROR_INVALID_HANDLE, EBADF },
> +        { ERROR_NOT_ENOUGH_MEMORY, ENOMEM },
> +        { ERROR_NOT_ENOUGH_MEMORY, ENOMEM },
> +        { ERROR_LOCK_VIOLATION, EACCES },
> +        { ERROR_FILE_EXISTS, EEXIST },
> +        { ERROR_INVALID_PARAMETER, EINVAL },
> +        { ERROR_FILENAME_EXCED_RANGE, ENAMETOOLONG },
> +    };
> +    const unsigned int WIN2ERRNO_TABLE_SIZE = sizeof(WIN2ERRNO_TABLE) /
> sizeof(WIN2ERRNO_TABLE[0]);
> +    const errno_t DEFAULT_ERRNO_ERROR = -1;
> +    unsigned int i;
> +
> +    for (i = 0; i<  WIN2ERRNO_TABLE_SIZE; ++i) {
> +        if (WIN2ERRNO_TABLE[i].windows_code == lastError) {
> +            return WIN2ERRNO_TABLE[i].errno_code;
> +        }
> +    }
> +    return DEFAULT_ERRNO_ERROR;
> +}
> +
>   struct dirent {
>   	char *d_name;
>   };
> @@ -493,9 +527,10 @@ DIR *opendir( char *path )
>
>   	h = FindFirstFile( tmp,&data );
>   	
> -	if ( h == INVALID_HANDLE_VALUE )
> +    if ( h == INVALID_HANDLE_VALUE ) {
> +        errno = win2errno(GetLastError());
>   		return NULL;
> -
> +    }
>   	d = ber_memalloc( sizeof(DIR) );
>   	if ( !d )
>   		return NULL;
> @@ -518,10 +553,11 @@ struct dirent *readdir(DIR *dir)
>   	}
>   	return&dir->data;
>   }
> -void closedir(DIR *dir)
> +int closedir(DIR *dir)
>   {
>   	FindClose(dir->dir);
>   	ber_memfree(dir);
> +    return 0;
>   }
>   #endif
>
>
>


-- 
   -- Howard Chu
   CTO, Symas Corp.           http://www.symas.com
   Director, Highland Sun     http://highlandsun.com/hyc/
   Chief Architect, OpenLDAP  http://www.openldap.org/project/