Skip to content

Commit eb602fd

Browse files
committed
New platform interface
1 parent aab148c commit eb602fd

12 files changed

+155
-76
lines changed

superuser_plugin_unix/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 1.0.0
2+
3+
* Add throw error if native code returns with error.
4+
15
## 0.1.0
26

37
* Define interface's result

superuser_plugin_unix/lib/superuser_plugin_unix.dart

Lines changed: 34 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -12,37 +12,47 @@ const String _libName = 'superuser_plugin_unix';
1212
///
1313
/// Remark: [isActivated] is identical with [isSuperuser]
1414
/// since `root` is a definition of superuser.
15-
final class UnixSuperuser implements SuperuserInterface {
16-
static UnixSuperuser? _instance;
15+
final class UnixSuperuser extends SuperuserPlatform {
16+
UnixSuperuser()
17+
: super(() {
18+
if (Platform.isMacOS) {
19+
return DynamicLibrary.open('$_libName.framework/$_libName');
20+
}
1721

18-
late final SuperuserPluginUnixBindings _bindings;
22+
if (Platform.isLinux) {
23+
return DynamicLibrary.open('lib$_libName.so');
24+
}
1925

20-
UnixSuperuser._() {
21-
_bindings = SuperuserPluginUnixBindings(() {
22-
if (Platform.isMacOS) {
23-
return DynamicLibrary.open('$_libName.framework/$_libName');
24-
}
25-
26-
if (Platform.isLinux) {
27-
return DynamicLibrary.open('lib$_libName.so');
28-
}
29-
30-
throw UnsupportedError('Unknown platform: ${Platform.operatingSystem}');
31-
}());
32-
}
33-
34-
factory UnixSuperuser() {
35-
_instance ??= UnixSuperuser._();
36-
37-
return _instance!;
38-
}
26+
throw UnsupportedError(
27+
'Unknown platform: ${Platform.operatingSystem}');
28+
});
3929

4030
@override
4131
bool get isActivated => isSuperuser;
4232

4333
@override
44-
bool get isSuperuser => _bindings.is_root();
34+
bool get isSuperuser =>
35+
onGettingProperties((lib) => SuperuserPluginUnixBindings(lib).is_root());
4536

4637
@override
47-
String get whoAmI => _bindings.get_uname().cast<ffi.Utf8>().toDartString();
38+
String get whoAmI => onGettingProperties((lib) {
39+
final SuperuserPluginUnixBindings bindings =
40+
SuperuserPluginUnixBindings(lib);
41+
42+
Pointer<Pointer<Char>> resultPtr = ffi.calloc<Pointer<Char>>();
43+
44+
try {
45+
int errCode = bindings.get_uname(resultPtr);
46+
47+
if (errCode != 0) {
48+
throw SuperuserProcessError(errCode, "Unable to retrive username.");
49+
}
50+
51+
String result = resultPtr.value.cast<ffi.Utf8>().toDartString();
52+
53+
return result;
54+
} finally {
55+
ffi.calloc.free(resultPtr);
56+
}
57+
});
4858
}

superuser_plugin_unix/lib/superuser_plugin_unix_bindings_generated.dart

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,17 @@ final class SuperuserPluginUnixBindings {
3737
late final _is_root = _is_rootPtr.asFunction<bool Function()>();
3838

3939
/// Obtain name of user.
40-
ffi.Pointer<ffi.Char> get_uname() {
41-
return _get_uname();
40+
int get_uname(
41+
ffi.Pointer<ffi.Pointer<ffi.Char>> result,
42+
) {
43+
return _get_uname(
44+
result,
45+
);
4246
}
4347

44-
late final _get_unamePtr =
45-
_lookup<ffi.NativeFunction<ffi.Pointer<ffi.Char> Function()>>(
46-
'get_uname');
47-
late final _get_uname =
48-
_get_unamePtr.asFunction<ffi.Pointer<ffi.Char> Function()>();
48+
late final _get_unamePtr = _lookup<
49+
ffi.NativeFunction<
50+
ffi.Int Function(ffi.Pointer<ffi.Pointer<ffi.Char>>)>>('get_uname');
51+
late final _get_uname = _get_unamePtr
52+
.asFunction<int Function(ffi.Pointer<ffi.Pointer<ffi.Char>>)>();
4953
}

superuser_plugin_unix/pubspec.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: superuser_plugin_unix
22
description: "Detect, verify user who execute Flutter program has superuser role in UNIX"
3-
version: 0.1.0
3+
version: 1.0.0
44
homepage: https://github.com/rk0cc/superuser
55
repository: https://github.com/rk0cc/superuser/tree/main/superuser_plugin_unix
66
environment:
@@ -11,7 +11,7 @@ dependencies:
1111
sdk: flutter
1212
plugin_platform_interface: ^2.1.8
1313
ffi: ^2.1.2
14-
superuser_interfaces: ^1.0.0
14+
superuser_interfaces: ^2.0.0
1515
dev_dependencies:
1616
ffigen: ^12.0.0
1717
flutter_lints: ^4.0.0

superuser_plugin_unix/src/superuser_plugin_unix.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#include <errno.h>
12
#include <pwd.h>
23
#include <unistd.h>
34

@@ -13,14 +14,19 @@ FFI_PLUGIN_EXPORT bool is_root()
1314
}
1415

1516
// Obtain name of user.
16-
FFI_PLUGIN_EXPORT char* get_uname()
17+
FFI_PLUGIN_EXPORT int get_uname(char** result)
1718
{
19+
errno = 0;
20+
1821
struct passwd *pw;
1922
UID uid = geteuid();
2023

2124
pw = getpwuid(uid);
2225
if (!pw)
23-
return "<Unknown username>";
26+
return errno;
27+
28+
29+
*result = pw->pw_name;
2430

25-
return pw->pw_name;
31+
return 0;
2632
}

superuser_plugin_unix/src/superuser_plugin_unix.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@
99
FFI_PLUGIN_EXPORT bool is_root();
1010

1111
// Obtain name of user.
12-
FFI_PLUGIN_EXPORT char* get_uname();
12+
FFI_PLUGIN_EXPORT int get_uname(char** result);
1313

1414
#endif
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
1+
## 1.0.0
2+
3+
* Add throw error if native code returns with error.
4+
* Improve memory effiency.
5+
16
## 0.1.0
27

38
* Define interface's result

superuser_plugin_windows/lib/superuser_plugin_windows.dart

Lines changed: 39 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,42 +2,57 @@ import 'dart:ffi';
22
import 'dart:io';
33

44
import 'package:ffi/ffi.dart' as ffi;
5-
import 'package:superuser_interfaces/superuser_interfaces.dart'
6-
show SuperuserInterface;
5+
import 'package:superuser_interfaces/superuser_interfaces.dart';
76

87
import 'superuser_plugin_windows_bindings_generated.dart';
98

109
const String _libName = 'superuser_plugin_windows';
1110

1211
/// Construct [SuperuserInterface] based on Windows API.
13-
final class WindowsSuperuser implements SuperuserInterface {
14-
static WindowsSuperuser? _instance;
12+
final class WindowsSuperuser extends SuperuserPlatform {
13+
WindowsSuperuser()
14+
: super(() {
15+
if (Platform.isWindows) {
16+
return DynamicLibrary.open('$_libName.dll');
17+
}
1518

16-
late final SuperuserPluginWindowsBindings _bindings;
19+
throw UnsupportedError(
20+
'Unknown platform: ${Platform.operatingSystem}');
21+
});
1722

18-
WindowsSuperuser._() {
19-
_bindings = SuperuserPluginWindowsBindings(() {
20-
if (Platform.isWindows) {
21-
return DynamicLibrary.open('$_libName.dll');
22-
}
23+
@override
24+
bool get isActivated => onGettingProperties(
25+
(lib) => SuperuserPluginWindowsBindings(lib).is_elevated());
26+
@override
27+
bool get isSuperuser => onGettingProperties(
28+
(lib) => SuperuserPluginWindowsBindings(lib).is_admin_user());
2329

24-
throw UnsupportedError('Unknown platform: ${Platform.operatingSystem}');
25-
}());
26-
}
30+
@override
31+
String get whoAmI => onGettingProperties((lib) {
32+
final SuperuserPluginWindowsBindings binding =
33+
SuperuserPluginWindowsBindings(lib);
2734

28-
factory WindowsSuperuser() {
29-
_instance ??= WindowsSuperuser._();
35+
Pointer<Pointer<Char>> resultPtr = ffi.calloc<Pointer<Char>>();
3036

31-
return _instance!;
32-
}
37+
try {
38+
int errResult = binding.get_current_username(resultPtr);
3339

34-
@override
35-
bool get isActivated => _bindings.is_elevated();
40+
if (errResult != 0) {
41+
throw SuperuserProcessError(
42+
errResult, "Unable to extract current username.");
43+
}
3644

37-
@override
38-
bool get isSuperuser => _bindings.is_admin_user();
45+
Pointer<Char> result = resultPtr.value;
3946

40-
@override
41-
String get whoAmI =>
42-
_bindings.get_current_username().cast<ffi.Utf8>().toDartString();
47+
try {
48+
Pointer<ffi.Utf8> ctx = result.cast<ffi.Utf8>();
49+
50+
return ctx.toDartString();
51+
} finally {
52+
binding.flush_string(result);
53+
}
54+
} finally {
55+
ffi.calloc.free(resultPtr);
56+
}
57+
});
4358
}

superuser_plugin_windows/lib/superuser_plugin_windows_bindings_generated.dart

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,36 @@ final class SuperuserPluginWindowsBindings {
4646
late final _is_elevated = _is_elevatedPtr.asFunction<bool Function()>();
4747

4848
/// Obtain name of user.
49-
ffi.Pointer<ffi.Char> get_current_username() {
50-
return _get_current_username();
49+
int get_current_username(
50+
ffi.Pointer<ffi.Pointer<ffi.Char>> result,
51+
) {
52+
return _get_current_username(
53+
result,
54+
);
5155
}
5256

53-
late final _get_current_usernamePtr =
54-
_lookup<ffi.NativeFunction<ffi.Pointer<ffi.Char> Function()>>(
55-
'get_current_username');
56-
late final _get_current_username =
57-
_get_current_usernamePtr.asFunction<ffi.Pointer<ffi.Char> Function()>();
57+
late final _get_current_usernamePtr = _lookup<
58+
ffi
59+
.NativeFunction<DWORD Function(ffi.Pointer<ffi.Pointer<ffi.Char>>)>>(
60+
'get_current_username');
61+
late final _get_current_username = _get_current_usernamePtr
62+
.asFunction<int Function(ffi.Pointer<ffi.Pointer<ffi.Char>>)>();
63+
64+
/// Flush string from dynamic allocated function.
65+
void flush_string(
66+
ffi.Pointer<ffi.Char> str,
67+
) {
68+
return _flush_string(
69+
str,
70+
);
71+
}
72+
73+
late final _flush_stringPtr =
74+
_lookup<ffi.NativeFunction<ffi.Void Function(ffi.Pointer<ffi.Char>)>>(
75+
'flush_string');
76+
late final _flush_string =
77+
_flush_stringPtr.asFunction<void Function(ffi.Pointer<ffi.Char>)>();
5878
}
79+
80+
typedef DWORD = ffi.UnsignedLong;
81+
typedef DartDWORD = int;

superuser_plugin_windows/pubspec.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: superuser_plugin_windows
22
description: "Detect, verify user who execute Flutter program has superuser role in Windows"
3-
version: 0.1.0
3+
version: 1.0.0
44
homepage: https://github.com/rk0cc/superuser
55
repository: https://github.com/rk0cc/superuser/tree/main/superuser_plugin_windows
66
environment:
@@ -11,7 +11,7 @@ dependencies:
1111
flutter:
1212
sdk: flutter
1313
plugin_platform_interface: ^2.1.8
14-
superuser_interfaces: ^1.0.0
14+
superuser_interfaces: ^2.0.0
1515
dev_dependencies:
1616
ffigen: ^12.0.0
1717
flutter_lints: ^4.0.0

0 commit comments

Comments
 (0)