/* * Copyright (c) 2008 - 2010 * Jonathan Schleifer <js@webkeks.org> * * All rights reserved. * * This file is part of ObjFW. It may be distributed under the terms of the * Q Public License 1.0, which can be found in the file LICENSE included in * the packaging of this file. */ #include "config.h" #include <stdio.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #import "OFFile.h" #import "OFString.h" #import "OFExceptions.h" #ifdef _WIN32 # import <windows.h> #endif OFFile *of_stdin = nil; OFFile *of_stdout = nil; OFFile *of_stderr = nil; /// \cond internal @interface OFFileSingleton: OFFile @end /// \endcond @implementation OFFile + (void)load { if (self != [OFFile class]) return; of_stdin = [[OFFileSingleton alloc] initWithFilePointer: stdin]; of_stdout = [[OFFileSingleton alloc] initWithFilePointer: stdout]; of_stderr = [[OFFileSingleton alloc] initWithFilePointer: stderr]; } + fileWithPath: (OFString*)path mode: (OFString*)mode { return [[[self alloc] initWithPath: path mode: mode] autorelease]; } + fileWithFilePointer: (FILE*)fp_ { return [[[self alloc] initWithFilePointer: fp_] autorelease]; } + (void)changeModeOfFile: (OFString*)path toMode: (mode_t)mode { #ifndef _WIN32 if (chmod([path cString], mode)) @throw [OFChangeFileModeFailedException newWithClass: self path: path mode: mode]; #else DWORD attrs = GetFileAttributes([path cString]); if (attrs == INVALID_FILE_ATTRIBUTES) @throw [OFChangeFileModeFailedException newWithClass: self path: path mode: mode]; if ((mode / 100) & 2) attrs &= ~FILE_ATTRIBUTE_READONLY; else attrs |= FILE_ATTRIBUTE_READONLY; if (!SetFileAttributes([path cString], attrs)) @throw [OFChangeFileModeFailedException newWithClass: self path: path mode: mode]; #endif } #ifndef _WIN32 + (void)changeOwnerOfFile: (OFString*)path toOwner: (uid_t)owner group: (gid_t)group { if (chown([path cString], owner, group)) @throw [OFChangeFileOwnerFailedException newWithClass: self path: path owner: owner group: group]; } #endif + (void)rename: (OFString*)from to: (OFString*)to { #ifndef _WIN32 if (rename([from cString], [to cString])) #else if (!MoveFile([from cString], [to cString])) #endif @throw [OFRenameFileFailedException newWithClass: self from: from to: to]; } + (void)delete: (OFString*)path { #ifndef _WIN32 if (unlink([path cString])) #else if (!DeleteFile([path cString])) #endif @throw [OFDeleteFileFailedException newWithClass: self path: path]; } #ifndef _WIN32 + (void)link: (OFString*)src to: (OFString*)dest { if (link([src cString], [dest cString]) != 0) @throw [OFLinkFailedException newWithClass: self source: src destination: dest]; } + (void)symlink: (OFString*)src to: (OFString*)dest { if (symlink([src cString], [dest cString]) != 0) @throw [OFSymlinkFailedException newWithClass: self source: src destination: dest]; } #endif - init { @throw [OFNotImplementedException newWithClass: isa selector: _cmd]; } - initWithPath: (OFString*)path mode: (OFString*)mode { Class c; self = [super init]; if ((fp = fopen([path cString], [mode cString])) == NULL) { c = isa; [super dealloc]; @throw [OFOpenFileFailedException newWithClass: c path: path mode: mode]; } close = YES; return self; } - initWithFilePointer: (FILE*)fp_ { self = [super init]; fp = fp_; return self; } - (void)dealloc { if (close && fp != NULL) fclose(fp); [super dealloc]; } - (BOOL)atEndOfStreamWithoutCache { if (fp == NULL) return YES; return (feof(fp) == 0 ? NO : YES); } - (size_t)readNBytesWithoutCache: (size_t)size intoBuffer: (char*)buf { size_t ret; if (fp == NULL || feof(fp) || ((ret = fread(buf, 1, size, fp)) == 0 && size != 0 && !feof(fp))) @throw [OFReadFailedException newWithClass: isa size: size]; return ret; } - (size_t)writeNBytes: (size_t)size fromBuffer: (const char*)buf { size_t ret; if (fp == NULL || feof(fp) || ((ret = fwrite(buf, 1, size, fp)) < size && size != 0)) @throw [OFWriteFailedException newWithClass: isa size: size]; return ret; } - close { if (fp != NULL) fclose(fp); fp = NULL; return self; } @end /// \cond internal @implementation OFFileSingleton - initWithPath: (OFString*)path mode: (OFString*)mode { @throw [OFNotImplementedException newWithClass: isa selector: _cmd]; } - autorelease { return self; } - retain { return self; } - (void)release { } - (size_t)retainCount { return SIZE_MAX; } - (void)dealloc { @throw [OFNotImplementedException newWithClass: isa selector: _cmd]; [super dealloc]; /* Get rid of stupid warning */ } @end /// \endcond