mirror of
https://github.com/gnustep/libs-base.git
synced 2025-06-01 01:01:03 +00:00
* Add support for systems that support unichar file paths (e.g.
Windows). * Headers/Foundation/NSFileManager.h (-localFromOpenStepPath:, _openStepPathFromLocal:): New methods. (NSDirectoryEnumerator): Updated ivars. * Source/NSFileManager.m: Idem. (-changeCurrentDirectoryPath, changeFileAttributes:, currentDirectoryPath, etc): Update for Windows unichar paths. * Headers/Foundation/NSString.h: (-unicharString, -localFromOpenStepPath:, _openStepPathFromLocal:): New methods. * Source/NSString.m: Idem. * Source/GSFileHandle.m (-initForReadingAtPath:, -initForWritingAtPath, -initForUpdatingAtPath:): Update for Windows unichar paths. * Source/NSData.m (readContentsOfFile, -writeToFile:, initWithContentsOfMappedFile:): Idem. * Source/NSTask.m (NSConcreteWindowsTask): Update for Windows unichar paths. (Patch from Roland Schwingle <roland.schwingel@onevision.de>) git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@20502 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
257787f99e
commit
142f0b1784
9 changed files with 1171 additions and 801 deletions
459
Source/NSData.m
459
Source/NSData.m
|
@ -64,6 +64,10 @@
|
|||
*
|
||||
*/
|
||||
|
||||
#if defined(__MINGW32__)
|
||||
#define UNICODE
|
||||
#define _UNICODE
|
||||
#endif
|
||||
#include "config.h"
|
||||
#include "GNUstepBase/GSObjCRuntime.h"
|
||||
#include "Foundation/NSObjCRuntime.h"
|
||||
|
@ -128,136 +132,149 @@ static IMP appendImp;
|
|||
static BOOL
|
||||
readContentsOfFile(NSString* path, void** buf, unsigned int* len, NSZone* zone)
|
||||
{
|
||||
char thePath[BUFSIZ*2];
|
||||
FILE *theFile = 0;
|
||||
void *tmp = 0;
|
||||
int c;
|
||||
long fileLength;
|
||||
|
||||
#if GS_WITH_GC == 1
|
||||
zone = GSAtomicMallocZone(); // Use non-GC memory inside NSData
|
||||
#endif
|
||||
|
||||
if ([path getFileSystemRepresentation: thePath
|
||||
maxLength: sizeof(thePath)-1] == NO)
|
||||
{
|
||||
NSWarnFLog(@"Open (%s) attempt failed - bad path", thePath);
|
||||
return NO;
|
||||
}
|
||||
|
||||
theFile = fopen(thePath, "rb");
|
||||
|
||||
if (theFile == NULL) /* We failed to open the file. */
|
||||
{
|
||||
NSWarnFLog(@"Open (%s) attempt failed - %s", thePath,
|
||||
GSLastErrorStr(errno));
|
||||
goto failure;
|
||||
}
|
||||
|
||||
/*
|
||||
* Seek to the end of the file.
|
||||
*/
|
||||
c = fseek(theFile, 0L, SEEK_END);
|
||||
if (c != 0)
|
||||
{
|
||||
NSWarnFLog(@"Seek to end of file (%s) failed - %s", thePath,
|
||||
GSLastErrorStr(errno));
|
||||
goto failure;
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine the length of the file (having seeked to the end of the
|
||||
* file) by calling ftell().
|
||||
*/
|
||||
fileLength = ftell(theFile);
|
||||
if (fileLength == -1)
|
||||
{
|
||||
NSWarnFLog(@"Ftell on %s failed - %s", thePath, GSLastErrorStr(errno));
|
||||
goto failure;
|
||||
}
|
||||
|
||||
/*
|
||||
* Rewind the file pointer to the beginning, preparing to read in
|
||||
* the file.
|
||||
*/
|
||||
c = fseek(theFile, 0L, SEEK_SET);
|
||||
if (c != 0)
|
||||
{
|
||||
NSWarnFLog(@"Fseek to start of file (%s) failed - %s",
|
||||
thePath, GSLastErrorStr(errno));
|
||||
goto failure;
|
||||
}
|
||||
|
||||
if (fileLength == 0)
|
||||
{
|
||||
unsigned char buf[BUFSIZ];
|
||||
|
||||
/*
|
||||
* Special case ... a file of length zero may be a named pipe or some
|
||||
* file in the /proc filesystem, which will return us data if we read
|
||||
* from it ... so we try reading as much as we can.
|
||||
*/
|
||||
while ((c = fread(buf, 1, BUFSIZ, theFile)) != 0)
|
||||
NSString *localPath = [path localFromOpenStepPath];
|
||||
|
||||
#if defined(__MINGW__)
|
||||
const unichar *thePath = NULL;
|
||||
#else
|
||||
const char *thePath = NULL;
|
||||
#endif
|
||||
FILE *theFile = 0;
|
||||
void *tmp = 0;
|
||||
int c;
|
||||
long fileLength;
|
||||
|
||||
#if GS_WITH_GC == 1
|
||||
zone = GSAtomicMallocZone(); // Use non-GC memory inside NSData
|
||||
#endif
|
||||
|
||||
#if defined(__MINGW__)
|
||||
thePath = [localPath unicharString];
|
||||
#else
|
||||
thePath = [localPath fileSystemRepresentation];
|
||||
#endif
|
||||
if (thePath == NULL)
|
||||
{
|
||||
if (tmp == 0)
|
||||
{
|
||||
tmp = NSZoneMalloc(zone, c);
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp = NSZoneRealloc(zone, tmp, fileLength + c);
|
||||
}
|
||||
if (tmp == 0)
|
||||
{
|
||||
NSLog(@"Malloc failed for file (%s) of length %d - %s",
|
||||
thePath, fileLength + c, GSLastErrorStr(errno));
|
||||
goto failure;
|
||||
}
|
||||
memcpy(tmp + fileLength, buf, c);
|
||||
fileLength += c;
|
||||
NSWarnFLog(@"Open (%@) attempt failed - bad path",localPath);
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp = NSZoneMalloc(zone, fileLength);
|
||||
if (tmp == 0)
|
||||
|
||||
#if defined(__MINGW__)
|
||||
theFile = _wfopen(thePath, L"rb");
|
||||
#else
|
||||
theFile = fopen(thePath, "rb");
|
||||
#endif
|
||||
|
||||
if (theFile == NULL) /* We failed to open the file. */
|
||||
{
|
||||
NSLog(@"Malloc failed for file (%s) of length %d - %s",
|
||||
thePath, fileLength, GSLastErrorStr(errno));
|
||||
goto failure;
|
||||
NSWarnFLog(@"Open (%@) attempt failed - %s",localPath,
|
||||
GSLastErrorStr(errno));
|
||||
goto failure;
|
||||
}
|
||||
|
||||
c = fread(tmp, 1, fileLength, theFile);
|
||||
if (c != (int)fileLength)
|
||||
|
||||
/*
|
||||
* Seek to the end of the file.
|
||||
*/
|
||||
c = fseek(theFile, 0L, SEEK_END);
|
||||
if (c != 0)
|
||||
{
|
||||
NSWarnFLog(@"read of file (%s) contents failed - %s",
|
||||
thePath, GSLastErrorStr(errno));
|
||||
goto failure;
|
||||
NSWarnFLog(@"Seek to end of file (%@) failed - %s",localPath,
|
||||
GSLastErrorStr(errno));
|
||||
goto failure;
|
||||
}
|
||||
}
|
||||
|
||||
*buf = tmp;
|
||||
*len = fileLength;
|
||||
fclose(theFile);
|
||||
return YES;
|
||||
|
||||
/*
|
||||
* Just in case the failure action needs to be changed.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Determine the length of the file (having seeked to the end of the
|
||||
* file) by calling ftell().
|
||||
*/
|
||||
fileLength = ftell(theFile);
|
||||
if (fileLength == -1)
|
||||
{
|
||||
NSWarnFLog(@"Ftell on %@ failed - %s",localPath,
|
||||
GSLastErrorStr(errno));
|
||||
goto failure;
|
||||
}
|
||||
|
||||
/*
|
||||
* Rewind the file pointer to the beginning, preparing to read in
|
||||
* the file.
|
||||
*/
|
||||
c = fseek(theFile, 0L, SEEK_SET);
|
||||
if (c != 0)
|
||||
{
|
||||
NSWarnFLog(@"Fseek to start of file (%@) failed - %s",localPath,
|
||||
GSLastErrorStr(errno));
|
||||
goto failure;
|
||||
}
|
||||
|
||||
if (fileLength == 0)
|
||||
{
|
||||
unsigned char buf[BUFSIZ];
|
||||
|
||||
/*
|
||||
* Special case ... a file of length zero may be a named pipe or some
|
||||
* file in the /proc filesystem, which will return us data if we read
|
||||
* from it ... so we try reading as much as we can.
|
||||
*/
|
||||
while ((c = fread(buf, 1, BUFSIZ, theFile)) != 0)
|
||||
{
|
||||
if (tmp == 0)
|
||||
{
|
||||
tmp = NSZoneMalloc(zone, c);
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp = NSZoneRealloc(zone, tmp, fileLength + c);
|
||||
}
|
||||
if (tmp == 0)
|
||||
{
|
||||
NSLog(@"Malloc failed for file (%@) of length %d - %s",localPath,
|
||||
fileLength + c, GSLastErrorStr(errno));
|
||||
goto failure;
|
||||
}
|
||||
memcpy(tmp + fileLength, buf, c);
|
||||
fileLength += c;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp = NSZoneMalloc(zone, fileLength);
|
||||
if (tmp == 0)
|
||||
{
|
||||
NSLog(@"Malloc failed for file (%@) of length %d - %s",localPath,
|
||||
fileLength, GSLastErrorStr(errno));
|
||||
goto failure;
|
||||
}
|
||||
|
||||
c = fread(tmp, 1, fileLength, theFile);
|
||||
if (c != (int)fileLength)
|
||||
{
|
||||
NSWarnFLog(@"read of file (%@) contents failed - %s",localPath,
|
||||
GSLastErrorStr(errno));
|
||||
goto failure;
|
||||
}
|
||||
}
|
||||
|
||||
*buf = tmp;
|
||||
*len = fileLength;
|
||||
fclose(theFile);
|
||||
return YES;
|
||||
|
||||
/*
|
||||
* Just in case the failure action needs to be changed.
|
||||
*/
|
||||
failure:
|
||||
if (tmp != 0)
|
||||
{
|
||||
NSZoneFree(zone, tmp);
|
||||
}
|
||||
if (theFile != 0)
|
||||
{
|
||||
fclose(theFile);
|
||||
}
|
||||
return NO;
|
||||
if (tmp != 0)
|
||||
{
|
||||
NSZoneFree(zone, tmp);
|
||||
}
|
||||
if (theFile != 0)
|
||||
{
|
||||
fclose(theFile);
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* NB, The start of the NSMutableDataMalloc instance variables must be
|
||||
* identical to that of NSDataMalloc in order to inherit its methods.
|
||||
|
@ -804,17 +821,39 @@ static unsigned gsu32Align;
|
|||
*/
|
||||
- (BOOL) writeToFile: (NSString*)path atomically: (BOOL)useAuxiliaryFile
|
||||
{
|
||||
char thePath[BUFSIZ*2+8];
|
||||
char theRealPath[BUFSIZ*2];
|
||||
int c;
|
||||
FILE *theFile;
|
||||
NSString *localPath = [path localFromOpenStepPath];
|
||||
#if defined(__MINGW__)
|
||||
unichar wthePath[[localPath length]+100];
|
||||
unichar wtheRealPath[[localPath length]+100];
|
||||
#else
|
||||
char thePath[BUFSIZ*2+8];
|
||||
char theRealPath[BUFSIZ*2];
|
||||
#endif
|
||||
int c;
|
||||
FILE *theFile;
|
||||
BOOL error_BadPath = YES;
|
||||
|
||||
if ([path getFileSystemRepresentation: theRealPath
|
||||
maxLength: sizeof(theRealPath)-1] == NO)
|
||||
{
|
||||
NSWarnMLog(@"Open (%s) attempt failed - bad path", theRealPath);
|
||||
return NO;
|
||||
}
|
||||
#if defined(__MINGW__)
|
||||
[localPath getCharacters:wtheRealPath];
|
||||
wtheRealPath[[localPath length]] = L'\0';
|
||||
error_BadPath = ([localPath length] <= 0);
|
||||
#else
|
||||
if ([localPath canBeConvertedToEncoding: [NSString defaultCStringEncoding]])
|
||||
{
|
||||
const char *local_c_path = [localPath cString];
|
||||
if (local_c_path != NULL && strlen(local_c_path) < (BUFSIZ*2))
|
||||
{
|
||||
strcpy(theRealPath,local_c_path);
|
||||
error_BadPath = NO;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (error_BadPath)
|
||||
{
|
||||
NSWarnMLog(@"Open (%@) attempt failed - bad path",path);
|
||||
return NO;
|
||||
}
|
||||
|
||||
#ifdef HAVE_MKSTEMP
|
||||
if (useAuxiliaryFile)
|
||||
|
@ -849,6 +888,17 @@ static unsigned gsu32Align;
|
|||
/* Use the path name of the destination file as a prefix for the
|
||||
* mktemp() call so that we can be sure that both files are on
|
||||
* the same filesystem and the subsequent rename() will work. */
|
||||
#if defined(__MINGW__)
|
||||
wcscpy(wthePath, wtheRealPath);
|
||||
wcscat(wthePath, L"XXXXXX");
|
||||
if (_wmktemp(wthePath) == 0)
|
||||
{
|
||||
NSWarnMLog(@"mktemp (%@) failed - %s",
|
||||
[NSString stringWithCharacters:wthePath length:wcslen(wthePath)],
|
||||
GSLastErrorStr(errno));
|
||||
goto failure;
|
||||
}
|
||||
#else
|
||||
strcpy(thePath, theRealPath);
|
||||
strcat(thePath, "XXXXXX");
|
||||
if (mktemp(thePath) == 0)
|
||||
|
@ -857,20 +907,35 @@ static unsigned gsu32Align;
|
|||
GSLastErrorStr(errno));
|
||||
goto failure;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined(__MINGW__)
|
||||
wcscpy(wthePath,wtheRealPath);
|
||||
#else
|
||||
strcpy(thePath, theRealPath);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Open the file (whether temp or real) for writing. */
|
||||
#if defined(__MINGW__)
|
||||
theFile = _wfopen(wthePath, L"wb");
|
||||
#else
|
||||
theFile = fopen(thePath, "wb");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (theFile == NULL) /* Something went wrong; we weren't
|
||||
* even able to open the file. */
|
||||
{
|
||||
#if defined(__MINGW__)
|
||||
NSWarnMLog(@"Open (%@) failed - %s",
|
||||
[NSString stringWithCharacters:wthePath length:wcslen(wthePath)],
|
||||
GSLastErrorStr(errno));
|
||||
#else
|
||||
NSWarnMLog(@"Open (%s) failed - %s", thePath, GSLastErrorStr(errno));
|
||||
#endif
|
||||
goto failure;
|
||||
}
|
||||
|
||||
|
@ -882,7 +947,13 @@ static unsigned gsu32Align;
|
|||
if (c < (int)[self length]) /* We failed to write everything for
|
||||
* some reason. */
|
||||
{
|
||||
#if defined(__MINGW__)
|
||||
NSWarnMLog(@"Fwrite (%@) failed - %s",
|
||||
[NSString stringWithCharacters:wthePath length:wcslen(wthePath)],
|
||||
GSLastErrorStr(errno));
|
||||
#else
|
||||
NSWarnMLog(@"Fwrite (%s) failed - %s", thePath, GSLastErrorStr(errno));
|
||||
#endif
|
||||
goto failure;
|
||||
}
|
||||
|
||||
|
@ -893,7 +964,13 @@ static unsigned gsu32Align;
|
|||
* closing the file, but we got here,
|
||||
* so we need to deal with it. */
|
||||
{
|
||||
#if defined(__MINGW__)
|
||||
NSWarnMLog(@"Fclose (%@) failed - %s",
|
||||
[NSString stringWithCharacters:wthePath length:wcslen(wthePath)],
|
||||
GSLastErrorStr(errno));
|
||||
#else
|
||||
NSWarnMLog(@"Fclose (%s) failed - %s", thePath, GSLastErrorStr(errno));
|
||||
#endif
|
||||
goto failure;
|
||||
}
|
||||
|
||||
|
@ -929,7 +1006,7 @@ static unsigned gsu32Align;
|
|||
c = -1;
|
||||
}
|
||||
#else
|
||||
if (MoveFileEx(thePath, theRealPath, MOVEFILE_REPLACE_EXISTING) != 0)
|
||||
if (MoveFileEx(wthePath, wtheRealPath, MOVEFILE_REPLACE_EXISTING) != 0)
|
||||
{
|
||||
c = 0;
|
||||
}
|
||||
|
@ -943,8 +1020,15 @@ static unsigned gsu32Align;
|
|||
#endif
|
||||
if (c != 0) /* Many things could go wrong, I guess. */
|
||||
{
|
||||
NSWarnMLog(@"Rename ('%s' to '%s') failed - %s",
|
||||
#if defined(__MINGW__)
|
||||
NSWarnMLog(@"Rename ('%@' to '%@') failed - %s",
|
||||
[NSString stringWithCharacters:wthePath length:wcslen(wthePath)],
|
||||
[NSString stringWithCharacters:wtheRealPath length:wcslen(wtheRealPath)],
|
||||
GSLastErrorStr(errno));
|
||||
#else
|
||||
NSWarnMLog(@"Rename ('%s' to '%s') failed - %s",
|
||||
thePath, theRealPath, GSLastErrorStr(errno));
|
||||
#endif
|
||||
goto failure;
|
||||
}
|
||||
|
||||
|
@ -990,7 +1074,11 @@ failure:
|
|||
*/
|
||||
if (useAuxiliaryFile)
|
||||
{
|
||||
#if defined(__MINGW__)
|
||||
_wunlink(wthePath);
|
||||
#else
|
||||
unlink(thePath);
|
||||
#endif
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
@ -2767,54 +2855,65 @@ getBytes(void* dst, void* src, unsigned len, unsigned limit, unsigned *pos)
|
|||
*/
|
||||
- (id) initWithContentsOfMappedFile: (NSString*)path
|
||||
{
|
||||
int fd;
|
||||
char thePath[BUFSIZ*2];
|
||||
int fd;
|
||||
NSString *localPath = [path localFromOpenStepPath];
|
||||
|
||||
#if defined(__MINGW__)
|
||||
const unichar *thePath = [localPath unicharString];
|
||||
#else
|
||||
const char *thePath;
|
||||
thePath = [localPath fileSystemRepresentation];
|
||||
#endif
|
||||
|
||||
if ([path getFileSystemRepresentation: thePath
|
||||
maxLength: sizeof(thePath)-1] == NO)
|
||||
{
|
||||
NSWarnMLog(@"Open (%s) attempt failed - bad path", thePath);
|
||||
RELEASE(self);
|
||||
return nil;
|
||||
}
|
||||
fd = open(thePath, O_RDONLY);
|
||||
if (fd < 0)
|
||||
{
|
||||
NSWarnMLog(@"unable to open %s - %s", thePath, GSLastErrorStr(errno));
|
||||
RELEASE(self);
|
||||
return nil;
|
||||
}
|
||||
/* Find size of file to be mapped. */
|
||||
length = lseek(fd, 0, SEEK_END);
|
||||
if (length < 0)
|
||||
{
|
||||
NSWarnMLog(@"unable to seek to eof %s - %s",
|
||||
thePath, GSLastErrorStr(errno));
|
||||
close(fd);
|
||||
RELEASE(self);
|
||||
return nil;
|
||||
}
|
||||
/* Position at start of file. */
|
||||
if (lseek(fd, 0, SEEK_SET) != 0)
|
||||
{
|
||||
NSWarnMLog(@"unable to seek to sof %s - %s",
|
||||
thePath, GSLastErrorStr(errno));
|
||||
close(fd);
|
||||
RELEASE(self);
|
||||
return nil;
|
||||
}
|
||||
bytes = mmap(0, length, PROT_READ, MAP_SHARED, fd, 0);
|
||||
if (bytes == MAP_FAILED)
|
||||
{
|
||||
NSWarnMLog(@"mapping failed for %s - %s",
|
||||
thePath, GSLastErrorStr(errno));
|
||||
close(fd);
|
||||
RELEASE(self);
|
||||
self = [dataMalloc allocWithZone: NSDefaultMallocZone()];
|
||||
self = [self initWithContentsOfFile: path];
|
||||
}
|
||||
close(fd);
|
||||
return self;
|
||||
if (thePath == NULL)
|
||||
{
|
||||
NSWarnMLog(@"Open (%@) attempt failed - bad path",localPath);
|
||||
RELEASE(self);
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
#if defined(__MINGW__)
|
||||
fd = _wopen(thePath, _O_RDONLY);
|
||||
#else
|
||||
fd = open(thePath, O_RDONLY);
|
||||
#endif
|
||||
if (fd < 0)
|
||||
{
|
||||
NSWarnMLog(@"unable to open %@ - %s",localPath,GSLastErrorStr(errno));
|
||||
RELEASE(self);
|
||||
return nil;
|
||||
}
|
||||
/* Find size of file to be mapped. */
|
||||
length = lseek(fd, 0, SEEK_END);
|
||||
if (length < 0)
|
||||
{
|
||||
NSWarnMLog(@"unable to seek to eof %@ - %s",localPath,
|
||||
GSLastErrorStr(errno));
|
||||
close(fd);
|
||||
RELEASE(self);
|
||||
return nil;
|
||||
}
|
||||
/* Position at start of file. */
|
||||
if (lseek(fd, 0, SEEK_SET) != 0)
|
||||
{
|
||||
NSWarnMLog(@"unable to seek to sof %@ - %s", localPath,
|
||||
GSLastErrorStr(errno));
|
||||
close(fd);
|
||||
RELEASE(self);
|
||||
return nil;
|
||||
}
|
||||
bytes = mmap(0, length, PROT_READ, MAP_SHARED, fd, 0);
|
||||
if (bytes == MAP_FAILED)
|
||||
{
|
||||
NSWarnMLog(@"mapping failed for %s - %s",localPath, GSLastErrorStr(errno));
|
||||
close(fd);
|
||||
RELEASE(self);
|
||||
self = [dataMalloc allocWithZone: NSDefaultMallocZone()];
|
||||
self = [self initWithContentsOfFile: path];
|
||||
}
|
||||
close(fd);
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue