2010-02-14 10:48:10 +00:00
|
|
|
/* Implementation of extension methods to base additions
|
|
|
|
|
|
|
|
Copyright (C) 2010 Free Software Foundation, Inc.
|
|
|
|
|
|
|
|
Written by: Richard Frith-Macdonald <rfm@gnu.org>
|
|
|
|
|
|
|
|
This file is part of the GNUstep Base Library.
|
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
|
|
modify it under the terms of the GNU Lesser General Public
|
|
|
|
License as published by the Free Software Foundation; either
|
|
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
Library General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
|
|
License along with this library; if not, write to the Free
|
|
|
|
Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
|
|
|
|
Boston, MA 02111 USA.
|
|
|
|
|
|
|
|
*/
|
2010-07-03 05:54:56 +00:00
|
|
|
|
2012-03-01 09:14:08 +00:00
|
|
|
/* Carefully turn on _XOPEN_SOURCE for string.h so we
|
2012-02-29 15:17:06 +00:00
|
|
|
* get the POSIX strerror_r
|
|
|
|
*/
|
2012-04-17 05:29:28 +00:00
|
|
|
#if defined(_GNU_SOURCE)
|
|
|
|
#undef _GNU_SOURCE
|
|
|
|
#endif
|
|
|
|
#if defined(_XOPEN_SOURCE)
|
|
|
|
#if _XOPEN_SOURCE < 600
|
2012-02-29 15:17:06 +00:00
|
|
|
#undef _XOPEN_SOURCE
|
2012-04-17 05:29:28 +00:00
|
|
|
#define _XOPEN_SOURCE 600
|
2011-10-15 07:59:19 +00:00
|
|
|
#endif
|
2012-04-17 05:29:28 +00:00
|
|
|
#else
|
2012-04-16 16:37:50 +00:00
|
|
|
#define _XOPEN_SOURCE 600
|
2012-04-17 05:29:28 +00:00
|
|
|
#endif
|
|
|
|
#include <string.h>
|
2012-02-29 15:17:06 +00:00
|
|
|
|
2012-03-01 09:14:08 +00:00
|
|
|
#import "common.h"
|
2012-02-29 15:17:06 +00:00
|
|
|
|
2012-04-16 15:31:46 +00:00
|
|
|
#include <errno.h>
|
2011-10-15 07:59:19 +00:00
|
|
|
#include <stdio.h>
|
2010-07-03 05:54:56 +00:00
|
|
|
|
2010-02-14 10:48:10 +00:00
|
|
|
#import "Foundation/NSDictionary.h"
|
|
|
|
#import "Foundation/NSError.h"
|
|
|
|
#import "GSPrivate.h"
|
|
|
|
|
|
|
|
/**
|
|
|
|
* GNUstep specific (non-standard) additions to the NSError class.
|
|
|
|
* Possibly to be made public
|
|
|
|
*/
|
2010-02-18 16:27:32 +00:00
|
|
|
@implementation NSError(GNUstepBase)
|
2010-02-14 10:48:10 +00:00
|
|
|
|
|
|
|
|
2010-03-19 12:10:11 +00:00
|
|
|
#if !defined(__MINGW__)
|
2010-02-14 10:48:10 +00:00
|
|
|
#if !defined(HAVE_STRERROR_R)
|
|
|
|
#if defined(HAVE_STRERROR)
|
|
|
|
static int
|
|
|
|
strerror_r(int eno, char *buf, int len)
|
|
|
|
{
|
|
|
|
const char *ptr;
|
|
|
|
int result;
|
|
|
|
|
|
|
|
[gnustep_global_lock lock];
|
|
|
|
ptr = strerror(eno);
|
|
|
|
if (ptr == 0)
|
|
|
|
{
|
2011-03-07 11:34:17 +00:00
|
|
|
strncpy(buf, "unknown error number", len - 1);
|
2010-02-14 10:48:10 +00:00
|
|
|
result = -1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2011-03-07 11:34:17 +00:00
|
|
|
strncpy(buf, strerror(eno), len - 1);
|
2010-02-14 10:48:10 +00:00
|
|
|
result = 0;
|
|
|
|
}
|
2011-03-07 11:34:17 +00:00
|
|
|
buf[len - 1] = '\0';
|
2010-02-14 10:48:10 +00:00
|
|
|
[gnustep_global_lock unlock];
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
#else
|
|
|
|
static int
|
|
|
|
strerror_r(int eno, char *buf, int len)
|
|
|
|
{
|
|
|
|
extern char *sys_errlist[];
|
|
|
|
extern int sys_nerr;
|
|
|
|
|
|
|
|
if (eno < 0 || eno >= sys_nerr)
|
|
|
|
{
|
2011-03-07 11:34:17 +00:00
|
|
|
strncpy(buf, "unknown error number", len - 1);
|
2010-02-14 10:48:10 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2011-03-07 11:34:17 +00:00
|
|
|
strncpy(buf, sys_errlist[eno], len - 1);
|
|
|
|
buf[len - 1] = '\0';
|
2010-02-14 10:48:10 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Returns an NSError instance encapsulating the last system error.
|
|
|
|
* The user info dictionary of this object will be mutable, so that
|
|
|
|
* additional information can be placed in it by higher level code.
|
|
|
|
*/
|
|
|
|
+ (NSError*) _last
|
|
|
|
{
|
|
|
|
int eno;
|
2010-03-19 12:10:11 +00:00
|
|
|
#if defined(__MINGW__)
|
2010-02-14 10:48:10 +00:00
|
|
|
eno = GetLastError();
|
|
|
|
if (eno == 0) eno = errno;
|
|
|
|
#else
|
|
|
|
eno = errno;
|
|
|
|
#endif
|
|
|
|
return [self _systemError: eno];
|
|
|
|
}
|
|
|
|
|
|
|
|
+ (NSError*) _systemError: (long)code
|
|
|
|
{
|
|
|
|
NSError *error;
|
|
|
|
NSString *domain;
|
|
|
|
NSDictionary *info;
|
2010-03-19 12:10:11 +00:00
|
|
|
#if defined(__MINGW__)
|
2010-02-14 10:48:10 +00:00
|
|
|
LPVOID lpMsgBuf;
|
2010-10-19 21:21:32 +00:00
|
|
|
NSString *message=nil;
|
2010-02-14 10:48:10 +00:00
|
|
|
|
|
|
|
domain = NSOSStatusErrorDomain;
|
|
|
|
FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
|
|
|
|
NULL, code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
|
|
|
(LPWSTR) &lpMsgBuf, 0, NULL );
|
2012-04-17 05:29:28 +00:00
|
|
|
if (lpMsgBuf != NULL)
|
|
|
|
{
|
|
|
|
message
|
|
|
|
= [NSString stringWithCharacters: lpMsgBuf length: wcslen(lpMsgBuf)];
|
|
|
|
LocalFree(lpMsgBuf);
|
|
|
|
}
|
2010-02-14 10:48:10 +00:00
|
|
|
info = [NSMutableDictionary dictionaryWithObjectsAndKeys:
|
|
|
|
message, NSLocalizedDescriptionKey,
|
|
|
|
nil];
|
|
|
|
#else
|
|
|
|
NSString *message;
|
|
|
|
char buf[BUFSIZ];
|
|
|
|
|
|
|
|
/* FIXME ... not all are POSIX, should we use NSMachErrorDomain for some? */
|
|
|
|
domain = NSPOSIXErrorDomain;
|
|
|
|
if (strerror_r(code, buf, BUFSIZ) < 0)
|
|
|
|
{
|
2011-03-07 15:34:06 +00:00
|
|
|
snprintf(buf, sizeof(buf), "%ld", code);
|
2010-02-14 10:48:10 +00:00
|
|
|
}
|
|
|
|
message = [NSString stringWithCString: buf
|
|
|
|
encoding: [NSString defaultCStringEncoding]];
|
|
|
|
/* FIXME ... can we do better localisation? */
|
|
|
|
info = [NSMutableDictionary dictionaryWithObjectsAndKeys:
|
|
|
|
message, NSLocalizedDescriptionKey,
|
|
|
|
nil];
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* NB we use a mutable dictionary so that calling code can add extra
|
|
|
|
* information to the dictionary before passing it up to higher level
|
|
|
|
* code.
|
|
|
|
*/
|
|
|
|
error = [self errorWithDomain: domain code: code userInfo: info];
|
|
|
|
return error;
|
|
|
|
}
|
|
|
|
@end
|