~ubuntu-branches/ubuntu/saucy/sope/saucy

« back to all changes in this revision

Viewing changes to sope-core/NGStreams/NGFileStream.m

  • Committer: Package Import Robot
  • Author(s): Jeroen Dekkers
  • Date: 2012-05-09 15:39:17 UTC
  • Revision ID: package-import@ubuntu.com-20120509153917-nr4jlm8mktma1yv3
Tags: upstream-1.3.14
ImportĀ upstreamĀ versionĀ 1.3.14

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
24
#if HAVE_UNISTD_H || __APPLE__
 
25
#  include <unistd.h>
 
26
#endif
 
27
#if HAVE_SYS_STAT_H
 
28
#  include <sys/stat.h>
 
29
#endif
 
30
#if HAVE_SYS_FCNTL_H
 
31
#  include <sys/fcntl.h>
 
32
#endif
 
33
#if HAVE_FCNTL_H || __APPLE__
 
34
#  include <fcntl.h>
 
35
#endif
 
36
 
 
37
#include <NGStreams/NGFileStream.h>
 
38
#include <NGStreams/NGBufferedStream.h>
 
39
#include <NGStreams/NGConcreteStreamFileHandle.h>
 
40
#include <NGStreams/NGLockingStream.h>
 
41
#include <NGStreams/NGStreamExceptions.h>
 
42
#include <NGStreams/NGDescriptorFunctions.h>
 
43
#include "common.h"
 
44
#import <Foundation/NSThread.h>
 
45
 
 
46
#if !defined(POLLRDNORM)
 
47
#  define POLLRDNORM POLLIN
 
48
#endif
 
49
 
 
50
// TODO: NGFileStream needs to be changed to operate without throwing 
 
51
//       exceptions
 
52
 
 
53
NGStreams_DECLARE NSString *NGFileReadOnly    = @"r";
 
54
NGStreams_DECLARE NSString *NGFileWriteOnly   = @"w";
 
55
NGStreams_DECLARE NSString *NGFileReadWrite   = @"rw";
 
56
NGStreams_DECLARE NSString *NGFileAppend      = @"a";
 
57
NGStreams_DECLARE NSString *NGFileReadAppend  = @"ra";
 
58
 
 
59
static const int NGInvalidUnixDescriptor = -1;
 
60
static const int NGFileCreationMask      = 0666; // rw-rw-rw-
 
61
 
 
62
@interface _NGConcreteFileStreamFileHandle : NGConcreteStreamFileHandle
 
63
@end
 
64
 
 
65
NGStreams_DECLARE id<NGInputStream>  NGIn  = nil;
 
66
NGStreams_DECLARE id<NGOutputStream> NGOut = nil;
 
67
NGStreams_DECLARE id<NGOutputStream> NGErr = nil;
 
68
 
 
69
@implementation NGFileStream
 
70
 
 
71
// stdio stream
 
72
 
 
73
#if defined(__MINGW32__)
 
74
- (id)__initWithInConsole {
 
75
  if ((self = [self init])) {
 
76
    self->systemPath = @"CONIN$";
 
77
    self->streamMode = NGStreamMode_readWrite;
 
78
    self->fh = GetStdHandle(STD_INPUT_HANDLE);
 
79
    /*
 
80
    self->fh = CreateFile("CONIN$", GENERIC_READ, FILE_SHARE_READ,
 
81
                          NULL,
 
82
                          OPEN_EXISTING,
 
83
                          0,
 
84
                          NULL);
 
85
     */
 
86
  }
 
87
  return self;
 
88
}
 
89
- (id)__initWithOutConsole {
 
90
  if ((self = [self init])) {
 
91
    DWORD written;
 
92
    self->systemPath = @"CONOUT$";
 
93
    self->streamMode = NGStreamMode_readWrite;
 
94
    self->fh         = GetStdHandle(STD_OUTPUT_HANDLE);
 
95
    /*
 
96
    self->fh = CreateFile("CONOUT$", GENERIC_WRITE, FILE_SHARE_WRITE,
 
97
                          NULL,
 
98
                          OPEN_EXISTING,
 
99
                          0,
 
100
                          NULL);
 
101
     */
 
102
    FlushFileBuffers(self->fh);
 
103
  }
 
104
  return self;
 
105
}
 
106
#else
 
107
- (id)__initWithDescriptor:(int)_fd mode:(NGStreamMode)_mode {
 
108
  if ((self = [self init])) {
 
109
    self->fd         = _fd;
 
110
    self->streamMode = _mode;
 
111
  }
 
112
  return self;
 
113
}
 
114
#endif
 
115
 
 
116
void NGInitStdio(void) {
 
117
  static BOOL isInitialized = NO;
 
118
  if (!isInitialized) {
 
119
    NGFileStream *ti = nil, *to = nil, *te = nil;
 
120
    
 
121
    isInitialized = YES;
 
122
 
 
123
#if defined(__MINGW32__)
 
124
    ti = [[NGFileStream alloc] __initWithInConsole];
 
125
    to = [[NGFileStream alloc] __initWithOutConsole];
 
126
    te = [to retain];
 
127
#else
 
128
    ti = [[NGFileStream alloc] __initWithDescriptor:0
 
129
                               mode:NGStreamMode_readOnly];
 
130
    to = [[NGFileStream alloc] __initWithDescriptor:1
 
131
                               mode:NGStreamMode_writeOnly];
 
132
    te = [[NGFileStream alloc] __initWithDescriptor:2
 
133
                               mode:NGStreamMode_writeOnly];
 
134
#endif
 
135
 
 
136
    NGIn  = [[NGBufferedStream alloc] initWithSource:(id)ti];
 
137
    NGOut = [[NGBufferedStream alloc] initWithSource:(id)to];
 
138
    NGErr = [[NGBufferedStream alloc] initWithSource:(id)te];
 
139
 
 
140
    [ti release]; ti = nil;
 
141
    [to release]; to = nil;
 
142
    [te release]; te = nil;
 
143
  }
 
144
}
 
145
 
 
146
+ (void)_makeThreadSafe:(NSNotification *)_notification {
 
147
  NGLockingStream *li = nil, *lo = nil, *le = nil;
 
148
  
 
149
  if ([NGIn isKindOfClass:[NGLockingStream class]])
 
150
    return;
 
151
  
 
152
  li = [[NGLockingStream alloc] initWithSource:(id)NGIn];
 
153
  [NGIn  release]; NGIn  = li;
 
154
  lo = [[NGLockingStream alloc] initWithSource:(id)NGOut]; 
 
155
  [NGOut release]; NGOut = lo;
 
156
  le = [[NGLockingStream alloc] initWithSource:(id)NGErr]; 
 
157
  [NGErr release]; NGErr = le;
 
158
}
 
159
 
 
160
+ (void)_flushForExit:(NSNotification *)_notification {
 
161
  //[NGIn  flush];
 
162
  [NGOut flush];
 
163
  [NGErr flush];
 
164
}
 
165
 
 
166
static void _flushForExit(void) {
 
167
  //[NGIn  flush];
 
168
  [NGOut flush];
 
169
  [NGErr flush];
 
170
}
 
171
 
 
172
+ (void)initialize {
 
173
  BOOL isInitialized = NO;
 
174
  if (!isInitialized) {
 
175
    isInitialized = YES;
 
176
 
 
177
    if ([NSThread isMultiThreaded])
 
178
      [self _makeThreadSafe:nil];
 
179
    else {
 
180
      [[NSNotificationCenter defaultCenter]
 
181
                             addObserver:self
 
182
                             selector:@selector(_makeThreadSafe:)
 
183
                             name:NSWillBecomeMultiThreadedNotification
 
184
                             object:nil];
 
185
    }
 
186
    atexit(_flushForExit);
 
187
  }
 
188
}
 
189
 
 
190
/* normal file stream */
 
191
 
 
192
- (id)init {
 
193
  if ((self = [super init])) {
 
194
    self->streamMode = NGStreamMode_undefined;
 
195
    self->systemPath = nil;
 
196
    self->markDelta  = -1;
 
197
    self->handle     = nil;
 
198
#if defined(__MINGW32__)
 
199
    self->fh         = INVALID_HANDLE_VALUE;
 
200
#else
 
201
    self->fd         = NGInvalidUnixDescriptor;
 
202
#endif
 
203
  }
 
204
  return self;
 
205
}
 
206
 
 
207
- (id)initWithPath:(NSString *)_path {
 
208
  if ((self = [self init])) {
 
209
    self->systemPath = [_path copy];
 
210
  }
 
211
  return self;
 
212
}
 
213
 
 
214
- (id)initWithFileHandle:(NSFileHandle *)_handle {
 
215
  if ((self = [self init])) {
 
216
#if defined(__MINGW32__)
 
217
    self->fh = [_handle nativeHandle];
 
218
#else
 
219
    self->fd = [_handle fileDescriptor];
 
220
#endif
 
221
  }
 
222
  return self;
 
223
}
 
224
 
 
225
- (void)gcFinalize {
 
226
  if ([self isOpen]) {
 
227
#if DEBUG && 0
 
228
    NSLog(@"NGFileStream(gcFinalize): closing %@", self);
 
229
#endif
 
230
    [self close];
 
231
  }
 
232
}
 
233
- (void)dealloc {
 
234
  [self gcFinalize];
 
235
  self->streamMode = NGStreamMode_undefined;
 
236
  [self->systemPath release]; self->systemPath = nil;
 
237
  self->handle = nil;
 
238
  [super dealloc];
 
239
}
 
240
 
 
241
// opening
 
242
 
 
243
- (BOOL)openInMode:(NSString *)_mode {
 
244
  // throws
 
245
  //   NGUnknownStreamModeException  when _mode is invalid
 
246
  //   NGCouldNotOpenStreamException when the file could not be opened
 
247
#if defined(__MINGW32__)
 
248
  DWORD openFlags;
 
249
  DWORD shareMode;
 
250
 
 
251
  if (self->fh != INVALID_HANDLE_VALUE)
 
252
    [self close]; // if stream is open, close and reopen
 
253
 
 
254
  if ([_mode isEqualToString:NGFileReadOnly]) {
 
255
    self->streamMode = NGStreamMode_readOnly;
 
256
    openFlags = GENERIC_READ;
 
257
    shareMode = FILE_SHARE_READ;
 
258
  }
 
259
  else if ([_mode isEqualToString:NGFileWriteOnly]) {
 
260
    self->streamMode = NGStreamMode_writeOnly;
 
261
    openFlags = GENERIC_WRITE;
 
262
    shareMode = FILE_SHARE_WRITE;
 
263
  }
 
264
  else if ([_mode isEqualToString:NGFileReadWrite]) {
 
265
    self->streamMode = NGStreamMode_readWrite;
 
266
    openFlags = GENERIC_READ | GENERIC_WRITE;
 
267
    shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
 
268
  }
 
269
  else {
 
270
    [[[NGUnknownStreamModeException alloc]
 
271
                                    initWithStream:self mode:_mode] raise];
 
272
    return NO;
 
273
  }
 
274
 
 
275
  self->fh = CreateFile([self->systemPath fileSystemRepresentation],
 
276
                        openFlags, shareMode, NULL,
 
277
                        OPEN_ALWAYS, // same as the Unix O_CREAT flag
 
278
                        0,           // security flags ?
 
279
                        NULL);
 
280
 
 
281
  if (self->fh == INVALID_HANDLE_VALUE)
 
282
    [NGCouldNotOpenStreamException raiseWithStream:self];
 
283
 
 
284
#else
 
285
  int openFlags; // flags passed to open() call
 
286
 
 
287
  if (self->fd != NGInvalidUnixDescriptor)
 
288
    [self close]; // if stream is open, close and reopen
 
289
 
 
290
  if ([_mode isEqualToString:NGFileReadOnly]) {
 
291
    self->streamMode = NGStreamMode_readOnly;
 
292
    openFlags = O_RDONLY;
 
293
  }
 
294
  else if ([_mode isEqualToString:NGFileWriteOnly]) {
 
295
    self->streamMode = NGStreamMode_writeOnly;
 
296
    openFlags = O_WRONLY | O_CREAT;
 
297
  }
 
298
  else if ([_mode isEqualToString:NGFileReadWrite]) {
 
299
    self->streamMode = NGStreamMode_readWrite;
 
300
    openFlags = O_RDWR | O_CREAT;
 
301
  }
 
302
  else if ([_mode isEqualToString:NGFileAppend]) {
 
303
    self->streamMode = NGStreamMode_writeOnly;
 
304
    openFlags = O_WRONLY | O_CREAT | O_APPEND;
 
305
  }
 
306
  else if ([_mode isEqualToString:NGFileReadAppend]) {
 
307
    self->streamMode = NGStreamMode_readWrite;
 
308
    openFlags = O_RDWR | O_CREAT | O_APPEND;
 
309
  }
 
310
  else {
 
311
    [[[NGUnknownStreamModeException alloc]
 
312
              initWithStream:self mode:_mode] raise];
 
313
    return NO;
 
314
  }
 
315
 
 
316
  self->fd = open([self->systemPath fileSystemRepresentation],
 
317
                  openFlags,
 
318
                  NGFileCreationMask);
 
319
 
 
320
  if (self->fd == -1) {
 
321
    self->fd = NGInvalidUnixDescriptor;
 
322
 
 
323
    [NGCouldNotOpenStreamException raiseWithStream:self];
 
324
    return NO;
 
325
  }
 
326
#endif
 
327
  
 
328
  self->markDelta = -1; // not marked
 
329
  return YES;
 
330
}
 
331
 
 
332
- (BOOL)isOpen {
 
333
#if defined(__MINGW32__)
 
334
  return (self->fh != INVALID_HANDLE_VALUE) ? YES : NO;
 
335
#else
 
336
  return (self->fd != NGInvalidUnixDescriptor) ? YES : NO;
 
337
#endif
 
338
}
 
339
 
 
340
// Foundation file handles
 
341
 
 
342
- (void)resetFileHandle { // called by NSFileHandle on dealloc
 
343
  self->handle = nil;
 
344
}
 
345
- (NSFileHandle *)fileHandle {
 
346
  if (self->handle == nil)
 
347
    self->handle = [[_NGConcreteFileStreamFileHandle allocWithZone:[self zone]]
 
348
                                                     initWithStream:self];
 
349
  return [self->handle autorelease];
 
350
}
 
351
 
 
352
#if defined(__MINGW32__)
 
353
- (HANDLE)windowsFileHandle {
 
354
  return self->fh;
 
355
}
 
356
#endif
 
357
 
 
358
- (int)fileDescriptor {
 
359
#if defined(__MINGW32__)
 
360
  return (int)[self fileHandle];
 
361
#else
 
362
  return self->fd;
 
363
#endif
 
364
}
 
365
 
 
366
// primitives
 
367
 
 
368
static void _checkOpen(NGFileStream *self, NSString *_reason) {
 
369
#if defined(__MINGW32__)
 
370
  if (self->fh == INVALID_HANDLE_VALUE)
 
371
    [NGStreamNotOpenException raiseWithStream:self reason:_reason];
 
372
#else
 
373
  if (self->fd == NGInvalidUnixDescriptor)
 
374
    [NGStreamNotOpenException raiseWithStream:self reason:_reason];
 
375
#endif
 
376
}
 
377
 
 
378
- (unsigned)readBytes:(void *)_buf count:(unsigned)_len {
 
379
  // throws
 
380
  //   NGWriteOnlyStreamException  when the stream is not readable
 
381
  //   NGStreamNotOpenException    when the stream is not open
 
382
  //   NGEndOfStreamException      when the end of the stream is reached
 
383
  //   NGStreamReadErrorException  when the read call failed
 
384
 
 
385
  _checkOpen(self, @"tried to read from a file stream which is closed");
 
386
 
 
387
  if (!NGCanReadInStreamMode(streamMode))
 
388
    [NGWriteOnlyStreamException raiseWithStream:self];
 
389
 
 
390
  {
 
391
#if defined(__MINGW32__)
 
392
    DWORD readResult = 0;
 
393
 
 
394
    if (ReadFile(self->fh, _buf, _len, &readResult, NULL) == FALSE) {
 
395
      DWORD lastErr = GetLastError();
 
396
 
 
397
      if (lastErr == ERROR_HANDLE_EOF)
 
398
        [NGEndOfStreamException raiseWithStream:self];
 
399
      else
 
400
        [NGStreamReadErrorException raiseWithStream:self errorCode:lastErr];
 
401
    }
 
402
    if (readResult == 0)
 
403
      [NGEndOfStreamException raiseWithStream:self];
 
404
#else
 
405
    int readResult;
 
406
    int retryCount = 0;
 
407
    
 
408
    do {
 
409
      readResult = read(self->fd, _buf, _len);
 
410
      
 
411
      if (readResult == 0)
 
412
        [NGEndOfStreamException raiseWithStream:self];
 
413
      else if (readResult == -1) {
 
414
        int errCode = errno;
 
415
 
 
416
        if (errCode == EINTR)
 
417
          // system call was interrupted
 
418
          retryCount++;
 
419
        else
 
420
          [NGStreamReadErrorException raiseWithStream:self errorCode:errCode];
 
421
      }
 
422
    }
 
423
    while ((readResult <= 0) && (retryCount < 10));
 
424
 
 
425
    if (retryCount >= 10)
 
426
      [NGStreamReadErrorException raiseWithStream:self errorCode:EINTR];
 
427
#endif
 
428
    
 
429
    NSAssert(readResult > 0, @"invalid read method state");
 
430
 
 
431
    // adjust mark
 
432
    if (self->markDelta != -1)
 
433
      self->markDelta += readResult; // increase delta
 
434
    
 
435
    return readResult;
 
436
  }
 
437
}
 
438
 
 
439
- (unsigned)writeBytes:(const void *)_buf count:(unsigned)_len {
 
440
  // throws
 
441
  //   NGReadOnlyStreamException   when the stream is not writeable
 
442
  //   NGStreamNotOpenException    when the stream is not open
 
443
  //   NGStreamWriteErrorException when the write call failed
 
444
  
 
445
  _checkOpen(self, @"tried to write to a file stream which is closed");
 
446
  
 
447
  if (!NGCanWriteInStreamMode(streamMode))
 
448
    [NGReadOnlyStreamException raiseWithStream:self];
 
449
 
 
450
  {
 
451
#if defined(__MINGW32__)
 
452
    DWORD writeResult = 0;
 
453
 
 
454
    if (WriteFile(self->fh, _buf, _len, &writeResult, NULL) == FALSE) {
 
455
      DWORD errorCode = GetLastError();
 
456
 
 
457
      switch (errorCode) {
 
458
        case ERROR_INVALID_HANDLE:
 
459
          [NGStreamWriteErrorException raiseWithStream:self
 
460
                                       reason:@"incorrect file handle"];
 
461
          break;
 
462
        case ERROR_WRITE_PROTECT:
 
463
          [NGStreamWriteErrorException raiseWithStream:self
 
464
                                       reason:@"disk write protected"];
 
465
          break;
 
466
        case ERROR_NOT_READY:
 
467
          [NGStreamWriteErrorException raiseWithStream:self
 
468
                                       reason:@"the drive is not ready"];
 
469
          break;
 
470
        case ERROR_HANDLE_EOF:
 
471
          [NGStreamWriteErrorException raiseWithStream:self
 
472
                                       reason:@"reached end of file"];
 
473
          break;
 
474
        case ERROR_DISK_FULL:
 
475
          [NGStreamWriteErrorException raiseWithStream:self
 
476
                                       reason:@"disk is full"];
 
477
          break;
 
478
        
 
479
        default:
 
480
          [NGStreamWriteErrorException raiseWithStream:self
 
481
                                       errorCode:GetLastError()];
 
482
      }
 
483
      
 
484
      NSLog(@"invalid program state, aborting");
 
485
      abort();
 
486
    }
 
487
#else
 
488
    int writeResult;
 
489
    int retryCount = 0;
 
490
 
 
491
    do {
 
492
      writeResult = write(self->fd, _buf, _len);
 
493
 
 
494
      if (writeResult == -1) {
 
495
        int errCode = errno;
 
496
 
 
497
        if (errCode == EINTR)
 
498
          // system call was interrupted
 
499
          retryCount++;
 
500
        else
 
501
          [NGStreamWriteErrorException raiseWithStream:self errorCode:errno];
 
502
      }
 
503
    }
 
504
    while ((writeResult == -1) && (retryCount < 10));
 
505
 
 
506
    if (retryCount >= 10)
 
507
      [NGStreamWriteErrorException raiseWithStream:self errorCode:EINTR];
 
508
#endif
 
509
    
 
510
    return writeResult;
 
511
  }
 
512
}
 
513
 
 
514
- (BOOL)close {
 
515
#if defined(__MINGW32__)
 
516
  if (self->fh == INVALID_HANDLE_VALUE) {
 
517
    NSLog(@"tried to close already closed stream %@", self);
 
518
    return YES; /* not signaled as an error .. */
 
519
  }
 
520
 
 
521
  if (CloseHandle(self->fh) == FALSE) {
 
522
    [NGCouldNotCloseStreamException raiseWithStream:self];
 
523
    return NO;
 
524
  }
 
525
  
 
526
  self->fh = INVALID_HANDLE_VALUE;
 
527
#else
 
528
  if (self->fd == NGInvalidUnixDescriptor) {
 
529
    NSLog(@"tried to close already closed stream %@", self);
 
530
    return YES; /* not signaled as an error .. */
 
531
  }
 
532
 
 
533
  if (close(self->fd) != 0) {
 
534
    [NGCouldNotCloseStreamException raiseWithStream:self];
 
535
    return NO;
 
536
  }
 
537
  
 
538
  self->fd = NGInvalidUnixDescriptor;
 
539
#endif
 
540
  self->markDelta = -1;
 
541
  return YES;
 
542
}
 
543
 
 
544
- (NGStreamMode)mode {
 
545
  return self->streamMode;
 
546
}
 
547
- (BOOL)isRootStream {
 
548
  return YES;
 
549
}
 
550
 
 
551
#if defined(__MINGW32__)
 
552
- (BOOL)flush {
 
553
  if (self->fh != INVALID_HANDLE_VALUE)
 
554
    FlushFileBuffers(self->fh);
 
555
  return YES;
 
556
}
 
557
#endif
 
558
 
 
559
// blocking
 
560
 
 
561
#if defined(__MINGW32__)
 
562
- (BOOL)wouldBlockInMode:(NGStreamMode)_mode {
 
563
  NSLog(@"%@ not supported in Windows environment !",
 
564
        NSStringFromSelector(_cmd));
 
565
  return YES;
 
566
}
 
567
#else
 
568
- (BOOL)wouldBlockInMode:(NGStreamMode)_mode {
 
569
  short events = 0;
 
570
 
 
571
  if (self->fd == NGInvalidUnixDescriptor)
 
572
    return NO;
 
573
 
 
574
  if (NGCanReadInStreamMode(_mode))  events |= POLLRDNORM;
 
575
  if (NGCanWriteInStreamMode(_mode)) events |= POLLWRNORM;
 
576
 
 
577
  // timeout of 0 means return immediatly
 
578
  return (NGPollDescriptor(self->fd, events, 0) == 1 ? NO : YES);
 
579
}
 
580
#endif
 
581
 
 
582
// marking
 
583
 
 
584
- (BOOL)mark {
 
585
  self->markDelta = 0;
 
586
  return YES;
 
587
}
 
588
- (BOOL)rewind {
 
589
  if (![self moveByOffset:-(self->markDelta)])
 
590
    return NO;
 
591
  self->markDelta = -1;
 
592
  return YES;
 
593
}
 
594
- (BOOL)markSupported {
 
595
  return YES;
 
596
}
 
597
 
 
598
// NGPositionableStream
 
599
 
 
600
- (BOOL)moveToLocation:(unsigned)_location {
 
601
  self->markDelta = -1;
 
602
 
 
603
#if defined(__MINGW32__)
 
604
  if (SetFilePointer(self->fh, _location, NULL, FILE_BEGIN) == -1) {
 
605
    [NGStreamSeekErrorException raiseWithStream:self errorCode:GetLastError()];
 
606
    return NO;
 
607
  }
 
608
#else
 
609
  if (lseek(self->fd, _location, SEEK_SET) == -1) {
 
610
    [NGStreamSeekErrorException raiseWithStream:self errorCode:errno];
 
611
    return NO;
 
612
  }
 
613
#endif
 
614
  return YES;
 
615
}
 
616
- (BOOL)moveByOffset:(int)_delta {
 
617
  self->markDelta += _delta;
 
618
  
 
619
#if defined(__MINGW32__)
 
620
  if (SetFilePointer(self->fh, _delta, NULL, FILE_CURRENT) == -1) {
 
621
    [NGStreamSeekErrorException raiseWithStream:self errorCode:GetLastError()];
 
622
    return NO;
 
623
  }
 
624
#else
 
625
  if (lseek(self->fd, _delta, SEEK_CUR) == -1) {
 
626
    [NGStreamSeekErrorException raiseWithStream:self errorCode:errno];
 
627
    return NO;
 
628
  }
 
629
#endif
 
630
  return YES;
 
631
}
 
632
 
 
633
/* description */
 
634
 
 
635
- (NSString *)description {
 
636
  return [NSString stringWithFormat:
 
637
                     @"<%@[0x%p] path=%@ mode=%@>",
 
638
                     NSStringFromClass([self class]), self,
 
639
                     self->systemPath ? self->systemPath : (NSString *)@"nil",
 
640
                     [self modeDescription]];
 
641
}
 
642
 
 
643
@end /* NGFileStream */
 
644
 
 
645
 
 
646
@implementation _NGConcreteFileStreamFileHandle
 
647
 
 
648
// accessors
 
649
 
 
650
#if defined(__MINGW32__)
 
651
- (HANDLE)fileHandle {
 
652
  return [(NGFileStream *)stream windowsFileHandle];
 
653
}
 
654
#endif
 
655
 
 
656
- (int)fileDescriptor {
 
657
  return [(NGFileStream *)stream fileDescriptor];
 
658
}
 
659
 
 
660
@end