Index: src/OFFile.h ================================================================== --- src/OFFile.h +++ src/OFFile.h @@ -164,11 +164,11 @@ #ifdef OF_HAVE_CHOWN /*! * @brief Changes the owner of an item. * - * This method is not available on Windows. + * This method is not available on some systems, most notably Windows. * * @param path The path to the item whose owner should be changed * @param owner The new owner for the item * @param group The new group for the item */ @@ -178,12 +178,13 @@ #endif /*! * @brief Copies a file, directory or symlink (if supported by the OS). * - * If an item already exists, it is replaced. This is also the case if a - * directory is copied and an item already exists in the destination directory. + * If an item already exists, the copy operation fails. This is also the case + * if a directory is copied and an item already exists in the destination + * directory. * * @param source The file, directory or symlink to copy * @param destination The destination path */ + (void)copyItemAtPath: (OFString*)source @@ -209,11 +210,11 @@ #ifdef OF_HAVE_LINK /*! * @brief Creates a hard link for the specified item. * - * Not available on Windows. + * This method is not available on some systems, most notably Windows. * * @param source The path of the item for which a link should be created * @param destination The path of the item which should link to the source */ + (void)linkItemAtPath: (OFString*)source @@ -222,11 +223,11 @@ #ifdef OF_HAVE_SYMLINK /*! * @brief Creates a symbolic link for an item. * - * Not available on Windows. + * This method is not available on some systems, most notably Windows. * * @param destination The path of the item which should symbolically link to the * source * @param source The path of the item for which a symbolic link should be * created Index: src/OFFile.m ================================================================== --- src/OFFile.m +++ src/OFFile.m @@ -548,10 +548,22 @@ if ([self directoryExistsAtPath: destination]) { OFArray *components = [OFArray arrayWithObjects: destination, [source lastPathComponent], nil]; destination = [OFString pathWithComponents: components]; } + +#ifndef _WIN32 + if (lstat([destination + cStringWithEncoding: OF_STRING_ENCODING_NATIVE], &s) == 0) { +#else + if (_wstat([destination UTF16String], &s) == 0) { +#endif + errno = EEXIST; + @throw [OFCopyItemFailedException + exceptionWithSourcePath: source + destinationPath: destination]; + } #ifndef _WIN32 if (lstat([source cStringWithEncoding: OF_STRING_ENCODING_NATIVE], &s)) #else if (_wstat([source UTF16String], &s)) @@ -558,66 +570,17 @@ #endif @throw [OFCopyItemFailedException exceptionWithSourcePath: source destinationPath: destination]; - if (S_ISREG(s.st_mode)) { -#ifdef OF_HAVE_CHMOD - bool override = [self fileExistsAtPath: destination]; -#endif - size_t pageSize = [OFSystemInfo pageSize]; - OFFile *sourceFile = nil; - OFFile *destinationFile = nil; - char *buffer; - - if ((buffer = malloc(pageSize)) == NULL) - @throw [OFOutOfMemoryException - exceptionWithRequestedSize: pageSize]; - - @try { -#ifdef OF_HAVE_SYMLINK - if ([OFFile symbolicLinkExistsAtPath: destination]) - [OFFile removeItemAtPath: destination]; -#endif - - sourceFile = [OFFile fileWithPath: source - mode: @"rb"]; - destinationFile = [OFFile fileWithPath: destination - mode: @"wb"]; - - while (![sourceFile isAtEndOfStream]) { - size_t length; - - length = [sourceFile readIntoBuffer: buffer - length: pageSize]; - [destinationFile writeBuffer: buffer - length: length]; - } - -#ifdef OF_HAVE_CHMOD - if (!override) - [self changePermissionsOfItemAtPath: destination - permissions: s.st_mode]; -#endif - } @catch (id e) { - @throw [OFCopyItemFailedException - exceptionWithSourcePath: source - destinationPath: destination]; - } @finally { - [sourceFile close]; - [destinationFile close]; - free(buffer); - } - } else if (S_ISDIR(s.st_mode)) { + if (S_ISDIR(s.st_mode)) { OFArray *contents; OFEnumerator *enumerator; OFString *item; @try { - if (![OFFile directoryExistsAtPath: destination]) - [OFFile createDirectoryAtPath: destination]; - + [OFFile createDirectoryAtPath: destination]; #ifdef OF_HAVE_CHMOD [OFFile changePermissionsOfItemAtPath: destination permissions: s.st_mode]; #endif @@ -645,18 +608,52 @@ [OFFile copyItemAtPath: sourcePath toPath: destinationPath]; objc_autoreleasePoolPop(pool2); + } + } else if (S_ISREG(s.st_mode)) { + size_t pageSize = [OFSystemInfo pageSize]; + OFFile *sourceFile = nil; + OFFile *destinationFile = nil; + char *buffer; + + if ((buffer = malloc(pageSize)) == NULL) + @throw [OFOutOfMemoryException + exceptionWithRequestedSize: pageSize]; + + @try { + sourceFile = [OFFile fileWithPath: source + mode: @"rb"]; + destinationFile = [OFFile fileWithPath: destination + mode: @"wb"]; + + while (![sourceFile isAtEndOfStream]) { + size_t length; + + length = [sourceFile readIntoBuffer: buffer + length: pageSize]; + [destinationFile writeBuffer: buffer + length: length]; + } + +#ifdef OF_HAVE_CHMOD + [self changePermissionsOfItemAtPath: destination + permissions: s.st_mode]; +#endif + } @catch (id e) { + @throw [OFCopyItemFailedException + exceptionWithSourcePath: source + destinationPath: destination]; + } @finally { + [sourceFile close]; + [destinationFile close]; + free(buffer); } #ifdef OF_HAVE_SYMLINK } else if (S_ISLNK(s.st_mode)) { @try { - if ([OFFile symbolicLinkExistsAtPath: destination] || - [OFFile fileExistsAtPath: destination]) - [OFFile removeItemAtPath: destination]; - source = [OFFile destinationOfSymbolicLinkAtPath: source]; [OFFile createSymbolicLinkAtPath: destination withDestinationPath: source];