Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/jenkins/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/cmake/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Rust 如何通过libc::getgroups为用户获取组?_Rust_Libc - Fatal编程技术网

Rust 如何通过libc::getgroups为用户获取组?

Rust 如何通过libc::getgroups为用户获取组?,rust,libc,Rust,Libc,这张照片 real user id 1000作为用户id 1000,作为用户组[],numgroups 9 我的假设是,它将显示9个组的向量。您需要通过添加虚拟元素而不仅仅是其容量来更改组的大小。大概是这样的: extern crate libc; fn example(guid: u32) { unsafe { let ruid = libc::getuid(); libc::seteuid(guid); let mut v = ve

这张照片

real user id 1000作为用户id 1000,作为用户组[],numgroups 9

我的假设是,它将显示9个组的向量。

您需要通过添加虚拟元素而不仅仅是其容量来更改
组的大小。大概是这样的:

extern crate libc;

fn example(guid: u32) {
    unsafe {
        let ruid = libc::getuid();
        libc::seteuid(guid);
        let mut v = vec![0; 0];
        let num_groups = libc::getgroups(0, v.as_mut_ptr());
        let mut groups = Vec::with_capacity(num_groups as usize);
        libc::getgroups(num_groups, groups.as_mut_ptr());
        println!(
            "real user id {} as user id {}, as user groups {:?}, numgroups {}",
            &ruid, &guid, &groups, &num_groups
        );
    }
}

您需要通过添加虚拟元素而不仅仅是其容量来更改组的大小。大概是这样的:

extern crate libc;

fn example(guid: u32) {
    unsafe {
        let ruid = libc::getuid();
        libc::seteuid(guid);
        let mut v = vec![0; 0];
        let num_groups = libc::getgroups(0, v.as_mut_ptr());
        let mut groups = Vec::with_capacity(num_groups as usize);
        libc::getgroups(num_groups, groups.as_mut_ptr());
        println!(
            "real user id {} as user id {}, as user groups {:?}, numgroups {}",
            &ruid, &guid, &groups, &num_groups
        );
    }
}
  • 您的代码都不会检查错误
    seteuid
    getgroups
    可以失败,但您的代码忽略了这种可能性。您正在尝试调试失败,但甚至没有花时间检查正在调用的函数是否成功

  • 在传递时要非常小心。
    v.as_mut_ptr()
    。空的
    Vec
    没有空指针。在这种情况下,这很好,因为手册页说它只关心计数

  • 在第一次呼叫和第二次呼叫之间,您无法处理组数大小发生变化的情况

这样,由于您只在
Vec
中存储
u32
,因此您可以通过相应地调整大小和容量来避免用伪值填充它:

unsafe {
    let ruid = libc::getuid();
    let guid = libc::getgid();
    let num_groups = libc::getgroups(0, ::std::ptr::null_mut());
    let mut groups = vec![0; num_groups as usize];
    libc::getgroups(num_groups, groups.as_mut_ptr());
    println!(
        "real user id {} as user id {}, as user groups {:?}, numgroups {}",
        &ruid, &guid, &groups, &num_groups
    );
}
extern板条箱libc;
#[导出(调试)]
结构信息{
guid:u32,
鲁伊德:u32,
组别:Vec,,
num_组:usize,
}
fn示例(guid:u32)->Info{
不安全{
设ruid=libc::getuid();
if-1==libc::seteuid(guid){
恐慌!(“塞特伊德”)
}
让mut groups=Vec::new();
让mut尝试=0;
环路{
让num_groups=libc::getgroups(groups.capacity()作为i32,groups.as_mut_ptr());
如果-1==num_组{
恐慌!(“getgroups”)
}
设num_groups=num_groups作为usize;
如果num_组=3{
恐慌!(“群体数量不稳定”)
}
}
}
}
fn main(){
println!(“{:?}”,示例(不安全的{libc::getuid()}));
}
然而,我不会重写所有这些,我会依赖现有的工作。提供了很好的包装:

extern crate libc;

#[derive(Debug)]
struct Info {
    guid: u32,
    ruid: u32,
    groups: Vec<u32>,
    num_groups: usize,
}

fn example(guid: u32) -> Info {
    unsafe {
        let ruid = libc::getuid();
        if -1 == libc::seteuid(guid) {
            panic!("seteuid")
        }

        let mut groups = Vec::new();
        let mut attempts = 0;
        loop {
            let num_groups = libc::getgroups(groups.capacity() as i32, groups.as_mut_ptr());
            if -1 == num_groups {
                panic!("getgroups")
            }

            let num_groups = num_groups as usize;

            if num_groups <= groups.capacity() {
                groups.set_len(num_groups);
                return Info {
                    guid,
                    ruid,
                    groups,
                    num_groups,
                };
            }

            groups.reserve_exact(num_groups);

            attempts += 1;
            if attempts >= 3 {
                panic!("Unstable amount of groups")
            }
        }
    }
}

fn main() {
    println!("{:?}", example(unsafe { libc::getuid() }));
}
extern板条箱尼克斯;
使用nix::unistd::{self,Uid};
使用std::u32;
fn示例(guid:Uid)->nix::Result{
设ruid=unistd::getuid();
让no_change=Uid::from_raw(u32::MAX);
unistd::setresuid(无更改、guid、无更改)?;
让groups=nix::unistd::getgroups()?;
普林顿(
“实际用户id{}作为用户id{},作为用户组{:?}”,
ruid、guid、组
);
好(())
}
fn main(){
println!(“{:?}”,示例(Uid::current());
}
  • 您的代码都不会检查错误
    seteuid
    getgroups
    可以失败,但您的代码忽略了这种可能性。您正在尝试调试失败,但甚至没有花时间检查正在调用的函数是否成功

  • 在传递时要非常小心。
    v.as_mut_ptr()
    。空的
    Vec
    没有空指针。在这种情况下,这很好,因为手册页说它只关心计数

  • 在第一次呼叫和第二次呼叫之间,您无法处理组数大小发生变化的情况

这样,由于您只在
Vec
中存储
u32
,因此您可以通过相应地调整大小和容量来避免用伪值填充它:

unsafe {
    let ruid = libc::getuid();
    let guid = libc::getgid();
    let num_groups = libc::getgroups(0, ::std::ptr::null_mut());
    let mut groups = vec![0; num_groups as usize];
    libc::getgroups(num_groups, groups.as_mut_ptr());
    println!(
        "real user id {} as user id {}, as user groups {:?}, numgroups {}",
        &ruid, &guid, &groups, &num_groups
    );
}
extern板条箱libc;
#[导出(调试)]
结构信息{
guid:u32,
鲁伊德:u32,
组别:Vec,,
num_组:usize,
}
fn示例(guid:u32)->Info{
不安全{
设ruid=libc::getuid();
if-1==libc::seteuid(guid){
恐慌!(“塞特伊德”)
}
让mut groups=Vec::new();
让mut尝试=0;
环路{
让num_groups=libc::getgroups(groups.capacity()作为i32,groups.as_mut_ptr());
如果-1==num_组{
恐慌!(“getgroups”)
}
设num_groups=num_groups作为usize;
如果num_组=3{
恐慌!(“群体数量不稳定”)
}
}
}
}
fn main(){
println!(“{:?}”,示例(不安全的{libc::getuid()}));
}
然而,我不会重写所有这些,我会依赖现有的工作。提供了很好的包装:

extern crate libc;

#[derive(Debug)]
struct Info {
    guid: u32,
    ruid: u32,
    groups: Vec<u32>,
    num_groups: usize,
}

fn example(guid: u32) -> Info {
    unsafe {
        let ruid = libc::getuid();
        if -1 == libc::seteuid(guid) {
            panic!("seteuid")
        }

        let mut groups = Vec::new();
        let mut attempts = 0;
        loop {
            let num_groups = libc::getgroups(groups.capacity() as i32, groups.as_mut_ptr());
            if -1 == num_groups {
                panic!("getgroups")
            }

            let num_groups = num_groups as usize;

            if num_groups <= groups.capacity() {
                groups.set_len(num_groups);
                return Info {
                    guid,
                    ruid,
                    groups,
                    num_groups,
                };
            }

            groups.reserve_exact(num_groups);

            attempts += 1;
            if attempts >= 3 {
                panic!("Unstable amount of groups")
            }
        }
    }
}

fn main() {
    println!("{:?}", example(unsafe { libc::getuid() }));
}
extern板条箱尼克斯;
使用nix::unistd::{self,Uid};
使用std::u32;
fn示例(guid:Uid)->nix::Result{
设ruid=unistd::getuid();
让no_change=Uid::from_raw(u32::MAX);
unistd::setresuid(无更改、guid、无更改)?;
让groups=nix::unistd::getgroups()?;
普林顿(
“实际用户id{}作为用户id{},作为用户组{:?}”,
ruid、guid、组
);
好(())
}
fn main(){
println!(“{:?}”,示例(Uid::current());
}

谢谢!。你能解释一下为什么
和_capacity
不起作用,即使在那之后我推送
元素吗?@user1685095一个C函数不会关心向量的容量或大小,也不会改变它们。因此,就向量而言,在调用
getgroups
之后,它仍然是空的。我的理解是,您可以将空指针传递给第一次调用
getgroups
@user1685095,将元素推到哪里?不是在你发布的代码中。@FlorianWeimer我看到了你最初的答案,并尝试了
,非常感谢!。你能解释一下为什么
和_capacity
不起作用,即使在那之后我推送
元素吗?@user1685095一个C函数不会关心向量的容量或大小,也不会改变它们。因此,就向量而言,在调用
getgroups
之后,它仍然是空的。我的理解是,您可以将一个空指针传递给第一次调用
getgroups
@user1685095,将