Skip to content

Commit

Permalink
Work on C side of capturing symlinks
Browse files Browse the repository at this point in the history
  • Loading branch information
charmoniumQ committed Jan 21, 2025
1 parent 7841783 commit fcf7b4a
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 44 deletions.
26 changes: 17 additions & 9 deletions cli-wrapper/macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,14 +174,26 @@ pub fn make_rust_op(input: TokenStream) -> TokenStream {
}

fn convert_bindgen_type(ty: &syn::Type) -> MacroResult<syn::Type> {
let ty_str = format!("Bindgen unsupported type: {:?}", ty);
let error = quote_spanned! {
ty.span() => compile_error!(#ty_str);
};
match ty {
// single pointers are treated as recorded as null-terminated byte-strings (as CString),
// double pointers are treated as null-terminated arrays of null-terminated byte-strings
// (as Vec<CString>).
syn::Type::Ptr(inner) => Ok(match inner.elem.as_ref() {
syn::Type::Ptr(_inner) => parse_quote!(::std::vec::Vec<::std::ffi::CString>),
_ => parse_quote!(::std::ffi::CString),
}),
syn::Type::Ptr(inner) => match inner.elem.as_ref() {
syn::Type::Ptr(_inner) => Ok(parse_quote!(::std::vec::Vec<::std::ffi::CString>)),
syn::Type::Path(path) => match path.path.segments.iter().last() {
None => Err(error.into()),
Some(last_path_seg) => match last_path_seg.ident.to_string().as_str() {
"c_char" => Ok(parse_quote!(::std::ffi::CString)),
"C_Path" => Ok(parse_quote!(*const C_Path)),
_ => Err(error.into()),
},
},
_ => Err(error.into()),
},
syn::Type::Array(inner) => {
let mut new = inner.clone();
new.elem = Box::new(convert_bindgen_type(&new.elem)?);
Expand All @@ -196,11 +208,7 @@ fn convert_bindgen_type(ty: &syn::Type) -> MacroResult<syn::Type> {
Ok(Type::Path(inner.clone()))
}
}
_ => Err(quote_spanned! {
ty.span() =>
compile_error!("Unable to convert bindgen type");
}
.into()),
_ => Err(error.into()),
}
}

Expand Down
23 changes: 17 additions & 6 deletions cli-wrapper/macros/src/pygen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,11 @@ fn basic_dataclass(name: String, pairs: &[(String, String)]) -> Dataclass {
}

fn convert_to_pytype(ty: &syn::Type) -> MacroResult<String> {
let msg = format!("Pygen unsupported type type: {:?}", ty);
let error = quote_spanned! {
ty.span() =>
compile_error!(#msg);
};
match ty {
syn::Type::Array(inner) => Ok(format!("list[{}]", convert_to_pytype(inner.elem.as_ref())?)),
syn::Type::Path(inner) => {
Expand Down Expand Up @@ -222,12 +227,18 @@ fn convert_to_pytype(ty: &syn::Type) -> MacroResult<String> {
}
}
})
}
_ => Err(quote_spanned! {
ty.span() =>
compile_error!("Unsupported type type");
}
.into()),
},
syn::Type::Ptr(inner) => match inner.elem.as_ref() {
syn::Type::Path(path) => match path.path.segments.iter().last() {
None => Err(error.into()),
Some(last_path_seg) => match last_path_seg.ident.to_string().as_str() {
"C_Path" => Ok("Path".to_owned()),
_ => Err(error.into()),
},
},
_ => Err(error.into()),
},
_ => Err(error.into()),
}
}

Expand Down
28 changes: 21 additions & 7 deletions libprobe/include/libprobe/prov_ops.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
struct SymlinkInfo;

/* TODO: rename this PathMetadata */
struct Path {
int32_t dirfd_minus_at_fdcwd;
const char* path; /* path valid if non-null */
Expand All @@ -10,15 +13,26 @@ struct Path {
size_t size;
bool stat_valid;
bool dirfd_valid;
const char* symlink_content;
struct Path* symlink_dst;
};

static const struct Path null_path = {
.dirfd_minus_at_fdcwd = -1,
.path = NULL,
.mode_and_type = -1,
.device_major = -1,
.device_minor = -1,
.inode = -1,
.mtime = {0},
.ctime = {0},
.size = 0,
.dirfd_valid = false,
.stat_valid = false,
.symlink_content = NULL,
.symlink_dst = NULL,
};

struct SymlinkInfo {
const Path src;
const char* content;
const Path dst;
}

static const struct Path null_path = {-1, NULL, -1, -1, -1, -1, {0}, {0}, 0, false, false};
/* We don't need to free paths since I switched to the Arena allocator */
/* static void free_path(struct Path path); */

Expand Down
6 changes: 0 additions & 6 deletions libprobe/src/global_state.c
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,6 @@ static int get_inodes_dirfd() {

static __thread struct ArenaDir __op_arena = { 0 };
static __thread struct ArenaDir __data_arena = { 0 };
static __thread struct ArenaDir __symlink_arena = { 0 };
static const size_t prov_log_arena_size = 64 * 1024;
static void init_log_arena() {
assert(!arena_is_initialized(&__op_arena));
Expand All @@ -220,7 +219,6 @@ static void init_log_arena() {
int thread_dirfd = mkdir_and_descend(get_epoch_dirfd(), NULL, my_gettid(), true, false);
EXPECT( == 0, arena_create(&__op_arena , thread_dirfd, "ops" , prov_log_arena_size));
EXPECT( == 0, arena_create(&__data_arena , thread_dirfd, "data" , prov_log_arena_size));
EXPECT( == 0, arena_create(&__symlink_arena, thread_dirfd, "symlinks", prov_log_arena_size));
}
static struct ArenaDir* get_op_arena() {
assert(arena_is_initialized(&__op_arena));
Expand All @@ -230,10 +228,6 @@ static struct ArenaDir* get_data_arena() {
assert(arena_is_initialized(&__data_arena));
return &__data_arena;
}
static struct ArenaDir* get_symlink_arena() {
assert(arena_is_initialized(&__symlink_arena));
return &__symlink_arena;
}

char* _DEFAULT_PATH = NULL;

Expand Down
30 changes: 14 additions & 16 deletions libprobe/src/prov_ops.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
static void link_deref(int dirfd, BORROWED struct Path* path);

static struct Path create_path_lazy(int dirfd, BORROWED const char* path, int flags) {
if (likely(prov_log_is_enabled())) {
struct Path ret = null_path;
Expand Down Expand Up @@ -31,8 +33,8 @@ static struct Path create_path_lazy(int dirfd, BORROWED const char* path, int fl
ret.ctime = statx_buf.stx_ctime;
ret.size = statx_buf.stx_size;
ret.stat_valid = true;
if (statx_buf.stx_type & S_IFMT == S_IFLNK) {
link_deref(dirfd, path, &ret);
if ((statx_buf.stx_mode & S_IFMT) == S_IFLNK) {
link_deref(dirfd, &ret);
}
} else {
DEBUG("Stat of %d,%s is not valid", dirfd, path);
Expand All @@ -44,26 +46,22 @@ static struct Path create_path_lazy(int dirfd, BORROWED const char* path, int fl
}
}

void link_deref(int dirfd, BORROWED const char* pathname, const Path* path) {
static void link_deref(int dirfd, BORROWED struct Path* path) {
/* Some magic symlinks under (for example) /proc and /sys
report 'st_size' as zero. In that case, take PATH_MAX as
a "good enough" estimate. */
size_t symlink_size = path->size == 0 ? PATH_MAX : path->size + 1;
char* referent_pathname = EXPECT_NONNULL(arena_calloc(get_data_arena(), symlink_size, 1));
ssize_t readlink_ret = unwrapped_readlinkat(dirfd, path, referent_pathname, symlink_size);
ssize_t symlink_size = path->size == 0 ? PATH_MAX : path->size + 1;
char* content = EXPECT_NONNULL(arena_calloc(get_data_arena(), symlink_size, 1));
ssize_t readlink_ret = unwrapped_readlinkat(dirfd, path->path, content, symlink_size);
assert(readlink_ret < symlink_size);
referent_pathname[readlink_ret] = '\0';
Path referent_path = create_path_lazy(dirfd, path, flags);
SymlinkInfo* info = EXPECT_NONNULL(arena_calloc(get_symlink_arena(), SymlinkInfo, 1));
/*
** TODO: this path gest copied twice; once in ops and once in symlinks
*/
info->src = path;
info->content = referent_pathname;
info->dst = referent_path;
content[readlink_ret] = '\0';
path->symlink_content = (const char*) content;
struct Path symlink_dst = create_path_lazy(dirfd, content, 0);
path->symlink_dst = EXPECT_NONNULL(arena_calloc(get_data_arena(), sizeof(struct Path), 1));
memcpy(path->symlink_dst, &symlink_dst, sizeof(struct Path));
}

void path_to_id_string(const struct Path* path, BORROWED char* string) {
static void path_to_id_string(const struct Path* path, BORROWED char* string) {
CHECK_SNPRINTF(
string,
PATH_MAX,
Expand Down

0 comments on commit fcf7b4a

Please sign in to comment.