Easier libc in Rust

The libc crate gives us access to the UNIX system calls. But calling these functions from Rust can be difficult. You will find yourself constantly converting between String/&str and char* and other C data types. Rust provides several wrappers that use idiomatic Rust data types and error handling. But they are sometimes hard to find. Here’s an index of some of the most commonly used libc calls and their higher level wrappers.


Use std::env::set_current_dir. Example:


Use std::fs::remove_file. Example:



Use std::fs::remove_dir. Example:

if let Err(error) = std::fs::remove_dir("a_dir") {
    println!("There was a problem: {}", error);


Use std::fs::rename.

if let Err(e) = std::fs::rename(
    "a_dir/new.txt") {
    println!("Failed to rename file: {}", e); 


Use std::env::current_dir. In the example below we try to convert the current directory name to a UTF-8 encoded &str:

if let Ok(path_buf) = std::env::current_dir() {
    if let Some(path_str) = path_buf.to_str() {
        println!("Current dir: {}", path_str);
    } else {
        println!("Could not convert path name to UTF-8.");
} else {
    println!("Could not get current directory.");


Use std::fs::metadata. UNIX specific data that is available from C’s struct stat can be accessed using the std::os::unix::fs::MetadataExt trait.

use std::os::unix::fs::MetadataExt;

fn main() {
    if let Ok(m) = std::fs::metadata("a_dir/file.txt") {
        println!("File size: {}", m.size());
        println!("Creation time: {}", m.ctime());
        println!("Access time: {}", m.atime());  
    } else {
        println!("Failed to get stat.");


The wrapper approach involves calling std::fs::set_permissions. But to construct a std::fs::Permissions using the UNIX mode flags you will need to bring the std::os::unix::prelude::PermissionsExt trait into scope.

use std::os::unix::prelude::PermissionsExt;

fn main() {
    //chmod to 666
    if let Err(e) = std::fs::set_permissions(
        std::fs::Permissions::from_mode(0o666)) {
        println!("Failed to chmod: {}", e);

You can also call chmod directly from libc crate. But the function is in a strange module.

extern crate libc;
use libc::funcs::posix88::stat_::chmod;
use libc::types::os::arch::posix88::mode_t;

fn easy_chmod(path: &str, mode: u64) -> bool  {
    if let Ok(c_str) = std::ffi::CString::new(path) {
        unsafe {
            let result = chmod(
                mode as mode_t);

            return result == 0;

    return false;

fn main() {
    if !easy_chmod("a_dir/file.txt", 0o666) {
        println!("Failed to chmod.");


Use std::fs::create_dir. I find this utility method useful.

fn make_dir(path: &str) -> std::io::Result<()> {
    let err = match std::fs::create_dir(path) {
        Ok(_) => return Ok(()),
        Err(e) => e

    match err.kind() {
        ErrorKind::AlreadyExists => return Ok(()),
        _ => {
            println!("Failed to create directory: {}", path);

            return Err(err);


Use std::env:var.

if let Ok(val) = std::env::var("HOME") {
    println!("Got variable: {}", val);
} else {
    println!("Failed to get env variable");


Use std:env:set_var.

std::env::set_var("GREET", "Hola");

Use std::fs::hard_link.

if let Err(e) = std::fs::hard_link(
    "a_dir/file.txt", "a_dir/another.txt") {
    println!("Failed to create hard link: {}", e);

Use std::os::unix::fs::symlink.

if let Err(e) = std::os::unix::fs::symlink(
    "a_dir/file.txt", "a_dir/another.txt") {
    println!("Failed to create soft link: {}", e);

One thought on “Easier libc in Rust

  1. This really helped me out! I really didn’t like having to use pointers and mark sections of code unsafe just to change the file permissions to executable. Thanks a ton!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s