2 NSPosixFileDescriptor.m
4 Copyright (C) 1995, 1996 Ovidiu Predescu and Mircea Oancea.
7 Author: Mircea Oancea <mircea@jupiter.elcom.pub.ro>
9 This file is part of libFoundation.
11 Permission to use, copy, modify, and distribute this software and its
12 documentation for any purpose and without fee is hereby granted, provided
13 that the above copyright notice appear in all copies and that both that
14 copyright notice and this permission notice appear in supporting
17 We disclaim all warranties with regard to this software, including all
18 implied warranties of merchantability and fitness, in no event shall
19 we be liable for any special, indirect or consequential damages or any
20 damages whatsoever resulting from loss of use, data or profits, whether in
21 an action of contract, negligence or other tortious action, arising out of
22 or in connection with the use or performance of this software.
28 #if defined(__MINGW32__)
32 # include <sys/ioctl.h>
35 #include <Foundation/common.h>
36 #include <Foundation/NSString.h>
37 #include <Foundation/NSArray.h>
38 #include <Foundation/NSData.h>
39 #include <Foundation/NSException.h>
40 #include <Foundation/NSPosixFileDescriptor.h>
41 #include <Foundation/NSRunLoop.h>
42 #include <Foundation/NSPathUtilities.h>
43 #include <Foundation/exceptions/GeneralExceptions.h>
45 #include "NSMappedData.h"
47 @implementation NSPosixFileDescriptor
49 // Getting a standard NSPosixFileDescriptor
51 static NSPosixFileDescriptor* descriptorForStandardInput = nil;
52 static NSPosixFileDescriptor* descriptorForStandardOutput = nil;
53 static NSPosixFileDescriptor* descriptorForStandardError = nil;
57 if (!descriptorForStandardInput)
58 descriptorForStandardInput = [[self alloc]
59 initWithFileDescriptor:fileno(stdin)];
60 if (!descriptorForStandardOutput)
61 descriptorForStandardOutput = [[self alloc]
62 initWithFileDescriptor:fileno(stdout)];
63 if (!descriptorForStandardError)
64 descriptorForStandardError = [[self alloc]
65 initWithFileDescriptor:fileno(stderr)];
68 + (id)descriptorWithStandardInput
70 return descriptorForStandardInput;
73 + (id)descriptorWithStandardOutput
75 return descriptorForStandardOutput;
78 + (id)descriptorWithStandardError
80 return descriptorForStandardError;
85 - (id)initWithFileDescriptor:(int)fileDescriptor
92 - (id)initWithCStringPath:(const char*)aPath flags:(int)someFlags
93 createMode:(int)someMode
95 fd = open(aPath, someFlags, someMode);
98 NSLog(@"%s: couldn't open file '%s': %s", __PRETTY_FUNCTION__,
99 aPath, strerror(errno));
108 - (id)initWithPath:(NSString*)aPath
110 return [self initWithCStringPath:[aPath fileSystemRepresentation]
111 flags:O_RDONLY createMode:0];
114 - (id)initWithPath:(NSString*)aPath flags:(int)someFlags
116 return [self initWithCStringPath:[aPath fileSystemRepresentation]
117 flags:someFlags createMode:0];
120 - (id)initWithPath:(NSString*)aPath flags:(int)someFlags
121 createMode:(int)someMode
123 return [self initWithCStringPath:[aPath fileSystemRepresentation]
124 flags:someFlags createMode:someMode];
136 - (int)fileDescriptor
143 - (NSData *)readEntireFile
148 if ((ret = lseek(fd, 0, SEEK_END)) == -1) {
150 [[[PosixFileOperationException alloc]
151 initWithFormat:@"could not lseek to end"] raise];
155 return [self readFileRange:range];
158 - (NSData *)readRestOfFile
163 if ((ret = lseek(fd, 0, SEEK_CUR)) == -1) {
165 [[[PosixFileOperationException alloc]
166 initWithFormat:@"could not lseek to cur"] raise];
169 range.location = ret;
171 if ((ret = lseek(fd, 0, SEEK_END)) == -1) {
173 [[[PosixFileOperationException alloc]
174 initWithFormat:@"could not lseek to end"] raise];
177 range.location = ret - range.location;
179 return [self readFileRange:range];
182 - (NSData *)readFileRange:(NSRange)range
187 bytes = MallocAtomic(range.length);
189 if ((ret = lseek(fd, range.location, SEEK_SET)) == -1) {
191 [[[PosixFileOperationException alloc]
192 initWithFormat:@"could not lseek set"] raise];
195 if (read(fd, bytes, range.length) != (int)range.length) {
197 [[[PosixFileOperationException alloc]
198 initWithFormat:@"could not read %d bytes", range.length] raise];
201 return AUTORELEASE([[NSData alloc]
202 initWithBytesNoCopy:bytes length:range.length]);
205 - (void)readBytes:(void *)bytes range:(NSRange)range
209 if ((ret = lseek(fd, range.location, SEEK_SET)) == -1) {
211 [[[PosixFileOperationException alloc]
212 initWithFormat:@"could not lseek set"] raise];
215 if (read(fd, bytes, range.length) != (int)range.length)
216 [[[PosixFileOperationException alloc]
217 initWithFormat:@"could not read %d bytes", range.length] raise];
220 - (NSData *)readFileLength:(long)length
225 NSAssert(length >= 0, @"invalid length %i", length);
228 if ((ret = lseek(fd, 0, SEEK_CUR)) == -1) {
230 [[[PosixFileOperationException alloc]
231 initWithFormat:@"could not lseek cur"] raise];
233 range.location = ret;
234 range.length = length;
236 return [self readFileRange:range];
241 - (void)writeData:(NSData*)aData
243 NSRange range = {0, [aData length]};
244 [self writeData:aData range:range];
247 - (void)writeData:(NSData*)aData range:(NSRange)range
251 if (range.location + range.length > [aData length]) {
252 [[[RangeException alloc]
253 initWithReason:@"invalid range in NSData" size:[aData length]
254 index:range.location+range.length] raise];
257 bytes = (char*)[aData bytes] + range.location;
258 if (write(fd, bytes, range.length) != (int)range.length) {
259 [[[PosixFileOperationException alloc]
260 initWithFormat:@"could not write %d bytes", range.length] raise];
264 - (void)writeString:(NSString*)string
266 NSRange range = {0, [string cStringLength]};
267 [self writeString:string range:range];
270 - (void)writeString:(NSString*)string range:(NSRange)range
272 unsigned len = range.length;
275 if (range.location + range.length > [string cStringLength])
276 [[[RangeException alloc]
277 initWithReason:@"invalid range in NSString"
278 size:[string cStringLength]
279 index:range.location + range.length] raise];
281 bytes = (char*)[string cString] + range.location;
283 int res = write(fd, bytes, len);
286 [[[PosixFileOperationException alloc]
287 initWithFormat:@"could not write %d bytes", len] raise];
296 - (int unsigned)fileLength
300 if ((cur = lseek(fd, 0, SEEK_CUR)) == -1) {
302 [[[PosixFileOperationException alloc]
303 initWithFormat:@"could not lseek to cur"] raise];
305 if ((len = lseek(fd, 0, SEEK_END)) == -1) {
307 [[[PosixFileOperationException alloc]
308 initWithFormat:@"could not lseek to end"] raise];
311 if ((ret = lseek(fd, cur, SEEK_SET)) == -1) {
313 [[[PosixFileOperationException alloc]
314 initWithFormat:@"could not lseek set"] raise];
319 - (int unsigned)filePosition
323 if ((ret = lseek(fd, 0, SEEK_CUR)) == -1) {
325 [[[PosixFileOperationException alloc]
326 initWithFormat:@"could not lseek to cur"] raise];
334 lseek(fd, 0, SEEK_END);
337 - (void)seekToPosition:(long)aPosition
339 lseek(fd, aPosition, SEEK_SET);
342 - (void)truncateAtPosition:(long)aPosition
344 lseek(fd, aPosition, SEEK_SET);
345 #if defined(__MINGW32__)
346 if (_chsize(fd, aPosition) != 0)
348 if (ftruncate(fd, aPosition) != 0)
350 [[[PosixFileOperationException alloc]
351 initWithFormat:@"could not truncate file"] raise];
354 // Mapping files to memory
356 - (NSData *)mapFileRange:(NSRange)range
358 return AUTORELEASE([[NSMappedData alloc]
359 initWithPosixFileDescriptor:self range:range]);
362 - (void)synchronizeFile
366 [[[PosixFileOperationException alloc]
367 initWithFormat:@"could not sync file"] raise];
371 // Monitoring file descriptors
373 - (void)ceaseMonitoringFileActivity
375 NSRunLoop* runLoop = [NSRunLoop currentRunLoop];
378 [runLoop removePosixFileDescriptor:self forMode:[runLoop currentMode]];
381 - (NSPosixFileActivities)fileActivity
386 - (void)monitorFileActivity:(NSPosixFileActivities)activity
388 NSRunLoop* runLoop = [NSRunLoop currentRunLoop];
390 fileActivity |= activity;
391 [runLoop addPosixFileDescriptor:self forMode:[runLoop currentMode]];
394 - (void)monitorActivity:(NSPosixFileActivities)activity delegate:(id)anObject
396 [self setDelegate:anObject];
397 [self monitorFileActivity:activity];
400 // File descriptor delegate
407 - (void)setDelegate:(id)aDelegate
409 delegate = aDelegate;
412 @end /* NSPosixFileDescriptor */