首页 > 代码库 > 一次 Rust 和C语言的混搭

一次 Rust 和C语言的混搭

存在内存泄露

extern crate libc;

use libc::size_t;
use libc::{FILE,c_char};
use std::string;

#[repr(C)]
pub struct mntent {
    mnt_fsname :*mut c_char,   /* 挂载的文件系统的名字 */
    mnt_dir  :*mut c_char,     /* 挂载点 */
    mnt_type :*mut c_char,     /* 文件系统类型:ufs、nfs 等 */
    mnt_opts :*mut c_char,     /* 选项,以逗号为分隔符 */
    mnt_freq : size_t,         /* Dump 的频率(以天为单位) */
    mnt_passno :size_t,        /* fsck检查的次序 */
}

#[link(name = "diskstat", kind="static")]
extern "C" {

    fn getdisk() -> *const c_char;
    pub fn setmntent(filename : *const  c_char,
                        ttype : *const c_char  ) -> FILE;
    pub fn getmntent(filep :FILE) -> mntent;
    pub fn endmntent(filep: FILE) -> size_t;
}

fn main(){
    let mut mnt  = unsafe { ( setmntent ("/etc/mtab".to_c_str().as_ptr(), "r".to_c_str().as_ptr())) };
    let mut disk_info = unsafe {  string::raw::from_buf (getdisk() as *const u8 ) };
    println!("{}", disk_info);
}


<!-- lang: cpp -->

// gcc -c diskstat.c -o diskstat.o -fPIC
// ar -r libdiskstat.a diskstat.o

#include <stdio.h>  
#include <mntent.h>  
#include <string.h>  
#include <sys/vfs.h>  

static const unsigned long long G = 1024*1024*1024ULL;  
static const unsigned long long M = 1024*1024;  
static const unsigned long long K = 1024;  
static char str[20];  

char* kscale(unsigned long b, unsigned long bs)  
{  
    unsigned long long size = b * (unsigned long long)bs;  
    if (size > G)  
    {  
        sprintf(str, "%0.2f GB", size/(G*1.0));  
        return str;  
    }  
    else if (size > M)  
    {  
        sprintf(str, "%0.2f MB", size/(1.0*M));  
        return str;  
    }  
    else if (size > K)  
    {  
        sprintf(str, "%0.2f K", size/(1.0*K));  
        return str;  
    }  
    else  
    {  
        sprintf(str, "%0.2f B", size*1.0);  
        return str;  
    }  
}

char* getdisk()  
{  
    FILE* mount_table;  
    struct mntent *mount_entry;  
    struct statfs s;  
    unsigned long blocks_used;  
    unsigned blocks_percent_used;  
    const char *disp_units_hdr = NULL;  
    mount_table = NULL;  
    mount_table = setmntent("/etc/mtab", "r");  
    if (!mount_table)  
    {  
        fprintf(stderr, "set mount entry error\n");  
        return -1;  
    } 

    disp_units_hdr = "     Size";  
    //printf("Filesystem           %-15sUsed Available %s Mounted on\n",  
    //        disp_units_hdr, "Use%");  


    char *disk_info = (char *)malloc(10000*sizeof(char));
    strcpy(disk_info, "["); //a
    // *disk_info = "[" ;
    char *z = (char *)malloc(1000*sizeof(char));
    while (1) {  
        const char *device;  
        const char *mount_point;  
        const char *fs_type;
        if (mount_table) {  
            mount_entry = getmntent(mount_table);  
            if ( !mount_entry ) {  
                endmntent(mount_table);  
                break;  
            }  
        }   
        else  
            continue;  
        device = mount_entry->mnt_fsname;  
        mount_point = mount_entry->mnt_dir;  
        fs_type = mount_entry->mnt_type;
        // fprintf(stderr, "error mount info: device=%s mountpoint=%s\n", device, mount_point);  

        if (statfs(mount_point, &s) != 0)   
        {  
            fprintf(stderr, "statfs failed!\n");      
            continue;  
        }

        if ((s.f_blocks > 0) || !mount_table )   
        {  
            blocks_used = s.f_blocks - s.f_bfree;  
            blocks_percent_used = 0;  
            if (blocks_used + s.f_bavail)   
            {  
                blocks_percent_used = (blocks_used * 100ULL  
                        + (blocks_used + s.f_bavail)/2  
                        ) / (blocks_used + s.f_bavail);  
            }  

            if (strcmp(device, "rootfs") == 0)  
                continue;  
            // if (printf("hello dksks \n%-20s" + 1, device) > 20)  
            //        printf("\n%-20s", "");  

            char s1[20];  
            char s2[20];  
            char s3[20];  
            strcpy(s1, kscale(s.f_blocks, s.f_bsize));  
            strcpy(s2, kscale(s.f_blocks - s.f_bfree, s.f_bsize));  
            strcpy(s3, kscale(s.f_bavail, s.f_bsize));  
            sprintf (z,  "{\"device\":\"%s\",\"fs_type\":\"%s\",\"mount_point\":\"%s\",\"size\":\"%s\",\"used\":%s,\"available\":\"%s\",\"use_percent\":\"%3u%%\"},",

                    device,
                    fs_type,
                    mount_point,
                    s1,
                    s2,
                    s3,
                    blocks_percent_used
             ); 
            strncat(disk_info,z , 1000);

        } 

    }
    strncat(disk_info, "]", 1);
    return disk_info;
}

一次 Rust 和C语言的混搭