Index: src/OFExceptions.h ================================================================== --- src/OFExceptions.h +++ src/OFExceptions.h @@ -7,11 +7,11 @@ * 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 +#include #import "OFObject.h" @class OFString; @@ -492,19 +492,19 @@ * \brief An exception indicating that changing the owner of a file failed. */ @interface OFChangeFileOwnerFailedException: OFException { OFString *path; - uid_t owner; - gid_t group; + OFString *owner; + OFString *group; int errNo; } #ifdef OF_HAVE_PROPERTIES @property (readonly, nonatomic) OFString *path; -@property (readonly) uid_t owner; -@property (readonly) gid_t group; +@property (readonly, nonatomic) OFString *owner; +@property (readonly, nonatomic) OFString *group; @property (readonly) int errNo; #endif /** * \param class_ The class of the object which caused the exception @@ -513,12 +513,12 @@ * \param group The new group for the file * \return An initialized change file owner failed exception */ + newWithClass: (Class)class_ path: (OFString*)path - owner: (uid_t)owner - group: (gid_t)group; + owner: (OFString*)owner + group: (OFString*)group; /** * Initializes an already allocated change file owner failed exception. * * \param class_ The class of the object which caused the exception @@ -527,12 +527,12 @@ * \param group The new group for the file * \return An initialized change file owner failed exception */ - initWithClass: (Class)class_ path: (OFString*)path - owner: (uid_t)owner - group: (gid_t)group; + owner: (OFString*)owner + group: (OFString*)group; /** * \return The errno from when the exception was created */ - (int)errNo; @@ -543,16 +543,16 @@ - (OFString*)path; /** * \return The new owner for the file */ -- (uid_t)owner; +- (OFString*)owner; /** * \return The new group for the file */ -- (gid_t)group; +- (OFString*)group; @end #endif /** * \brief An exception indicating that copying a file failed. Index: src/OFExceptions.m ================================================================== --- src/OFExceptions.m +++ src/OFExceptions.m @@ -751,12 +751,12 @@ #ifndef _WIN32 @implementation OFChangeFileOwnerFailedException + newWithClass: (Class)class_ path: (OFString*)path - owner: (uid_t)owner - group: (gid_t)group + owner: (OFString*)owner + group: (OFString*)group { return [[self alloc] initWithClass: class_ path: path owner: owner group: group]; @@ -770,19 +770,19 @@ selector: _cmd]; } - initWithClass: (Class)class_ path: (OFString*)path_ - owner: (uid_t)owner_ - group: (gid_t)group_ + owner: (OFString*)owner_ + group: (OFString*)group_ { self = [super initWithClass: class_]; @try { path = [path_ copy]; - owner = owner_; - group = group_; + owner = [owner_ copy]; + group = [group_ copy]; errNo = GET_ERRNO; } @catch (id e) { [self release]; @throw e; } @@ -791,22 +791,36 @@ } - (void)dealloc { [path release]; + [owner release]; + [group release]; [super dealloc]; } - (OFString*)description { if (description != nil) return description; - description = [[OFString alloc] initWithFormat: - @"Failed to change owner for file %s to %d:%d in class %s! " ERRFMT, - [path cString], owner, group, [inClass className], ERRPARAM]; + if (group == nil) + description = [[OFString alloc] initWithFormat: + @"Failed to change owner for file %s to %s in class %s! " + ERRFMT, [path cString], [owner cString], + [inClass className], ERRPARAM]; + else if (owner == nil) + description = [[OFString alloc] initWithFormat: + @"Failed to change group for file %s to %s in class %s! " + ERRFMT, [path cString], [group cString], + [inClass className], ERRPARAM]; + else + description = [[OFString alloc] initWithFormat: + @"Failed to change owner for file %s to %s:%s in class %s! " + ERRFMT, [path cString], [owner cString], [group cString], + [inClass className], ERRPARAM]; return description; } - (int)errNo @@ -817,16 +831,16 @@ - (OFString*)path { return path; } -- (uid_t)owner +- (OFString*)owner { return owner; } -- (gid_t)group +- (OFString*)group { return group; } @end #endif Index: src/OFFile.h ================================================================== --- src/OFFile.h +++ src/OFFile.h @@ -94,12 +94,12 @@ * string * \param owner The new owner for the file * \param group The new group for the file */ + (void)changeOwnerOfFile: (OFString*)path - toOwner: (uid_t)owner - group: (gid_t)group; + toOwner: (OFString*)owner + group: (OFString*)group; #endif /** * Copies a file. * Index: src/OFFile.m ================================================================== --- src/OFFile.m +++ src/OFFile.m @@ -17,14 +17,20 @@ #include #include #include #include + +#ifndef _WIN32 +# include +# include +#endif #import "OFFile.h" #import "OFString.h" #import "OFArray.h" +#import "OFThread.h" #import "OFAutoreleasePool.h" #import "OFExceptions.h" #import "macros.h" #ifdef _WIN32 @@ -52,10 +58,14 @@ #define DIR_MODE DEFAULT_MODE | S_IXUSR | S_IXGRP | S_IXOTH OFFile *of_stdin = nil; OFFile *of_stdout = nil; OFFile *of_stderr = nil; + +#ifndef _WIN32 +static OFMutex *mutex; +#endif static int parse_mode(const char *mode) { if (!strcmp(mode, "r")) return O_RDONLY; @@ -96,10 +106,18 @@ of_stdin = [[OFFileSingleton alloc] initWithFileDescriptor: 0]; of_stdout = [[OFFileSingleton alloc] initWithFileDescriptor: 1]; of_stderr = [[OFFileSingleton alloc] initWithFileDescriptor: 2]; } + +#ifndef _WIN32 ++ (void)initialize +{ + if (self == [OFFile class]) + mutex = [[OFMutex alloc] init]; +} +#endif + fileWithPath: (OFString*)path mode: (OFString*)mode { return [[[self alloc] initWithPath: path @@ -285,14 +303,53 @@ #endif } #ifndef _WIN32 + (void)changeOwnerOfFile: (OFString*)path - toOwner: (uid_t)owner - group: (gid_t)group + toOwner: (OFString*)owner + group: (OFString*)group { - if (chown([path cString], owner, group)) + uid_t uid = -1; + gid_t gid = -1; + + if (owner == nil && group == nil) + @throw [OFInvalidArgumentException newWithClass: self + selector: _cmd]; + + [mutex lock]; + + @try { + if (owner != nil) { + struct passwd *pw; + + if ((pw = getpwnam([owner cString])) == NULL) + @throw [OFChangeFileOwnerFailedException + newWithClass: self + path: path + owner: owner + group: group]; + + uid = pw->pw_uid; + } + + if (group != nil) { + struct group *gr; + + if ((gr = getgrnam([group cString])) == NULL) + @throw [OFChangeFileOwnerFailedException + newWithClass: self + path: path + owner: owner + group: group]; + + gid = gr->gr_gid; + } + } @finally { + [mutex unlock]; + } + + if (chown([path cString], uid, gid)) @throw [OFChangeFileOwnerFailedException newWithClass: self path: path owner: owner group: group]; }