Merge branch 'MaikuZ/libgen' into 'master'
Implement libgen.h See merge request redox-os/relibc!175
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
sys_includes = []
|
||||
include_guard = "_LIBGEN_H"
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
|
||||
[enum]
|
||||
prefix_with_name = true
|
||||
@@ -0,0 +1,49 @@
|
||||
//! libgen implementation for Redox, following http://pubs.opengroup.org/onlinepubs/7908799/xsh/libgen.h.html
|
||||
|
||||
use core::ptr;
|
||||
|
||||
use platform::types::c_char;
|
||||
|
||||
use header::string::strlen;
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn basename(str: *mut c_char) -> *mut c_char {
|
||||
if str == ptr::null_mut() || strlen(str) == 0 {
|
||||
return ".\0".as_ptr() as *mut c_char;
|
||||
}
|
||||
let mut end = strlen(str) as isize - 1;
|
||||
while end >= 0 && *str.offset(end) == b'/' as c_char {
|
||||
end -= 1;
|
||||
}
|
||||
if end == -1 {
|
||||
return "/\0".as_ptr() as *mut c_char;
|
||||
}
|
||||
let mut begin = end;
|
||||
while begin >= 0 && *str.offset(begin) != b'/' as c_char {
|
||||
begin -= 1;
|
||||
}
|
||||
*str.offset(end + 1) = 0;
|
||||
return str.offset(begin + 1) as *mut c_char;
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn dirname(str: *mut c_char) -> *mut c_char {
|
||||
if str == ptr::null_mut() || strlen(str) == 0 {
|
||||
return ".\0".as_ptr() as *mut c_char;
|
||||
}
|
||||
let mut end = strlen(str) as isize - 1;
|
||||
while end > 0 && *str.offset(end) == b'/' as c_char {
|
||||
end -= 1;
|
||||
}
|
||||
while end >= 0 && *str.offset(end) != b'/' as c_char {
|
||||
end -= 1;
|
||||
}
|
||||
while end > 0 && *str.offset(end) == b'/' as c_char {
|
||||
end -= 1;
|
||||
}
|
||||
if end == -1 {
|
||||
return ".\0".as_ptr() as *mut c_char;
|
||||
}
|
||||
*str.offset(end + 1) = 0;
|
||||
return str;
|
||||
}
|
||||
@@ -12,6 +12,7 @@ pub mod getopt;
|
||||
pub mod grp;
|
||||
pub mod inttypes;
|
||||
pub mod limits;
|
||||
pub mod libgen;
|
||||
pub mod locale;
|
||||
pub mod netdb;
|
||||
pub mod netinet_in;
|
||||
|
||||
@@ -11,6 +11,7 @@ EXPECT_BINS=\
|
||||
fcntl/create \
|
||||
fcntl/fcntl \
|
||||
fnmatch \
|
||||
libgen \
|
||||
locale \
|
||||
math \
|
||||
netdb \
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
Testing libgen.h
|
||||
OK on basename(/usr/lib), expected: 'lib', got: 'lib'
|
||||
OK on basename(//usr//lib//), expected: 'lib', got: 'lib'
|
||||
OK on basename(/usr/), expected: 'usr', got: 'usr'
|
||||
OK on basename(), expected: '.', got: '.'
|
||||
OK on basename(/), expected: '/', got: '/'
|
||||
OK on basename(///), expected: '/', got: '/'
|
||||
OK on basename(NULL), expected: '.', got: '.'
|
||||
OK on dirname(/usr/lib), expected: '/usr', got: '/usr'
|
||||
OK on dirname(//usr//lib//), expected: '//usr', got: '//usr'
|
||||
OK on dirname(/usr), expected: '/', got: '/'
|
||||
OK on dirname(usr), expected: '.', got: '.'
|
||||
OK on dirname(/), expected: '/', got: '/'
|
||||
OK on dirname(///), expected: '/', got: '/'
|
||||
OK on dirname(.), expected: '.', got: '.'
|
||||
OK on dirname(..), expected: '.', got: '.'
|
||||
OK on dirname(), expected: '.', got: '.'
|
||||
OK on dirname(NULL), expected: '.', got: '.'
|
||||
@@ -0,0 +1,81 @@
|
||||
#include <libgen.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
typedef struct {
|
||||
char * in;
|
||||
char * expected_out;
|
||||
} test_case;
|
||||
|
||||
// API for basename and dirname allow the passed in string to
|
||||
// be modified. This means we have to pass a modifiable copy.
|
||||
char * get_mutable_string(char *str) {
|
||||
if (str == NULL)
|
||||
return NULL;
|
||||
char * copy = malloc(sizeof(char) * (strlen(str) + 1));
|
||||
copy = strcpy(copy, str);
|
||||
return copy;
|
||||
}
|
||||
|
||||
void test_basename() {
|
||||
test_case test_cases[] =
|
||||
{ {"/usr/lib", "lib"},
|
||||
{"//usr//lib//", "lib"},
|
||||
{"/usr/", "usr"},
|
||||
{"", "."},
|
||||
{"/", "/"},
|
||||
{"///","/"},
|
||||
{NULL, "."}
|
||||
};
|
||||
for (int i = 0;i < sizeof(test_cases)/sizeof(test_case);i++) {
|
||||
char * in = get_mutable_string(test_cases[i].in);
|
||||
char * out = basename(in);
|
||||
if (!out) {
|
||||
printf("Error on basename(%s), expected: '%s', got NULL\n", test_cases[i].in != 0 ? test_cases[i].in : "NULL", test_cases[i].expected_out);
|
||||
} else if (strcmp(out, test_cases[i].expected_out) != 0) {
|
||||
printf("Error on basename(%s), expected: '%s', got: '%s'\n", test_cases[i].in != 0 ? test_cases[i].in : "NULL", test_cases[i].expected_out, out);
|
||||
} else {
|
||||
printf("OK on basename(%s), expected: '%s', got: '%s'\n", test_cases[i].in != 0 ? test_cases[i].in : "NULL", test_cases[i].expected_out, out);
|
||||
}
|
||||
if (!in)
|
||||
free(in);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
void test_dirname() {
|
||||
test_case test_cases[] =
|
||||
{ {"/usr/lib", "/usr"},
|
||||
{"//usr//lib//", "//usr"},
|
||||
{"/usr", "/"},
|
||||
{"usr", "."},
|
||||
{"/", "/"},
|
||||
{"///","/"},
|
||||
{".", "."},
|
||||
{"..", "."},
|
||||
{"", "."},
|
||||
{NULL, "."}
|
||||
};
|
||||
for (int i = 0;i < sizeof(test_cases)/sizeof(test_case);i++) {
|
||||
char * in = get_mutable_string(test_cases[i].in);
|
||||
char * out = dirname(in);
|
||||
if (!out) {
|
||||
printf("Error on dirname(%s), expected: '%s', got NULL\n", test_cases[i].in != 0 ? test_cases[i].in : "NULL", test_cases[i].expected_out);
|
||||
} else if (strcmp(out, test_cases[i].expected_out) != 0) {
|
||||
printf("Error on dirname(%s), expected: '%s', got: '%s'\n", test_cases[i].in != 0 ? test_cases[i].in : "NULL", test_cases[i].expected_out, out);
|
||||
} else {
|
||||
printf("OK on dirname(%s), expected: '%s', got: '%s'\n", test_cases[i].in != 0 ? test_cases[i].in : "NULL", test_cases[i].expected_out, out);
|
||||
}
|
||||
if (!in)
|
||||
free(in);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int main() {
|
||||
printf("Testing libgen.h\n");
|
||||
test_basename();
|
||||
test_dirname();
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user