Index: ObjFW.xcodeproj/project.pbxproj ================================================================== --- ObjFW.xcodeproj/project.pbxproj +++ ObjFW.xcodeproj/project.pbxproj @@ -47,14 +47,10 @@ /* Begin PBXBuildFile section */ 4B0256E4172B60400062B5F1 /* OFStdIOStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B0256E2172B60400062B5F1 /* OFStdIOStream.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B0256E5172B60400062B5F1 /* OFStdIOStream.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B0256E3172B60400062B5F1 /* OFStdIOStream.m */; }; 4B067FBB177BA6F900B8CFDA /* OFChangeCurrentDirectoryPathFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B067FAF177BA6F900B8CFDA /* OFChangeCurrentDirectoryPathFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B067FBC177BA6F900B8CFDA /* OFChangeCurrentDirectoryPathFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B067FB0177BA6F900B8CFDA /* OFChangeCurrentDirectoryPathFailedException.m */; }; - 4B067FBD177BA6F900B8CFDA /* OFChangeOwnerFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B067FB1177BA6F900B8CFDA /* OFChangeOwnerFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4B067FBE177BA6F900B8CFDA /* OFChangeOwnerFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B067FB2177BA6F900B8CFDA /* OFChangeOwnerFailedException.m */; }; - 4B067FBF177BA6F900B8CFDA /* OFChangePermissionsFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B067FB3177BA6F900B8CFDA /* OFChangePermissionsFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4B067FC0177BA6F900B8CFDA /* OFChangePermissionsFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B067FB4177BA6F900B8CFDA /* OFChangePermissionsFailedException.m */; }; 4B067FC1177BA6F900B8CFDA /* OFCreateSymbolicLinkFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B067FB5177BA6F900B8CFDA /* OFCreateSymbolicLinkFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B067FC2177BA6F900B8CFDA /* OFCreateSymbolicLinkFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B067FB6177BA6F900B8CFDA /* OFCreateSymbolicLinkFailedException.m */; }; 4B06855318B2AD3800FC731A /* OFINICategory.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B06855018B2AD3800FC731A /* OFINICategory.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B06855418B2AD3800FC731A /* OFINICategory.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B06855118B2AD3800FC731A /* OFINICategory.m */; }; 4B06855518B2AD3800FC731A /* OFINICategory+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B06855218B2AD3800FC731A /* OFINICategory+Private.h */; }; @@ -332,12 +328,10 @@ 4B2C219A1DA292BE00735907 /* OFAddressTranslationFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B90B797133AD87D00BD33CB /* OFAddressTranslationFailedException.m */; }; 4B2C219B1DA292BE00735907 /* OFAllocFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B17FF7E133A2D17003E6DCD /* OFAllocFailedException.m */; }; 4B2C219C1DA292BE00735907 /* OFAlreadyConnectedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B90B788133AD46700BD33CB /* OFAlreadyConnectedException.m */; }; 4B2C219D1DA292BE00735907 /* OFBindFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B90B799133AD87D00BD33CB /* OFBindFailedException.m */; }; 4B2C219E1DA292BE00735907 /* OFChangeCurrentDirectoryPathFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B067FB0177BA6F900B8CFDA /* OFChangeCurrentDirectoryPathFailedException.m */; }; - 4B2C219F1DA292BE00735907 /* OFChangeOwnerFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B067FB2177BA6F900B8CFDA /* OFChangeOwnerFailedException.m */; }; - 4B2C21A01DA292BE00735907 /* OFChangePermissionsFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B067FB4177BA6F900B8CFDA /* OFChangePermissionsFailedException.m */; }; 4B2C21A11DA292BE00735907 /* OFChecksumFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BE52D2417B990DA005958D1 /* OFChecksumFailedException.m */; }; 4B2C21A21DA292BE00735907 /* OFConditionBroadcastFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B8B1702133A3B8E007CD8B3 /* OFConditionBroadcastFailedException.m */; }; 4B2C21A31DA292BE00735907 /* OFConditionSignalFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B8B1704133A3B8E007CD8B3 /* OFConditionSignalFailedException.m */; }; 4B2C21A41DA292BE00735907 /* OFConditionStillWaitingException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B7FF3B3133CED6100000324 /* OFConditionStillWaitingException.m */; }; 4B2C21A51DA292BE00735907 /* OFConditionWaitFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B8B1706133A3B8E007CD8B3 /* OFConditionWaitFailedException.m */; }; @@ -371,11 +365,10 @@ 4B2C21C11DA292BE00735907 /* OFReadFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B55A10D133AC24500B58A93 /* OFReadFailedException.m */; }; 4B2C21C21DA292BE00735907 /* OFReadOrWriteFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B55A10F133AC24500B58A93 /* OFReadOrWriteFailedException.m */; }; 4B2C21C31DA292BE00735907 /* OFRemoveItemFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BFF3711177E17C100192782 /* OFRemoveItemFailedException.m */; }; 4B2C21C41DA292BE00735907 /* OFSeekFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B29BC3A133AC4E80004B236 /* OFSeekFailedException.m */; }; 4B2C21C51DA292BE00735907 /* OFSetOptionFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B90B78C133AD46700BD33CB /* OFSetOptionFailedException.m */; }; - 4B2C21C61DA292BE00735907 /* OFStatItemFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B72F7DD1AD9311B00CE253C /* OFStatItemFailedException.m */; }; 4B2C21C71DA292BE00735907 /* OFStillLockedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B6743EE163C384A00EB1E59 /* OFStillLockedException.m */; }; 4B2C21C81DA292BE00735907 /* OFThreadJoinFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B55A0FA133ABEA900B58A93 /* OFThreadJoinFailedException.m */; }; 4B2C21C91DA292BE00735907 /* OFThreadStartFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B55A0FC133ABEA900B58A93 /* OFThreadStartFailedException.m */; }; 4B2C21CA1DA292BE00735907 /* OFThreadStillRunningException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B55A0FE133ABEA900B58A93 /* OFThreadStillRunningException.m */; }; 4B2C21CB1DA292BE00735907 /* OFTruncatedDataException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B17FFA8133A34E1003E6DCD /* OFTruncatedDataException.m */; }; @@ -511,12 +504,10 @@ 4B2C22551DA292BE00735907 /* OFAddressTranslationFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B90B796133AD87D00BD33CB /* OFAddressTranslationFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B2C22561DA292BE00735907 /* OFAllocFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B17FF7D133A2D16003E6DCD /* OFAllocFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B2C22571DA292BE00735907 /* OFAlreadyConnectedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B90B787133AD46700BD33CB /* OFAlreadyConnectedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B2C22581DA292BE00735907 /* OFBindFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B90B798133AD87D00BD33CB /* OFBindFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B2C22591DA292BE00735907 /* OFChangeCurrentDirectoryPathFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B067FAF177BA6F900B8CFDA /* OFChangeCurrentDirectoryPathFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4B2C225A1DA292BE00735907 /* OFChangeOwnerFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B067FB1177BA6F900B8CFDA /* OFChangeOwnerFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4B2C225B1DA292BE00735907 /* OFChangePermissionsFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B067FB3177BA6F900B8CFDA /* OFChangePermissionsFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B2C225C1DA292BE00735907 /* OFChecksumFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BE52D2317B990DA005958D1 /* OFChecksumFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B2C225D1DA292BE00735907 /* OFConditionBroadcastFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B8B1701133A3B8E007CD8B3 /* OFConditionBroadcastFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B2C225E1DA292BE00735907 /* OFConditionSignalFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B8B1703133A3B8E007CD8B3 /* OFConditionSignalFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B2C225F1DA292BE00735907 /* OFConditionStillWaitingException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B7FF3B2133CED6100000324 /* OFConditionStillWaitingException.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B2C22601DA292BE00735907 /* OFConditionWaitFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B8B1705133A3B8E007CD8B3 /* OFConditionWaitFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -549,11 +540,10 @@ 4B2C227B1DA292BE00735907 /* OFReadFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B55A10C133AC24500B58A93 /* OFReadFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B2C227C1DA292BE00735907 /* OFReadOrWriteFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B55A10E133AC24500B58A93 /* OFReadOrWriteFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B2C227D1DA292BE00735907 /* OFRemoveItemFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BFF3710177E17C100192782 /* OFRemoveItemFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B2C227E1DA292BE00735907 /* OFSeekFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B29BC39133AC4E80004B236 /* OFSeekFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B2C227F1DA292BE00735907 /* OFSetOptionFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B90B78B133AD46700BD33CB /* OFSetOptionFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4B2C22801DA292BE00735907 /* OFStatItemFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B72F7DC1AD9311B00CE253C /* OFStatItemFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B2C22811DA292BE00735907 /* OFStillLockedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B6743ED163C384A00EB1E59 /* OFStillLockedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B2C22821DA292BE00735907 /* OFTruncatedDataException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B17FFA7133A34DF003E6DCD /* OFTruncatedDataException.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B2C22831DA292BE00735907 /* OFThreadJoinFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B55A0F9133ABEA900B58A93 /* OFThreadJoinFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B2C22841DA292BE00735907 /* OFThreadStartFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B55A0FB133ABEA900B58A93 /* OFThreadStartFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B2C22851DA292BE00735907 /* OFThreadStillRunningException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B55A0FD133ABEA900B58A93 /* OFThreadStillRunningException.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -827,12 +817,10 @@ 4B6C8ADE17BD5C2E00B194F2 /* OFZIPArchiveEntry+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B6C8AD717BD5C2E00B194F2 /* OFZIPArchiveEntry+Private.h */; }; 4B6D0A891D4459D900901D8D /* OFHMAC.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B6D0A871D4459D900901D8D /* OFHMAC.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B6D0A8A1D4459D900901D8D /* OFHMAC.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B6D0A881D4459D900901D8D /* OFHMAC.m */; }; 4B7161AD17A6FC7600B74970 /* OFHTTPResponse.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B7161AB17A6FC7600B74970 /* OFHTTPResponse.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B7161AE17A6FC7600B74970 /* OFHTTPResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B7161AC17A6FC7600B74970 /* OFHTTPResponse.m */; }; - 4B72F7DE1AD9311B00CE253C /* OFStatItemFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B72F7DC1AD9311B00CE253C /* OFStatItemFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 4B72F7DF1AD9311B00CE253C /* OFStatItemFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B72F7DD1AD9311B00CE253C /* OFStatItemFailedException.m */; }; 4B7327771F93EC3A00E1607F /* module.modulemap in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4B7327731F93EBC400E1607F /* module.modulemap */; }; 4B7327791F93EC5700E1607F /* module.modulemap in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4BEAF52519A8107500B61868 /* module.modulemap */; }; 4B73277B1F93EC6A00E1607F /* module.modulemap in CopyFiles */ = {isa = PBXBuildFile; fileRef = 4B7327731F93EBC400E1607F /* module.modulemap */; }; 4B745BA5168B25E600A6C20E /* OFSystemInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 4B745BA3168B25E600A6C20E /* OFSystemInfo.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4B745BA6168B25E600A6C20E /* OFSystemInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B745BA4168B25E600A6C20E /* OFSystemInfo.m */; }; @@ -1043,10 +1031,18 @@ 4BF20C541EEBF5F000C53220 /* OFInflate64Stream.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BF20C4E1EEBF5F000C53220 /* OFInflate64Stream.m */; }; 4BF20C551EEBF5F000C53220 /* OFInflateStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BF20C4F1EEBF5F000C53220 /* OFInflateStream.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4BF20C561EEBF5F000C53220 /* OFInflateStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BF20C4F1EEBF5F000C53220 /* OFInflateStream.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4BF20C571EEBF5F000C53220 /* OFInflateStream.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BF20C501EEBF5F000C53220 /* OFInflateStream.m */; }; 4BF20C581EEBF5F000C53220 /* OFInflateStream.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BF20C501EEBF5F000C53220 /* OFInflateStream.m */; }; + 4BF2771D1FB8C113009F8FCF /* OFSetItemAttributesFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BF277191FB8C112009F8FCF /* OFSetItemAttributesFailedException.m */; }; + 4BF2771E1FB8C113009F8FCF /* OFSetItemAttributesFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BF277191FB8C112009F8FCF /* OFSetItemAttributesFailedException.m */; }; + 4BF2771F1FB8C113009F8FCF /* OFRetrieveItemAttributesFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BF2771A1FB8C113009F8FCF /* OFRetrieveItemAttributesFailedException.m */; }; + 4BF277201FB8C113009F8FCF /* OFRetrieveItemAttributesFailedException.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BF2771A1FB8C113009F8FCF /* OFRetrieveItemAttributesFailedException.m */; }; + 4BF277211FB8C113009F8FCF /* OFRetrieveItemAttributesFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BF2771B1FB8C113009F8FCF /* OFRetrieveItemAttributesFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4BF277221FB8C113009F8FCF /* OFRetrieveItemAttributesFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BF2771B1FB8C113009F8FCF /* OFRetrieveItemAttributesFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4BF277231FB8C113009F8FCF /* OFSetItemAttributesFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BF2771C1FB8C113009F8FCF /* OFSetItemAttributesFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4BF277241FB8C113009F8FCF /* OFSetItemAttributesFailedException.h in Headers */ = {isa = PBXBuildFile; fileRef = 4BF2771C1FB8C113009F8FCF /* OFSetItemAttributesFailedException.h */; settings = {ATTRIBUTES = (Public, ); }; }; 4BF33AFB133807590059CEF7 /* ObjFW.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4B3D23761337FBC800DD29B8 /* ObjFW.framework */; }; 4BF33AFC133807A20059CEF7 /* OFArrayTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B6EF66E1235358D0076B512 /* OFArrayTests.m */; }; 4BF33AFD133807A20059CEF7 /* OFBlockTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BE5F0E412DF4259005C7A0C /* OFBlockTests.m */; }; 4BF33AFE133807A20059CEF7 /* OFDataTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4B6EF66F1235358D0076B512 /* OFDataTests.m */; }; 4BF33AFF133807A20059CEF7 /* OFDateTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 4BE5F0E512DF4259005C7A0C /* OFDateTests.m */; }; @@ -1254,14 +1250,10 @@ 4B0108CA10EB8C9300631877 /* OFEnumerator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFEnumerator.m; path = src/OFEnumerator.m; sourceTree = ""; }; 4B0256E2172B60400062B5F1 /* OFStdIOStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFStdIOStream.h; path = src/OFStdIOStream.h; sourceTree = ""; }; 4B0256E3172B60400062B5F1 /* OFStdIOStream.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFStdIOStream.m; path = src/OFStdIOStream.m; sourceTree = ""; }; 4B067FAF177BA6F900B8CFDA /* OFChangeCurrentDirectoryPathFailedException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFChangeCurrentDirectoryPathFailedException.h; path = src/exceptions/OFChangeCurrentDirectoryPathFailedException.h; sourceTree = ""; }; 4B067FB0177BA6F900B8CFDA /* OFChangeCurrentDirectoryPathFailedException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFChangeCurrentDirectoryPathFailedException.m; path = src/exceptions/OFChangeCurrentDirectoryPathFailedException.m; sourceTree = ""; }; - 4B067FB1177BA6F900B8CFDA /* OFChangeOwnerFailedException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFChangeOwnerFailedException.h; path = src/exceptions/OFChangeOwnerFailedException.h; sourceTree = ""; }; - 4B067FB2177BA6F900B8CFDA /* OFChangeOwnerFailedException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFChangeOwnerFailedException.m; path = src/exceptions/OFChangeOwnerFailedException.m; sourceTree = ""; }; - 4B067FB3177BA6F900B8CFDA /* OFChangePermissionsFailedException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFChangePermissionsFailedException.h; path = src/exceptions/OFChangePermissionsFailedException.h; sourceTree = ""; }; - 4B067FB4177BA6F900B8CFDA /* OFChangePermissionsFailedException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFChangePermissionsFailedException.m; path = src/exceptions/OFChangePermissionsFailedException.m; sourceTree = ""; }; 4B067FB5177BA6F900B8CFDA /* OFCreateSymbolicLinkFailedException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFCreateSymbolicLinkFailedException.h; path = src/exceptions/OFCreateSymbolicLinkFailedException.h; sourceTree = ""; }; 4B067FB6177BA6F900B8CFDA /* OFCreateSymbolicLinkFailedException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFCreateSymbolicLinkFailedException.m; path = src/exceptions/OFCreateSymbolicLinkFailedException.m; sourceTree = ""; }; 4B06855018B2AD3800FC731A /* OFINICategory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFINICategory.h; path = src/OFINICategory.h; sourceTree = ""; }; 4B06855118B2AD3800FC731A /* OFINICategory.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFINICategory.m; path = src/OFINICategory.m; sourceTree = ""; }; 4B06855218B2AD3800FC731A /* OFINICategory+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "OFINICategory+Private.h"; path = "src/OFINICategory+Private.h"; sourceTree = ""; }; @@ -1585,12 +1577,10 @@ 4B6EF6811235358D0076B512 /* TestsAppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TestsAppDelegate.m; path = tests/TestsAppDelegate.m; sourceTree = SOURCE_ROOT; }; 4B6EF684123535B60076B512 /* TestPlugin.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TestPlugin.m; path = tests/plugin/TestPlugin.m; sourceTree = SOURCE_ROOT; }; 4B6EF685123535C80076B512 /* test.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = test.m; path = tests/objc_sync/test.m; sourceTree = SOURCE_ROOT; }; 4B7161AB17A6FC7600B74970 /* OFHTTPResponse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFHTTPResponse.h; path = src/OFHTTPResponse.h; sourceTree = ""; }; 4B7161AC17A6FC7600B74970 /* OFHTTPResponse.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFHTTPResponse.m; path = src/OFHTTPResponse.m; sourceTree = ""; }; - 4B72F7DC1AD9311B00CE253C /* OFStatItemFailedException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFStatItemFailedException.h; path = src/exceptions/OFStatItemFailedException.h; sourceTree = ""; }; - 4B72F7DD1AD9311B00CE253C /* OFStatItemFailedException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFStatItemFailedException.m; path = src/exceptions/OFStatItemFailedException.m; sourceTree = ""; }; 4B7327731F93EBC400E1607F /* module.modulemap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = "sourcecode.module-map"; name = module.modulemap; path = src/bridge/module.modulemap; sourceTree = ""; }; 4B745BA3168B25E600A6C20E /* OFSystemInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFSystemInfo.h; path = src/OFSystemInfo.h; sourceTree = ""; }; 4B745BA4168B25E600A6C20E /* OFSystemInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFSystemInfo.m; path = src/OFSystemInfo.m; sourceTree = ""; }; 4B76F4751DA2C2BB00CFF831 /* Tests (iOS).app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Tests (iOS).app"; sourceTree = BUILT_PRODUCTS_DIR; }; 4B7769EB1895C07D00D12284 /* resolver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = resolver.h; path = src/resolver.h; sourceTree = ""; }; @@ -1779,10 +1769,14 @@ 4BF1BCCF11C9663F0025511F /* OFXMLAttribute.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFXMLAttribute.m; path = src/OFXMLAttribute.m; sourceTree = ""; }; 4BF20C4D1EEBF5F000C53220 /* OFInflate64Stream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFInflate64Stream.h; path = src/OFInflate64Stream.h; sourceTree = ""; }; 4BF20C4E1EEBF5F000C53220 /* OFInflate64Stream.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFInflate64Stream.m; path = src/OFInflate64Stream.m; sourceTree = ""; }; 4BF20C4F1EEBF5F000C53220 /* OFInflateStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFInflateStream.h; path = src/OFInflateStream.h; sourceTree = ""; }; 4BF20C501EEBF5F000C53220 /* OFInflateStream.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFInflateStream.m; path = src/OFInflateStream.m; sourceTree = ""; }; + 4BF277191FB8C112009F8FCF /* OFSetItemAttributesFailedException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFSetItemAttributesFailedException.m; path = src/exceptions/OFSetItemAttributesFailedException.m; sourceTree = ""; }; + 4BF2771A1FB8C113009F8FCF /* OFRetrieveItemAttributesFailedException.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = OFRetrieveItemAttributesFailedException.m; path = src/exceptions/OFRetrieveItemAttributesFailedException.m; sourceTree = ""; }; + 4BF2771B1FB8C113009F8FCF /* OFRetrieveItemAttributesFailedException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFRetrieveItemAttributesFailedException.h; path = src/exceptions/OFRetrieveItemAttributesFailedException.h; sourceTree = ""; }; + 4BF2771C1FB8C113009F8FCF /* OFSetItemAttributesFailedException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = OFSetItemAttributesFailedException.h; path = src/exceptions/OFSetItemAttributesFailedException.h; sourceTree = ""; }; 4BF33AF0133807310059CEF7 /* Tests */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = Tests; sourceTree = BUILT_PRODUCTS_DIR; }; 4BF33B4213380CD40059CEF7 /* testfile.bin */ = {isa = PBXFileReference; lastKnownFileType = archive.macbinary; name = testfile.bin; path = tests/testfile.bin; sourceTree = ""; }; 4BF33B4313380CD40059CEF7 /* testfile.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; name = testfile.txt; path = tests/testfile.txt; sourceTree = ""; }; 4BF3A2281E25EA48002EA46F /* windows-1251.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "windows-1251.m"; path = "src/encodings/windows-1251.m"; sourceTree = ""; }; 4BF5CB8F1E2DC1D800CF7584 /* iso_8859-2.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "iso_8859-2.m"; path = "src/encodings/iso_8859-2.m"; sourceTree = ""; }; @@ -1888,14 +1882,10 @@ 4B90B788133AD46700BD33CB /* OFAlreadyConnectedException.m */, 4B90B798133AD87D00BD33CB /* OFBindFailedException.h */, 4B90B799133AD87D00BD33CB /* OFBindFailedException.m */, 4B067FAF177BA6F900B8CFDA /* OFChangeCurrentDirectoryPathFailedException.h */, 4B067FB0177BA6F900B8CFDA /* OFChangeCurrentDirectoryPathFailedException.m */, - 4B067FB1177BA6F900B8CFDA /* OFChangeOwnerFailedException.h */, - 4B067FB2177BA6F900B8CFDA /* OFChangeOwnerFailedException.m */, - 4B067FB3177BA6F900B8CFDA /* OFChangePermissionsFailedException.h */, - 4B067FB4177BA6F900B8CFDA /* OFChangePermissionsFailedException.m */, 4BE52D2317B990DA005958D1 /* OFChecksumFailedException.h */, 4BE52D2417B990DA005958D1 /* OFChecksumFailedException.m */, 4B8B1701133A3B8E007CD8B3 /* OFConditionBroadcastFailedException.h */, 4B8B1702133A3B8E007CD8B3 /* OFConditionBroadcastFailedException.m */, 4B8B1703133A3B8E007CD8B3 /* OFConditionSignalFailedException.h */, @@ -1962,18 +1952,20 @@ 4B55A10D133AC24500B58A93 /* OFReadFailedException.m */, 4B55A10E133AC24500B58A93 /* OFReadOrWriteFailedException.h */, 4B55A10F133AC24500B58A93 /* OFReadOrWriteFailedException.m */, 4BFF3710177E17C100192782 /* OFRemoveItemFailedException.h */, 4BFF3711177E17C100192782 /* OFRemoveItemFailedException.m */, + 4BF2771B1FB8C113009F8FCF /* OFRetrieveItemAttributesFailedException.h */, + 4BF2771A1FB8C113009F8FCF /* OFRetrieveItemAttributesFailedException.m */, 4B14EAC51E9A8292005E8BFD /* OFSandboxActivationFailedException.h */, 4B14EAC61E9A8292005E8BFD /* OFSandboxActivationFailedException.m */, 4B29BC39133AC4E80004B236 /* OFSeekFailedException.h */, 4B29BC3A133AC4E80004B236 /* OFSeekFailedException.m */, + 4BF2771C1FB8C113009F8FCF /* OFSetItemAttributesFailedException.h */, + 4BF277191FB8C112009F8FCF /* OFSetItemAttributesFailedException.m */, 4B90B78B133AD46700BD33CB /* OFSetOptionFailedException.h */, 4B90B78C133AD46700BD33CB /* OFSetOptionFailedException.m */, - 4B72F7DC1AD9311B00CE253C /* OFStatItemFailedException.h */, - 4B72F7DD1AD9311B00CE253C /* OFStatItemFailedException.m */, 4B6743ED163C384A00EB1E59 /* OFStillLockedException.h */, 4B6743EE163C384A00EB1E59 /* OFStillLockedException.m */, 4B55A0F9133ABEA900B58A93 /* OFThreadJoinFailedException.h */, 4B55A0FA133ABEA900B58A93 /* OFThreadJoinFailedException.m */, 4B55A0FB133ABEA900B58A93 /* OFThreadStartFailedException.h */, @@ -2736,12 +2728,10 @@ 4B2C22551DA292BE00735907 /* OFAddressTranslationFailedException.h in Headers */, 4B2C22561DA292BE00735907 /* OFAllocFailedException.h in Headers */, 4B2C22571DA292BE00735907 /* OFAlreadyConnectedException.h in Headers */, 4B2C22581DA292BE00735907 /* OFBindFailedException.h in Headers */, 4B2C22591DA292BE00735907 /* OFChangeCurrentDirectoryPathFailedException.h in Headers */, - 4B2C225A1DA292BE00735907 /* OFChangeOwnerFailedException.h in Headers */, - 4B2C225B1DA292BE00735907 /* OFChangePermissionsFailedException.h in Headers */, 4B2C225C1DA292BE00735907 /* OFChecksumFailedException.h in Headers */, 4B2C225D1DA292BE00735907 /* OFConditionBroadcastFailedException.h in Headers */, 4B2C225E1DA292BE00735907 /* OFConditionSignalFailedException.h in Headers */, 4B2C225F1DA292BE00735907 /* OFConditionStillWaitingException.h in Headers */, 4B2C22601DA292BE00735907 /* OFConditionWaitFailedException.h in Headers */, @@ -2772,14 +2762,15 @@ 4B2C22791DA292BE00735907 /* OFOutOfMemoryException.h in Headers */, 4B2C227A1DA292BE00735907 /* OFOutOfRangeException.h in Headers */, 4B2C227B1DA292BE00735907 /* OFReadFailedException.h in Headers */, 4B2C227C1DA292BE00735907 /* OFReadOrWriteFailedException.h in Headers */, 4B2C227D1DA292BE00735907 /* OFRemoveItemFailedException.h in Headers */, + 4BF277221FB8C113009F8FCF /* OFRetrieveItemAttributesFailedException.h in Headers */, 4B14EAC81E9A8292005E8BFD /* OFSandboxActivationFailedException.h in Headers */, 4B2C227E1DA292BE00735907 /* OFSeekFailedException.h in Headers */, + 4BF277241FB8C113009F8FCF /* OFSetItemAttributesFailedException.h in Headers */, 4B2C227F1DA292BE00735907 /* OFSetOptionFailedException.h in Headers */, - 4B2C22801DA292BE00735907 /* OFStatItemFailedException.h in Headers */, 4B2C22811DA292BE00735907 /* OFStillLockedException.h in Headers */, 4B2C22821DA292BE00735907 /* OFTruncatedDataException.h in Headers */, 4B2C22831DA292BE00735907 /* OFThreadJoinFailedException.h in Headers */, 4B2C22841DA292BE00735907 /* OFThreadStartFailedException.h in Headers */, 4B2C22851DA292BE00735907 /* OFThreadStillRunningException.h in Headers */, @@ -2975,12 +2966,10 @@ 4B90B7A0133AD87D00BD33CB /* OFAddressTranslationFailedException.h in Headers */, 4B17FF7F133A2D17003E6DCD /* OFAllocFailedException.h in Headers */, 4B90B78D133AD46700BD33CB /* OFAlreadyConnectedException.h in Headers */, 4B90B7A2133AD87D00BD33CB /* OFBindFailedException.h in Headers */, 4B067FBB177BA6F900B8CFDA /* OFChangeCurrentDirectoryPathFailedException.h in Headers */, - 4B067FBD177BA6F900B8CFDA /* OFChangeOwnerFailedException.h in Headers */, - 4B067FBF177BA6F900B8CFDA /* OFChangePermissionsFailedException.h in Headers */, 4BE52D2517B990DA005958D1 /* OFChecksumFailedException.h in Headers */, 4B29BC58133AC8540004B236 /* OFConditionBroadcastFailedException.h in Headers */, 4B29BC59133AC8540004B236 /* OFConditionSignalFailedException.h in Headers */, 4B7FF3B4133CED6200000324 /* OFConditionStillWaitingException.h in Headers */, 4B29BC5A133AC8540004B236 /* OFConditionWaitFailedException.h in Headers */, @@ -3011,14 +3000,15 @@ 4B17FF83133A2DFB003E6DCD /* OFOutOfMemoryException.h in Headers */, 4B17FF7B133A2C15003E6DCD /* OFOutOfRangeException.h in Headers */, 4B55A112133AC24600B58A93 /* OFReadFailedException.h in Headers */, 4B55A114133AC24600B58A93 /* OFReadOrWriteFailedException.h in Headers */, 4BFF3714177E17C100192782 /* OFRemoveItemFailedException.h in Headers */, + 4BF277211FB8C113009F8FCF /* OFRetrieveItemAttributesFailedException.h in Headers */, 4B14EAC71E9A8292005E8BFD /* OFSandboxActivationFailedException.h in Headers */, 4B29BC41133AC4E80004B236 /* OFSeekFailedException.h in Headers */, + 4BF277231FB8C113009F8FCF /* OFSetItemAttributesFailedException.h in Headers */, 4B90B791133AD46700BD33CB /* OFSetOptionFailedException.h in Headers */, - 4B72F7DE1AD9311B00CE253C /* OFStatItemFailedException.h in Headers */, 4B6743F3163C384A00EB1E59 /* OFStillLockedException.h in Headers */, 4B17FFA9133A34E7003E6DCD /* OFTruncatedDataException.h in Headers */, 4B55A0FF133ABEA900B58A93 /* OFThreadJoinFailedException.h in Headers */, 4B55A101133ABEA900B58A93 /* OFThreadStartFailedException.h in Headers */, 4B55A103133ABEA900B58A93 /* OFThreadStillRunningException.h in Headers */, @@ -3530,12 +3520,10 @@ 4B2C219A1DA292BE00735907 /* OFAddressTranslationFailedException.m in Sources */, 4B2C219B1DA292BE00735907 /* OFAllocFailedException.m in Sources */, 4B2C219C1DA292BE00735907 /* OFAlreadyConnectedException.m in Sources */, 4B2C219D1DA292BE00735907 /* OFBindFailedException.m in Sources */, 4B2C219E1DA292BE00735907 /* OFChangeCurrentDirectoryPathFailedException.m in Sources */, - 4B2C219F1DA292BE00735907 /* OFChangeOwnerFailedException.m in Sources */, - 4B2C21A01DA292BE00735907 /* OFChangePermissionsFailedException.m in Sources */, 4B2C21A11DA292BE00735907 /* OFChecksumFailedException.m in Sources */, 4B2C21A21DA292BE00735907 /* OFConditionBroadcastFailedException.m in Sources */, 4B2C21A31DA292BE00735907 /* OFConditionSignalFailedException.m in Sources */, 4B2C21A41DA292BE00735907 /* OFConditionStillWaitingException.m in Sources */, 4B2C21A51DA292BE00735907 /* OFConditionWaitFailedException.m in Sources */, @@ -3567,14 +3555,15 @@ 4B2C21BF1DA292BE00735907 /* OFOutOfMemoryException.m in Sources */, 4B2C21C01DA292BE00735907 /* OFOutOfRangeException.m in Sources */, 4B2C21C11DA292BE00735907 /* OFReadFailedException.m in Sources */, 4B2C21C21DA292BE00735907 /* OFReadOrWriteFailedException.m in Sources */, 4B2C21C31DA292BE00735907 /* OFRemoveItemFailedException.m in Sources */, + 4BF277201FB8C113009F8FCF /* OFRetrieveItemAttributesFailedException.m in Sources */, 4B14EACA1E9A8292005E8BFD /* OFSandboxActivationFailedException.m in Sources */, 4B2C21C41DA292BE00735907 /* OFSeekFailedException.m in Sources */, + 4BF2771E1FB8C113009F8FCF /* OFSetItemAttributesFailedException.m in Sources */, 4B2C21C51DA292BE00735907 /* OFSetOptionFailedException.m in Sources */, - 4B2C21C61DA292BE00735907 /* OFStatItemFailedException.m in Sources */, 4B2C21C71DA292BE00735907 /* OFStillLockedException.m in Sources */, 4B2C21C81DA292BE00735907 /* OFThreadJoinFailedException.m in Sources */, 4B2C21C91DA292BE00735907 /* OFThreadStartFailedException.m in Sources */, 4B2C21CA1DA292BE00735907 /* OFThreadStillRunningException.m in Sources */, 4B2C21CB1DA292BE00735907 /* OFTruncatedDataException.m in Sources */, @@ -3744,12 +3733,10 @@ 4B90B7A1133AD87D00BD33CB /* OFAddressTranslationFailedException.m in Sources */, 4B17FF80133A2D17003E6DCD /* OFAllocFailedException.m in Sources */, 4B90B78E133AD46700BD33CB /* OFAlreadyConnectedException.m in Sources */, 4B90B7A3133AD87D00BD33CB /* OFBindFailedException.m in Sources */, 4B067FBC177BA6F900B8CFDA /* OFChangeCurrentDirectoryPathFailedException.m in Sources */, - 4B067FBE177BA6F900B8CFDA /* OFChangeOwnerFailedException.m in Sources */, - 4B067FC0177BA6F900B8CFDA /* OFChangePermissionsFailedException.m in Sources */, 4BE52D2617B990DA005958D1 /* OFChecksumFailedException.m in Sources */, 4B8B170D133A3C11007CD8B3 /* OFConditionBroadcastFailedException.m in Sources */, 4B8B170E133A3C11007CD8B3 /* OFConditionSignalFailedException.m in Sources */, 4B7FF3B5133CED6200000324 /* OFConditionStillWaitingException.m in Sources */, 4B8B170F133A3C11007CD8B3 /* OFConditionWaitFailedException.m in Sources */, @@ -3781,14 +3768,15 @@ 4B17FF84133A2DFB003E6DCD /* OFOutOfMemoryException.m in Sources */, 4B17FF7C133A2C15003E6DCD /* OFOutOfRangeException.m in Sources */, 4B55A113133AC24600B58A93 /* OFReadFailedException.m in Sources */, 4B55A115133AC24600B58A93 /* OFReadOrWriteFailedException.m in Sources */, 4BFF3715177E17C100192782 /* OFRemoveItemFailedException.m in Sources */, + 4BF2771F1FB8C113009F8FCF /* OFRetrieveItemAttributesFailedException.m in Sources */, 4B14EAC91E9A8292005E8BFD /* OFSandboxActivationFailedException.m in Sources */, 4B29BC42133AC4E80004B236 /* OFSeekFailedException.m in Sources */, + 4BF2771D1FB8C113009F8FCF /* OFSetItemAttributesFailedException.m in Sources */, 4B90B792133AD46700BD33CB /* OFSetOptionFailedException.m in Sources */, - 4B72F7DF1AD9311B00CE253C /* OFStatItemFailedException.m in Sources */, 4B6743F4163C384A00EB1E59 /* OFStillLockedException.m in Sources */, 4B55A100133ABEA900B58A93 /* OFThreadJoinFailedException.m in Sources */, 4B55A102133ABEA900B58A93 /* OFThreadStartFailedException.m in Sources */, 4B55A104133ABEA900B58A93 /* OFThreadStillRunningException.m in Sources */, 4B17FFAA133A34E7003E6DCD /* OFTruncatedDataException.m in Sources */, Index: src/OFData.m ================================================================== --- src/OFData.m +++ src/OFData.m @@ -191,17 +191,18 @@ #ifdef OF_HAVE_FILES - (instancetype)initWithContentsOfFile: (OFString *)path { @try { - of_offset_t size = [[OFFileManager defaultManager] - sizeOfFileAtPath: path]; + uintmax_t size = [[[OFFileManager defaultManager] + attributesOfItemAtPath: path] fileSize]; char *buffer; - if (sizeof(of_offset_t) > sizeof(size_t) && - size > (of_offset_t)SIZE_MAX) +# if UINTMAX_MAX > SIZE_MAX + if (size > SIZE_MAX) @throw [OFOutOfRangeException exception]; +# endif buffer = malloc((size_t)size); if (buffer == NULL) @throw [OFOutOfMemoryException exceptionWithRequestedSize: (size_t)size]; Index: src/OFFileManager.h ================================================================== --- src/OFFileManager.h +++ src/OFFileManager.h @@ -13,13 +13,16 @@ * LICENSE.GPLv2 or LICENSE.GPLv3 respectively included in the packaging of this * file. */ #import "OFObject.h" +#import "OFDictionary.h" #import "OFSeekableStream.h" OF_ASSUME_NONNULL_BEGIN + +/*! @file */ #if defined(OF_HAVE_CHMOD) && !defined(OF_MORPHOS) # define OF_FILE_MANAGER_SUPPORTS_PERMISSIONS #endif #if defined(OF_HAVE_CHOWN) && !defined(OF_MORPHOS) @@ -34,10 +37,194 @@ @class OFArray OF_GENERIC(ObjectType); @class OFDate; @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_type_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_type_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 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 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 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 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 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 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 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 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 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 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 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. @@ -60,10 +247,50 @@ /*! * @brief Returns the default file manager. */ + (OFFileManager *)defaultManager; +/*! + * @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; + +/*! + * @brief Returns the attributes for the item at the specified URL. + * + * @param URL The URL to return the attributes for + * @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; + +/*! + * @brief Sets the attributes for the item at the specified path. + * + * All attributes not part of the dictionary are left unchanged. + * + * @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; + +/*! + * @brief Sets the attributes for the item at the specified URL. + * + * All attributes not part of the dictionary are left unchanged. + * + * @param attributes The attributes to set for the specified URL + * @param URL The URL of the item to set the attributes for + */ +- (void)setAttributes: (of_file_attributes_t)attributes + ofItemAtURL: (OFURL *)URL; + /*! * @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 @@ -92,28 +319,10 @@ * @param URL The URL to check * @return A boolean whether there is a directory at the specified URL */ - (bool)directoryExistsAtURL: (OFURL *)URL; -#ifdef OF_FILE_MANAGER_SUPPORTS_SYMLINKS -/*! - * @brief Checks whether a symbolic link exists at the specified path. - * - * @param path The path to check - * @return A boolean whether there is a symbolic link at the specified path - */ -- (bool)symbolicLinkExistsAtPath: (OFString *)path; - -/*! - * @brief Checks whether a symbolic link exists at the specified URL. - * - * @param URL The URL to check - * @return A boolean whether there is a symbolic link at the specified URL - */ -- (bool)symbolicLinkExistsAtURL: (OFURL *)URL; -#endif - /*! * @brief Creates a directory at the specified path. * * @param path The path of the directory to create */ @@ -177,242 +386,36 @@ * @param URL The new directory to change to */ - (void)changeCurrentDirectoryURL: (OFURL *)URL; /*! - * @brief Returns the size of the specified file. - * - * @param path The path to the file whose size should be returned - * - * @return The size of the specified file - */ -- (of_offset_t)sizeOfFileAtPath: (OFString *)path; - -/*! - * @brief Returns the size of the specified file. - * - * @param URL The URL to the file whose size should be returned - * - * @return The size of the specified file - */ -- (of_offset_t)sizeOfFileAtURL: (OFURL *)URL; - -/*! - * @brief Returns the last access time of the specified item. - * - * @param path The path to the item whose last access time should be returned - * - * @return The last access time of the specified item - */ -- (OFDate *)accessTimeOfItemAtPath: (OFString *)path; - -/*! - * @brief Returns the last access time of the specified item. - * - * @param URL The URL to the item whose last access time should be returned - * - * @return The last access time of the specified item - */ -- (OFDate *)accessTimeOfItemAtURL: (OFURL *)URL; - -/*! - * @brief Returns the last modification date of the specified item. - * - * @param path The path to the item whose last modification date should be - * returned - * - * @return The last modification date of the specified item - */ -- (OFDate *)modificationDateOfItemAtPath: (OFString *)path; - -/*! - * @brief Returns the last modification date of the specified item. - * - * @param URL The URL to the item whose last modification date should be - * returned - * - * @return The last modification date of the specified item - */ -- (OFDate *)modificationDateOfItemAtURL: (OFURL *)URL; - -/*! - * @brief Returns the last status change time of the specified item. - * - * @param path The path to the item whose last status change time should be - * returned - * - * @return The last status change time of the specified item - */ -- (OFDate *)statusChangeTimeOfItemAtPath: (OFString *)path; - -/*! - * @brief Returns the last status change time of the specified item. - * - * @param URL The URL to the item whose last status change time should be - * returned - * - * @return The last status change time of the specified item - */ -- (OFDate *)statusChangeTimeOfItemAtURL: (OFURL *)URL; - -#ifdef OF_FILE_MANAGER_SUPPORTS_PERMISSIONS -/*! - * @brief Returns the permissions of the specified item. - * - * This returns only the permissions, meaning read, write and execute for - * owner, user and group, along with the sticky, setuid and setgid bit. In - * other words, only bits that match the mask 07777. - * - * @param path The path to the item whose permissions should be returned - * - * @return The permissions of the specified item - */ -- (uint16_t)permissionsOfItemAtPath: (OFString *)path; - -/*! - * @brief Returns the permissions of the specified item. - * - * This returns only the permissions, meaning read, write and execute for - * owner, user and group, along with the sticky, setuid and setgid bit. In - * other words, only bits that match the mask 07777. - * - * @param URL The URL to the item whose permissions should be returned - * - * @return The permissions of the specified item - */ -- (uint16_t)permissionsOfItemAtURL: (OFURL *)URL; - -/*! - * @brief Changes the permissions of an item. - * - * This only changes the permissions, meaning read, write and execute for - * owner, user and group. For security reasons, it ignores all other bits. In - * other words, the permissions are masked with 0777. - * - * This method only changes the read-only flag on Windows. - * - * @param path The path to the item whose permissions should be changed - * @param permissions The new permissions for the item - */ -- (void)changePermissionsOfItemAtPath: (OFString *)path - permissions: (uint16_t)permissions; - -/*! - * @brief Changes the permissions of an item. - * - * This only changes the permissions, meaning read, write and execute for - * owner, user and group. For security reasons, it ignores all other bits. In - * other words, the permissions are masked with 0777. - * - * This method only changes the read-only flag on Windows. - * - * @param URL The URL to the item whose permissions should be changed - * @param permissions The new permissions for the item - */ -- (void)changePermissionsOfItemAtURL: (OFURL *)URL - permissions: (uint16_t)permissions; -#endif - -#ifdef OF_FILE_MANAGER_SUPPORTS_OWNER -/*! - * @brief Get the UID and GID of the specified item. - * - * @param UID A pointer to an uint16_t to store the UID, or NULL - * @param GID A pointer to an uint16_t to store the GID, or NULL - * @param path The path to the item whose UID and GID should be retrieved - */ -- (void)getUID: (nullable uint16_t *)UID - GID: (nullable uint16_t *)GID - ofItemAtPath: (OFString *)path; - -/*! - * @brief Get the UID and GID of the specified item. - * - * @param UID A pointer to an uint16_t to store the UID, or NULL - * @param GID A pointer to an uint16_t to store the GID, or NULL - * @param URL The URL to the item whose UID and GID should be retrieved - */ -- (void)getUID: (nullable uint16_t *)UID - GID: (nullable uint16_t *)GID - ofItemAtURL: (OFURL *)URL; - -/*! - * @brief Get the owner and group of the specified item. - * - * @param owner A pointer to an `OFString *` to store the owner, or NULL - * @param group A pointer to an `OFString *` to store the group, or NULL - * @param path The path to the item whose owner and group should be retrieved - */ -- (void)getOwner: (OFString *__autoreleasing _Nonnull *_Nullable)owner - group: (OFString *__autoreleasing _Nonnull *_Nullable)group - ofItemAtPath: (OFString *)path; - -/*! - * @brief Get the owner and group of the specified item. - * - * @param owner A pointer to an `OFString *` to store the owner, or NULL - * @param group A pointer to an `OFString *` to store the group, or NULL - * @param URL The URL to the item whose owner and group should be retrieved - */ -- (void)getOwner: (OFString *__autoreleasing _Nonnull *_Nullable)owner - group: (OFString *__autoreleasing _Nonnull *_Nullable)group - ofItemAtURL: (OFURL *)URL; - -/*! - * @brief Changes the owner of an item. - * - * 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 - */ -- (void)changeOwnerOfItemAtPath: (OFString *)path - owner: (OFString *)owner - group: (OFString *)group; - -/*! - * @brief Changes the owner of an item. - * - * This method is not available on some systems, most notably Windows. - * - * @param URL The URL to the item whose owner should be changed - * @param owner The new owner for the item - * @param group The new group for the item - */ -- (void)changeOwnerOfItemAtURL: (OFURL *)URL - owner: (OFString *)owner - group: (OFString *)group; -#endif - -/*! - * @brief Copies a file, directory or symlink (if supported by the OS). + * @brief Copies a file, directory or symbolic link (if supported by the OS). * * The destination path must be a full path, which means it must include the * name of the item. * * 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 source The file, directory or symbolic link to copy * @param destination The destination path */ - (void)copyItemAtPath: (OFString *)source toPath: (OFString *)destination; /*! - * @brief Copies a file, directory or symlink (if supported by the OS). + * @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 * name of the item. * * 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 source The file, directory or symbolic link to copy * @param destination The destination URL */ - (void)copyItemAtURL: (OFURL *)source toURL: (OFURL *)destination; @@ -532,31 +535,89 @@ * @param source The URL to the item for which a symbolic link should be * created */ - (void)createSymbolicLinkAtURL: (OFURL *)destination withDestinationURL: (OFURL *)source; - -/*! - * @brief Returns the destination of the symbolic link at the specified path. - * - * @param path The path to the symbolic link - * - * @note On Windows, at least Windows Vista is required. - * - * @return The destination of the symbolic link at the specified path - */ -- (OFString *)destinationOfSymbolicLinkAtPath: (OFString *)path; - -/*! - * @brief Returns the destination of the symbolic link at the specified URL. - * - * @param URL The URL to the symbolic link - * - * @note On Windows, at least Windows Vista is required. - * - * @return The destination of the symbolic link at the specified URL - */ -- (OFString *)destinationOfSymbolicLinkAtURL: (OFURL *)URL; -#endif +#endif +@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 @@ -32,26 +32,26 @@ #endif #ifdef HAVE_GRP_H # include #endif -#import "OFFileManager.h" #import "OFArray.h" #import "OFDate.h" +#import "OFDictionary.h" #import "OFFile.h" +#import "OFFileManager.h" #import "OFLocalization.h" +#import "OFNumber.h" #import "OFString.h" #import "OFSystemInfo.h" #import "OFURL.h" #ifdef OF_HAVE_THREADS # import "OFMutex.h" #endif #import "OFChangeCurrentDirectoryPathFailedException.h" -#import "OFChangeOwnerFailedException.h" -#import "OFChangePermissionsFailedException.h" #import "OFCopyItemFailedException.h" #import "OFCreateDirectoryFailedException.h" #import "OFCreateSymbolicLinkFailedException.h" #import "OFInitializationFailedException.h" #import "OFInvalidArgumentException.h" @@ -62,11 +62,13 @@ #import "OFOpenItemFailedException.h" #import "OFOutOfMemoryException.h" #import "OFOutOfRangeException.h" #import "OFReadFailedException.h" #import "OFRemoveItemFailedException.h" -#import "OFStatItemFailedException.h" +#import "OFRetrieveItemAttributesFailedException.h" +#import "OFSetItemAttributesFailedException.h" +#import "OFUndefinedKeyException.h" #import "OFUnlockFailedException.h" #ifdef OF_WINDOWS # include # include @@ -101,10 +103,42 @@ @interface OFFileManager_default: OFFileManager @end static OFFileManager *defaultManager; +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"; + #if defined(OF_HAVE_CHOWN) && defined(OF_HAVE_THREADS) && !defined(OF_MORPHOS) static OFMutex *passwdMutex; #endif #if !defined(HAVE_READDIR_R) && defined(OF_HAVE_THREADS) && !defined(OF_WINDOWS) static OFMutex *readdirMutex; @@ -207,10 +241,208 @@ # endif #else return of_stat(path, buffer); #endif } + +static void +setTypeAttribute(of_mutable_file_attributes_t attributes, of_stat_t *s) +{ + if (S_ISREG(s->st_mode)) + [attributes setObject: of_file_type_regular + forKey: of_file_attribute_key_type]; + else if (S_ISDIR(s->st_mode)) + [attributes setObject: of_file_type_directory + forKey: of_file_attribute_key_type]; +#ifdef S_ISLNK + else if (S_ISLNK(s->st_mode)) + [attributes setObject: of_file_type_symbolic_link + forKey: of_file_attribute_key_type]; +#endif +#ifdef S_ISFIFO + else if (S_ISFIFO(s->st_mode)) + [attributes setObject: of_file_type_fifo + forKey: of_file_attribute_key_type]; +#endif +#ifdef S_ISCHR + else if (S_ISCHR(s->st_mode)) + [attributes setObject: of_file_type_character_special + forKey: of_file_attribute_key_type]; +#endif +#ifdef S_ISBLK + else if (S_ISBLK(s->st_mode)) + [attributes setObject: of_file_type_block_special + forKey: of_file_attribute_key_type]; +#endif +#ifdef S_ISSOCK + else if (S_ISSOCK(s->st_mode)) + [attributes setObject: of_file_type_socket + forKey: of_file_attribute_key_type]; +#endif +} + +static void +setDateAttributes(of_mutable_file_attributes_t attributes, of_stat_t *s) +{ + /* FIXME: We could be more precise on some OSes */ + [attributes + setObject: [OFDate dateWithTimeIntervalSince1970: s->st_atime] + forKey: of_file_attribute_key_last_access_date]; + [attributes + setObject: [OFDate dateWithTimeIntervalSince1970: s->st_mtime] + forKey: of_file_attribute_key_modification_date]; + [attributes + setObject: [OFDate dateWithTimeIntervalSince1970: s->st_ctime] + forKey: of_file_attribute_key_status_change_date]; +} + +static void +setOwnerAndGroupAttributes(of_mutable_file_attributes_t attributes, + of_stat_t *s) +{ +#ifdef OF_FILE_MANAGER_SUPPORTS_OWNER + [attributes setObject: [NSNumber numberWithUInt16: s->st_uid] + forKey: of_file_attribute_key_posix_uid]; + [attributes setObject: [NSNumber numberWithUInt16: s->st_gid] + forKey: of_file_attribute_key_posix_gid]; + +# ifdef OF_HAVE_THREADS + [passwdMutex lock]; + @try { +# endif + of_string_encoding_t encoding = [OFLocalization encoding]; + struct passwd *passwd = getpwuid(s->st_uid); + struct group *group_ = getgrgid(s->st_gid); + + if (passwd != NULL) { + OFString *owner = [OFString + stringWithCString: passwd->pw_name + encoding: encoding]; + + [attributes setObject: owner + forKey: of_file_attribute_key_owner]; + } + + if (group_ != NULL) { + OFString *group = [OFString + stringWithCString: group_->gr_name + encoding: encoding]; + + [attributes setObject: group + forKey: of_file_attribute_key_group]; + } +# ifdef OF_HAVE_THREADS + } @finally { + [passwdMutex unlock]; + } +# endif +#endif +} + +static void +setSymbolicLinkDestinationAttribute(of_mutable_file_attributes_t attributes, + of_stat_t *s, OFString *path) +{ +#ifdef OF_FILE_MANAGER_SUPPORTS_SYMLINKS +# ifndef OF_WINDOWS + if (S_ISLNK(s->st_mode)) { + of_string_encoding_t encoding = [OFLocalization encoding]; + char destinationC[PATH_MAX]; + ssize_t length; + OFString *destination; + of_file_attribute_key_t key; + + length = readlink([path cStringWithEncoding: encoding], + destinationC, PATH_MAX); + + if (length < 0) + @throw [OFRetrieveItemAttributesFailedException + exceptionWithPath: path + errNo: errno]; + + destination = [OFString stringWithCString: destinationC + encoding: encoding + length: length]; + + key = of_file_attribute_key_symbolic_link_destination; + [attributes setObject: destination + forKey: key]; + } +# else + WIN32_FIND_DATAW data; + + if (func_CreateSymbolicLinkW != NULL && + FindFirstFileW([path UTF16String], &data) && + (data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) && + data.dwReserved0 == IO_REPARSE_TAG_SYMLINK) { + HANDLE handle; + OFString *destination; + + if ((handle = CreateFileW([path UTF16String], 0, + (FILE_SHARE_READ | FILE_SHARE_WRITE), NULL, OPEN_EXISTING, + FILE_FLAG_OPEN_REPARSE_POINT, NULL)) == + INVALID_HANDLE_VALUE) + @throw [OFRetrieveItemAttributesFailedException + exceptionWithPath: path + errNo: 0]; + + @try { + union { + char bytes[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; + REPARSE_DATA_BUFFER data; + } buffer; + DWORD size; + wchar_t *tmp; + of_file_attribute_key_t key; + + if (!DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, + NULL, 0, buffer.bytes, + MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &size, NULL)) + @throw [OFRetrieveItemAttributesFailedException + exceptionWithPath: path + errNo: 0]; + + if (buffer.data.ReparseTag != IO_REPARSE_TAG_SYMLINK) + @throw [OFRetrieveItemAttributesFailedException + exceptionWithPath: path + errNo: 0]; + +# define slrb buffer.data.SymbolicLinkReparseBuffer + tmp = slrb.PathBuffer + + (slrb.SubstituteNameOffset / sizeof(wchar_t)); + + destination = [OFString + stringWithUTF16String: tmp + length: slrb.SubstituteNameLength / + sizeof(wchar_t)]; + + [attributes setObject: of_file_type_symbolic_link + forKey: of_file_attribute_key_type]; + key = of_file_attribute_key_symbolic_link_destination; + [attributes setObject: destination + forKey: key]; +# undef slrb + } @finally { + CloseHandle(handle); + } + } +# 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 { #ifdef OF_WINDOWS @@ -315,10 +547,198 @@ objc_autoreleasePoolPop(pool); return URL; } + +- (of_file_attributes_t)attributesOfItemAtPath: (OFString *)path +{ + of_mutable_file_attributes_t ret = [OFMutableDictionary dictionary]; + void *pool = objc_autoreleasePoolPush(); + of_stat_t s; + + if (path == nil) + @throw [OFInvalidArgumentException exception]; + + if (of_lstat(path, &s) == -1) + @throw [OFRetrieveItemAttributesFailedException + exceptionWithPath: path + errNo: errno]; + + if (s.st_size < 0) + @throw [OFOutOfRangeException exception]; + + [ret setObject: [NSNumber numberWithUIntMax: s.st_size] + forKey: of_file_attribute_key_size]; + + setTypeAttribute(ret, &s); + + [ret setObject: [NSNumber numberWithUInt16: s.st_mode & 07777] + forKey: of_file_attribute_key_posix_permissions]; + + setOwnerAndGroupAttributes(ret, &s); + setDateAttributes(ret, &s); + setSymbolicLinkDestinationAttribute(ret, &s, path); + + objc_autoreleasePoolPop(pool); + + return ret; +} + +- (of_file_attributes_t)attributesOfItemAtURL: (OFURL *)URL +{ + void *pool = objc_autoreleasePoolPush(); + of_file_attributes_t ret = [self attributesOfItemAtPath: + [URL fileSystemRepresentation]]; + + [ret retain]; + + objc_autoreleasePoolPop(pool); + + return [ret autorelease]; +} + +- (void)of_setPOSIXPermissions: (OFNumber *)permissions + ofItemAtPath: (OFString *)path + attributes: (of_file_attributes_t)attributes +{ +#ifdef OF_FILE_MANAGER_SUPPORTS_PERMISSIONS + uint16_t mode = [permissions uInt16Value] & 0777; + +# ifndef OF_WINDOWS + if (chmod([path cStringWithEncoding: [OFLocalization encoding]], + mode) != 0) +# else + if (_wchmod([path UTF16String], mode) != 0) +# endif + @throw [OFSetItemAttributesFailedException + exceptionWithPath: path + attributes: attributes + failedAttribute: of_file_attribute_key_posix_permissions + errNo: errno]; +#else + @throw [OFNotImplementedException exceptionWithSelector: _cmd + object: self]; +#endif +} + +- (void)of_setOwner: (OFString *)owner + andGroup: (OFString *)group + ofItemAtPath: (OFString *)path + attributeKey: (of_file_attribute_key_t)attributeKey + attributes: (of_file_attributes_t)attributes +{ +#ifdef OF_FILE_MANAGER_SUPPORTS_OWNER + uid_t uid = -1; + gid_t gid = -1; + of_string_encoding_t encoding; + + if (owner == nil && group == nil) + @throw [OFInvalidArgumentException exception]; + + encoding = [OFLocalization encoding]; + +# ifdef OF_HAVE_THREADS + [passwdMutex lock]; + @try { +# endif + if (owner != nil) { + struct passwd *passwd; + + if ((passwd = getpwnam([owner + cStringWithEncoding: encoding])) == NULL) + @throw [OFSetItemAttributesFailedException + exceptionWithPath: path + attributes: attributes + failedAttribute: attributeKey + errNo: errno]; + + uid = passwd->pw_uid; + } + + if (group != nil) { + struct group *group_; + + if ((group_ = getgrnam([group + cStringWithEncoding: encoding])) == NULL) + @throw [OFSetItemAttributesFailedException + exceptionWithPath: path + attributes: attributes + failedAttribute: attributeKey + errNo: errno]; + + gid = group_->gr_gid; + } +# ifdef OF_HAVE_THREADS + } @finally { + [passwdMutex unlock]; + } +# endif + + if (chown([path cStringWithEncoding: encoding], uid, gid) != 0) + @throw [OFSetItemAttributesFailedException + exceptionWithPath: path + attributes: attributes + failedAttribute: attributeKey + errNo: errno]; +#else + @throw [OFNotImplementedException exceptionWithSelector: _cmd + object: self]; +#endif +} + +- (void)setAttributes: (of_file_attributes_t)attributes + ofItemAtPath: (OFString *)path +{ + void *pool; + OFEnumerator OF_GENERIC(of_file_attribute_key_t) *keyEnumerator; + OFEnumerator *objectEnumerator; + of_file_attribute_key_t key; + id object; + + if (path == nil) + @throw [OFInvalidArgumentException exception]; + + pool = objc_autoreleasePoolPush(); + keyEnumerator = [attributes keyEnumerator]; + objectEnumerator = [attributes objectEnumerator]; + + while ((key = [keyEnumerator nextObject]) != nil && + (object = [objectEnumerator nextObject]) != nil) { + if ([key isEqual: of_file_attribute_key_posix_permissions]) + [self of_setPOSIXPermissions: object + ofItemAtPath: path + attributes: attributes]; + else if ([key isEqual: of_file_attribute_key_owner]) + [self of_setOwner: object + andGroup: nil + ofItemAtPath: path + attributeKey: key + attributes: attributes]; + else if ([key isEqual: of_file_attribute_key_group]) + [self of_setOwner: nil + andGroup: object + ofItemAtPath: path + attributeKey: key + attributes: attributes]; + else + @throw [OFInvalidArgumentException exception]; + } + + objc_autoreleasePoolPop(pool); +} + +- (void)setAttributes: (of_file_attributes_t)attributes + ofItemAtURL: (OFURL *)URL +{ + void *pool = objc_autoreleasePoolPush(); + + [self setAttributes: attributes + ofItemAtPath: [URL fileSystemRepresentation]]; + + objc_autoreleasePoolPop(pool); +} - (bool)fileExistsAtPath: (OFString *)path { of_stat_t s; @@ -362,49 +782,10 @@ objc_autoreleasePoolPop(pool); return ret; } -#ifdef OF_FILE_MANAGER_SUPPORTS_SYMLINKS -- (bool)symbolicLinkExistsAtPath: (OFString *)path -{ -# ifndef OF_WINDOWS - of_stat_t s; - - if (path == nil) - @throw [OFInvalidArgumentException exception]; - - if (of_lstat(path, &s) == -1) - return false; - - return S_ISLNK(s.st_mode); -# else - WIN32_FIND_DATAW data; - - if (!FindFirstFileW([path UTF16String], &data)) - return false; - - if ((data.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) && - data.dwReserved0 == IO_REPARSE_TAG_SYMLINK) - return true; - - return false; -# endif -} - -- (bool)symbolicLinkExistsAtURL: (OFURL *)URL -{ - void *pool = objc_autoreleasePoolPush(); - bool ret = [self symbolicLinkExistsAtPath: - [URL fileSystemRepresentation]]; - - objc_autoreleasePoolPop(pool); - - return ret; -} -#endif - - (void)createDirectoryAtPath: (OFString *)path { if (path == nil) @throw [OFInvalidArgumentException exception]; @@ -764,368 +1145,55 @@ [self changeCurrentDirectoryPath: [URL fileSystemRepresentation]]; objc_autoreleasePoolPop(pool); } -- (of_offset_t)sizeOfFileAtPath: (OFString *)path -{ - of_stat_t s; - - if (path == nil) - @throw [OFInvalidArgumentException exception]; - - if (of_stat(path, &s) != 0) - @throw [OFStatItemFailedException exceptionWithPath: path - errNo: errno]; - - return s.st_size; -} - -- (of_offset_t)sizeOfFileAtURL: (OFURL *)URL -{ - void *pool = objc_autoreleasePoolPush(); - of_offset_t ret = [self sizeOfFileAtPath: - [URL fileSystemRepresentation]]; - - objc_autoreleasePoolPop(pool); - - return ret; -} - -- (OFDate *)accessTimeOfItemAtPath: (OFString *)path -{ - of_stat_t s; - - if (path == nil) - @throw [OFInvalidArgumentException exception]; - - if (of_stat(path, &s) != 0) - @throw [OFStatItemFailedException exceptionWithPath: path - errNo: errno]; - - /* FIXME: We could be more precise on some OSes */ - return [OFDate dateWithTimeIntervalSince1970: s.st_atime]; -} - -- (OFDate *)accessTimeOfItemAtURL: (OFURL *)URL -{ - void *pool = objc_autoreleasePoolPush(); - OFDate *ret = [self accessTimeOfItemAtPath: - [URL fileSystemRepresentation]]; - - [ret retain]; - - objc_autoreleasePoolPop(pool); - - return [ret autorelease]; -} - -- (OFDate *)modificationDateOfItemAtPath: (OFString *)path -{ - of_stat_t s; - - if (path == nil) - @throw [OFInvalidArgumentException exception]; - - if (of_stat(path, &s) != 0) - @throw [OFStatItemFailedException exceptionWithPath: path - errNo: errno]; - - /* FIXME: We could be more precise on some OSes */ - return [OFDate dateWithTimeIntervalSince1970: s.st_mtime]; -} - -- (OFDate *)modificationDateOfItemAtURL: (OFURL *)URL -{ - void *pool = objc_autoreleasePoolPush(); - OFDate *ret = [self modificationDateOfItemAtPath: - [URL fileSystemRepresentation]]; - - [ret retain]; - - objc_autoreleasePoolPop(pool); - - return [ret autorelease]; -} - -- (OFDate *)statusChangeTimeOfItemAtPath: (OFString *)path -{ - of_stat_t s; - - if (path == nil) - @throw [OFInvalidArgumentException exception]; - - if (of_stat(path, &s) != 0) - @throw [OFStatItemFailedException exceptionWithPath: path - errNo: errno]; - - /* FIXME: We could be more precise on some OSes */ - return [OFDate dateWithTimeIntervalSince1970: s.st_ctime]; -} - -- (OFDate *)statusChangeTimeOfItemAtURL: (OFURL *)URL -{ - void *pool = objc_autoreleasePoolPush(); - OFDate *ret = [self statusChangeTimeOfItemAtPath: - [URL fileSystemRepresentation]]; - - [ret retain]; - - objc_autoreleasePoolPop(pool); - - return [ret autorelease]; -} - -#ifdef OF_FILE_MANAGER_SUPPORTS_PERMISSIONS -- (uint16_t)permissionsOfItemAtPath: (OFString *)path -{ - of_stat_t s; - - if (path == nil) - @throw [OFInvalidArgumentException exception]; - - if (of_stat(path, &s) != 0) - @throw [OFStatItemFailedException exceptionWithPath: path - errNo: errno]; - - return s.st_mode & 07777; -} - -- (uint16_t)permissionsOfItemAtURL: (OFURL *)URL -{ - void *pool = objc_autoreleasePoolPush(); - uint16_t ret = [self permissionsOfItemAtPath: - [URL fileSystemRepresentation]]; - - objc_autoreleasePoolPop(pool); - - return ret; -} - -- (void)changePermissionsOfItemAtPath: (OFString *)path - permissions: (uint16_t)permissions -{ - if (path == nil) - @throw [OFInvalidArgumentException exception]; - - permissions &= 0777; - -# ifndef OF_WINDOWS - if (chmod([path cStringWithEncoding: [OFLocalization encoding]], - permissions) != 0) -# else - if (_wchmod([path UTF16String], permissions) != 0) -# endif - @throw [OFChangePermissionsFailedException - exceptionWithPath: path - permissions: permissions - errNo: errno]; -} - -- (void)changePermissionsOfItemAtURL: (OFURL *)URL - permissions: (uint16_t)permissions -{ - void *pool = objc_autoreleasePoolPush(); - - [self changePermissionsOfItemAtPath: [URL fileSystemRepresentation] - permissions: permissions]; - - objc_autoreleasePoolPop(pool); -} -#endif - -#ifdef OF_FILE_MANAGER_SUPPORTS_OWNER -- (void)getUID: (uint16_t *)UID - GID: (uint16_t *)GID - ofItemAtPath: (OFString *)path -{ - of_stat_t s; - - if (path == nil) - @throw [OFInvalidArgumentException exception]; - - if (of_stat(path, &s) != 0) - @throw [OFStatItemFailedException exceptionWithPath: path - errNo: errno]; - - if (UID != NULL) - *UID = s.st_uid; - if (GID != NULL) - *GID = s.st_gid; -} - -- (void)getUID: (uint16_t *)UID - GID: (uint16_t *)GID - ofItemAtURL: (OFURL *)URL -{ - void *pool = objc_autoreleasePoolPush(); - - [self getUID: UID - GID: GID - ofItemAtPath: [URL fileSystemRepresentation]]; - - objc_autoreleasePoolPop(pool); -} - -- (void)getOwner: (OFString **)owner - group: (OFString **)group - ofItemAtPath: (OFString *)path -{ - uint16_t UID, GID; - - [self getUID: &UID - GID: &GID - ofItemAtPath: path]; - -# ifdef OF_HAVE_THREADS - [passwdMutex lock]; - @try { -# endif - of_string_encoding_t encoding = [OFLocalization encoding]; - - if (owner != NULL) { - struct passwd *passwd = getpwuid(UID); - - *owner = [OFString stringWithCString: passwd->pw_name - encoding: encoding]; - } - - if (group != NULL) { - struct group *group_ = getgrgid(GID); - - *group = [OFString stringWithCString: group_->gr_name - encoding: encoding]; - } -# ifdef OF_HAVE_THREADS - } @finally { - [passwdMutex unlock]; - } -# endif -} - -- (void)getOwner: (OFString **)owner - group: (OFString **)group - ofItemAtURL: (OFURL *)URL -{ - void *pool = objc_autoreleasePoolPush(); - OFString *path = [URL fileSystemRepresentation]; - - [path retain]; - - objc_autoreleasePoolPop(pool); - - @try { - [self getOwner: owner - group: group - ofItemAtPath: path]; - } @finally { - [path release]; - } -} - -- (void)changeOwnerOfItemAtPath: (OFString *)path - owner: (OFString *)owner - group: (OFString *)group -{ - uid_t uid = -1; - gid_t gid = -1; - of_string_encoding_t encoding; - - if (path == nil || (owner == nil && group == nil)) - @throw [OFInvalidArgumentException exception]; - - encoding = [OFLocalization encoding]; - -# ifdef OF_HAVE_THREADS - [passwdMutex lock]; - @try { -# endif - if (owner != nil) { - struct passwd *passwd; - - if ((passwd = getpwnam([owner - cStringWithEncoding: encoding])) == NULL) - @throw [OFChangeOwnerFailedException - exceptionWithPath: path - owner: owner - group: group - errNo: errno]; - - uid = passwd->pw_uid; - } - - if (group != nil) { - struct group *group_; - - if ((group_ = getgrnam([group - cStringWithEncoding: encoding])) == NULL) - @throw [OFChangeOwnerFailedException - exceptionWithPath: path - owner: owner - group: group - errNo: errno]; - - gid = group_->gr_gid; - } -# ifdef OF_HAVE_THREADS - } @finally { - [passwdMutex unlock]; - } -# endif - - if (chown([path cStringWithEncoding: encoding], uid, gid) != 0) - @throw [OFChangeOwnerFailedException exceptionWithPath: path - owner: owner - group: group - errNo: errno]; -} - -- (void)changeOwnerOfItemAtURL: (OFURL *)URL - owner: (OFString *)owner - group: (OFString *)group -{ - void *pool = objc_autoreleasePoolPush(); - - [self changeOwnerOfItemAtPath: [URL fileSystemRepresentation] - owner: owner - group: group]; - - objc_autoreleasePoolPop(pool); -} -#endif - - (void)copyItemAtPath: (OFString *)source toPath: (OFString *)destination { void *pool; - of_stat_t s; + of_file_attributes_t attributes; + of_file_type_t type; if (source == nil || destination == nil) @throw [OFInvalidArgumentException exception]; pool = objc_autoreleasePoolPush(); - if (of_lstat(destination, &s) == 0) + if ([self fileExistsAtPath: destination]) @throw [OFCopyItemFailedException exceptionWithSourcePath: source destinationPath: destination errNo: EEXIST]; - if (of_lstat(source, &s) != 0) + @try { + attributes = [self attributesOfItemAtPath: source]; + } @catch (OFRetrieveItemAttributesFailedException *e) { @throw [OFCopyItemFailedException exceptionWithSourcePath: source destinationPath: destination - errNo: errno]; + errNo: [e errNo]]; + } - if (S_ISDIR(s.st_mode)) { + type = [attributes fileType]; + + if ([type isEqual: of_file_type_directory]) { OFArray *contents; @try { [self createDirectoryAtPath: destination]; + #ifdef OF_FILE_MANAGER_SUPPORTS_PERMISSIONS - [self changePermissionsOfItemAtPath: destination - permissions: s.st_mode]; + 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 + ofItemAtPath: destination]; #endif contents = [self contentsOfDirectoryAtPath: source]; } @catch (id e) { /* @@ -1155,11 +1223,11 @@ [self copyItemAtPath: sourcePath toPath: destinationPath]; objc_autoreleasePoolPop(pool2); } - } else if (S_ISREG(s.st_mode)) { + } else if ([type isEqual: of_file_type_regular]) { size_t pageSize = [OFSystemInfo pageSize]; OFFile *sourceFile = nil; OFFile *destinationFile = nil; char *buffer; @@ -1181,12 +1249,19 @@ [destinationFile writeBuffer: buffer length: length]; } #ifdef OF_FILE_MANAGER_SUPPORTS_PERMISSIONS - [self changePermissionsOfItemAtPath: destination - permissions: s.st_mode]; + 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 + ofItemAtPath: destination]; #endif } @catch (id e) { /* * Only convert exceptions to OFCopyItemFailedException * that have an errNo property. This covers all I/O @@ -1204,13 +1279,13 @@ [sourceFile close]; [destinationFile close]; free(buffer); } #ifdef OF_FILE_MANAGER_SUPPORTS_SYMLINKS - } else if (S_ISLNK(s.st_mode)) { + } else if ([type isEqual: of_file_type_symbolic_link]) { @try { - source = [self destinationOfSymbolicLinkAtPath: source]; + source = [attributes fileSymbolicLinkDestination]; [self createSymbolicLinkAtPath: destination withDestinationPath: source]; } @catch (id e) { /* @@ -1552,94 +1627,76 @@ [self createSymbolicLinkAtPath: [destination fileSystemRepresentation] withDestinationPath: [source fileSystemRepresentation]]; objc_autoreleasePoolPop(pool); } - -- (OFString *)destinationOfSymbolicLinkAtPath: (OFString *)path -{ - if (path == nil) - @throw [OFInvalidArgumentException exception]; - -# ifndef OF_WINDOWS - char destination[PATH_MAX]; - ssize_t length; - of_string_encoding_t encoding; - - encoding = [OFLocalization encoding]; - length = readlink([path cStringWithEncoding: encoding], - destination, PATH_MAX); - - if (length < 0) - @throw [OFStatItemFailedException exceptionWithPath: path - errNo: errno]; - - return [OFString stringWithCString: destination - encoding: encoding - length: length]; -# else - HANDLE handle; - - /* Check if we're on a version that actually supports symlinks. */ - if (func_CreateSymbolicLinkW == NULL) - @throw [OFNotImplementedException exceptionWithSelector: _cmd - object: self]; - - if ((handle = CreateFileW([path UTF16String], 0, - (FILE_SHARE_READ | FILE_SHARE_WRITE), NULL, OPEN_EXISTING, - FILE_FLAG_OPEN_REPARSE_POINT, NULL)) == INVALID_HANDLE_VALUE) - @throw [OFStatItemFailedException exceptionWithPath: path - errNo: 0]; - - @try { - union { - char bytes[MAXIMUM_REPARSE_DATA_BUFFER_SIZE]; - REPARSE_DATA_BUFFER data; - } buffer; - DWORD size; - wchar_t *tmp; - - if (!DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, NULL, 0, - buffer.bytes, MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &size, - NULL)) - @throw [OFStatItemFailedException - exceptionWithPath: path - errNo: 0]; - - if (buffer.data.ReparseTag != IO_REPARSE_TAG_SYMLINK) - @throw [OFStatItemFailedException - exceptionWithPath: path - errNo: 0]; - -# define slrb buffer.data.SymbolicLinkReparseBuffer - tmp = slrb.PathBuffer + - (slrb.SubstituteNameOffset / sizeof(wchar_t)); - - return [OFString - stringWithUTF16String: tmp - length: slrb.SubstituteNameLength / - sizeof(wchar_t)]; -# undef slrb - } @finally { - CloseHandle(handle); - } -# endif -} - -- (OFString *)destinationOfSymbolicLinkAtURL: (OFURL *)URL -{ - void *pool = objc_autoreleasePoolPush(); - OFString *ret = [self destinationOfSymbolicLinkAtPath: - [URL fileSystemRepresentation]]; - - [ret retain]; - - objc_autoreleasePoolPop(pool); - - return [ret autorelease]; -} -#endif +#endif +@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 @implementation OFFileManager_default - (instancetype)autorelease { Index: src/OFString.m ================================================================== --- src/OFString.m +++ src/OFString.m @@ -49,11 +49,11 @@ #import "OFInvalidFormatException.h" #import "OFNotImplementedException.h" #import "OFOpenItemFailedException.h" #import "OFOutOfMemoryException.h" #import "OFOutOfRangeException.h" -#import "OFStatItemFailedException.h" +#import "OFRetrieveItemAttributesFailedException.h" #import "OFTruncatedDataException.h" #import "OFUnsupportedProtocolException.h" #import "of_asprintf.h" #import "unicode.h" @@ -1013,28 +1013,32 @@ - (instancetype)initWithContentsOfFile: (OFString *)path encoding: (of_string_encoding_t)encoding { char *tmp; - of_offset_t fileSize; + uintmax_t fileSize; @try { + void *pool = objc_autoreleasePoolPush(); OFFile *file; @try { - fileSize = [[OFFileManager defaultManager] - sizeOfFileAtPath: path]; - } @catch (OFStatItemFailedException *e) { + fileSize = [[[OFFileManager defaultManager] + attributesOfItemAtPath: path] fileSize]; + } @catch (OFRetrieveItemAttributesFailedException *e) { @throw [OFOpenItemFailedException exceptionWithPath: path mode: @"r" errNo: errno]; } - if (sizeof(of_offset_t) > sizeof(size_t) && - fileSize > (of_offset_t)SIZE_MAX) + objc_autoreleasePoolPop(pool); + +# if UINTMAX_MAX > SIZE_MAX + if (fileSize > SIZE_MAX) @throw [OFOutOfRangeException exception]; +#endif file = [[OFFile alloc] initWithPath: path mode: @"r"]; @try { Index: src/ObjFW.h ================================================================== --- src/ObjFW.h +++ src/ObjFW.h @@ -121,12 +121,10 @@ # import "OFAddressTranslationFailedException.h" # import "OFAlreadyConnectedException.h" # import "OFBindFailedException.h" #endif #import "OFChangeCurrentDirectoryPathFailedException.h" -#import "OFChangeOwnerFailedException.h" -#import "OFChangePermissionsFailedException.h" #import "OFChecksumFailedException.h" #ifdef OF_HAVE_THREADS # import "OFConditionBroadcastFailedException.h" # import "OFConditionSignalFailedException.h" # import "OFConditionStillWaitingException.h" @@ -167,14 +165,15 @@ #import "OFOutOfMemoryException.h" #import "OFOutOfRangeException.h" #import "OFReadFailedException.h" #import "OFReadOrWriteFailedException.h" #import "OFRemoveItemFailedException.h" +#import "OFRetrieveItemAttributesFailedException.h" #import "OFSandboxActivationFailedException.h" #import "OFSeekFailedException.h" +#import "OFSetItemAttributesFailedException.h" #import "OFSetOptionFailedException.h" -#import "OFStatItemFailedException.h" #import "OFStillLockedException.h" #ifdef OF_HAVE_THREADS # import "OFThreadJoinFailedException.h" # import "OFThreadStartFailedException.h" # import "OFThreadStillRunningException.h" Index: src/exceptions/Makefile ================================================================== --- src/exceptions/Makefile +++ src/exceptions/Makefile @@ -3,12 +3,10 @@ STATIC_PIC_LIB_NOINST = ${EXCEPTIONS_LIB_A} STATIC_LIB_NOINST = ${EXCEPTIONS_A} SRCS = OFAllocFailedException.m \ OFChangeCurrentDirectoryPathFailedException.m \ - OFChangeOwnerFailedException.m \ - OFChangePermissionsFailedException.m \ OFChecksumFailedException.m \ OFCopyItemFailedException.m \ OFCreateDirectoryFailedException.m \ OFCreateSymbolicLinkFailedException.m \ OFEnumerationMutationException.m \ @@ -32,14 +30,15 @@ OFOutOfMemoryException.m \ OFOutOfRangeException.m \ OFReadFailedException.m \ OFReadOrWriteFailedException.m \ OFRemoveItemFailedException.m \ + OFRetrieveItemAttributesFailedException.m \ OFSandboxActivationFailedException.m \ OFSeekFailedException.m \ + OFSetItemAttributesFailedException.m \ OFSetOptionFailedException.m \ - OFStatItemFailedException.m \ OFStillLockedException.m \ OFTruncatedDataException.m \ OFUnboundNamespaceException.m \ OFUnboundPrefixException.m \ OFUndefinedKeyException.m \ DELETED src/exceptions/OFChangeOwnerFailedException.h Index: src/exceptions/OFChangeOwnerFailedException.h ================================================================== --- src/exceptions/OFChangeOwnerFailedException.h +++ src/exceptions/OFChangeOwnerFailedException.h @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 - * Jonathan Schleifer - * - * 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.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * 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 "OFException.h" - -OF_ASSUME_NONNULL_BEGIN - -/*! - * @class OFChangeOwnerFailedException \ - * OFChangeOwnerFailedException.h ObjFW/OFChangeOwnerFailedException.h - * - * @brief An exception indicating that changing the owner of an item failed. - */ -@interface OFChangeOwnerFailedException: OFException -{ - OFString *_path, *_owner, *_group; - int _errNo; -} - -/*! - * The path of the item. - */ -@property (readonly, nonatomic) OFString *path; - -/*! - * The new owner for the item. - */ -@property OF_NULLABLE_PROPERTY (readonly, nonatomic) OFString *owner; - -/*! - * The new group for the item. - */ -@property OF_NULLABLE_PROPERTY (readonly, nonatomic) OFString *group; - -/*! - * The errno of the error that occurred. - */ -@property (readonly, nonatomic) int errNo; - -+ (instancetype)exception OF_UNAVAILABLE; - -/*! - * @brief Creates a new, autoreleased change owner failed exception. - * - * @param path The path of the item - * @param owner The new owner for the item - * @param group The new group for the item - * @param errNo The errno of the error that occurred - * @return A new, autoreleased change owner failed exception - */ -+ (instancetype)exceptionWithPath: (OFString *)path - owner: (nullable OFString *)owner - group: (nullable OFString *)group - errNo: (int)errNo; - -- (instancetype)init OF_UNAVAILABLE; - -/*! - * @brief Initializes an already allocated change owner failed exception. - * - * @param path The path of the item - * @param owner The new owner for the item - * @param group The new group for the item - * @param errNo The errno of the error that occurred - * @return An initialized change owner failed exception - */ -- (instancetype)initWithPath: (OFString *)path - owner: (nullable OFString *)owner - group: (nullable OFString *)group - errNo: (int)errNo OF_DESIGNATED_INITIALIZER; -@end - -OF_ASSUME_NONNULL_END DELETED src/exceptions/OFChangeOwnerFailedException.m Index: src/exceptions/OFChangeOwnerFailedException.m ================================================================== --- src/exceptions/OFChangeOwnerFailedException.m +++ src/exceptions/OFChangeOwnerFailedException.m @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 - * Jonathan Schleifer - * - * 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.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * 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. - */ - -#include "config.h" - -#import "OFChangeOwnerFailedException.h" -#import "OFString.h" - -@implementation OFChangeOwnerFailedException -@synthesize path = _path, owner = _owner, group = _group, errNo = _errNo; - -+ (instancetype)exception -{ - OF_UNRECOGNIZED_SELECTOR -} - -+ (instancetype)exceptionWithPath: (OFString *)path - owner: (OFString *)owner - group: (OFString *)group - errNo: (int)errNo -{ - return [[[self alloc] initWithPath: path - owner: owner - group: group - errNo: errNo] autorelease]; -} - -- (instancetype)init -{ - OF_INVALID_INIT_METHOD -} - -- (instancetype)initWithPath: (OFString *)path - owner: (OFString *)owner - group: (OFString *)group - errNo: (int)errNo -{ - self = [super init]; - - @try { - _path = [path copy]; - _owner = [owner copy]; - _group = [group copy]; - _errNo = errNo; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (void)dealloc -{ - [_path release]; - [_owner release]; - [_group release]; - - [super dealloc]; -} - -- (OFString *)description -{ - if (_group == nil) - return [OFString stringWithFormat: - @"Failed to change owner of item at path %@ to %@: %@", - _path, _owner, of_strerror(_errNo)]; - else if (_owner == nil) - return [OFString stringWithFormat: - @"Failed to change group of item at path %@ to %@: %@", - _path, _group, of_strerror(_errNo)]; - else - return [OFString stringWithFormat: - @"Failed to change owner of item at path %@ to %@:%@: %@", - _path, _owner, _group, of_strerror(_errNo)]; -} -@end DELETED src/exceptions/OFChangePermissionsFailedException.h Index: src/exceptions/OFChangePermissionsFailedException.h ================================================================== --- src/exceptions/OFChangePermissionsFailedException.h +++ src/exceptions/OFChangePermissionsFailedException.h @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 - * Jonathan Schleifer - * - * 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.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * 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 "OFException.h" - -OF_ASSUME_NONNULL_BEGIN - -/*! - * @class OFChangePermissionsFailedException \ - * OFChangePermissionsFailedException.h \ - * ObjFW/OFChangePermissionsFailedException.h - * - * @brief An exception indicating that changing the permissions of an item - * failed. - */ -@interface OFChangePermissionsFailedException: OFException -{ - OFString *_path; - uint16_t _permissions; - int _errNo; -} - -/*! - * The path of the item. - */ -@property (readonly, nonatomic) OFString *path; - -/*! - * The new permissions for the item. - */ -@property (readonly, nonatomic) uint16_t permissions; - -/*! - * The errno of the error that occurred. - */ -@property (readonly, nonatomic) int errNo; - -+ (instancetype)exception OF_UNAVAILABLE; - -/*! - * @brief Creates a new, autoreleased change permissions failed exception. - * - * @param path The path of the item - * @param permissions The new permissions for the item - * @param errNo The errno of the error that occurred - * @return A new, autoreleased change permissions failed exception - */ -+ (instancetype)exceptionWithPath: (OFString *)path - permissions: (uint16_t)permissions - errNo: (int)errNo; - -- (instancetype)init OF_UNAVAILABLE; - -/*! - * @brief Initializes an already allocated change permissions failed exception. - * - * @param path The path of the item - * @param permissions The new permissions for the item - * @param errNo The errno of the error that occurred - * @return An initialized change permissions failed exception - */ -- (instancetype)initWithPath: (OFString *)path - permissions: (uint16_t)permissions - errNo: (int)errNo OF_DESIGNATED_INITIALIZER; -@end - -OF_ASSUME_NONNULL_END DELETED src/exceptions/OFChangePermissionsFailedException.m Index: src/exceptions/OFChangePermissionsFailedException.m ================================================================== --- src/exceptions/OFChangePermissionsFailedException.m +++ src/exceptions/OFChangePermissionsFailedException.m @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 - * Jonathan Schleifer - * - * 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.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * 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. - */ - -#include "config.h" - -#import "OFChangePermissionsFailedException.h" -#import "OFString.h" - -@implementation OFChangePermissionsFailedException -@synthesize path = _path, permissions = _permissions, errNo = _errNo; - -+ (instancetype)exception -{ - OF_UNRECOGNIZED_SELECTOR -} - -+ (instancetype)exceptionWithPath: (OFString *)path - permissions: (uint16_t)permissions - errNo: (int)errNo -{ - return [[[self alloc] initWithPath: path - permissions: permissions - errNo: errNo] autorelease]; -} - -- (instancetype)init -{ - OF_INVALID_INIT_METHOD -} - -- (instancetype)initWithPath: (OFString *)path - permissions: (uint16_t)permissions - errNo: (int)errNo -{ - self = [super init]; - - @try { - _path = [path copy]; - _permissions = permissions; - _errNo = errNo; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (void)dealloc -{ - [_path release]; - - [super dealloc]; -} - -- (OFString *)description -{ - return [OFString stringWithFormat: - @"Failed to change permissions of item at path %@ to %04o: %@", - _path, _permissions, of_strerror(_errNo)]; -} -@end ADDED src/exceptions/OFRetrieveItemAttributesFailedException.h Index: src/exceptions/OFRetrieveItemAttributesFailedException.h ================================================================== --- src/exceptions/OFRetrieveItemAttributesFailedException.h +++ src/exceptions/OFRetrieveItemAttributesFailedException.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 + * Jonathan Schleifer + * + * 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.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * 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 "OFException.h" + +OF_ASSUME_NONNULL_BEGIN + +/*! + * @class OFRetrieveItemAttributesFailedException \ + * OFRetrieveItemAttributesFailedException.h \ + * ObjFW/OFRetrieveItemAttributesFailedException.h + * + * @brief An exception indicating an item's attributes could not be retrieved. + */ +@interface OFRetrieveItemAttributesFailedException: OFException +{ + OFString *_path; + int _errNo; +} + +/*! + * A string with the path of the item whose attributes could not be retrieved. + */ +@property (readonly, nonatomic) OFString *path; + +/*! + * The errno of the error that occurred. + */ +@property (readonly, nonatomic) int errNo; + ++ (instancetype)exception OF_UNAVAILABLE; + +/*! + * @brief Creates a new, autoreleased retrieve item attributes failed exception. + * + * @param path A string with the path of the item whose attributes could not be + * retrieved + * @param errNo The errno of the error that occurred + * @return A new, autoreleased retrieve item attributes failed exception + */ ++ (instancetype)exceptionWithPath: (OFString *)path + errNo: (int)errNo; + +- (instancetype)init OF_UNAVAILABLE; + +/*! + * @brief Initializes an already allocated retrieve item attributes failed + * exception. + * + * @param path A string with the path of the item whose attributes could not be + * retrieved + * @param errNo The errno of the error that occurred + * @return An initialized retrieve item attributes failed exception + */ +- (instancetype)initWithPath: (OFString *)path + errNo: (int)errNo OF_DESIGNATED_INITIALIZER; +@end + +OF_ASSUME_NONNULL_END ADDED src/exceptions/OFRetrieveItemAttributesFailedException.m Index: src/exceptions/OFRetrieveItemAttributesFailedException.m ================================================================== --- src/exceptions/OFRetrieveItemAttributesFailedException.m +++ src/exceptions/OFRetrieveItemAttributesFailedException.m @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 + * Jonathan Schleifer + * + * 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.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * 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. + */ + +#include "config.h" + +#import "OFRetrieveItemAttributesFailedException.h" +#import "OFString.h" + +@implementation OFRetrieveItemAttributesFailedException +@synthesize path = _path, errNo = _errNo; + ++ (instancetype)exception +{ + OF_UNRECOGNIZED_SELECTOR +} + ++ (instancetype)exceptionWithPath: (OFString *)path + errNo: (int)errNo +{ + return [[[self alloc] initWithPath: path + errNo: errNo] autorelease]; +} + +- (instancetype)init +{ + OF_INVALID_INIT_METHOD +} + +- (instancetype)initWithPath: (OFString *)path + errNo: (int)errNo +{ + self = [super init]; + + @try { + _path = [path copy]; + _errNo = errNo; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + [_path release]; + + [super dealloc]; +} + +- (OFString *)description +{ + return [OFString stringWithFormat: + @"Failed to retrieve attributes for item %@: %@", + _path, of_strerror(_errNo)]; +} +@end ADDED src/exceptions/OFSetItemAttributesFailedException.h Index: src/exceptions/OFSetItemAttributesFailedException.h ================================================================== --- src/exceptions/OFSetItemAttributesFailedException.h +++ src/exceptions/OFSetItemAttributesFailedException.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 + * Jonathan Schleifer + * + * 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.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * 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 "OFException.h" +#import "OFFileManager.h" + +OF_ASSUME_NONNULL_BEGIN + +/*! + * @class OFSetItemAttributesFailedException \ + * OFSetItemAttributesFailedException.h \ + * ObjFW/OFSetItemAttributesFailedException.h + * + * @brief An exception indicating an item's attributes could not be set. + */ +@interface OFSetItemAttributesFailedException: OFException +{ + OFString *_path; + of_file_attributes_t _attributes; + of_file_attribute_key_t _failedAttribute; + int _errNo; +} + +/*! + * A string with the path of the item whose attributes could not be set. + */ +@property (readonly, nonatomic) OFString *path; + +/*! + * The errno of the error that occurred. + */ +@property (readonly, nonatomic) int errNo; + +/*! + * The attributes that should have been set. + */ +@property (readonly, nonatomic) of_file_attributes_t attributes; + +/*! + * The first attribute that could not be set. + */ +@property (readonly, nonatomic) of_file_attribute_key_t failedAttribute; + ++ (instancetype)exception OF_UNAVAILABLE; + +/*! + * @brief Creates a new, autoreleased set item attributes failed exception. + * + * @param path A string with the path of the item whose attributes could not be + * set + * @param attributes The attributes that should have been set for the specified + * item. + * @param failedAttribute The first attribute that could not be set + * @param errNo The errno of the error that occurred + * @return A new, autoreleased set item attributes failed exception + */ ++ (instancetype)exceptionWithPath: (OFString *)path + attributes: (of_file_attributes_t)attributes + failedAttribute: (of_file_attribute_key_t)failedAttribute + errNo: (int)errNo; + +- (instancetype)init OF_UNAVAILABLE; + +/*! + * @brief Initializes an already allocated set item attributes failed exception. + * + * @param path A string with the path of the item whose attributes could not be + * set + * @param attributes The attributes that should have been set for the specified + * item. + * @param failedAttribute The first attribute that could not be set + * @param errNo The errno of the error that occurred + * @return An initialized set item attributes failed exception + */ +- (instancetype)initWithPath: (OFString *)path + attributes: (of_file_attributes_t)attributes + failedAttribute: (of_file_attribute_key_t)failedAttribute + errNo: (int)errNo OF_DESIGNATED_INITIALIZER; +@end + +OF_ASSUME_NONNULL_END ADDED src/exceptions/OFSetItemAttributesFailedException.m Index: src/exceptions/OFSetItemAttributesFailedException.m ================================================================== --- src/exceptions/OFSetItemAttributesFailedException.m +++ src/exceptions/OFSetItemAttributesFailedException.m @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 + * Jonathan Schleifer + * + * 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.QPL included in + * the packaging of this file. + * + * Alternatively, it may be distributed under the terms of the GNU General + * 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. + */ + +#include "config.h" + +#import "OFSetItemAttributesFailedException.h" +#import "OFString.h" + +@implementation OFSetItemAttributesFailedException +@synthesize path = _path, attributes = _attributes; +@synthesize failedAttribute = _failedAttribute, errNo = _errNo; + ++ (instancetype)exception +{ + OF_UNRECOGNIZED_SELECTOR +} + ++ (instancetype)exceptionWithPath: (OFString *)path + attributes: (of_file_attributes_t)attributes + failedAttribute: (of_file_attribute_key_t)failedAttribute + errNo: (int)errNo +{ + return [[[self alloc] initWithPath: path + attributes: attributes + failedAttribute: failedAttribute + errNo: errNo] autorelease]; +} + +- (instancetype)init +{ + OF_INVALID_INIT_METHOD +} + +- (instancetype)initWithPath: (OFString *)path + attributes: (of_file_attributes_t)attributes + failedAttribute: (of_file_attribute_key_t)failedAttribute + errNo: (int)errNo +{ + self = [super init]; + + @try { + _path = [path copy]; + _attributes = [attributes copy]; + _failedAttribute = [failedAttribute copy]; + _errNo = errNo; + } @catch (id e) { + [self release]; + @throw e; + } + + return self; +} + +- (void)dealloc +{ + [_path release]; + [_attributes release]; + [_failedAttribute release]; + + [super dealloc]; +} + +- (OFString *)description +{ + return [OFString stringWithFormat: + @"Failed to set attribute %@ for item %@: %@", + _failedAttribute, _path, of_strerror(_errNo)]; +} +@end DELETED src/exceptions/OFStatItemFailedException.h Index: src/exceptions/OFStatItemFailedException.h ================================================================== --- src/exceptions/OFStatItemFailedException.h +++ src/exceptions/OFStatItemFailedException.h @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 - * Jonathan Schleifer - * - * 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.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * 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 "OFException.h" - -OF_ASSUME_NONNULL_BEGIN - -/*! - * @class OFStatItemFailedException \ - * OFStatItemFailedException.h ObjFW/OFStatItemFailedException.h - * - * @brief An exception indicating an item's status could not be retrieved. - */ -@interface OFStatItemFailedException: OFException -{ - OFString *_path; - int _errNo; -} - -/*! - * A string with the path of the item whose status could not be retrieved. - */ -@property (readonly, nonatomic) OFString *path; - -/*! - * The errno of the error that occurred. - */ -@property (readonly, nonatomic) int errNo; - -+ (instancetype)exception OF_UNAVAILABLE; - -/*! - * @brief Creates a new, autoreleased stat item failed exception. - * - * @param path A string with the path of the item whose status could not be - * retrieved - * @param errNo The errno of the error that occurred - * @return A new, autoreleased stat item failed exception - */ -+ (instancetype)exceptionWithPath: (OFString *)path - errNo: (int)errNo; - -- (instancetype)init OF_UNAVAILABLE; - -/*! - * @brief Initializes an already allocated stat item failed exception. - * - * @param path A string with the path of the item whose status could not be - * retrieved - * @param errNo The errno of the error that occurred - * @return An initialized stat item failed exception - */ -- (instancetype)initWithPath: (OFString *)path - errNo: (int)errNo OF_DESIGNATED_INITIALIZER; -@end - -OF_ASSUME_NONNULL_END DELETED src/exceptions/OFStatItemFailedException.m Index: src/exceptions/OFStatItemFailedException.m ================================================================== --- src/exceptions/OFStatItemFailedException.m +++ src/exceptions/OFStatItemFailedException.m @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 - * Jonathan Schleifer - * - * 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.QPL included in - * the packaging of this file. - * - * Alternatively, it may be distributed under the terms of the GNU General - * 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. - */ - -#include "config.h" - -#import "OFStatItemFailedException.h" -#import "OFString.h" - -@implementation OFStatItemFailedException -@synthesize path = _path, errNo = _errNo; - -+ (instancetype)exception -{ - OF_UNRECOGNIZED_SELECTOR -} - -+ (instancetype)exceptionWithPath: (OFString *)path - errNo: (int)errNo -{ - return [[[self alloc] initWithPath: path - errNo: errNo] autorelease]; -} - -- (instancetype)init -{ - OF_INVALID_INIT_METHOD -} - -- (instancetype)initWithPath: (OFString *)path - errNo: (int)errNo -{ - self = [super init]; - - @try { - _path = [path copy]; - _errNo = errNo; - } @catch (id e) { - [self release]; - @throw e; - } - - return self; -} - -- (void)dealloc -{ - [_path release]; - - [super dealloc]; -} - -- (OFString *)description -{ - return [OFString stringWithFormat: - @"Failed to stat item %@: %@", _path, of_strerror(_errNo)]; -} -@end Index: src/exceptions/OFUndefinedKeyException.h ================================================================== --- src/exceptions/OFUndefinedKeyException.h +++ src/exceptions/OFUndefinedKeyException.h @@ -20,17 +20,18 @@ /*! * @class OFUndefinedKeyException \ * OFUndefinedKeyException.h ObjFW/OFUndefinedKeyException.h * - * @brief An exception indicating that a key for Key Value Coding is undefined. + * @brief An exception indicating that a key is undefined (e.g. for Key Value + * Coding). */ @interface OFUndefinedKeyException: OFException { id _object; OFString *_key; - id _value; + id _Nullable _value; } /*! * The object on which the key is undefined. */ @@ -42,11 +43,11 @@ @property (readonly, nonatomic) OFString *key; /*! * The value for the undefined key */ -@property (readonly, nonatomic) id value; +@property OF_NULLABLE_PROPERTY (readonly, nonatomic) id value; + (instancetype)exception OF_UNAVAILABLE; /*! * @brief Creates a new, autoreleased undefined key exception. Index: utils/ofhttp/OFHTTP.m ================================================================== --- utils/ofhttp/OFHTTP.m +++ utils/ofhttp/OFHTTP.m @@ -40,11 +40,11 @@ #import "OFInvalidFormatException.h" #import "OFInvalidServerReplyException.h" #import "OFOpenItemFailedException.h" #import "OFOutOfRangeException.h" #import "OFReadFailedException.h" -#import "OFStatItemFailedException.h" +#import "OFRetrieveItemAttributesFailedException.h" #import "OFUnsupportedProtocolException.h" #import "OFWriteFailedException.h" #import "ProgressBar.h" @@ -932,12 +932,12 @@ if (_currentFileName == nil) _currentFileName = [[[URL path] lastPathComponent] copy]; if (_continue) { @try { - of_offset_t size = [[OFFileManager defaultManager] - sizeOfFileAtPath: _currentFileName]; + uintmax_t size = [[[OFFileManager defaultManager] + attributesOfItemAtPath: _currentFileName] fileSize]; OFString *range; if (size > INTMAX_MAX) @throw [OFOutOfRangeException exception]; @@ -945,11 +945,11 @@ range = [OFString stringWithFormat: @"bytes=%jd-", _resumedFrom]; [clientHeaders setObject: range forKey: @"Range"]; - } @catch (OFStatItemFailedException *e) { + } @catch (OFRetrieveItemAttributesFailedException *e) { } } request = [OFHTTPRequest requestWithURL: URL]; [request setHeaders: clientHeaders]; Index: utils/ofzip/GZIPArchive.m ================================================================== --- utils/ofzip/GZIPArchive.m +++ utils/ofzip/GZIPArchive.m @@ -29,14 +29,19 @@ static void setPermissions(OFString *destination, OFString *source) { #ifdef OF_FILE_MANAGER_SUPPORTS_PERMISSIONS OFFileManager *fileManager = [OFFileManager defaultManager]; - uint16_t mode = [fileManager permissionsOfItemAtPath: source]; + of_file_attributes_t attributes = + [fileManager attributesOfItemAtPath: source]; + of_file_attribute_key_t key = of_file_attribute_key_size; + of_file_attributes_t destinationAttributes = [OFDictionary + dictionaryWithObject: [attributes objectForKey: key] + forKey: key]; - [fileManager changePermissionsOfItemAtPath: destination - permissions: mode]; + [fileManager setAttributes: destinationAttributes + ofItemAtPath: destination]; #endif } @implementation GZIPArchive + (void)initialize Index: utils/ofzip/TarArchive.m ================================================================== --- utils/ofzip/TarArchive.m +++ utils/ofzip/TarArchive.m @@ -16,16 +16,17 @@ #include "config.h" #include -#import "OFDate.h" -#import "OFSet.h" #import "OFApplication.h" +#import "OFDate.h" #import "OFFileManager.h" -#import "OFStdIOStream.h" #import "OFLocalization.h" +#import "OFNumber.h" +#import "OFSet.h" +#import "OFStdIOStream.h" #import "TarArchive.h" #import "OFZIP.h" static OFZIP *app; @@ -32,13 +33,16 @@ static void setPermissions(OFString *path, OFTarArchiveEntry *entry) { #ifdef OF_FILE_MANAGER_SUPPORTS_PERMISSIONS - [[OFFileManager defaultManager] - changePermissionsOfItemAtPath: path - permissions: [entry mode]]; + of_file_attributes_t attributes = [OFDictionary + dictionaryWithObject: [OFNumber numberWithUInt16: [entry mode]] + forKey: of_file_attribute_key_posix_permissions]; + + [[OFFileManager defaultManager] setAttributes: attributes + ofItemAtPath: path]; #endif } @implementation TarArchive + (void)initialize @@ -454,54 +458,46 @@ return; } for (OFString *fileName in files) { void *pool = objc_autoreleasePoolPush(); + of_file_attributes_t attributes; + of_file_type_t type; OFMutableTarArchiveEntry *entry; OFStream *output; if (app->_outputLevel >= 0) [of_stdout writeString: OF_LOCALIZED(@"adding_file", @"Adding %[file]...", @"file", fileName)]; + attributes = [fileManager attributesOfItemAtPath: fileName]; + type = [attributes fileType]; entry = [OFMutableTarArchiveEntry entryWithFileName: fileName]; #ifdef OF_FILE_MANAGER_SUPPORTS_PERMISSIONS - [entry setMode: - [fileManager permissionsOfItemAtPath: fileName]]; + [entry setMode: [attributes filePOSIXPermissions]]; #endif - [entry setSize: [fileManager sizeOfFileAtPath: fileName]]; - [entry setModificationDate: - [fileManager modificationDateOfItemAtPath: fileName]]; + [entry setSize: [attributes fileSize]]; + [entry setModificationDate: [attributes fileModificationDate]]; #ifdef OF_FILE_MANAGER_SUPPORTS_OWNER - uint16_t UID, GID; - OFString *owner, *group; - - [fileManager getUID: &UID - GID: &GID - ofItemAtPath: fileName]; - [fileManager getOwner: &owner - group: &group - ofItemAtPath: fileName]; - - [entry setUID: UID]; - [entry setGID: GID]; - [entry setOwner: owner]; - [entry setGroup: group]; + [entry setUID: [attributes filePOSIXUID]]; + [entry setGID: [attributes filePOSIXGID]]; + [entry setOwner: [attributes fileOwner]]; + [entry setGroup: [attributes fileGroup]]; #endif - if ([fileManager fileExistsAtPath: fileName]) + if ([type isEqual: of_file_type_regular]) [entry setType: OF_TAR_ARCHIVE_ENTRY_TYPE_FILE]; - else if ([fileManager directoryExistsAtPath: fileName]) { + else if ([type isEqual: of_file_type_directory]) { [entry setType: OF_TAR_ARCHIVE_ENTRY_TYPE_DIRECTORY]; [entry setSize: 0]; - } else if ([fileManager symbolicLinkExistsAtPath: fileName]) { + } else if ([type isEqual: of_file_type_symbolic_link]) { [entry setType: OF_TAR_ARCHIVE_ENTRY_TYPE_SYMLINK]; - [entry setTargetFileName: [fileManager - destinationOfSymbolicLinkAtPath: fileName]]; + [entry setTargetFileName: + [attributes fileSymbolicLinkDestination]]; [entry setSize: 0]; } [entry makeImmutable]; Index: utils/ofzip/ZIPArchive.m ================================================================== --- utils/ofzip/ZIPArchive.m +++ utils/ofzip/ZIPArchive.m @@ -17,16 +17,17 @@ #include "config.h" #include #include -#import "OFDate.h" -#import "OFSet.h" #import "OFApplication.h" +#import "OFDate.h" #import "OFFileManager.h" -#import "OFStdIOStream.h" #import "OFLocalization.h" +#import "OFNumber.h" +#import "OFSet.h" +#import "OFStdIOStream.h" #import "ZIPArchive.h" #import "OFZIP.h" #import "OFInvalidFormatException.h" @@ -40,14 +41,18 @@ { #ifdef OF_FILE_MANAGER_SUPPORTS_PERMISSIONS if (([entry versionMadeBy] >> 8) == OF_ZIP_ARCHIVE_ENTRY_ATTR_COMPAT_UNIX) { uint16_t mode = [entry versionSpecificAttributes] >> 16; + of_file_attribute_key_t key = + of_file_attribute_key_posix_permissions; + of_file_attributes_t attributes = [OFDictionary + dictionaryWithObject: [OFNumber numberWithUInt16: mode] + forKey: key]; - [[OFFileManager defaultManager] - changePermissionsOfItemAtPath: path - permissions: mode]; + [[OFFileManager defaultManager] setAttributes: attributes + ofItemAtPath: path]; } #endif } @implementation ZIPArchive @@ -386,19 +391,23 @@ for (OFString *localFileName in files) { void *pool = objc_autoreleasePoolPush(); OFArray OF_GENERIC (OFString *) *components; OFString *fileName; + of_file_attributes_t attributes; bool isDirectory = false; OFMutableZIPArchiveEntry *entry; - of_offset_t size; + uintmax_t size; OFStream *output; components = [localFileName pathComponents]; fileName = [components componentsJoinedByString: @"/"]; - if ([fileManager directoryExistsAtPath: localFileName]) { + attributes = [fileManager + attributesOfItemAtPath: localFileName]; + + if ([[attributes fileType] isEqual: of_file_type_directory]) { isDirectory = true; fileName = [fileName stringByAppendingString: @"/"]; } if (app->_outputLevel >= 0) @@ -409,29 +418,28 @@ entry = [OFMutableZIPArchiveEntry entryWithFileName: fileName]; if (isDirectory) size = 0; else - size = [fileManager sizeOfFileAtPath: localFileName]; + size = [attributes fileSize]; if (size > INT64_MAX) @throw [OFOutOfRangeException exception]; [entry setCompressedSize: (int64_t)size]; [entry setUncompressedSize: (int64_t)size]; [entry setCompressionMethod: OF_ZIP_ARCHIVE_ENTRY_COMPRESSION_METHOD_NONE]; - [entry setModificationDate: - [fileManager modificationDateOfItemAtPath: localFileName]]; + [entry setModificationDate: [attributes fileModificationDate]]; [entry makeImmutable]; output = [_archive streamForWritingEntry: entry]; if (!isDirectory) { - int64_t written = 0; + uintmax_t written = 0; int8_t percent = -1, newPercent; OFFile *input = [OFFile fileWithPath: fileName mode: @"r"];