1/* 2 Copyright (C) 2000-2007 SKYRIX Software AG 3 Copyright (C) 2007 Helge Hess 4 5 This file is part of SOPE. 6 7 SOPE is free software; you can redistribute it and/or modify it under 8 the terms of the GNU Lesser General Public License as published by the 9 Free Software Foundation; either version 2, or (at your option) any 10 later version. 11 12 SOPE is distributed in the hope that it will be useful, but WITHOUT ANY 13 WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 15 License for more details. 16 17 You should have received a copy of the GNU Lesser General Public 18 License along with SOPE; see the file COPYING. If not, write to the 19 Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 20 02111-1307, USA. 21*/ 22 23#include "NGMimeFileData.h" 24#include "common.h" 25#include <string.h> 26#include <unistd.h> 27#include <sys/types.h> 28#include <sys/stat.h> 29#include <fcntl.h> 30 31@implementation NGMimeFileData 32 33static NSString *TmpPath = nil; 34static NSProcessInfo *Pi = nil; 35static unsigned tmpmask = 0600; 36 37+ (void)initialize { 38 NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; 39 40 if (TmpPath == nil) { 41 TmpPath = [ud stringForKey:@"NGMimeBuildMimeTempDirectory"]; 42 if (TmpPath == nil) TmpPath = @"/tmp/"; 43 TmpPath = [[TmpPath stringByAppendingPathComponent:@"OGo"] copy]; 44 } 45 if (Pi == nil) Pi = [[NSProcessInfo processInfo] retain]; 46} 47 48- (id)initWithPath:(NSString *)_path removeFile:(BOOL)_remove { 49#if !GNUSTEP_BASE_LIBRARY 50 /* 51 see OGo bug #1890, the gstep-base -init clashes and we don't exactly need 52 it ... (but I guess its better to call it on other Foundations) 53 */ 54 if ((self = [super init]) != nil) { 55#endif 56 if (![[NSFileManager defaultManager] fileExistsAtPath:_path]) { 57 NSLog(@"ERROR[%s]: missing file at path %@", __PRETTY_FUNCTION__, _path); 58 [self release]; 59 return nil; 60 } 61 self->path = [_path copy]; 62 self->removeFile = _remove; 63 self->length = -1; 64#if !GNUSTEP_BASE_LIBRARY 65 } 66#endif 67 return self; 68} 69 70- (id)initWithBytes:(const void*)_bytes 71 length:(NSUInteger)_length 72{ 73 NSString *filename = nil; 74 int fd; 75 76 filename = [Pi temporaryFileName:TmpPath]; 77 78 fd = open([filename fileSystemRepresentation], 79 O_WRONLY | O_CREAT | O_TRUNC, tmpmask); 80 if (fd == -1) { 81 fprintf(stderr, "Could not open file for writing %s: %s\n", 82 [filename fileSystemRepresentation], strerror(errno)); 83 [self release]; 84 return nil; 85 } 86 if (write(fd, _bytes, _length) != (int)_length) { 87 fprintf(stderr, 88#if GS_64BIT_OLD 89 "Failed to write %i bytes to %s: %s\n", 90#else 91 "Failed to write %li bytes to %s: %s\n", 92#endif 93 _length, [filename fileSystemRepresentation], strerror(errno)); 94 close(fd); 95 [self release]; 96 return nil; 97 } 98 99 close(fd); 100 101 return [self initWithPath:filename removeFile:YES]; 102} 103 104- (void)dealloc { 105 if (self->removeFile) { 106 [[NSFileManager defaultManager] 107 removeFileAtPath:self->path handler:nil]; 108 } 109 [self->path release]; 110 [super dealloc]; 111} 112 113- (NSData *)_data { 114 return [NSData dataWithContentsOfMappedFile:self->path]; 115} 116 117- (id)copyWithZone:(NSZone *)zone { 118 return [self retain]; 119} 120 121- (const void*)bytes { 122 return [[self _data] bytes]; 123} 124 125- (NSUInteger)length { 126 if (self->length == -1) { 127 self->length = [[[[NSFileManager defaultManager] 128 fileAttributesAtPath:self->path 129 traverseLink:NO] 130 objectForKey:NSFileSize] intValue]; 131 } 132 return self->length; 133} 134 135- (BOOL)appendDataToFileDesc:(int)_fd { 136 NGFileStream *fs; 137 int bufCnt = 8192; 138 char buffer[bufCnt]; 139 BOOL result; 140 int fileLen; 141 142 if (![[NSFileManager defaultManager] isReadableFileAtPath:self->path]) { 143 NSLog(@"ERROR[%s] missing file at path %@", __PRETTY_FUNCTION__, 144 self->path); 145 return NO; 146 } 147 148 fileLen = [self length]; 149 result = YES; 150 fs = [NGFileStream alloc]; /* to keep gcc 3.4 happy */ 151 fs = [fs initWithPath:self->path]; 152 153 if (![fs openInMode:@"r"]) { 154 NSLog(@"%s: could not open file stream ... %@", 155 __PRETTY_FUNCTION__, self->path); 156 [fs release]; fs = nil; 157 return NO; 158 } 159 160 NS_DURING { 161 NSInteger read; 162 NSInteger alreadyRead; 163 164 alreadyRead = 0; 165 166 read = (bufCnt > (fileLen - alreadyRead)) ? fileLen - alreadyRead : bufCnt; 167 168 while ((read = [fs readBytes:buffer count:read])) { 169 alreadyRead += read; 170 if (write(_fd, buffer, read) != read) { 171 fprintf(stderr, 172#if GS_64BIT_OLD 173 "%s: Failed to write %i bytes to file\n", 174#else 175 "%s: Failed to write %li bytes to file\n", 176#endif 177 __PRETTY_FUNCTION__, read); 178 result = NO; 179 break; 180 } 181 if (alreadyRead == fileLen) 182 break; 183 } 184 } 185 NS_HANDLER { 186 printf("got exceptions %s\n", [[localException description] cString]); 187 if (![localException isKindOfClass:[NGEndOfStreamException class]]) { 188 [fs release]; fs = nil; 189 result = NO; 190 } 191 } 192 NS_ENDHANDLER; 193 [fs release]; fs = nil; 194 return result; 195} 196 197/* description */ 198 199- (NSString *)description { 200 return [NSString stringWithFormat:@"<0x%p[%@]: path=%@>", 201 self, NSStringFromClass([self class]), self->path]; 202} 203 204@end /* NGMimeFileData */ 205