Skip to content

Commit

Permalink
[Foundation] Several fixes to NSFileManager. (#18371)
Browse files Browse the repository at this point in the history
* Enable nullability.
* Add API that was previously iOS-specific to all platforms.
  • Loading branch information
rolfbjarne authored Jun 2, 2023
1 parent 7198886 commit a43b664
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 101 deletions.
115 changes: 68 additions & 47 deletions src/Foundation/NSFileManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,15 @@
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//
using CoreFoundation;
using ObjCRuntime;

using System;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;

#nullable enable

namespace Foundation {

// This is a convenience enum around a set of native strings.
Expand All @@ -57,15 +61,15 @@ public class NSFileAttributes {
public bool? AppendOnly { get; set; }
public bool? Busy { get; set; }
public bool? ExtensionHidden { get; set; }
public NSDate CreationDate { get; set; }
public string OwnerAccountName { get; set; }
public string GroupOwnerAccountName { get; set; }
public NSDate? CreationDate { get; set; }
public string? OwnerAccountName { get; set; }
public string? GroupOwnerAccountName { get; set; }
public nint? SystemNumber { get; set; } // NSInteger
public nuint? DeviceIdentifier { get; set; } // unsigned long
public nuint? GroupOwnerAccountID { get; set; } // unsigned long

public bool? Immutable { get; set; }
public NSDate ModificationDate { get; set; }
public NSDate? ModificationDate { get; set; }
public nuint? OwnerAccountID { get; set; } // unsigned long
public nuint? HfsCreatorCode { get; set; }
public nuint? HfsTypeCode { get; set; } // unsigned long
Expand All @@ -83,7 +87,7 @@ public class NSFileAttributes {
internal NSDictionary ToDictionary ()
{
NSFileType? type;
NSString v = null;
NSString? v = null;
var dict = new NSMutableDictionary ();
if (AppendOnly.HasValue)
dict.SetObject (NSNumber.FromBoolean (AppendOnly.Value), NSFileManager.AppendOnly);
Expand Down Expand Up @@ -158,7 +162,8 @@ internal NSDictionary ToDictionary ()
case NSFileProtection.CompleteUntilFirstUserAuthentication:
v = NSFileManager.FileProtectionCompleteUntilFirstUserAuthentication; break;
}
dict.SetObject (v, NSFileManager.FileProtectionKey);
if (v is not null)
dict.SetObject (v, NSFileManager.FileProtectionKey);
}
#endif
return dict;
Expand Down Expand Up @@ -222,7 +227,7 @@ internal NSDictionary ToDictionary ()
}
#endregion

public static NSFileAttributes FromDictionary (NSDictionary dict)
public static NSFileAttributes? FromDictionary (NSDictionary dict)
{
if (dict is null)
return null;
Expand All @@ -247,9 +252,7 @@ public static NSFileAttributes FromDictionary (NSDictionary dict)
ret.SystemFileNumber = fetch_nuint (dict, NSFileManager.SystemFileNumber);
ret.Size = fetch_ulong (dict, NSFileManager.Size);

NSString name;

name = dict.ObjectForKey (NSFileManager.NSFileType) as NSString;
var name = dict.ObjectForKey (NSFileManager.NSFileType) as NSString;
if (name is not null) {
NSFileType? type = null;

Expand Down Expand Up @@ -314,7 +317,7 @@ internal NSFileSystemAttributes (NSDictionary dict)
// "The value corresponds to the value of st_dev, as returned by stat(2)" => st_dev is defined to be int32_t in all architectures.
public uint Number { get; internal set; }

internal static NSFileSystemAttributes FromDictionary (NSDictionary dict)
internal static NSFileSystemAttributes? FromDictionary (NSDictionary dict)
{
if (dict is null)
return null;
Expand All @@ -341,108 +344,99 @@ public partial class NSFileManager {
[DllImport (Constants.FoundationLibrary)]
static extern IntPtr NSUserName ();

public static string UserName {
public static string? UserName {
get {
using (var nsstring = ObjCRuntime.Runtime.GetNSObject<NSString> (NSUserName ()))
return nsstring.ToString ();
return CFString.FromHandle (NSUserName ());
}
}

[DllImport (Constants.FoundationLibrary)]
static extern IntPtr NSFullUserName ();

public static string FullUserName {
public static string? FullUserName {
get {
using (var nsstring = ObjCRuntime.Runtime.GetNSObject<NSString> (NSFullUserName ()))
return nsstring.ToString ();
return CFString.FromHandle (NSFullUserName ());
}
}

[DllImport (Constants.FoundationLibrary)]
static extern IntPtr NSHomeDirectory ();

public static string HomeDirectory {
public static string? HomeDirectory {
get {
using (var nsstring = ObjCRuntime.Runtime.GetNSObject<NSString> (NSHomeDirectory ()))
return nsstring.ToString ();
return CFString.FromHandle (NSHomeDirectory ());
}
}

[DllImport (Constants.FoundationLibrary)]
static extern IntPtr NSHomeDirectoryForUser (/* NSString */IntPtr userName);

public static string GetHomeDirectory (string userName)
public static string? GetHomeDirectory (string userName)
{
if (userName is null)
throw new ArgumentNullException (nameof (userName));

using (var nsstring = new NSString (userName))
using (var homeDir = ObjCRuntime.Runtime.GetNSObject<NSString> (NSHomeDirectoryForUser (nsstring.GetHandle ())))
return homeDir.ToString ();
var userNamePtr = CFString.CreateNative (userName);
var rv = CFString.FromHandle (NSHomeDirectoryForUser (userNamePtr));
CFString.ReleaseNative (userNamePtr);
return rv;
}

[DllImport (Constants.FoundationLibrary)]
static extern IntPtr NSTemporaryDirectory ();

public static string TemporaryDirectory {
public static string? TemporaryDirectory {
get {
using (var nsstring = ObjCRuntime.Runtime.GetNSObject<NSString> (NSTemporaryDirectory ()))
return nsstring.ToString ();
return CFString.FromHandle (NSTemporaryDirectory ());
}
}

public bool SetAttributes (NSFileAttributes attributes, string path, out NSError error)
{
if (attributes is null)
throw new ArgumentNullException ("attributes");
throw new ArgumentNullException (nameof (attributes));
return SetAttributes (attributes.ToDictionary (), path, out error);
}

public bool SetAttributes (NSFileAttributes attributes, string path)
{
if (attributes is null)
throw new ArgumentNullException ("attributes");
throw new ArgumentNullException (nameof (attributes));

return SetAttributes (attributes.ToDictionary (), path, out _);
}

public bool CreateDirectory (string path, bool createIntermediates, NSFileAttributes attributes, out NSError error)
public bool CreateDirectory (string path, bool createIntermediates, NSFileAttributes? attributes, out NSError error)
{
var dict = attributes is null ? null : attributes.ToDictionary ();
return CreateDirectory (path, createIntermediates, dict, out error);
return CreateDirectory (path, createIntermediates, attributes?.ToDictionary (), out error);
}

public bool CreateDirectory (string path, bool createIntermediates, NSFileAttributes attributes)
public bool CreateDirectory (string path, bool createIntermediates, NSFileAttributes? attributes)
{
NSError error;
var dict = attributes is null ? null : attributes.ToDictionary ();
return CreateDirectory (path, createIntermediates, dict, out error);
return CreateDirectory (path, createIntermediates, attributes?.ToDictionary (), out var _);
}

public bool CreateFile (string path, NSData data, NSFileAttributes attributes)
public bool CreateFile (string path, NSData data, NSFileAttributes? attributes)
{
var dict = attributes is null ? null : attributes.ToDictionary ();
return CreateFile (path, data, dict);
return CreateFile (path, data, attributes?.ToDictionary ());
}

public NSFileAttributes GetAttributes (string path, out NSError error)
public NSFileAttributes? GetAttributes (string path, out NSError error)
{
return NSFileAttributes.FromDictionary (_GetAttributes (path, out error));
}

public NSFileAttributes GetAttributes (string path)
public NSFileAttributes? GetAttributes (string path)
{
NSError error;
return NSFileAttributes.FromDictionary (_GetAttributes (path, out error));
return NSFileAttributes.FromDictionary (_GetAttributes (path, out var _));
}

public NSFileSystemAttributes GetFileSystemAttributes (string path)
public NSFileSystemAttributes? GetFileSystemAttributes (string path)
{
NSError error;
return NSFileSystemAttributes.FromDictionary (_GetFileSystemAttributes (path, out error));
return NSFileSystemAttributes.FromDictionary (_GetFileSystemAttributes (path, out var _));
}

public NSFileSystemAttributes GetFileSystemAttributes (string path, out NSError error)
public NSFileSystemAttributes? GetFileSystemAttributes (string path, out NSError error)
{
return NSFileSystemAttributes.FromDictionary (_GetFileSystemAttributes (path, out error));
}
Expand All @@ -458,5 +452,32 @@ public string CurrentDirectory {
// ignore boolean return value
set { ChangeCurrentDirectory (value); }
}

public static NSError SetSkipBackupAttribute (string filename, bool skipBackup)
{
if (filename is null)
throw new ArgumentNullException (nameof (filename));

using (var url = NSUrl.FromFilename (filename)) {
url.SetResource (NSUrl.IsExcludedFromBackupKey, (NSNumber) (skipBackup ? 1 : 0), out var error);
return error;
}
}

public static bool GetSkipBackupAttribute (string filename)
{
return GetSkipBackupAttribute (filename, out var _);
}

public static bool GetSkipBackupAttribute (string filename, out NSError error)
{
if (filename is null)
throw new ArgumentNullException (nameof (filename));

using (var url = NSUrl.FromFilename (filename)) {
url.TryGetResource (NSUrl.IsExcludedFromBackupKey, out var value, out error);
return (error is null) && ((long) ((NSNumber) value) == 1);
}
}
}
}
50 changes: 0 additions & 50 deletions src/Foundation/NSFileManager.iOS.cs

This file was deleted.

1 change: 0 additions & 1 deletion src/frameworks.sources
Original file line number Diff line number Diff line change
Expand Up @@ -821,7 +821,6 @@ FOUNDATION_SOURCES = \
Foundation/NSFastEnumerationState.cs \
Foundation/NSFastEnumerator.cs \
Foundation/NSFileManager.cs \
Foundation/NSFileManager.iOS.cs \
Foundation/NSFileManagerDelegate.cs \
Foundation/NSFormatter.cs \
Foundation/NSHost.cs \
Expand Down
3 changes: 0 additions & 3 deletions tests/monotouch-test/Foundation/FileManagerTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,6 @@ public void GetUrlForUbiquityContainer ()
// aborting is evil, so don't bother aborting the thread, just let it run its course
}
}
//GetSkipBackupAttribute doesn't exist on Mac
#if !MONOMAC

[Test]
public void GetSkipBackupAttribute ()
Expand All @@ -113,7 +111,6 @@ public void GetSkipBackupAttribute ()
File.Delete (filename);
}
}
#endif

[Test]
public void DefaultManager ()
Expand Down

6 comments on commit a43b664

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

@vs-mobiletools-engineering-service2

This comment was marked as outdated.

Please sign in to comment.