【发布时间】:2021-10-28 08:29:06
【问题描述】:
我需要在 Linux 机器上进行一些简单的文件操作,用于服务安装程序。 代码是 .NET 5.0。
我当前的版本使用Process.Start()执行shell命令来更改文件和目录的所有者并设置权限。
这很慢(我使用异步方法),尤其是与 Windows 等价物相比。
我看到可以从 .NET 调用的 libc 具有方法 chmod 和 chown,但是它需要 uid 和 gid 参数。我的应用程序不知道 id,至少不使用 shell。
到目前为止,我得到了这样的东西:
const string LIBC = "libc";
[DllImport(LIBC, SetLastError = true)]
private static extern int chmod(string path, uint mode);
[DllImport(LIBC, SetLastError = true)]
private static extern int chown(string path, int owner, int group);
那么...如何获得所需的这 2 个整数?
更新
为什么有人认为这个问题(特别是考虑到它的标题)是关于类似但不同事物的问题的重复。
我知道如何通过多种方式更改 Linux 文件的所有者和权限。最简单的方法是使用 Linux shell。最快最简单的方法是使用Mono.Posix.NETStandard 库,它在内部调用libc。
我的具体问题是它是如何制造的?它是如何工作的?
更具体地说:
这是getpwnam() 的 Linux 手册页:
https://man7.org/linux/man-pages/man3/getpwnam.3.html
如何使用 p/invoke 从 C# 调用它?我在许多示例中看到,当他们用string 替换char* 时,它以某种方式神奇地起作用。我创建了一个这样的结构:
public struct PASSWD {
public string pw_name; /* username */
public string pw_passwd; /* user password */
public int pw_uid; /* user ID */
public int pw_gid; /* group ID */
public string pw_gecos; /* user information */
public string pw_dir; /* home directory */
public string pw_shell; /* shell program */
};
...并尝试将其用作签名的out 参数。
我没有收到任何错误,但它不起作用。我得到的结构是空的。
因此,我们再次使用 Platform Invoke,在 C# 中,我们调用 libc,我们希望从结构中获取结果。据我用谷歌搜索 - 它不能用谷歌搜索。只有Mono 源代码,它使用实现我需要的外部模块。我怀疑他们这样做是出于性能原因,也 - 使用了一些特殊工具,因为在 cmets 中,代码是生成的。
我的问题又是,如何使用 Linux 手册页定义为 C# 创建适当的方法签名,以便能够从 getpwnam() 中提取这两个整数。
我也很好奇 .NET 本身是否已经存在类似的东西,但我想它不存在。
【问题讨论】:
-
同一个库有 getpwnam 和 getgrnam 函数,它们允许您获取给定名称的用户和组 ID。
-
我知道,它是
Mono,但我不想添加Mono依赖项。我检查了源代码,但这部分非常复杂。尤其是getpwnam,它依赖于除libc之外的其他原生库。 -
不确定你的意思,这些函数是标准 LibC 库的一部分,即使实现可能依赖于其他本机库 - 这不应该是你关心的问题。你只需 pinvoke 并调用它。 Mono 也与此无关。您可以使用 `Mono.Posix' nuget 包免费获取所有这些绑定(顺便说一下,它与 Mono 运行时没有任何关系),或者您可以自己重新实现它。
-
我只想实现 chown,我知道它在 Mono.Posix.NETStandard 中。好吧,我可能会使用它,但我只是好奇它是如何制作的。