Index: src/Makefile ================================================================== --- src/Makefile +++ src/Makefile @@ -34,10 +34,11 @@ OFData+CryptoHashing.m \ OFData+MessagePackValue.m \ OFDate.m \ OFDictionary.m \ OFEnumerator.m \ + OFFileManager.m \ OFGZIPStream.m \ OFHMAC.m \ OFInflate64Stream.m \ OFInflateStream.m \ OFIntrospection.m \ @@ -127,11 +128,10 @@ ${USE_SRCS_PLUGINS} \ ${USE_SRCS_SOCKETS} \ ${USE_SRCS_THREADS} \ ${USE_SRCS_WINDOWS} SRCS_FILES = OFFile.m \ - OFFileManager.m \ OFINICategory.m \ OFINIFile.m \ OFSettings.m \ OFString+PathAdditions.m SRCS_PLUGINS = OFPlugin.m Index: src/OFFileManager.h ================================================================== --- src/OFFileManager.h +++ src/OFFileManager.h @@ -14,31 +14,221 @@ * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ #import "OFObject.h" -#import "OFURLHandler.h" +#import "OFDictionary.h" OF_ASSUME_NONNULL_BEGIN -#if defined(OF_HAVE_CHMOD) && !defined(OF_AMIGAOS) -# define OF_FILE_MANAGER_SUPPORTS_PERMISSIONS -#endif -#if defined(OF_HAVE_CHOWN) && !defined(OF_AMIGAOS) -# define OF_FILE_MANAGER_SUPPORTS_OWNER -#endif -#if (defined(OF_HAVE_LINK) && !defined(OF_AMIGAOS)) || defined(OF_WINDOWS) -# define OF_FILE_MANAGER_SUPPORTS_LINKS -#endif -#if (defined(OF_HAVE_SYMLINK) && !defined(OF_AMIGAOS)) || defined(OF_WINDOWS) -# define OF_FILE_MANAGER_SUPPORTS_SYMLINKS +/*! @file */ + +#ifdef OF_HAVE_FILES +# if defined(OF_HAVE_CHMOD) && !defined(OF_AMIGAOS) +# define OF_FILE_MANAGER_SUPPORTS_PERMISSIONS +# endif +# if defined(OF_HAVE_CHOWN) && !defined(OF_AMIGAOS) +# define OF_FILE_MANAGER_SUPPORTS_OWNER +# endif +# if (defined(OF_HAVE_LINK) && !defined(OF_AMIGAOS)) || defined(OF_WINDOWS) +# define OF_FILE_MANAGER_SUPPORTS_LINKS +# endif +# if (defined(OF_HAVE_SYMLINK) && !defined(OF_AMIGAOS)) || defined(OF_WINDOWS) +# define OF_FILE_MANAGER_SUPPORTS_SYMLINKS +# endif #endif @class OFArray OF_GENERIC(ObjectType); +@class OFConstantString; @class OFDate; +@class OFString; @class OFURL; +/*! + * @brief A key for a file attribute in the file attributes dictionary. + * + * Possible keys for file URLs are: + * + * * @ref of_file_attribute_key_size + * * @ref of_file_attribute_key_type + * * @ref of_file_attribute_key_posix_permissions + * * @ref of_file_attribute_key_posix_uid + * * @ref of_file_attribute_key_posix_gid + * * @ref of_file_attribute_key_owner + * * @ref of_file_attribute_key_group + * * @ref of_file_attribute_key_last_access_date + * * @ref of_file_attribute_key_modification_date + * * @ref of_file_attribute_key_status_change_date + * * @ref of_file_attribute_key_symbolic_link_destination + * + * Other URL schemes might not have all keys and might have keys not listed. + */ +typedef OFConstantString *of_file_attribute_key_t; + +/*! + * @brief The type of a file. + * + * Possibles values for file URLs are: + * + * * @ref of_file_type_regular + * * @ref of_file_type_directory + * * @ref of_file_type_symbolic_link + * * @ref of_file_type_fifo + * * @ref of_file_type_character_special + * * @ref of_file_type_block_special + * * @ref of_file_type_socket + * + * Other URL schemes might not have all types and might have types not listed. + */ +typedef OFConstantString *of_file_type_t; + +/*! + * @brief A dictionary mapping keys of type @ref of_file_attribute_key_t + * to their attribute values. + */ +typedef OFDictionary OF_GENERIC(of_file_attribute_key_t, id) + *of_file_attributes_t; + +/*! + * @brief A mutable dictionary mapping keys of type + * @ref of_file_attribute_key_t to their attribute values. + */ +typedef OFMutableDictionary OF_GENERIC(of_file_attribute_key_t, id) + *of_mutable_file_attributes_t; + +#ifdef __cplusplus +extern "C" { +#endif +/*! + * @brief The size of the file as an @ref OFNumber. + * + * For convenience, a category on @ref OFDictionary is provided to access this + * via @ref OFDictionary#fileSize. + */ +extern const of_file_attribute_key_t of_file_attribute_key_size; + +/*! + * @brief The type of the file. + * + * The corresponding value is of type @ref of_file_type_t. + * + * For convenience, a category on @ref OFDictionary is provided to access this + * via @ref OFDictionary#fileType. + */ +extern const of_file_attribute_key_t of_file_attribute_key_type; + +/*! + * @brief The POSIX permissions of the file as an @ref OFNumber. + * + * For convenience, a category on @ref OFDictionary is provided to access this + * via @ref OFDictionary#filePOSIXPermissions. + */ +extern const of_file_attribute_key_t of_file_attribute_key_posix_permissions; + +/*! + * @brief The POSIX UID of the file as an @ref OFNumber. + * + * For convenience, a category on @ref OFDictionary is provided to access this + * via @ref OFDictionary#filePOSIXUID. + */ +extern const of_file_attribute_key_t of_file_attribute_key_posix_uid; + +/*! + * @brief The POSIX GID of the file as an @ref OFNumber. + * + * For convenience, a category on @ref OFDictionary is provided to access this + * via @ref OFDictionary#filePOSIXGID. + */ +extern const of_file_attribute_key_t of_file_attribute_key_posix_gid; + +/*! + * @brief The owner of the file as an @ref OFString. + * + * For convenience, a category on @ref OFDictionary is provided to access this + * via @ref OFDictionary#fileOwner. + */ +extern const of_file_attribute_key_t of_file_attribute_key_owner; + +/*! + * @brief The group of the file as an @ref OFString. + * + * For convenience, a category on @ref OFDictionary is provided to access this + * via @ref OFDictionary#fileGroup. + */ +extern const of_file_attribute_key_t of_file_attribute_key_group; + +/*! + * @brief The last access date of the file as an @ref OFDate. + * + * For convenience, a category on @ref OFDictionary is provided to access this + * via @ref OFDictionary#fileLastAccessDate. + */ +extern const of_file_attribute_key_t of_file_attribute_key_last_access_date; + +/*! + * @brief The last modification date of the file as an @ref OFDate. + * + * For convenience, a category on @ref OFDictionary is provided to access this + * via @ref OFDictionary#fileModificationDate. + */ +extern const of_file_attribute_key_t of_file_attribute_key_modification_date; + +/*! + * @brief The last status change date of the file as an @ref OFDate. + * + * For convenience, a category on @ref OFDictionary is provided to access this + * via @ref OFDictionary#fileStatusChangeDate. + */ +extern const of_file_attribute_key_t of_file_attribute_key_status_change_date; + +/*! + * @brief The destination of a symbolic link as an @ref OFString. + * + * For convenience, a category on @ref OFDictionary is provided to access this + * via @ref OFDictionary#fileSymbolicLinkDestination. + */ +extern const of_file_attribute_key_t + of_file_attribute_key_symbolic_link_destination; + +/*! + * @brief A regular file. + */ +extern const of_file_type_t of_file_type_regular; + +/*! + * @brief A directory. + */ +extern const of_file_type_t of_file_type_directory; + +/*! + * @brief A symbolic link. + */ +extern const of_file_type_t of_file_type_symbolic_link; + +/*! + * @brief A FIFO. + */ +extern const of_file_type_t of_file_type_fifo; + +/*! + * @brief A character special file. + */ +extern const of_file_type_t of_file_type_character_special; + +/*! + * @brief A block special file. + */ +extern const of_file_type_t of_file_type_block_special; + +/*! + * @brief A socket. + */ +extern const of_file_type_t of_file_type_socket; +#ifdef __cplusplus +} +#endif + /*! * @class OFFileManager OFFileManager.h ObjFW/OFFileManager.h * * @brief A class which provides management for files, e.g. reading contents of * directories, deleting files, renaming files, etc. @@ -46,33 +236,37 @@ @interface OFFileManager: OFObject #ifdef OF_HAVE_CLASS_PROPERTIES @property (class, readonly, nonatomic) OFFileManager *defaultManager; #endif +#ifdef OF_HAVE_FILES /*! * @brief The path of the current working directory. */ @property (readonly, nonatomic) OFString *currentDirectoryPath; /*! * @brief The URL of the current working directory. */ @property (readonly, nonatomic) OFURL *currentDirectoryURL; +#endif /*! * @brief Returns the default file manager. */ + (OFFileManager *)defaultManager; +#ifdef OF_HAVE_FILES /*! * @brief Returns the attributes for the item at the specified path. * * @param path The path to return the attributes for * @return A dictionary of attributes for the specified path, with the keys of * type @ref of_file_attribute_key_t */ - (of_file_attributes_t)attributesOfItemAtPath: (OFString *)path; +#endif /*! * @brief Returns the attributes for the item at the specified URL. * * @param URL The URL to return the attributes for @@ -79,10 +273,11 @@ * @return A dictionary of attributes for the specified URL, with the keys of * type @ref of_file_attribute_key_t */ - (of_file_attributes_t)attributesOfItemAtURL: (OFURL *)URL; +#ifdef OF_HAVE_FILES /*! * @brief Sets the attributes for the item at the specified path. * * All attributes not part of the dictionary are left unchanged. * @@ -89,10 +284,11 @@ * @param attributes The attributes to set for the specified path * @param path The path of the item to set the attributes for */ - (void)setAttributes: (of_file_attributes_t)attributes ofItemAtPath: (OFString *)path; +#endif /*! * @brief Sets the attributes for the item at the specified URL. * * All attributes not part of the dictionary are left unchanged. @@ -101,42 +297,47 @@ * @param URL The URL of the item to set the attributes for */ - (void)setAttributes: (of_file_attributes_t)attributes ofItemAtURL: (OFURL *)URL; +#ifdef OF_HAVE_FILES /*! * @brief Checks whether a file exists at the specified path. * * @param path The path to check * @return A boolean whether there is a file at the specified path */ - (bool)fileExistsAtPath: (OFString *)path; +#endif /*! * @brief Checks whether a file exists at the specified URL. * * @param URL The URL to check * @return A boolean whether there is a file at the specified URL */ - (bool)fileExistsAtURL: (OFURL *)URL; +#ifdef OF_HAVE_FILES /*! * @brief Checks whether a directory exists at the specified path. * * @param path The path to check * @return A boolean whether there is a directory at the specified path */ - (bool)directoryExistsAtPath: (OFString *)path; +#endif /*! * @brief Checks whether a directory exists at the specified URL. * * @param URL The URL to check * @return A boolean whether there is a directory at the specified URL */ - (bool)directoryExistsAtURL: (OFURL *)URL; +#ifdef OF_HAVE_FILES /*! * @brief Creates a directory at the specified path. * * @param path The path of the directory to create */ @@ -148,10 +349,11 @@ * @param path The path of the directory to create * @param createParents Whether to create the parents of the directory */ - (void)createDirectoryAtPath: (OFString *)path createParents: (bool)createParents; +#endif /*! * @brief Creates a directory at the specified URL. * * @param URL The URL of the directory to create @@ -165,19 +367,21 @@ * @param createParents Whether to create the parents of the directory */ - (void)createDirectoryAtURL: (OFURL *)URL createParents: (bool)createParents; +#ifdef OF_HAVE_FILES /*! * @brief Returns an array with the items in the specified directory. * * @note `.` and `..` are not part of the returned array. * * @param path The path to the directory whose items should be returned * @return An array of OFString with the items in the specified directory */ - (OFArray OF_GENERIC(OFString *) *)contentsOfDirectoryAtPath: (OFString *)path; +#endif /*! * @brief Returns an array with the items in the specified directory. * * @note `.` and `..` are not part of the returned array. @@ -185,10 +389,11 @@ * @param URL The URL to the directory whose items should be returned * @return An array of OFString with the items in the specified directory */ - (OFArray OF_GENERIC(OFString *) *)contentsOfDirectoryAtURL: (OFURL *)URL; +#ifdef OF_HAVE_FILES /*! * @brief Changes the current working directory. * * @param path The new directory to change to */ @@ -214,10 +419,11 @@ * @param source The file, directory or symbolic link to copy * @param destination The destination path */ - (void)copyItemAtPath: (OFString *)source toPath: (OFString *)destination; +#endif /*! * @brief Copies a file, directory or symbolic link (if supported by the OS). * * The destination URL must have a full path, which means it must include the @@ -231,10 +437,11 @@ * @param destination The destination URL */ - (void)copyItemAtURL: (OFURL *)source toURL: (OFURL *)destination; +#ifdef OF_HAVE_FILES /*! * @brief Moves an item. * * The destination path must be a full path, which means it must include the * name of the item. @@ -246,10 +453,11 @@ * @param source The item to rename * @param destination The new name for the item */ - (void)moveItemAtPath: (OFString *)source toPath: (OFString *)destination; +#endif /*! * @brief Moves an item. * * The destination URL must have a full path, which means it must include the @@ -263,18 +471,20 @@ * @param destination The new name for the item */ - (void)moveItemAtURL: (OFURL *)source toURL: (OFURL *)destination; +#ifdef OF_HAVE_FILES /*! * @brief Removes the item at the specified path. * * If the item at the specified path is a directory, it is removed recursively. * * @param path The path to the item which should be removed */ - (void)removeItemAtPath: (OFString *)path; +#endif /*! * @brief Removes the item at the specified URL. * * If the item at the specified URL is a directory, it is removed recursively. @@ -347,7 +557,87 @@ * @param target The target of the symbolic link */ - (void)createSymbolicLinkAtURL: (OFURL *)URL withDestinationPath: (OFString *)target; @end + +@interface OFDictionary (FileAttributes) +/*! + * The @ref of_file_attribute_key_size key from the dictionary. + * + * Raises an @ref OFUndefinedKeyException if the key is missing. + */ +@property (readonly, nonatomic) uintmax_t fileSize; + +/*! + * The @ref of_file_attribute_key_type key from the dictionary. + * + * Raises an @ref OFUndefinedKeyException if the key is missing. + */ +@property (readonly, nonatomic) of_file_type_t fileType; + +/*! + * The @ref of_file_attribute_key_posix_permissions key from the dictionary. + * + * Raises an @ref OFUndefinedKeyException if the key is missing. + */ +@property (readonly, nonatomic) uint16_t filePOSIXPermissions; + +/*! + * The @ref of_file_attribute_key_posix_uid key from the dictionary. + * + * Raises an @ref OFUndefinedKeyException if the key is missing. + */ +@property (readonly, nonatomic) uint32_t filePOSIXUID; + +/*! + * The @ref of_file_attribute_key_posix_gid key from the dictionary. + * + * Raises an @ref OFUndefinedKeyException if the key is missing. + */ +@property (readonly, nonatomic) uint32_t filePOSIXGID; + +/*! + * The @ref of_file_attribute_key_owner key from the dictionary. + * + * Raises an @ref OFUndefinedKeyException if the key is missing. + */ +@property (readonly, nonatomic) OFString *fileOwner; + +/*! + * The @ref of_file_attribute_key_group key from the dictionary. + * + * Raises an @ref OFUndefinedKeyException if the key is missing. + */ +@property (readonly, nonatomic) OFString *fileGroup; + +/*! + * The @ref of_file_attribute_key_last_access_date key from the dictionary. + * + * Raises an @ref OFUndefinedKeyException if the key is missing. + */ +@property (readonly, nonatomic) OFDate *fileLastAccessDate; + +/*! + * The @ref of_file_attribute_key_modification_date key from the dictionary. + * + * Raises an @ref OFUndefinedKeyException if the key is missing. + */ +@property (readonly, nonatomic) OFDate *fileModificationDate; + +/*! + * The @ref of_file_attribute_key_status_change_date key from the dictionary. + * + * Raises an @ref OFUndefinedKeyException if the key is missing. + */ +@property (readonly, nonatomic) OFDate *fileStatusChangeDate; + +/*! + * The @ref of_file_attribute_key_symbolic_link_destination key from the + * dictionary. + * + * Raises an @ref OFUndefinedKeyException if the key is missing. + */ +@property (readonly, nonatomic) OFString *fileSymbolicLinkDestination; +@end OF_ASSUME_NONNULL_END Index: src/OFFileManager.m ================================================================== --- src/OFFileManager.m +++ src/OFFileManager.m @@ -28,14 +28,17 @@ #endif #import "OFArray.h" #import "OFDate.h" #import "OFDictionary.h" -#import "OFFile.h" +#ifdef OF_HAVE_FILES +# import "OFFile.h" +#endif #import "OFFileManager.h" #import "OFLocale.h" #import "OFNumber.h" +#import "OFStream.h" #import "OFString.h" #import "OFSystemInfo.h" #import "OFURL.h" #import "OFURLHandler.h" @@ -44,14 +47,16 @@ #import "OFCreateDirectoryFailedException.h" #import "OFGetCurrentDirectoryPathFailedException.h" #import "OFInitializationFailedException.h" #import "OFInvalidArgumentException.h" #import "OFMoveItemFailedException.h" +#import "OFNotImplementedException.h" #import "OFOutOfMemoryException.h" #import "OFOutOfRangeException.h" #import "OFRemoveItemFailedException.h" #import "OFRetrieveItemAttributesFailedException.h" +#import "OFUndefinedKeyException.h" #import "OFUnsupportedProtocolException.h" #ifdef OF_WINDOWS # include # include @@ -70,10 +75,42 @@ #endif @interface OFFileManager_default: OFFileManager @end +const of_file_attribute_key_t of_file_attribute_key_size = + @"of_file_attribute_key_size"; +const of_file_attribute_key_t of_file_attribute_key_type = + @"of_file_attribute_key_type"; +const of_file_attribute_key_t of_file_attribute_key_posix_permissions = + @"of_file_attribute_key_posix_permissions"; +const of_file_attribute_key_t of_file_attribute_key_posix_uid = + @"of_file_attribute_key_posix_uid"; +const of_file_attribute_key_t of_file_attribute_key_posix_gid = + @"of_file_attribute_key_posix_gid"; +const of_file_attribute_key_t of_file_attribute_key_owner = + @"of_file_attribute_key_owner"; +const of_file_attribute_key_t of_file_attribute_key_group = + @"of_file_attribute_key_group"; +const of_file_attribute_key_t of_file_attribute_key_last_access_date = + @"of_file_attribute_key_last_access_date"; +const of_file_attribute_key_t of_file_attribute_key_modification_date = + @"of_file_attribute_key_modification_date"; +const of_file_attribute_key_t of_file_attribute_key_status_change_date = + @"of_file_attribute_key_status_change_date"; +const of_file_attribute_key_t of_file_attribute_key_symbolic_link_destination = + @"of_file_attribute_key_symbolic_link_destination"; + +const of_file_type_t of_file_type_regular = @"of_file_type_regular"; +const of_file_type_t of_file_type_directory = @"of_file_type_directory"; +const of_file_type_t of_file_type_symbolic_link = @"of_file_type_symbolic_link"; +const of_file_type_t of_file_type_fifo = @"of_file_type_fifo"; +const of_file_type_t of_file_type_character_special = + @"of_file_type_character_special"; +const of_file_type_t of_file_type_block_special = @"of_file_type_block_special"; +const of_file_type_t of_file_type_socket = @"of_file_type_socket"; + #ifdef OF_AMIGAOS4 extern struct ExecIFace *IExec; static struct Library *DOSBase = NULL; static struct DOSIFace *IDOS = NULL; #endif @@ -96,10 +133,23 @@ if (DOSBase != NULL) CloseLibrary(DOSBase); # endif } #endif + +static id +attributeForKeyOrException(of_file_attributes_t attributes, + of_file_attribute_key_t key) +{ + id object = [attributes objectForKey: key]; + + if (object == nil) + @throw [OFUndefinedKeyException exceptionWithObject: attributes + key: key]; + + return object; +} @implementation OFFileManager + (void)initialize { if (self != [OFFileManager class]) @@ -114,27 +164,30 @@ GetInterface(DOSBase, "main", 1, NULL)) == NULL) @throw [OFInitializationFailedException exceptionWithClass: self]; #endif +#ifdef OF_HAVE_FILES /* * Make sure OFFile is initialized. * On some systems, this is needed to initialize the file system driver. */ [OFFile class]; +#endif defaultManager = [[OFFileManager_default alloc] init]; } + (OFFileManager *)defaultManager { return defaultManager; } +#ifdef OF_HAVE_FILES - (OFString *)currentDirectoryPath { -#if defined(OF_WINDOWS) +# if defined(OF_WINDOWS) OFString *ret; wchar_t *buffer = _wgetcwd(NULL, 0); @try { ret = [OFString stringWithUTF16String: buffer]; @@ -141,11 +194,11 @@ } @finally { free(buffer); } return ret; -#elif defined(OF_AMIGAOS) +# elif defined(OF_AMIGAOS) char buffer[512]; if (!NameFromLock(((struct Process *)FindTask(NULL))->pr_CurrentDir, buffer, 512)) { if (IoErr() == ERROR_LINE_TOO_LONG) @@ -154,30 +207,30 @@ return nil; } return [OFString stringWithCString: buffer encoding: [OFLocale encoding]]; -#else +# else char buffer[PATH_MAX]; if ((getcwd(buffer, PATH_MAX)) == NULL) @throw [OFGetCurrentDirectoryPathFailedException exceptionWithErrNo: errno]; -# ifdef OF_DJGPP +# ifdef OF_DJGPP /* * For some reason, getcwd() returns forward slashes on DJGPP, even * though the native format is to use backwards slashes. */ for (char *tmp = buffer; *tmp != '\0'; tmp++) if (*tmp == '/') *tmp = '\\'; -# endif +# endif return [OFString stringWithCString: buffer encoding: [OFLocale encoding]]; -#endif +# endif } - (OFURL *)currentDirectoryURL { void *pool = objc_autoreleasePoolPush(); @@ -187,10 +240,11 @@ [ret retain]; objc_autoreleasePoolPop(pool); return [ret autorelease]; } +#endif - (of_file_attributes_t)attributesOfItemAtURL: (OFURL *)URL { OFURLHandler *URLHandler; @@ -201,10 +255,11 @@ @throw [OFUnsupportedProtocolException exceptionWithURL: URL]; return [URLHandler attributesOfItemAtURL: URL]; } +#ifdef OF_HAVE_FILES - (of_file_attributes_t)attributesOfItemAtPath: (OFString *)path { void *pool = objc_autoreleasePoolPush(); of_file_attributes_t ret; @@ -214,10 +269,11 @@ objc_autoreleasePoolPop(pool); return [ret autorelease]; } +#endif - (void)setAttributes: (of_file_attributes_t)attributes ofItemAtURL: (OFURL *)URL { OFURLHandler *URLHandler; @@ -230,10 +286,11 @@ [URLHandler setAttributes: attributes ofItemAtURL: URL]; } +#ifdef OF_HAVE_FILES - (void)setAttributes: (of_file_attributes_t)attributes ofItemAtPath: (OFString *)path { void *pool = objc_autoreleasePoolPush(); @@ -240,10 +297,11 @@ [self setAttributes: attributes ofItemAtURL: [OFURL fileURLWithPath: path]]; objc_autoreleasePoolPop(pool); } +#endif - (bool)fileExistsAtURL: (OFURL *)URL { OFURLHandler *URLHandler; @@ -254,10 +312,11 @@ @throw [OFUnsupportedProtocolException exceptionWithURL: URL]; return [URLHandler fileExistsAtURL: URL]; } +#ifdef OF_HAVE_FILES - (bool)fileExistsAtPath: (OFString *)path { void *pool = objc_autoreleasePoolPush(); bool ret; @@ -265,10 +324,11 @@ objc_autoreleasePoolPop(pool); return ret; } +#endif - (bool)directoryExistsAtURL: (OFURL *)URL { OFURLHandler *URLHandler; @@ -279,10 +339,11 @@ @throw [OFUnsupportedProtocolException exceptionWithURL: URL]; return [URLHandler directoryExistsAtURL: URL]; } +#ifdef OF_HAVE_FILES - (bool)directoryExistsAtPath: (OFString *)path { void *pool = objc_autoreleasePoolPush(); bool ret; @@ -290,10 +351,11 @@ objc_autoreleasePoolPop(pool); return ret; } +#endif - (void)createDirectoryAtURL: (OFURL *)URL { OFURLHandler *URLHandler; @@ -355,10 +417,11 @@ } objc_autoreleasePoolPop(pool); } +#ifdef OF_HAVE_FILES - (void)createDirectoryAtPath: (OFString *)path { void *pool = objc_autoreleasePoolPush(); [self createDirectoryAtURL: [OFURL fileURLWithPath: path]]; @@ -374,10 +437,11 @@ [self createDirectoryAtURL: [OFURL fileURLWithPath: path] createParents: createParents]; objc_autoreleasePoolPop(pool); } +#endif - (OFArray OF_GENERIC(OFString *) *)contentsOfDirectoryAtURL: (OFURL *)URL { OFURLHandler *URLHandler; @@ -388,10 +452,11 @@ @throw [OFUnsupportedProtocolException exceptionWithURL: URL]; return [URLHandler contentsOfDirectoryAtURL: URL]; } +#ifdef OF_HAVE_FILES - (OFArray OF_GENERIC(OFString *) *)contentsOfDirectoryAtPath: (OFString *)path { void *pool = objc_autoreleasePoolPush(); OFArray OF_GENERIC(OFString *) *ret; @@ -407,16 +472,16 @@ - (void)changeCurrentDirectoryPath: (OFString *)path { if (path == nil) @throw [OFInvalidArgumentException exception]; -#if defined(OF_WINDOWS) +# if defined(OF_WINDOWS) if (_wchdir(path.UTF16String) != 0) @throw [OFChangeCurrentDirectoryPathFailedException exceptionWithPath: path errNo: errno]; -#elif defined(OF_AMIGAOS) +# elif defined(OF_AMIGAOS) BPTR lock, oldLock; if ((lock = Lock([path cStringWithEncoding: [OFLocale encoding]], SHARED_LOCK)) == 0) { int errNo; @@ -445,16 +510,16 @@ originalDirLock = oldLock; else UnLock(oldLock); dirChanged = true; -#else +# else if (chdir([path cStringWithEncoding: [OFLocale encoding]]) != 0) @throw [OFChangeCurrentDirectoryPathFailedException exceptionWithPath: path errNo: errno]; -#endif +# endif } - (void)changeCurrentDirectoryURL: (OFURL *)URL { void *pool = objc_autoreleasePoolPush(); @@ -472,10 +537,11 @@ [self copyItemAtURL: [OFURL fileURLWithPath: source] toURL: [OFURL fileURLWithPath: destination]]; objc_autoreleasePoolPop(pool); } +#endif - (void)copyItemAtURL: (OFURL *)source toURL: (OFURL *)destination { void *pool; @@ -517,21 +583,27 @@ OFArray *contents; @try { [self createDirectoryAtURL: destination]; -#ifdef OF_FILE_MANAGER_SUPPORTS_PERMISSIONS - of_file_attribute_key_t key = - of_file_attribute_key_posix_permissions; - OFNumber *permissions = [attributes objectForKey: key]; - of_file_attributes_t destinationAttributes = - [OFDictionary dictionaryWithObject: permissions - forKey: key]; - - [self setAttributes: destinationAttributes - ofItemAtURL: destination]; -#endif + @try { + of_file_attribute_key_t key = + of_file_attribute_key_posix_permissions; + OFNumber *permissions = + [attributes objectForKey: key]; + of_file_attributes_t destinationAttributes; + + if (permissions != nil) { + destinationAttributes = [OFDictionary + dictionaryWithObject: permissions + forKey: key]; + [self + setAttributes: destinationAttributes + ofItemAtURL: destination]; + } + } @catch (OFNotImplementedException *e) { + } contents = [self contentsOfDirectoryAtURL: source]; } @catch (id e) { /* * Only convert exceptions to OFCopyItemFailedException @@ -588,21 +660,27 @@ length: pageSize]; [destinationStream writeBuffer: buffer length: length]; } -#ifdef OF_FILE_MANAGER_SUPPORTS_PERMISSIONS - of_file_attribute_key_t key = - of_file_attribute_key_posix_permissions; - OFNumber *permissions = [attributes objectForKey: key]; - of_file_attributes_t destinationAttributes = - [OFDictionary dictionaryWithObject: permissions - forKey: key]; - - [self setAttributes: destinationAttributes - ofItemAtURL: destination]; -#endif + @try { + of_file_attribute_key_t key = + of_file_attribute_key_posix_permissions; + OFNumber *permissions = [attributes + objectForKey: key]; + of_file_attributes_t destinationAttributes; + + if (permissions != nil) { + destinationAttributes = [OFDictionary + dictionaryWithObject: permissions + forKey: key]; + [self + setAttributes: destinationAttributes + ofItemAtURL: destination]; + } + } @catch (OFNotImplementedException *e) { + } } @catch (id e) { /* * Only convert exceptions to OFCopyItemFailedException * that have an errNo property. This covers all I/O * related exceptions from the operations used to copy @@ -618,11 +696,10 @@ } @finally { [sourceStream close]; [destinationStream close]; free(buffer); } -#ifdef OF_FILE_MANAGER_SUPPORTS_SYMLINKS } else if ([type isEqual: of_file_type_symbolic_link]) { @try { OFString *linkDestination = attributes.fileSymbolicLinkDestination; @@ -641,20 +718,20 @@ destinationURL: destination errNo: [e errNo]]; @throw e; } -#endif } else @throw [OFCopyItemFailedException exceptionWithSourceURL: source destinationURL: destination errNo: EINVAL]; objc_autoreleasePoolPop(pool); } +#ifdef OF_HAVE_FILES - (void)moveItemAtPath: (OFString *)source toPath: (OFString *)destination { void *pool = objc_autoreleasePoolPush(); @@ -661,10 +738,11 @@ [self moveItemAtURL: [OFURL fileURLWithPath: source] toURL: [OFURL fileURLWithPath: destination]]; objc_autoreleasePoolPop(pool); } +#endif - (void)moveItemAtURL: (OFURL *)source toURL: (OFURL *)destination { void *pool; @@ -729,18 +807,20 @@ @throw [OFUnsupportedProtocolException exceptionWithURL: URL]; [URLHandler removeItemAtURL: URL]; } +#ifdef OF_HAVE_FILES - (void)removeItemAtPath: (OFString *)path { void *pool = objc_autoreleasePoolPush(); [self removeItemAtURL: [OFURL fileURLWithPath: path]]; objc_autoreleasePoolPop(pool); } +#endif - (void)linkItemAtURL: (OFURL *)source toURL: (OFURL *)destination { void *pool = objc_autoreleasePoolPush(); @@ -829,5 +909,70 @@ - (unsigned int)retainCount { return OF_RETAIN_COUNT_MAX; } @end + +@implementation OFDictionary (FileAttributes) +- (uintmax_t)fileSize +{ + return [attributeForKeyOrException(self, of_file_attribute_key_size) + uIntMaxValue]; +} + +- (of_file_type_t)fileType +{ + return attributeForKeyOrException(self, of_file_attribute_key_type); +} + +- (uint16_t)filePOSIXPermissions +{ + return [attributeForKeyOrException(self, + of_file_attribute_key_posix_permissions) uInt16Value]; +} + +- (uint32_t)filePOSIXUID +{ + return [attributeForKeyOrException(self, + of_file_attribute_key_posix_uid) uInt32Value]; +} + +- (uint32_t)filePOSIXGID +{ + return [attributeForKeyOrException(self, + of_file_attribute_key_posix_gid) uInt32Value]; +} + +- (OFString *)fileOwner +{ + return attributeForKeyOrException(self, of_file_attribute_key_owner); +} + +- (OFString *)fileGroup +{ + return attributeForKeyOrException(self, of_file_attribute_key_group); +} + +- (OFDate *)fileLastAccessDate +{ + return attributeForKeyOrException(self, + of_file_attribute_key_last_access_date); +} + +- (OFDate *)fileModificationDate +{ + return attributeForKeyOrException(self, + of_file_attribute_key_modification_date); +} + +- (OFDate *)fileStatusChangeDate +{ + return attributeForKeyOrException(self, + of_file_attribute_key_status_change_date); +} + +- (OFString *)fileSymbolicLinkDestination +{ + return attributeForKeyOrException(self, + of_file_attribute_key_symbolic_link_destination); +} +@end Index: src/OFURLHandler.h ================================================================== --- src/OFURLHandler.h +++ src/OFURLHandler.h @@ -13,207 +13,21 @@ * Public License, either version 2 or 3, which can be found in the file * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ +#import "OFFileManager.h" #import "OFObject.h" -#import "OFDictionary.h" #import "OFString.h" OF_ASSUME_NONNULL_BEGIN -/*! @file */ - @class OFArray OF_GENERIC(ObjectType); @class OFDate; @class OFStream; @class OFURL; -/*! - * @brief A key for a file attribute in the file attributes dictionary. - * - * Possible keys for file URLs are: - * - * * @ref of_file_attribute_key_size - * * @ref of_file_attribute_key_type - * * @ref of_file_attribute_key_posix_permissions - * * @ref of_file_attribute_key_posix_uid - * * @ref of_file_attribute_key_posix_gid - * * @ref of_file_attribute_key_owner - * * @ref of_file_attribute_key_group - * * @ref of_file_attribute_key_last_access_date - * * @ref of_file_attribute_key_modification_date - * * @ref of_file_attribute_key_status_change_date - * * @ref of_file_attribute_key_symbolic_link_destination - * - * Other URL schemes might not have all keys and might have keys not listed. - */ -typedef OFConstantString *of_file_attribute_key_t; - -/*! - * @brief The type of a file. - * - * Possibles values for file URLs are: - * - * * @ref of_file_type_regular - * * @ref of_file_type_directory - * * @ref of_file_type_symbolic_link - * * @ref of_file_type_fifo - * * @ref of_file_type_character_special - * * @ref of_file_type_block_special - * * @ref of_file_type_socket - * - * Other URL schemes might not have all types and might have types not listed. - */ -typedef OFConstantString *of_file_type_t; - -/*! - * @brief A dictionary mapping keys of type @ref of_file_attribute_key_t - * to their attribute values. - */ -typedef OFDictionary OF_GENERIC(of_file_attribute_key_t, id) - *of_file_attributes_t; - -/*! - * @brief A mutable dictionary mapping keys of type - * @ref of_file_attribute_key_t to their attribute values. - */ -typedef OFMutableDictionary OF_GENERIC(of_file_attribute_key_t, id) - *of_mutable_file_attributes_t; - -#ifdef __cplusplus -extern "C" { -#endif -/*! - * @brief The size of the file as an @ref OFNumber. - * - * For convenience, a category on @ref OFDictionary is provided to access this - * via @ref OFDictionary#fileSize. - */ -extern const of_file_attribute_key_t of_file_attribute_key_size; - -/*! - * @brief The type of the file. - * - * The corresponding value is of type @ref of_file_type_t. - * - * For convenience, a category on @ref OFDictionary is provided to access this - * via @ref OFDictionary#fileType. - */ -extern const of_file_attribute_key_t of_file_attribute_key_type; - -/*! - * @brief The POSIX permissions of the file as an @ref OFNumber. - * - * For convenience, a category on @ref OFDictionary is provided to access this - * via @ref OFDictionary#filePOSIXPermissions. - */ -extern const of_file_attribute_key_t of_file_attribute_key_posix_permissions; - -/*! - * @brief The POSIX UID of the file as an @ref OFNumber. - * - * For convenience, a category on @ref OFDictionary is provided to access this - * via @ref OFDictionary#filePOSIXUID. - */ -extern const of_file_attribute_key_t of_file_attribute_key_posix_uid; - -/*! - * @brief The POSIX GID of the file as an @ref OFNumber. - * - * For convenience, a category on @ref OFDictionary is provided to access this - * via @ref OFDictionary#filePOSIXGID. - */ -extern const of_file_attribute_key_t of_file_attribute_key_posix_gid; - -/*! - * @brief The owner of the file as an @ref OFString. - * - * For convenience, a category on @ref OFDictionary is provided to access this - * via @ref OFDictionary#fileOwner. - */ -extern const of_file_attribute_key_t of_file_attribute_key_owner; - -/*! - * @brief The group of the file as an @ref OFString. - * - * For convenience, a category on @ref OFDictionary is provided to access this - * via @ref OFDictionary#fileGroup. - */ -extern const of_file_attribute_key_t of_file_attribute_key_group; - -/*! - * @brief The last access date of the file as an @ref OFDate. - * - * For convenience, a category on @ref OFDictionary is provided to access this - * via @ref OFDictionary#fileLastAccessDate. - */ -extern const of_file_attribute_key_t of_file_attribute_key_last_access_date; - -/*! - * @brief The last modification date of the file as an @ref OFDate. - * - * For convenience, a category on @ref OFDictionary is provided to access this - * via @ref OFDictionary#fileModificationDate. - */ -extern const of_file_attribute_key_t of_file_attribute_key_modification_date; - -/*! - * @brief The last status change date of the file as an @ref OFDate. - * - * For convenience, a category on @ref OFDictionary is provided to access this - * via @ref OFDictionary#fileStatusChangeDate. - */ -extern const of_file_attribute_key_t of_file_attribute_key_status_change_date; - -/*! - * @brief The destination of a symbolic link as an @ref OFString. - * - * For convenience, a category on @ref OFDictionary is provided to access this - * via @ref OFDictionary#fileSymbolicLinkDestination. - */ -extern const of_file_attribute_key_t - of_file_attribute_key_symbolic_link_destination; - -/*! - * @brief A regular file. - */ -extern const of_file_type_t of_file_type_regular; - -/*! - * @brief A directory. - */ -extern const of_file_type_t of_file_type_directory; - -/*! - * @brief A symbolic link. - */ -extern const of_file_type_t of_file_type_symbolic_link; - -/*! - * @brief A FIFO. - */ -extern const of_file_type_t of_file_type_fifo; - -/*! - * @brief A character special file. - */ -extern const of_file_type_t of_file_type_character_special; - -/*! - * @brief A block special file. - */ -extern const of_file_type_t of_file_type_block_special; - -/*! - * @brief A socket. - */ -extern const of_file_type_t of_file_type_socket; -#ifdef __cplusplus -} -#endif - /*! * @class OFURLHandler OFURLHandler.h ObjFW/OFURLHandler.h * * @brief A handler for a URL scheme. */ @@ -413,86 +227,6 @@ */ - (bool)moveItemAtURL: (OFURL *)source toURL: (OFURL *)destination; @end -@interface OFDictionary (FileAttributes) -/*! - * The @ref of_file_attribute_key_size key from the dictionary. - * - * Raises an @ref OFUndefinedKeyException if the key is missing. - */ -@property (readonly, nonatomic) uintmax_t fileSize; - -/*! - * The @ref of_file_attribute_key_type key from the dictionary. - * - * Raises an @ref OFUndefinedKeyException if the key is missing. - */ -@property (readonly, nonatomic) of_file_type_t fileType; - -/*! - * The @ref of_file_attribute_key_posix_permissions key from the dictionary. - * - * Raises an @ref OFUndefinedKeyException if the key is missing. - */ -@property (readonly, nonatomic) uint16_t filePOSIXPermissions; - -/*! - * The @ref of_file_attribute_key_posix_uid key from the dictionary. - * - * Raises an @ref OFUndefinedKeyException if the key is missing. - */ -@property (readonly, nonatomic) uint32_t filePOSIXUID; - -/*! - * The @ref of_file_attribute_key_posix_gid key from the dictionary. - * - * Raises an @ref OFUndefinedKeyException if the key is missing. - */ -@property (readonly, nonatomic) uint32_t filePOSIXGID; - -/*! - * The @ref of_file_attribute_key_owner key from the dictionary. - * - * Raises an @ref OFUndefinedKeyException if the key is missing. - */ -@property (readonly, nonatomic) OFString *fileOwner; - -/*! - * The @ref of_file_attribute_key_group key from the dictionary. - * - * Raises an @ref OFUndefinedKeyException if the key is missing. - */ -@property (readonly, nonatomic) OFString *fileGroup; - -/*! - * The @ref of_file_attribute_key_last_access_date key from the dictionary. - * - * Raises an @ref OFUndefinedKeyException if the key is missing. - */ -@property (readonly, nonatomic) OFDate *fileLastAccessDate; - -/*! - * The @ref of_file_attribute_key_modification_date key from the dictionary. - * - * Raises an @ref OFUndefinedKeyException if the key is missing. - */ -@property (readonly, nonatomic) OFDate *fileModificationDate; - -/*! - * The @ref of_file_attribute_key_status_change_date key from the dictionary. - * - * Raises an @ref OFUndefinedKeyException if the key is missing. - */ -@property (readonly, nonatomic) OFDate *fileStatusChangeDate; - -/*! - * The @ref of_file_attribute_key_symbolic_link_destination key from the - * dictionary. - * - * Raises an @ref OFUndefinedKeyException if the key is missing. - */ -@property (readonly, nonatomic) OFString *fileSymbolicLinkDestination; -@end - OF_ASSUME_NONNULL_END Index: src/OFURLHandler.m ================================================================== --- src/OFURLHandler.m +++ src/OFURLHandler.m @@ -16,10 +16,11 @@ */ #include "config.h" #import "OFURLHandler.h" +#import "OFDictionary.h" #import "OFNumber.h" #import "OFURL.h" #ifdef OF_HAVE_THREADS # import "OFMutex.h" @@ -30,62 +31,15 @@ #endif #if defined(OF_HAVE_SOCKETS) && defined(OF_HAVE_THREADS) # import "OFURLHandler_HTTP.h" #endif -#import "OFUndefinedKeyException.h" - -const of_file_attribute_key_t of_file_attribute_key_size = - @"of_file_attribute_key_size"; -const of_file_attribute_key_t of_file_attribute_key_type = - @"of_file_attribute_key_type"; -const of_file_attribute_key_t of_file_attribute_key_posix_permissions = - @"of_file_attribute_key_posix_permissions"; -const of_file_attribute_key_t of_file_attribute_key_posix_uid = - @"of_file_attribute_key_posix_uid"; -const of_file_attribute_key_t of_file_attribute_key_posix_gid = - @"of_file_attribute_key_posix_gid"; -const of_file_attribute_key_t of_file_attribute_key_owner = - @"of_file_attribute_key_owner"; -const of_file_attribute_key_t of_file_attribute_key_group = - @"of_file_attribute_key_group"; -const of_file_attribute_key_t of_file_attribute_key_last_access_date = - @"of_file_attribute_key_last_access_date"; -const of_file_attribute_key_t of_file_attribute_key_modification_date = - @"of_file_attribute_key_modification_date"; -const of_file_attribute_key_t of_file_attribute_key_status_change_date = - @"of_file_attribute_key_status_change_date"; -const of_file_attribute_key_t of_file_attribute_key_symbolic_link_destination = - @"of_file_attribute_key_symbolic_link_destination"; - -const of_file_type_t of_file_type_regular = @"of_file_type_regular"; -const of_file_type_t of_file_type_directory = @"of_file_type_directory"; -const of_file_type_t of_file_type_symbolic_link = @"of_file_type_symbolic_link"; -const of_file_type_t of_file_type_fifo = @"of_file_type_fifo"; -const of_file_type_t of_file_type_character_special = - @"of_file_type_character_special"; -const of_file_type_t of_file_type_block_special = @"of_file_type_block_special"; -const of_file_type_t of_file_type_socket = @"of_file_type_socket"; - static OFMutableDictionary OF_GENERIC(OFString *, OFURLHandler *) *handlers; #ifdef OF_HAVE_THREADS static OFMutex *mutex; #endif -static id -attributeForKeyOrException(of_file_attributes_t attributes, - of_file_attribute_key_t key) -{ - id object = [attributes objectForKey: key]; - - if (object == nil) - @throw [OFUndefinedKeyException exceptionWithObject: attributes - key: key]; - - return object; -} - @implementation OFURLHandler @synthesize scheme = _scheme; + (void)initialize { @@ -240,71 +194,6 @@ - (bool)moveItemAtURL: (OFURL *)source toURL: (OFURL *)destination { return false; } -@end - -@implementation OFDictionary (FileAttributes) -- (uintmax_t)fileSize -{ - return [attributeForKeyOrException(self, of_file_attribute_key_size) - uIntMaxValue]; -} - -- (of_file_type_t)fileType -{ - return attributeForKeyOrException(self, of_file_attribute_key_type); -} - -- (uint16_t)filePOSIXPermissions -{ - return [attributeForKeyOrException(self, - of_file_attribute_key_posix_permissions) uInt16Value]; -} - -- (uint32_t)filePOSIXUID -{ - return [attributeForKeyOrException(self, - of_file_attribute_key_posix_uid) uInt32Value]; -} - -- (uint32_t)filePOSIXGID -{ - return [attributeForKeyOrException(self, - of_file_attribute_key_posix_gid) uInt32Value]; -} - -- (OFString *)fileOwner -{ - return attributeForKeyOrException(self, of_file_attribute_key_owner); -} - -- (OFString *)fileGroup -{ - return attributeForKeyOrException(self, of_file_attribute_key_group); -} - -- (OFDate *)fileLastAccessDate -{ - return attributeForKeyOrException(self, - of_file_attribute_key_last_access_date); -} - -- (OFDate *)fileModificationDate -{ - return attributeForKeyOrException(self, - of_file_attribute_key_modification_date); -} - -- (OFDate *)fileStatusChangeDate -{ - return attributeForKeyOrException(self, - of_file_attribute_key_status_change_date); -} - -- (OFString *)fileSymbolicLinkDestination -{ - return attributeForKeyOrException(self, - of_file_attribute_key_symbolic_link_destination); -} @end Index: src/OFURLHandler_file.m ================================================================== --- src/OFURLHandler_file.m +++ src/OFURLHandler_file.m @@ -690,11 +690,13 @@ andGroup: object ofItemAtURL: URL attributeKey: key attributes: attributes]; else - @throw [OFInvalidArgumentException exception]; + @throw [OFNotImplementedException + exceptionWithSelector: _cmd + object: self]; } objc_autoreleasePoolPop(pool); } Index: src/ObjFW.h ================================================================== --- src/ObjFW.h +++ src/ObjFW.h @@ -62,13 +62,13 @@ #import "OFLHAArchiveEntry.h" #import "OFTarArchive.h" #import "OFTarArchiveEntry.h" #import "OFZIPArchive.h" #import "OFZIPArchiveEntry.h" +#import "OFFileManager.h" #ifdef OF_HAVE_FILES # import "OFFile.h" -# import "OFFileManager.h" # import "OFINIFile.h" # import "OFSettings.h" #endif #ifdef OF_HAVE_SOCKETS # import "OFStreamSocket.h"