Patches from Frith-MacDonald.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@2734 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
fedor 1998-02-05 22:06:20 +00:00
parent 955bd04d2b
commit 5732e71692
11 changed files with 749 additions and 109 deletions

View file

@ -1,3 +1,40 @@
Thu Feb 5 10:12:00 1998 Richard Frith-Macdonald <richard@brainstorm.co.uk>
* src/NSConcreteNumber.m: Defined preprocessor values to handle
'promotion' of numeric types and added private methods to support
this. Modified ([-compare:]) to promote numeric values so that
comparisons work as expected. Implemented ([-isEqualToNumber:]),
Implemented ([-description]) and partially ([-descriptionWithLocale:])
Implemented ([-hash]) so that numbers which compare the same also
has the same (so we can use NSNumbers as dictionary keys).
* src/NSData.m: Added non-openstep method ([-relinquishAllocatedBytes])
to ask a data object to hand over it's malloced buffer.
* src/NSNumber.m: Added initialisation methods specified in Rhapsody
documentation.
* src/NSString.m: ([-dataUsingEncoding:allowLossyConversion:]) made
tiny change for efficiency - moving test outside loop - perhaps the
compiler would have optimised it anyway.
* src/Port.m: Modified initialisaers to test for failure to create
NSData objects and return nil as appropriate.
* src/TcpPort.m: ([+newForReceivingFromPortNumber:]) release newly
created port before raising exceptions.
In both ([-invalidate]) methods we remove the port from the various
maps before doing anything else so that invalid ports can't be found
by accident during the invalidation process.
* src/UnixFileHandle.m: ([-readDataOfLength:]) fixed problem with
data object causing read value to be overwritten with nuls.
* src/include/NSData.h: Added ([-relinquishAllocatedBytes])
* src/NSValue.h: Added initialisation methods for NSNumber and
([-isEqualToNumber:]) method.
Thu Feb 5 10:48:35 1998 Adam Fedor <fedor@ultra.doc.com> Thu Feb 5 10:48:35 1998 Adam Fedor <fedor@ultra.doc.com>
* GNUmakefile (GNUSTEP_MAKEFILE_DIR): New variable. Use it to * GNUmakefile (GNUSTEP_MAKEFILE_DIR): New variable. Use it to

View file

@ -94,6 +94,16 @@
+ (id) dataWithShmID: (int)anID length: (unsigned) length; + (id) dataWithShmID: (int)anID length: (unsigned) length;
+ (id) dataWithSharedBytes: (const void*)bytes length: (unsigned) length; + (id) dataWithSharedBytes: (const void*)bytes length: (unsigned) length;
+ (id) dataWithStaticBytes: (const void*)bytes length: (unsigned) length; + (id) dataWithStaticBytes: (const void*)bytes length: (unsigned) length;
/*
* -relinquishAllocatedBytes
* For an NSData object with a malloced buffer, returns that buffer and
* removes it from the NSData object, otherwise returns a nul pointer.
* Use with care, preferably when no-one else has retained the NSData
* object - or they will find it's buffer disappearing unexpectedly.
* Once you have used this method, you own the malloced data and are
* responsible for freeing it.
*/
- (void*) relinquishAllocatedBytes;
@end @end

View file

@ -1,4 +1,4 @@
/* Interface for NSArray for GNUStep /* Interface for NSValue for GNUStep
Copyright (C) 1995, 1996 Free Software Foundation, Inc. Copyright (C) 1995, 1996 Free Software Foundation, Inc.
Written by: Adam Fedor <fedor@boulder.colorado.edu> Written by: Adam Fedor <fedor@boulder.colorado.edu>
@ -74,6 +74,20 @@
+ (NSNumber*) numberWithUnsignedLongLong: (unsigned long long)value; + (NSNumber*) numberWithUnsignedLongLong: (unsigned long long)value;
+ (NSNumber*) numberWithUnsignedShort: (unsigned short)value; + (NSNumber*) numberWithUnsignedShort: (unsigned short)value;
- (id)initWithBool:(BOOL)value;
- (id)initWithChar:(char)value;
- (id)initWithDouble:(double)value;
- (id)initWithFloat:(float)value;
- (id)initWithInt:(int)value;
- (id)initWithLong:(long)value;
- (id)initWithLongLong:(long long)value;
- (id)initWithShort:(short)value;
- (id)initWithUnsignedChar:(unsigned char)value;
- (id)initWithUnsignedInt:(unsigned int)value;
- (id)initWithUnsignedLong:(unsigned long)value;
- (id)initWithUnsignedLongLong:(unsigned long long)value;
- (id)initWithUnsignedShort:(unsigned short)value;
// Accessing Data // Accessing Data
- (BOOL) boolValue; - (BOOL) boolValue;
@ -91,7 +105,11 @@
- (unsigned long) unsignedLongValue; - (unsigned long) unsignedLongValue;
- (unsigned short) unsignedShortValue; - (unsigned short) unsignedShortValue;
- (NSString*) description;
- (NSString*) descriptionWithLocale: (NSDictionary*)locale;
- (NSComparisonResult) compare: (NSNumber*)otherNumber; - (NSComparisonResult) compare: (NSNumber*)otherNumber;
- (BOOL) isEqualToNumber: (NSNumber*)otherNumber;
@end @end

View file

@ -36,56 +36,124 @@
# define NumberTemplate NSBoolNumber # define NumberTemplate NSBoolNumber
# define TYPE_METHOD boolValue # define TYPE_METHOD boolValue
# define TYPE_FORMAT @"%uc" # define TYPE_FORMAT @"%uc"
# define NEXT_ORDER 4
# define NEXT_METHOD shortValue
# define NEXT_CTYPE short
#elif TYPE_ORDER == 1 #elif TYPE_ORDER == 1
# define NumberTemplate NSUCharNumber # define NumberTemplate NSUCharNumber
# define TYPE_METHOD unsignedCharValue # define TYPE_METHOD unsignedCharValue
# define TYPE_FORMAT @"%uc" # define TYPE_FORMAT @"%uc"
# define NEXT_ORDER 4
# define NEXT_METHOD shortValue
# define NEXT_CTYPE short
#elif TYPE_ORDER == 2 #elif TYPE_ORDER == 2
# define NumberTemplate NSCharNumber # define NumberTemplate NSCharNumber
# define TYPE_METHOD charValue # define TYPE_METHOD charValue
# define TYPE_FORMAT @"%c" # define TYPE_FORMAT @"%c"
# define NEXT_ORDER 4
# define NEXT_METHOD shortValue
# define NEXT_CTYPE short
#elif TYPE_ORDER == 3 #elif TYPE_ORDER == 3
# define NumberTemplate NSUShortNumber # define NumberTemplate NSUShortNumber
# define TYPE_METHOD unsignedShortValue # define TYPE_METHOD unsignedShortValue
# define TYPE_FORMAT @"%hu" # define TYPE_FORMAT @"%hu"
# define NEXT_ORDER 6
# define NEXT_METHOD intValue
# define NEXT_CTYPE int
#elif TYPE_ORDER == 4 #elif TYPE_ORDER == 4
# define NumberTemplate NSShortNumber # define NumberTemplate NSShortNumber
# define TYPE_METHOD shortValue # define TYPE_METHOD shortValue
# define TYPE_FORMAT @"%hd" # define TYPE_FORMAT @"%hd"
# define NEXT_ORDER 6
# define NEXT_METHOD intValue
# define NEXT_CTYPE int
#elif TYPE_ORDER == 5 #elif TYPE_ORDER == 5
# define NumberTemplate NSUIntNumber # define NumberTemplate NSUIntNumber
# define TYPE_METHOD unsignedIntValue # define TYPE_METHOD unsignedIntValue
# define TYPE_FORMAT @"%u" # define TYPE_FORMAT @"%u"
# define NEXT_ORDER 8
# define NEXT_METHOD longValue
# define NEXT_CTYPE long
#elif TYPE_ORDER == 6 #elif TYPE_ORDER == 6
# define NumberTemplate NSIntNumber # define NumberTemplate NSIntNumber
# define TYPE_METHOD intValue # define TYPE_METHOD intValue
# define TYPE_FORMAT @"%d" # define TYPE_FORMAT @"%d"
# define NEXT_ORDER 8
# define NEXT_METHOD longValue
# define NEXT_CTYPE long
#elif TYPE_ORDER == 7 #elif TYPE_ORDER == 7
# define NumberTemplate NSULongNumber # define NumberTemplate NSULongNumber
# define TYPE_METHOD unsignedLongValue # define TYPE_METHOD unsignedLongValue
# define TYPE_FORMAT @"%lu" # define TYPE_FORMAT @"%lu"
# define NEXT_ORDER 10
# define NEXT_METHOD longLongValue
# define NEXT_CTYPE long long
#elif TYPE_ORDER == 8 #elif TYPE_ORDER == 8
# define NumberTemplate NSLongNumber # define NumberTemplate NSLongNumber
# define TYPE_METHOD longValue # define TYPE_METHOD longValue
# define TYPE_FORMAT @"%ld" # define TYPE_FORMAT @"%ld"
# define NEXT_ORDER 10
# define NEXT_METHOD longLongValue
# define NEXT_CTYPE long long
#elif TYPE_ORDER == 9 #elif TYPE_ORDER == 9
# define NumberTemplate NSULongLongNumber # define NumberTemplate NSULongLongNumber
# define TYPE_METHOD unsignedLongLongValue # define TYPE_METHOD unsignedLongLongValue
# define TYPE_FORMAT @"%llu" # define TYPE_FORMAT @"%llu"
# define NEXT_ORDER 12
# define NEXT_METHOD doubleValue
# define NEXT_CTYPE double
#elif TYPE_ORDER == 10 #elif TYPE_ORDER == 10
# define NumberTemplate NSLongLongNumber # define NumberTemplate NSLongLongNumber
# define TYPE_METHOD longLongValue # define TYPE_METHOD longLongValue
# define TYPE_FORMAT @"%lld" # define TYPE_FORMAT @"%lld"
# define NEXT_ORDER 12
# define NEXT_METHOD doubleValue
# define NEXT_CTYPE double
#elif TYPE_ORDER == 11 #elif TYPE_ORDER == 11
# define NumberTemplate NSFloatNumber # define NumberTemplate NSFloatNumber
# define TYPE_METHOD floatValue # define TYPE_METHOD floatValue
# define TYPE_FORMAT @"%f" # define TYPE_FORMAT @"%f"
# define NEXT_ORDER 12
# define NEXT_METHOD doubleValue
# define NEXT_CTYPE double
#elif TYPE_ORDER == 12 #elif TYPE_ORDER == 12
# define NumberTemplate NSDoubleNumber # define NumberTemplate NSDoubleNumber
# define TYPE_METHOD doubleValue # define TYPE_METHOD doubleValue
# define TYPE_FORMAT @"%g" # define TYPE_FORMAT @"%g"
# define NEXT_ORDER 12
# define NEXT_METHOD doubleValue
# define NEXT_CTYPE double
#endif #endif
@interface NSNumber (Private)
- (int)_nextOrder;
- (NSComparisonResult) _promotedCompare: (NSNumber*)other;
- (int)_typeOrder;
@end
@implementation NumberTemplate (Private)
- (int)_nextOrder
{
return NEXT_ORDER;
}
- (NSComparisonResult) _promotedCompare: (NSNumber*)other
{
NEXT_CTYPE v0, v1;
v0 = [self NEXT_METHOD];
v1 = [other NEXT_METHOD];
if (v0 == v1)
return NSOrderedSame;
else
return (v0 < v1) ? NSOrderedAscending : NSOrderedDescending;
}
- (int)_typeOrder
{
return TYPE_ORDER;
}
@end
@implementation NumberTemplate @implementation NumberTemplate
- initValue:(const void *)value withObjCType:(const char *)type; - initValue:(const void *)value withObjCType:(const char *)type;
@ -136,11 +204,6 @@
return data; return data;
} }
- (NSString *)stringValue
{
return [NSString stringWithFormat:TYPE_FORMAT, data];
}
- (unsigned char)unsignedCharValue - (unsigned char)unsignedCharValue
{ {
return data; return data;
@ -166,15 +229,84 @@
return data; return data;
} }
- (NSComparisonResult)compare:(NSNumber *)otherNumber - (NSComparisonResult)compare:(NSNumber *)other
{ {
typedef _dt = data; int o = [self _typeOrder];
_dt other_data = [otherNumber TYPE_METHOD];
if (o == [other _typeOrder] || o >= [other _nextOrder]) {
typedef _dt = data;
_dt other_data = [other TYPE_METHOD];
if (data == other_data) if (data == other_data)
return NSOrderedSame; return NSOrderedSame;
else else
return (data < other_data) ? NSOrderedAscending : NSOrderedDescending; return (data < other_data) ?
NSOrderedAscending : NSOrderedDescending;
}
o = [self _nextOrder];
if (o <= [other _typeOrder]) {
NSComparisonResult r = [other compare: self];
if (r == NSOrderedAscending) {
return NSOrderedDescending;
}
if (r == NSOrderedDescending) {
return NSOrderedAscending;
}
return r;
}
if (o >= [other _nextOrder]) {
return [self _promotedCompare: other];
}
else {
NSComparisonResult r = [other _promotedCompare: self];
if (r == NSOrderedAscending) {
return NSOrderedDescending;
}
if (r == NSOrderedDescending) {
return NSOrderedAscending;
}
return r;
}
}
/* Because of the rule that two numbers which are the same according to
* [-isEqual:] must generate the same hash, we must generate the hash
* from the most general representation of the number.
*/
- (unsigned) hash
{
union {
double d;
unsigned char c[sizeof(double)];
} val;
unsigned hash = 0;
int i;
val.d = [self doubleValue];
for (i = 0; i < sizeof(double); i++) {
hash += val.c[i];
}
return hash;
}
- (BOOL) isEqualToNumber: (NSNumber*)o
{
if ([self compare: o] == NSOrderedSame)
return YES;
return NO;
}
- (BOOL) isEqual: o
{
if ([o isKindOf: [NSNumber class]])
return [self isEqualToNumber: (NSNumber*)o];
else
return [super isEqual: o];
}
- (NSString *)descriptionWithLocale: (NSDictionary*)locale
{
return [NSString stringWithFormat:TYPE_FORMAT, data];
} }
// Override these from NSValue // Override these from NSValue
@ -194,18 +326,6 @@
return @encode(_dt); return @encode(_dt);
} }
- (unsigned) hash
{
return (unsigned)data;
}
- (BOOL) isEqual: o
{
if ([o isKindOf: [NSValue class]])
return ((unsigned)data == [o unsignedIntValue]) ? YES : NO;
return NO;
}
// NSCoding // NSCoding
- classForCoder - classForCoder
{ {

View file

@ -800,6 +800,11 @@ readContentsOfFile(NSString* path, void** buf, unsigned* len)
return [[[NSDataStatic alloc] initWithBytesNoCopy:(void*)bytes length:length] return [[[NSDataStatic alloc] initWithBytesNoCopy:(void*)bytes length:length]
autorelease]; autorelease];
} }
- (void*) relinquishAllocatedBytes
{
return 0; /* No data from malloc - return nul pointer */
}
@end @end
@ -1312,6 +1317,15 @@ readContentsOfFile(NSString* path, void** buf, unsigned* len)
length: length]; length: length];
} }
- (void*) relinquishAllocatedBytes
{
void *buf = bytes;
bytes = 0;
length = 0;
return buf;
}
@end @end
#if HAVE_MMAP #if HAVE_MMAP
@ -1732,6 +1746,12 @@ readContentsOfFile(NSString* path, void** buf, unsigned* len)
length = size; length = size;
} }
- (void*) relinquishAllocatedBytes
{
capacity = 0;
return [super relinquishAllocatedBytes];
}
@end @end

View file

@ -31,6 +31,8 @@
#include <Foundation/NSAutoreleasePool.h> #include <Foundation/NSAutoreleasePool.h>
#include <Foundation/NSLock.h> #include <Foundation/NSLock.h>
#include <stdio.h>
/* determine directory reading files */ /* determine directory reading files */
#if defined(HAVE_DIRENT_H) #if defined(HAVE_DIRENT_H)
@ -91,12 +93,22 @@
# include <sys/statfs.h> # include <sys/statfs.h>
#endif #endif
#if HAVE_SYS_FILE_H
#include <sys/file.h>
#endif
#include <errno.h> #include <errno.h>
#ifdef HAVE_SYS_STAT_H #ifdef HAVE_SYS_STAT_H
#include <sys/stat.h> #include <sys/stat.h>
#endif #endif
#include <fcntl.h>
#if HAVE_UTIME_H
# include <utime.h>
#endif
/* include usual headers */ /* include usual headers */
#include <Foundation/NSArray.h> #include <Foundation/NSArray.h>
@ -108,6 +120,19 @@
#include <Foundation/NSPathUtilities.h> #include <Foundation/NSPathUtilities.h>
#include <Foundation/NSFileManager.h> #include <Foundation/NSFileManager.h>
@interface NSFileManager (PrivateMethods)
/* Copies the contents of source file to destination file. Assumes source
and destination are regular files or symbolic links. */
- (BOOL)_copyFile:(NSString*)source toFile:(NSString*)destination
handler:handler;
/* Recursively copies the contents of source directory to destination. */
- (BOOL)_copyPath:(NSString*)source toPath:(NSString*)destination
handler:handler;
@end /* NSFileManager (PrivateMethods) */
/* /*
* NSFileManager implementation * NSFileManager implementation
*/ */
@ -237,44 +262,139 @@ static NSFileManager* defaultManager = nil;
- (BOOL)copyPath:(NSString*)source toPath:(NSString*)destination - (BOOL)copyPath:(NSString*)source toPath:(NSString*)destination
handler:handler handler:handler
{ {
// TODO BOOL sourceIsDir, fileExists;
NSDictionary* attributes;
fileExists = [self fileExistsAtPath:source isDirectory:&sourceIsDir];
if (!fileExists)
return NO;
fileExists = [self fileExistsAtPath:destination];
if (fileExists)
return NO;
attributes = [self fileAttributesAtPath:source traverseLink:NO];
if (sourceIsDir) {
/* If destination directory is a descendant of source directory copying
isn't possible. */
if ([[destination stringByAppendingString:@"/"]
hasPrefix:[source stringByAppendingString:@"/"]])
return NO;
[handler fileManager:self willProcessPath:destination];
if (![self createDirectoryAtPath:destination attributes:attributes]) {
if (handler) {
NSDictionary* errorInfo
= [NSDictionary dictionaryWithObjectsAndKeys:
destination, @"Path",
@"cannot create directory", @"Error",
nil];
return [handler fileManager:self
shouldProceedAfterError:errorInfo];
}
else
return NO;
}
}
if (sourceIsDir) {
if (![self _copyPath:source toPath:destination handler:handler])
return NO;
else {
[self changeFileAttributes:attributes atPath:destination];
return YES;
}
}
else {
[handler fileManager:self willProcessPath:source];
if (![self _copyFile:source toFile:destination handler:handler])
return NO;
else {
[self changeFileAttributes:attributes atPath:destination];
return YES;
}
}
return NO; return NO;
} }
- (BOOL)movePath:(NSString*)source toPath:(NSString*)destination - (BOOL)movePath:(NSString*)source toPath:(NSString*)destination
handler:handler handler:handler
{ {
BOOL sourceIsDir; BOOL sourceIsDir, fileExists;
const char* sourcePath = [self fileSystemRepresentationWithPath:source]; const char* sourcePath = [self fileSystemRepresentationWithPath:source];
const char* destPath = [self fileSystemRepresentationWithPath:destination]; const char* destPath = [self fileSystemRepresentationWithPath:destination];
NSString* destinationParent;
unsigned int sourceDevice, destinationDevice;
if ([self fileExistsAtPath:source isDirectory:&sourceIsDir] fileExists = [self fileExistsAtPath:source isDirectory:&sourceIsDir];
&& !sourceIsDir) { if (!fileExists)
/* `source' is file so simply move it to destination. */ return NO;
fileExists = [self fileExistsAtPath:destination];
if (fileExists)
return NO;
/* Check to see if the source and destination's parent are on the same
physical device so we can perform a rename syscall directly. */
sourceDevice = [[[self fileSystemAttributesAtPath:source]
objectForKey:NSFileSystemNumber]
unsignedIntValue];
destinationParent = [destination stringByDeletingLastPathComponent];
if ([destinationParent isEqual:@""])
destinationParent = @".";
destinationDevice
= [[[self fileSystemAttributesAtPath:destinationParent]
objectForKey:NSFileSystemNumber]
unsignedIntValue];
if (sourceDevice != destinationDevice) {
/* If destination directory is a descendant of source directory moving
isn't possible. */
if (sourceIsDir && [[destination stringByAppendingString:@"/"]
hasPrefix:[source stringByAppendingString:@"/"]])
return NO;
if ([self copyPath:source toPath:destination handler:handler]) {
NSDictionary* attributes;
attributes = [self fileAttributesAtPath:source traverseLink:NO];
[self changeFileAttributes:attributes atPath:destination];
return [self removeFileAtPath:source handler:handler];
}
else
return NO;
}
else {
/* source and destination are on the same device so we can simply
invoke rename on source. */
[handler fileManager:self willProcessPath:source]; [handler fileManager:self willProcessPath:source];
if (rename(sourcePath, destPath) == -1) { if (rename (sourcePath, destPath) == -1) {
if (handler) { if (handler) {
NSDictionary* dict NSDictionary* errorInfo
= [NSDictionary dictionaryWithObjectsAndKeys: = [NSDictionary dictionaryWithObjectsAndKeys:
source, @"Path", source, @"Path",
[NSString stringWithCString:strerror(errno)], @"Error",
destination, @"ToPath", destination, @"ToPath",
@"cannot move file", @"Error",
nil]; nil];
if ([handler fileManager:self shouldProceedAfterError:dict]) if ([handler fileManager:self
shouldProceedAfterError:errorInfo])
return YES; return YES;
} }
return NO; return NO;
} }
return YES;
} }
// TODO: handle directories return NO;
return YES;
} }
- (BOOL)linkPath:(NSString*)source toPath:(NSString*)destination - (BOOL)linkPath:(NSString*)source toPath:(NSString*)destination
handler:handler handler:handler
{ {
// TODO // TODO
[self notImplemented:_cmd];
return NO; return NO;
} }
@ -361,8 +481,26 @@ static NSFileManager* defaultManager = nil;
- (BOOL)createFileAtPath:(NSString*)path contents:(NSData*)contents - (BOOL)createFileAtPath:(NSString*)path contents:(NSData*)contents
attributes:(NSDictionary*)attributes attributes:(NSDictionary*)attributes
{ {
// TODO int fd, len, written;
return NO;
fd = open ([self fileSystemRepresentationWithPath:path],
O_WRONLY|O_TRUNC|O_CREAT, 0644);
if (fd < 0)
return NO;
if (![self changeFileAttributes:attributes atPath:path]) {
close (fd);
return NO;
}
len = [contents length];
if (len)
written = write (fd, [contents bytes], len);
else
written = 0;
close (fd);
return written == len;
} }
// Getting and comparing file contents // Getting and comparing file contents
@ -370,12 +508,14 @@ static NSFileManager* defaultManager = nil;
- (NSData*)contentsAtPath:(NSString*)path - (NSData*)contentsAtPath:(NSString*)path
{ {
// TODO // TODO
[self notImplemented:_cmd];
return nil; return nil;
} }
- (BOOL)contentsEqualAtPath:(NSString*)path1 andPath:(NSString*)path2 - (BOOL)contentsEqualAtPath:(NSString*)path1 andPath:(NSString*)path2
{ {
// TODO // TODO
[self notImplemented:_cmd];
return NO; return NO;
} }
@ -495,12 +635,16 @@ static NSFileManager* defaultManager = nil;
values[8] = NSFileTypeCharacterSpecial; values[8] = NSFileTypeCharacterSpecial;
else if (mode == S_IFBLK) else if (mode == S_IFBLK)
values[8] = NSFileTypeBlockSpecial; values[8] = NSFileTypeBlockSpecial;
#ifdef S_IFLNK
else if (mode == S_IFLNK) else if (mode == S_IFLNK)
values[8] = NSFileTypeSymbolicLink; values[8] = NSFileTypeSymbolicLink;
#endif
else if (mode == S_IFIFO) else if (mode == S_IFIFO)
values[8] = NSFileTypeFifo; values[8] = NSFileTypeFifo;
#ifdef S_IFSOCK
else if (mode == S_IFSOCK) else if (mode == S_IFSOCK)
values[8] = NSFileTypeSocket; values[8] = NSFileTypeSocket;
#endif
else else
values[8] = NSFileTypeUnknown; values[8] = NSFileTypeUnknown;
@ -963,4 +1107,185 @@ static NSFileManager* defaultManager = nil;
{return [self objectForKey:NSFileModificationDate];} {return [self objectForKey:NSFileModificationDate];}
- (NSNumber*)filePosixPermissions; - (NSNumber*)filePosixPermissions;
{return [self objectForKey:NSFilePosixPermissions];} {return [self objectForKey:NSFilePosixPermissions];}
@implementation NSFileManager (PrivateMethods)
- (BOOL)_copyFile:(NSString*)source toFile:(NSString*)destination
handler:handler
{
NSDictionary* attributes;
int i, bufsize = 8096;
int sourceFd, destFd, fileSize, fileMode;
int rbytes, wbytes;
char buffer[bufsize];
/* Assumes source is a file and exists! */
NSAssert1 ([self fileExistsAtPath:source],
@"source file '%@' does not exist!", source);
attributes = [self fileAttributesAtPath:source traverseLink:NO];
NSAssert1 (attributes, @"could not get the attributes for file '%@'",
source);
fileSize = [[attributes objectForKey:NSFileSize] intValue];
fileMode = [[attributes objectForKey:NSFilePosixPermissions] intValue];
/* Open the source file. In case of error call the handler. */
sourceFd = open ([self fileSystemRepresentationWithPath:source], O_RDONLY);
if (sourceFd < 0) {
if (handler) {
NSDictionary* errorInfo
= [NSDictionary dictionaryWithObjectsAndKeys:
source, @"Path",
@"cannot open file for reading", @"Error",
nil];
return [handler fileManager:self
shouldProceedAfterError:errorInfo];
}
else
return NO;
}
/* Open the destination file. In case of error call the handler. */
destFd = open ([self fileSystemRepresentationWithPath:destination],
O_WRONLY|O_CREAT|O_TRUNC, fileMode);
if (destFd < 0) {
if (handler) {
NSDictionary* errorInfo
= [NSDictionary dictionaryWithObjectsAndKeys:
destination, @"ToPath",
@"cannot open file for writing", @"Error",
nil];
close (sourceFd);
return [handler fileManager:self
shouldProceedAfterError:errorInfo];
}
else
return NO;
}
/* Read bufsize bytes from source file and write them into the destination
file. In case of errors call the handler and abort the operation. */
for (i = 0; i < fileSize; i += rbytes) {
rbytes = read (sourceFd, buffer, bufsize);
if (rbytes < 0) {
if (handler) {
NSDictionary* errorInfo
= [NSDictionary dictionaryWithObjectsAndKeys:
source, @"Path",
@"cannot read from file", @"Error",
nil];
close (sourceFd);
close (destFd);
return [handler fileManager:self
shouldProceedAfterError:errorInfo];
}
else
return NO;
}
wbytes = write (destFd, buffer, rbytes);
if (wbytes != rbytes) {
if (handler) {
NSDictionary* errorInfo
= [NSDictionary dictionaryWithObjectsAndKeys:
source, @"Path",
destination, @"ToPath",
@"cannot write to file", @"Error",
nil];
close (sourceFd);
close (destFd);
return [handler fileManager:self
shouldProceedAfterError:errorInfo];
}
else
return NO;
}
}
close (sourceFd);
close (destFd);
return YES;
}
- (BOOL)_copyPath:(NSString*)source
toPath:(NSString*)destination
handler:handler
{
NSDirectoryEnumerator* enumerator;
NSString* dirEntry;
NSString* sourceFile;
NSString* fileType;
NSString* destinationFile;
NSDictionary* attributes;
NSAutoreleasePool* pool;
pool = [NSAutoreleasePool new];
enumerator = [self enumeratorAtPath:source];
while ((dirEntry = [enumerator nextObject])) {
attributes = [enumerator fileAttributes];
fileType = [attributes objectForKey:NSFileType];
sourceFile = [source stringByAppendingPathComponent:dirEntry];
destinationFile
= [destination stringByAppendingPathComponent:dirEntry];
[handler fileManager:self willProcessPath:sourceFile];
if ([fileType isEqual:NSFileTypeDirectory]) {
if (![self createDirectoryAtPath:destinationFile
attributes:attributes]) {
if (handler) {
NSDictionary* errorInfo
= [NSDictionary dictionaryWithObjectsAndKeys:
destinationFile, @"Path",
@"cannot create directory", @"Error",
nil];
if (![handler fileManager:self
shouldProceedAfterError:errorInfo])
return NO;
}
else
return NO;
}
else {
[enumerator skipDescendents];
if (![self _copyPath:sourceFile toPath:destinationFile
handler:handler])
return NO;
}
}
else if ([fileType isEqual:NSFileTypeRegular]) {
if (![self _copyFile:sourceFile toFile:destinationFile
handler:handler])
return NO;
}
else if ([fileType isEqual:NSFileTypeSymbolicLink]) {
if (![self createSymbolicLinkAtPath:destinationFile
pathContent:sourceFile]) {
if (handler) {
NSDictionary* errorInfo
= [NSDictionary dictionaryWithObjectsAndKeys:
sourceFile, @"Path",
destinationFile, @"ToPath",
@"cannot create symbolic link", @"Error",
nil];
if (![handler fileManager:self
shouldProceedAfterError:errorInfo])
return NO;
}
else
return NO;
}
}
else {
NSLog(@"cannot copy file '%@' of type '%@'", sourceFile, fileType);
}
[self changeFileAttributes:attributes atPath:destinationFile];
}
[pool release];
return YES;
}
@end /* NSFileManager (PrivateMethods) */
@end @end

View file

@ -182,6 +182,95 @@
return [NSNumber numberWithInt: 0]; return [NSNumber numberWithInt: 0];
} }
- (id)initWithBool:(BOOL)value
{
[self dealloc];
return self=[[NSBoolNumber alloc] initValue:&value withObjCType:NULL];
}
- (id)initWithChar:(char)value
{
[self dealloc];
return self=[[NSCharNumber alloc] initValue:&value withObjCType:NULL];
}
- (id)initWithDouble:(double)value
{
[self dealloc];
return self=[[NSDoubleNumber alloc] initValue:&value withObjCType:NULL];
}
- (id)initWithFloat:(float)value
{
[self dealloc];
return self=[[NSFloatNumber alloc] initValue:&value withObjCType:NULL];
}
- (id)initWithInt:(int)value
{
[self dealloc];
return self=[[NSIntNumber alloc] initValue:&value withObjCType:NULL];
}
- (id)initWithLong:(long)value
{
[self dealloc];
return self=[[NSLongNumber alloc] initValue:&value withObjCType:NULL];
}
- (id)initWithLongLong:(long long)value
{
[self dealloc];
return self=[[NSLongLongNumber alloc] initValue:&value withObjCType:NULL];
}
- (id)initWithShort:(short)value
{
[self dealloc];
return self=[[NSShortNumber alloc] initValue:&value withObjCType:NULL];
}
- (id)initWithUnsignedChar:(unsigned char)value
{
[self dealloc];
return self=[[NSUCharNumber alloc] initValue:&value withObjCType:NULL];
}
- (id)initWithUnsignedInt:(unsigned int)value
{
[self dealloc];
return self=[[NSUIntNumber alloc] initValue:&value withObjCType:NULL];
}
- (id)initWithUnsignedLong:(unsigned long)value
{
[self dealloc];
return self=[[NSULongNumber alloc] initValue:&value withObjCType:NULL];
}
- (id)initWithUnsignedLongLong:(unsigned long long)value
{
[self dealloc];
return self=[[NSULongLongNumber alloc] initValue:&value withObjCType:NULL];
}
- (id)initWithUnsignedShort:(unsigned short)value
{
[self dealloc];
return self=[[NSUShortNumber alloc] initValue:&value withObjCType:NULL];
}
- (NSString*) description
{
return [self descriptionWithLocale: nil];
}
- (NSString*) descriptionWithLocale: (NSDictionary*)locale
{
[self subclassResponsibility:_cmd];
return nil;
}
/* All the rest of these methods must be implemented by a subclass */ /* All the rest of these methods must be implemented by a subclass */
- (BOOL)boolValue - (BOOL)boolValue
{ {
@ -233,8 +322,7 @@
- (NSString *)stringValue - (NSString *)stringValue
{ {
[self subclassResponsibility:_cmd]; return [self descriptionWithLocale: nil];
return 0;
} }
- (unsigned char)unsignedCharValue - (unsigned char)unsignedCharValue
@ -273,6 +361,18 @@
return 0; return 0;
} }
- (unsigned) hash
{
[self subclassResponsibility:_cmd];
return 0;
}
- (BOOL)isEqualToNumber:(NSNumber *)otherNumber
{
[self subclassResponsibility:_cmd];
return NO;
}
// NSCoding (done by subclasses) // NSCoding (done by subclasses)
- (void)encodeWithCoder:(NSCoder *)coder - (void)encodeWithCoder:(NSCoder *)coder
{ {
@ -286,9 +386,4 @@
return self; return self;
} }
- description
{
return [self stringValue];
}
@end @end

View file

@ -2016,13 +2016,14 @@ else
unsigned char *buff; unsigned char *buff;
char t; char t;
OBJC_MALLOC(buff, char, len+1); OBJC_MALLOC(buff, char, len+1);
for(count=0; count<len; count++) if(!flag)
if(!flag) for(count=0; count<len; count++)
if((t = encode_unitochar([self characterAtIndex: count], encoding))) if((t = encode_unitochar([self characterAtIndex: count], encoding)))
buff[count] = t; buff[count] = t;
else else
return nil; return nil;
else /* lossy */ else /* lossy */
for(count=0; count<len; count++)
if((t = encode_unitochar([self characterAtIndex: count], encoding))) if((t = encode_unitochar([self characterAtIndex: count], encoding)))
buff[count] = t; buff[count] = t;
else else
@ -2039,7 +2040,7 @@ else
simple replacement for character */ simple replacement for character */
buff[count] = '*'; buff[count] = '*';
}; };
buff[count]=0; buff[count]=0;
return [NSData dataWithBytes: (char *)buff length: count]; return [NSData dataWithBytes: (char *)buff length: count];
} }
else else

View file

@ -165,12 +165,14 @@
receivingInPort: ip receivingInPort: ip
replyOutPort: op replyOutPort: op
{ {
[super initWithCapacity: c self = [super initWithCapacity: c prefix: 0];
prefix: 0]; if (self)
assert ([op isValid]); {
assert (!ip || [ip isValid]); assert ([op isValid]);
_reply_out_port = op; assert (!ip || [ip isValid]);
_receiving_in_port = ip; _reply_out_port = op;
_receiving_in_port = ip;
}
return self; return self;
} }
@ -193,10 +195,12 @@
- initForSendingWithCapacity: (unsigned)c - initForSendingWithCapacity: (unsigned)c
replyInPort: ip replyInPort: ip
{ {
[super initWithCapacity: c self = [super initWithCapacity: c prefix: [[self class] prefixSize]];
prefix: [[self class] prefixSize]]; if (self)
assert ([ip isValid]); {
_reply_in_port = ip; assert ([ip isValid]);
_reply_in_port = ip;
}
return self; return self;
} }

View file

@ -720,6 +720,7 @@ static NSMapTable* port_number_2_port;
p->_port_socket = socket (AF_INET, SOCK_STREAM, 0); p->_port_socket = socket (AF_INET, SOCK_STREAM, 0);
if (p->_port_socket < 0) if (p->_port_socket < 0)
{ {
[p release];
[NSException raise: NSInternalInconsistencyException [NSException raise: NSInternalInconsistencyException
format: @"[TcpInPort +newForReceivingFromPortNumber:] socket(): %s", format: @"[TcpInPort +newForReceivingFromPortNumber:] socket(): %s",
strerror(errno)]; strerror(errno)];
@ -779,6 +780,7 @@ static NSMapTable* port_number_2_port;
} }
} }
if (ok == NO) { if (ok == NO) {
[p release];
[NSException raise: NSInternalInconsistencyException [NSException raise: NSInternalInconsistencyException
format: @"[TcpInPort +newForReceivingFromPortNumber:] bind(): %s", format: @"[TcpInPort +newForReceivingFromPortNumber:] bind(): %s",
strerror(errno)]; strerror(errno)];
@ -796,6 +798,7 @@ static NSMapTable* port_number_2_port;
&size) &size)
< 0) < 0)
{ {
[p release];
[NSException raise: NSInternalInconsistencyException [NSException raise: NSInternalInconsistencyException
format: @"[TcpInPort +newForReceivingFromPortNumber:] getsockname(): %s", format: @"[TcpInPort +newForReceivingFromPortNumber:] getsockname(): %s",
strerror(errno)]; strerror(errno)];
@ -811,6 +814,7 @@ static NSMapTable* port_number_2_port;
unique host address that can identify us across the network. */ unique host address that can identify us across the network. */
if (gethostname (hostname, len) < 0) if (gethostname (hostname, len) < 0)
{ {
[p release];
[NSException raise: NSInternalInconsistencyException [NSException raise: NSInternalInconsistencyException
format: @"[TcpInPort +newForReceivingFromPortNumber:] gethostname(): %s", format: @"[TcpInPort +newForReceivingFromPortNumber:] gethostname(): %s",
strerror(errno)]; strerror(errno)];
@ -832,6 +836,7 @@ static NSMapTable* port_number_2_port;
/* xxx Make this "10" a class variable? */ /* xxx Make this "10" a class variable? */
if (listen (p->_port_socket, 10) < 0) if (listen (p->_port_socket, 10) < 0)
{ {
[p release];
[NSException raise: NSInternalInconsistencyException [NSException raise: NSInternalInconsistencyException
format: @"[TcpInPort +newForReceivingFromPortNumber:] listen(): %s", format: @"[TcpInPort +newForReceivingFromPortNumber:] listen(): %s",
strerror(errno)]; strerror(errno)];
@ -860,7 +865,7 @@ static NSMapTable* port_number_2_port;
if (p) { if (p) {
int port = [p portNumber]; int port = [p portNumber];
if (nameServer([name cStringNoCopy], 0, GDO_REGISTER, &sin, port, 1) == 0) { if (nameServer([name cString], 0, GDO_REGISTER, &sin, port, 1) == 0) {
[p release]; [p release];
return nil; return nil;
} }
@ -868,7 +873,7 @@ static NSMapTable* port_number_2_port;
return p; return p;
#else #else
return [self newForReceivingFromPortNumber: return [self newForReceivingFromPortNumber:
name_2_port_number ([name cStringNoCopy])]; name_2_port_number ([name cString])];
#endif /* GDOMAP */ #endif /* GDOMAP */
} }
@ -990,7 +995,7 @@ static NSMapTable* port_number_2_port;
fprintf (stderr, fprintf (stderr,
"%s: Accepted connection from\n %s.\n", "%s: Accepted connection from\n %s.\n",
object_get_class_name (self), object_get_class_name (self),
[[op description] cStringNoCopy]); [[op description] cString]);
[NotificationDispatcher [NotificationDispatcher
postNotificationName: InPortAcceptedClientNotification postNotificationName: InPortAcceptedClientNotification
object: self object: self
@ -1154,7 +1159,7 @@ assert(type == ET_RPORT);
fprintf (stderr, fprintf (stderr,
"%s: Closed connection from\n %s\n", "%s: Closed connection from\n %s\n",
object_get_class_name (self), object_get_class_name (self),
[[p description] cStringNoCopy]); [[p description] cString]);
packet = NSMapGet (_client_sock_2_packet, (void*)s); packet = NSMapGet (_client_sock_2_packet, (void*)s);
if (packet) if (packet)
@ -1198,6 +1203,12 @@ assert(type == ET_RPORT);
id out_ports[count]; id out_ports[count];
int i; int i;
/* These are here, and not in -dealloc, to prevent
+newForReceivingFromPortNumber: from returning invalid sockets. */
NSMapRemove (socket_2_port, (void*)_port_socket);
NSMapRemove (port_number_2_port,
(void*)(int) ntohs(_listening_address.sin_port));
for (i = 0; for (i = 0;
NSNextMapEnumeratorPair (&me, (void*)&sock, (void*)&out_port); NSNextMapEnumeratorPair (&me, (void*)&sock, (void*)&out_port);
i++) i++)
@ -1213,17 +1224,14 @@ assert(type == ET_RPORT);
getting it. This may help Connection invalidation confusion. getting it. This may help Connection invalidation confusion.
However, then the process might run out of FD's if the close() However, then the process might run out of FD's if the close()
was delayed too long. */ was delayed too long. */
if (_port_socket > 0)
{
#ifdef __WIN32__ #ifdef __WIN32__
closesocket (_port_socket); closesocket (_port_socket);
#else #else
close (_port_socket); close (_port_socket);
#endif /* __WIN32__ */ #endif /* __WIN32__ */
}
/* These are here, and not in -dealloc, to prevent
+newForReceivingFromPortNumber: from returning invalid sockets. */
NSMapRemove (socket_2_port, (void*)_port_socket);
NSMapRemove (port_number_2_port,
(void*)(int) ntohs(_listening_address.sin_port));
/* This also posts a NSPortDidBecomeInvalidNotification. */ /* This also posts a NSPortDidBecomeInvalidNotification. */
[super invalidate]; [super invalidate];
@ -1414,15 +1422,20 @@ static NSMapTable *out_port_bag = NULL;
!= sockaddr->sin_addr.s_addr)) != sockaddr->sin_addr.s_addr))
[self error:"Can't change reply port of an out port once set"]; [self error:"Can't change reply port of an out port once set"];
#else #else
/* If someone is trying to change the port of this socket, the
old one must have died - invalidate it. */
if ((p->_remote_in_port_address.sin_port if ((p->_remote_in_port_address.sin_port
!= sockaddr->sin_port) != sockaddr->sin_port)
|| (p->_remote_in_port_address.sin_addr.s_addr || (p->_remote_in_port_address.sin_addr.s_addr
!= sockaddr->sin_addr.s_addr)) != sockaddr->sin_addr.s_addr))
{ {
[p invalidate]; NSString *od = [p description];
p = nil;
NSMapRemove (out_port_bag, (void*)p);
memcpy (&(p->_remote_in_port_address),
sockaddr,
sizeof (p->_remote_in_port_address));
NSMapInsert (out_port_bag, (void*)p, (void*)p);
NSLog(@"Out port changed from %@ to %@\n", od,
[p description]);
} }
#endif #endif
} }
@ -1434,7 +1447,7 @@ static NSMapTable *out_port_bag = NULL;
sizeof (p->_remote_in_port_address)); sizeof (p->_remote_in_port_address));
if (debug_tcp_port) if (debug_tcp_port)
printf ("TcpOutPort setting remote address\n%s\n", printf ("TcpOutPort setting remote address\n%s\n",
[[self description] cStringNoCopy]); [[self description] cString]);
} }
} }
if (p) if (p)
@ -1456,6 +1469,7 @@ static NSMapTable *out_port_bag = NULL;
p->_port_socket = socket (AF_INET, SOCK_STREAM, 0); p->_port_socket = socket (AF_INET, SOCK_STREAM, 0);
if (p->_port_socket < 0) if (p->_port_socket < 0)
{ {
[p release];
[NSException raise: NSInternalInconsistencyException [NSException raise: NSInternalInconsistencyException
format: @"[TcpInPort newForSendingToSockaddr:...] socket(): %s", format: @"[TcpInPort newForSendingToSockaddr:...] socket(): %s",
strerror(errno)]; strerror(errno)];
@ -1478,9 +1492,7 @@ static NSMapTable *out_port_bag = NULL;
time being, and may get set later by calling time being, and may get set later by calling
+newForSendingToSockaddr.. with a non-zero socket, and a +newForSendingToSockaddr.. with a non-zero socket, and a
non-NULL sockaddr. */ non-NULL sockaddr. */
p->_remote_in_port_address.sin_family = 0; memset (&(p->_remote_in_port_address), '\0', sizeof(*sockaddr));
p->_remote_in_port_address.sin_port = 0;
p->_remote_in_port_address.sin_addr.s_addr = 0;
} }
/* xxx Do I need to bind(_port_socket) to this address? I don't think so. */ /* xxx Do I need to bind(_port_socket) to this address? I don't think so. */
@ -1494,18 +1506,12 @@ static NSMapTable *out_port_bag = NULL;
if (connect (p->_port_socket, if (connect (p->_port_socket,
(struct sockaddr*)&(p->_remote_in_port_address), (struct sockaddr*)&(p->_remote_in_port_address),
sizeof(p->_remote_in_port_address)) sizeof(p->_remote_in_port_address)) < 0)
< 0)
{ {
#if 0 [p release];
close(p->_port_socket); [NSException raise: NSInternalInconsistencyException
[NSException raise: NSInternalInconsistencyException
format: @"[TcpInPort newForSendingToSockaddr:...] connect(): %s", format: @"[TcpInPort newForSendingToSockaddr:...] connect(): %s",
strerror(errno)]; strerror(errno)];
#else
[p release];
return nil;
#endif
} }
/* /*
@ -1565,7 +1571,7 @@ static NSMapTable *out_port_bag = NULL;
*first_dot = '\0'; *first_dot = '\0';
} }
else else
host_cstring = [hostname cStringNoCopy]; host_cstring = [hostname cString];
hp = gethostbyname ((char*)host_cstring); hp = gethostbyname ((char*)host_cstring);
if (!hp) if (!hp)
[self error: "unknown host: \"%s\"", host_cstring]; [self error: "unknown host: \"%s\"", host_cstring];
@ -1589,7 +1595,7 @@ static NSMapTable *out_port_bag = NULL;
int i; int i;
id c = nil; id c = nil;
found = nameServer([name cStringNoCopy], [hostname cStringNoCopy], found = nameServer([name cString], [hostname cString],
GDO_LOOKUP, sin, 0, 100); GDO_LOOKUP, sin, 0, 100);
for (i = 0; c == nil && i < found; i++) for (i = 0; c == nil && i < found; i++)
{ {
@ -1600,8 +1606,7 @@ static NSMapTable *out_port_bag = NULL;
return c; return c;
#else #else
return [self newForSendingToPortNumber: return [self newForSendingToPortNumber:
name_2_port_number ([name cStringNoCopy]) name_2_port_number ([name cString]) onHost: hostname];;
onHost: hostname];;
#endif /* GDOMAP */ #endif /* GDOMAP */
} }
@ -1700,22 +1705,6 @@ static NSMapTable *out_port_bag = NULL;
_polling_in_port = nil; _polling_in_port = nil;
/* This also posts a NSPortDidBecomeInvalidNotification. */
[super invalidate];
/* xxx Perhaps should delay this close() to keep another port from
getting it. This may help Connection invalidation confusion. */
#ifdef __WIN32__
if (closesocket (_port_socket) < 0)
#else
if (close (_port_socket) < 0)
#endif /* __WIN32 */
{
[NSException raise: NSInternalInconsistencyException
format: @"[TcpOutPort -invalidate:] close(): %s",
strerror(errno)];
}
/* This is here, and not in -dealloc, because invalidated /* This is here, and not in -dealloc, because invalidated
but not dealloc'ed ports should not be returned from but not dealloc'ed ports should not be returned from
the out_port_bag in +newForSendingToSockaddr:... */ the out_port_bag in +newForSendingToSockaddr:... */
@ -1725,6 +1714,25 @@ static NSMapTable *out_port_bag = NULL;
the socket_2_port in +newForSendingToSockaddr:... */ the socket_2_port in +newForSendingToSockaddr:... */
NSMapRemove (socket_2_port, (void*)_port_socket); NSMapRemove (socket_2_port, (void*)_port_socket);
/* This also posts a NSPortDidBecomeInvalidNotification. */
[super invalidate];
/* xxx Perhaps should delay this close() to keep another port from
getting it. This may help Connection invalidation confusion. */
if (_port_socket > 0)
{
#ifdef __WIN32__
if (closesocket (_port_socket) < 0)
#else
if (close (_port_socket) < 0)
#endif /* __WIN32 */
{
[NSException raise: NSInternalInconsistencyException
format: @"[TcpOutPort -invalidate:] close(): %s",
strerror(errno)];
}
}
[port _connectedOutPortInvalidated: self]; [port _connectedOutPortInvalidated: self];
[port release]; [port release];
} }

View file

@ -631,9 +631,11 @@ getAddr(NSString* name, NSString* svc, NSString* pcl, struct sockaddr_in *sin)
{ {
NSMutableData* d; NSMutableData* d;
int pos; int pos;
char *buf;
[self checkRead]; [self checkRead];
d = [NSMutableData dataWithCapacity:len]; buf = objc_malloc(len);
d = [NSMutableData dataWithBytesNoCopy: buf length: len];
if ((pos = read(descriptor, [d mutableBytes], len)) < 0) if ((pos = read(descriptor, [d mutableBytes], len)) < 0)
{ {
[NSException raise: NSFileHandleOperationException [NSException raise: NSFileHandleOperationException