diff --git a/libbpf-tools/offcputime.c b/libbpf-tools/offcputime.c index 9ed73f690af..4d50be56f81 100644 --- a/libbpf-tools/offcputime.c +++ b/libbpf-tools/offcputime.c @@ -80,27 +80,6 @@ static const struct argp_option opts[] = { {}, }; -static int split_pidstr(char *s, char* delim, int max_split, pid_t *pids) -{ - char *pid; - int nr = 0; - - errno = 0; - pid = strtok(s, delim); - while (pid) { - if (nr >= max_split) - return -ENOBUFS; - - pids[nr++] = strtol(pid, NULL, 10); - if (errno) - return -errno; - - pid = strtok(NULL, delim); - } - - return 0; -} - static error_t parse_arg(int key, char *arg, struct argp_state *state) { static int pos_args; @@ -114,7 +93,8 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state) env.verbose = true; break; case 'p': - ret = split_pidstr(strdup(arg), ",", MAX_PID_NR, env.pids); + ret = split_convert(strdup(arg), ",", env.pids, sizeof(env.pids), + sizeof(pid_t), str_to_int); if (ret) { if (ret == -ENOBUFS) fprintf(stderr, "the number of pid is too big, please " @@ -126,7 +106,8 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state) } break; case 't': - ret = split_pidstr(strdup(arg), ",", MAX_TID_NR, env.tids); + ret = split_convert(strdup(arg), ",", env.tids, sizeof(env.tids), + sizeof(pid_t), str_to_int); if (ret) { if (ret == -ENOBUFS) fprintf(stderr, "the number of tid is too big, please " diff --git a/libbpf-tools/profile.c b/libbpf-tools/profile.c index 03f0ee46c79..b8315865609 100644 --- a/libbpf-tools/profile.c +++ b/libbpf-tools/profile.c @@ -132,27 +132,6 @@ struct syms_cache *syms_cache; struct syms *syms; static char syminfo[SYM_INFO_LEN]; -static int split_pidstr(char *s, char* sep, int max_split, pid_t *pids) -{ - char *pid; - int nr = 0; - - errno = 0; - pid = strtok(s, sep); - while (pid) { - if (nr >= max_split) - return -ENOBUFS; - - pids[nr++] = strtol(pid, NULL, 10); - if (errno) - return -errno; - - pid = strtok(NULL, ","); - } - - return 0; -} - static error_t parse_arg(int key, char *arg, struct argp_state *state) { static int pos_args; @@ -166,7 +145,8 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state) env.verbose = true; break; case 'p': - ret = split_pidstr(strdup(arg), ",", MAX_PID_NR, env.pids); + ret = split_convert(strdup(arg), ",", env.pids, sizeof(env.pids), + sizeof(pid_t), str_to_int); if (ret) { if (ret == -ENOBUFS) fprintf(stderr, "the number of pid is too big, please " @@ -178,7 +158,8 @@ static error_t parse_arg(int key, char *arg, struct argp_state *state) } break; case 'L': - ret = split_pidstr(strdup(arg), ",", MAX_TID_NR, env.tids); + ret = split_convert(strdup(arg), ",", env.tids, sizeof(env.tids), + sizeof(pid_t), str_to_int); if (ret) { if (ret == -ENOBUFS) fprintf(stderr, "the number of tid is too big, please " diff --git a/libbpf-tools/trace_helpers.c b/libbpf-tools/trace_helpers.c index 732627a2140..8ae3669d33e 100644 --- a/libbpf-tools/trace_helpers.c +++ b/libbpf-tools/trace_helpers.c @@ -1247,3 +1247,42 @@ bool probe_ringbuf() close(map_fd); return true; } + +int split_convert(char *s, const char* delim, void *elems, size_t elems_size, + size_t elem_size, convert_fn_t convert) +{ + char *token; + int ret; + char *pos = (char *)elems; + + if (!s || !delim || !elems) + return -EINVAL; + + errno = 0; + token = strtok(s, delim); + while (token) { + if (pos >= (char*)elems + elems_size) + return -ENOBUFS; + + ret = convert(token, pos); + if (ret) + return -ret; + + pos += elem_size; + token = strtok(NULL, delim); + } + + return 0; +} + +int str_to_int(const char *src, void *dest) +{ + *(int*)dest = strtol(src, NULL, 10); + return errno; +} + +int str_to_long(const char *src, void *dest) +{ + *(long*)dest = strtol(src, NULL, 10); + return errno; +} diff --git a/libbpf-tools/trace_helpers.h b/libbpf-tools/trace_helpers.h index 651cd107e91..582f19054f8 100644 --- a/libbpf-tools/trace_helpers.h +++ b/libbpf-tools/trace_helpers.h @@ -108,4 +108,16 @@ bool module_btf_exists(const char *mod); bool probe_tp_btf(const char *name); bool probe_ringbuf(); +typedef int (*convert_fn_t)(const char *src, void *dest); +int split_convert(char *s, const char* delim, void *elems, size_t elems_size, + size_t elem_size, convert_fn_t convert); +/* + * Implementations of convert_fn_t. + * This can be replaced with a user-defined callback function. + */ +/* converts a string to an integer */ +int str_to_int(const char *src, void *dest); +/* converts a string to a long integer */ +int str_to_long(const char *src, void *dest); + #endif /* __TRACE_HELPERS_H */