1/* 2 Copyright (C) 2000-2005 SKYRIX Software AG 3 4 This file is part of SOPE. 5 6 SOPE is free software; you can redistribute it and/or modify it under 7 the terms of the GNU Lesser General Public License as published by the 8 Free Software Foundation; either version 2, or (at your option) any 9 later version. 10 11 SOPE is distributed in the hope that it will be useful, but WITHOUT ANY 12 WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 14 License for more details. 15 16 You should have received a copy of the GNU Lesser General Public 17 License along with SOPE; see the file COPYING. If not, write to the 18 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 19 02111-1307, USA. 20*/ 21 22#include "config.h" 23#include "common.h" 24#include "NGStreamPipe.h" 25#include "NGFileStream.h" 26#include "NGBufferedStream.h" 27 28#if defined(WIN32) 29 30@implementation NGStreamPipe 31@end 32 33#else 34 35static const int NGInvalidUnixDescriptor = -1; 36 37@interface _NGConcretePipeFileHandle : NSFileHandle 38{ 39@public 40 int *fd; 41} 42 43- (id)initWithDescriptor:(int *)_fd; 44 45@end 46 47@interface NGFileStream(PrivateMethods) 48- (id)__initWithDescriptor:(int)_fd mode:(NGStreamMode)_mode; 49@end 50 51@implementation NGStreamPipe 52 53+ (id)pipe { 54 return [[[self alloc] init] autorelease]; 55} 56 57- (id)init { 58 if (pipe(self->fildes) == -1) { 59 NSLog (@"pipe() system call failed: %s", strerror (errno)); 60 self = [self autorelease]; 61 return nil; 62 } 63 return self; 64} 65 66- (void)gcFinalize { 67 [self close]; 68} 69 70- (void)dealloc { 71 [self gcFinalize]; 72 [self->fhIn release]; 73 [self->fhOut release]; 74 [super dealloc]; 75} 76 77- (NSFileHandle *)fileHandleForReading { 78 if (self->fhIn == nil) { 79 self->fhIn = [[_NGConcretePipeFileHandle alloc] 80 initWithDescriptor:&(self->fildes[0])]; 81 } 82 return self->fhIn; 83} 84- (NSFileHandle *)fileHandleForWriting { 85 if (self->fhOut == nil) { 86 self->fhOut = [[_NGConcretePipeFileHandle alloc] 87 initWithDescriptor:&(self->fildes[1])]; 88 } 89 return self->fhOut; 90} 91 92- (id<NGByteSequenceStream>)streamForReading { 93 return self; 94} 95- (id<NGOutputStream>)streamForWriting { 96 return self; 97} 98 99- (NSException *)lastException { 100 return nil; 101} 102 103/* NGInputStream */ 104 105- (unsigned)readBytes:(void *)_buf count:(unsigned)_len { 106 int readResult; 107 108 if (self->fildes[0] == NGInvalidUnixDescriptor) { 109 [NGStreamReadErrorException raiseWithStream:self 110 reason:@"read end of pipe is closed"]; 111 } 112 113 readResult = read(self->fildes[0], _buf, _len); 114 115 if (readResult == 0) 116 [NGEndOfStreamException raiseWithStream:self]; 117 else if (readResult == -1) 118 [NGStreamReadErrorException raiseWithStream:self errorCode:errno]; 119 120 return readResult; 121} 122- (BOOL)safeReadBytes:(void *)_buf count:(unsigned)_len { 123 return NGSafeReadBytesFromStream(self, _buf, _len); 124} 125 126/* marks */ 127 128- (BOOL)mark { 129 NSLog(@"WARNING: called mark on a stream which doesn't support marking !"); 130 return NO; 131} 132- (BOOL)rewind { 133 [NGStreamException raiseWithStream:self reason:@"marking not supported"]; 134 return NO; 135} 136- (BOOL)markSupported { 137 return NO; 138} 139 140/* NGOutputStream */ 141 142- (unsigned)writeBytes:(const void *)_buf count:(unsigned)_len { 143 int writeResult; 144 145 if (self->fildes[1] == NGInvalidUnixDescriptor) { 146 [NGStreamWriteErrorException raiseWithStream:self 147 reason:@"write end of pipe is closed"]; 148 } 149 150 writeResult = write(self->fildes[1], _buf, _len); 151 152 if (writeResult == -1) 153 [NGStreamWriteErrorException raiseWithStream:self errorCode:errno]; 154 return writeResult; 155} 156- (BOOL)safeWriteBytes:(const void *)_buf count:(unsigned)_len { 157 return NGSafeWriteBytesToStream(self, _buf, _len); 158} 159 160- (BOOL)flush { 161 return YES; 162} 163 164/* NGStream */ 165 166- (BOOL)close { 167 if (self->fildes[0] != NGInvalidUnixDescriptor) close(self->fildes[0]); 168 if (self->fildes[1] != NGInvalidUnixDescriptor) close(self->fildes[1]); 169 return YES; 170} 171 172- (NGStreamMode)mode { 173 NGStreamMode mode = NGStreamMode_undefined; 174 175 if (self->fildes[0] != NGInvalidUnixDescriptor) 176 mode |= NGStreamMode_readOnly; 177 if (self->fildes[1] != NGInvalidUnixDescriptor) 178 mode |= NGStreamMode_writeOnly; 179 180 return mode; 181} 182 183// NGByteSequenceStream 184 185- (int)readByte { 186 return NGReadByteFromStream(self); 187} 188 189// Extensions 190 191- (BOOL)isOpen { 192 return (self->fildes[0] == NGInvalidUnixDescriptor) && 193 (self->fildes[1] == NGInvalidUnixDescriptor) ? NO : YES; 194} 195 196/* description */ 197 198- (NSString *)description { 199 return [NSString stringWithFormat:@"<0x%p[%@]: in=%i out=%i>", 200 self, NSStringFromClass([self class]), 201 self->fildes[0], self->fildes[1]]; 202} 203 204@end /* NGStreamPipe */ 205 206@implementation _NGConcretePipeFileHandle 207 208- (id)initWithDescriptor:(int *)_fd { 209 self->fd = _fd; 210 return self; 211} 212 213- (int)fileDescriptor { 214 return *(self->fd); 215} 216 217- (void)closeFile { 218 close(*(self->fd)); 219 *(self->fd) = NGInvalidUnixDescriptor; 220} 221 222@end 223 224#endif /* WIN32 */ 225