/** * strlcat - Append a length-limited, %NUL-terminated string to another * @dest: The string to be appended to * @src: The string to append to it * @count: The size of the destination buffer. */ size_t strlcat(char *dest, const char *src, size_t count) { size_t dsize = strlen(dest); size_t len = strlen(src); size_t res = dsize + len; DIE_IF(dsize >= count); dest += dsize; count -= dsize; if (len >= count) len = count - 1; memcpy(dest, src, len); dest[len] = 0; return res; }
/* Parse probepoint definition. */ static void parse_perf_probe_probepoint(char *arg, struct probe_point *pp) { char *ptr, *tmp; char c, nc = 0; /* * <Syntax> * perf probe [EVENT=]SRC[:LN|;PTN] * perf probe [EVENT=]FUNC[@SRC][+OFFS|%return|:LN|;PAT] * * TODO:Group name support */ ptr = strpbrk(arg, ";=@+%"); if (ptr && *ptr == '=') { /* Event name */ *ptr = '\0'; tmp = ptr + 1; ptr = strchr(arg, ':'); if (ptr) /* Group name is not supported yet. */ semantic_error("Group name is not supported yet."); if (!check_event_name(arg)) semantic_error("%s is bad for event name -it must " "follow C symbol-naming rule.", arg); pp->event = strdup(arg); arg = tmp; } ptr = strpbrk(arg, ";:+@%"); if (ptr) { nc = *ptr; *ptr++ = '\0'; } /* Check arg is function or file and copy it */ if (strchr(arg, '.')) /* File */ pp->file = strdup(arg); else /* Function */ pp->function = strdup(arg); DIE_IF(pp->file == NULL && pp->function == NULL); /* Parse other options */ while (ptr) { arg = ptr; c = nc; if (c == ';') { /* Lazy pattern must be the last part */ pp->lazy_line = strdup(arg); break; } ptr = strpbrk(arg, ";:+@%"); if (ptr) { nc = *ptr; *ptr++ = '\0'; } switch (c) { case ':': /* Line number */ pp->line = strtoul(arg, &tmp, 0); if (*tmp != '\0') semantic_error("There is non-digit char" " in line number."); break; case '+': /* Byte offset from a symbol */ pp->offset = strtoul(arg, &tmp, 0); if (*tmp != '\0') semantic_error("There is non-digit character" " in offset."); break; case '@': /* File name */ if (pp->file) semantic_error("SRC@SRC is not allowed."); pp->file = strdup(arg); DIE_IF(pp->file == NULL); break; case '%': /* Probe places */ if (strcmp(arg, "return") == 0) { pp->retprobe = 1; } else /* Others not supported yet */ semantic_error("%%%s is not supported.", arg); break; default: DIE_IF("Program has a bug."); break; } } /* Exclusion check */ if (pp->lazy_line && pp->line) semantic_error("Lazy pattern can't be used with line number."); if (pp->lazy_line && pp->offset) semantic_error("Lazy pattern can't be used with offset."); if (pp->line && pp->offset) semantic_error("Offset can't be used with line number."); if (!pp->line && !pp->lazy_line && pp->file && !pp->function) semantic_error("File always requires line number or " "lazy pattern."); if (pp->offset && !pp->function) semantic_error("Offset requires an entry function."); if (pp->retprobe && !pp->function) semantic_error("Return probe requires an entry function."); if ((pp->offset || pp->line || pp->lazy_line) && pp->retprobe) semantic_error("Offset/Line/Lazy pattern can't be used with " "return probe."); pr_debug("symbol:%s file:%s line:%d offset:%d return:%d lazy:%s\n", pp->function, pp->file, pp->line, pp->offset, pp->retprobe, pp->lazy_line); }