probe-event.c (7ae383be81781c5e1347f71c3eb0d53ce5188200) | probe-event.c (ae2cb1ac60758e99cec15e9edd68e0d22bfd310e) |
---|---|
1/* 2 * probe-event.c : perf-probe definition to probe_events format converter 3 * 4 * Written by Masami Hiramatsu <mhiramat@redhat.com> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or --- 1063 unchanged lines hidden (view full) --- 1072} 1073 1074/* Parse probepoint definition. */ 1075static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev) 1076{ 1077 struct perf_probe_point *pp = &pev->point; 1078 char *ptr, *tmp; 1079 char c, nc = 0; | 1/* 2 * probe-event.c : perf-probe definition to probe_events format converter 3 * 4 * Written by Masami Hiramatsu <mhiramat@redhat.com> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or --- 1063 unchanged lines hidden (view full) --- 1072} 1073 1074/* Parse probepoint definition. */ 1075static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev) 1076{ 1077 struct perf_probe_point *pp = &pev->point; 1078 char *ptr, *tmp; 1079 char c, nc = 0; |
1080 bool file_spec = false; |
|
1080 /* 1081 * <Syntax> 1082 * perf probe [EVENT=]SRC[:LN|;PTN] 1083 * perf probe [EVENT=]FUNC[@SRC][+OFFS|%return|:LN|;PAT] 1084 * 1085 * TODO:Group name support 1086 */ | 1081 /* 1082 * <Syntax> 1083 * perf probe [EVENT=]SRC[:LN|;PTN] 1084 * perf probe [EVENT=]FUNC[@SRC][+OFFS|%return|:LN|;PAT] 1085 * 1086 * TODO:Group name support 1087 */ |
1087 if (!arg) 1088 return -EINVAL; | |
1089 1090 ptr = strpbrk(arg, ";=@+%"); 1091 if (ptr && *ptr == '=') { /* Event name */ 1092 *ptr = '\0'; 1093 tmp = ptr + 1; 1094 if (strchr(arg, ':')) { 1095 semantic_error("Group name is not supported yet.\n"); 1096 return -ENOTSUP; --- 5 unchanged lines hidden (view full) --- 1102 } 1103 pev->event = strdup(arg); 1104 if (pev->event == NULL) 1105 return -ENOMEM; 1106 pev->group = NULL; 1107 arg = tmp; 1108 } 1109 | 1088 1089 ptr = strpbrk(arg, ";=@+%"); 1090 if (ptr && *ptr == '=') { /* Event name */ 1091 *ptr = '\0'; 1092 tmp = ptr + 1; 1093 if (strchr(arg, ':')) { 1094 semantic_error("Group name is not supported yet.\n"); 1095 return -ENOTSUP; --- 5 unchanged lines hidden (view full) --- 1101 } 1102 pev->event = strdup(arg); 1103 if (pev->event == NULL) 1104 return -ENOMEM; 1105 pev->group = NULL; 1106 arg = tmp; 1107 } 1108 |
1109 /* 1110 * Check arg is function or file name and copy it. 1111 * 1112 * We consider arg to be a file spec if and only if it satisfies 1113 * all of the below criteria:: 1114 * - it does not include any of "+@%", 1115 * - it includes one of ":;", and 1116 * - it has a period '.' in the name. 1117 * 1118 * Otherwise, we consider arg to be a function specification. 1119 */ 1120 if (!strpbrk(arg, "+@%") && (ptr = strpbrk(arg, ";:")) != NULL) { 1121 /* This is a file spec if it includes a '.' before ; or : */ 1122 if (memchr(arg, '.', ptr - arg)) 1123 file_spec = true; 1124 } 1125 |
|
1110 ptr = strpbrk(arg, ";:+@%"); 1111 if (ptr) { 1112 nc = *ptr; 1113 *ptr++ = '\0'; 1114 } 1115 1116 tmp = strdup(arg); 1117 if (tmp == NULL) 1118 return -ENOMEM; 1119 | 1126 ptr = strpbrk(arg, ";:+@%"); 1127 if (ptr) { 1128 nc = *ptr; 1129 *ptr++ = '\0'; 1130 } 1131 1132 tmp = strdup(arg); 1133 if (tmp == NULL) 1134 return -ENOMEM; 1135 |
1120 /* Check arg is function or file and copy it */ 1121 if (strchr(tmp, '.')) /* File */ | 1136 if (file_spec) |
1122 pp->file = tmp; | 1137 pp->file = tmp; |
1123 else /* Function */ | 1138 else |
1124 pp->function = tmp; 1125 1126 /* Parse other options */ 1127 while (ptr) { 1128 arg = ptr; 1129 c = nc; 1130 if (c == ';') { /* Lazy pattern must be the last part */ 1131 pp->lazy_line = strdup(arg); --- 994 unchanged lines hidden (view full) --- 2126 pr_info(" %s", buf); 2127 } 2128 } 2129 pr_info(")\n"); 2130 free(place); 2131 return ret; 2132} 2133 | 1139 pp->function = tmp; 1140 1141 /* Parse other options */ 1142 while (ptr) { 1143 arg = ptr; 1144 c = nc; 1145 if (c == ';') { /* Lazy pattern must be the last part */ 1146 pp->lazy_line = strdup(arg); --- 994 unchanged lines hidden (view full) --- 2141 pr_info(" %s", buf); 2142 } 2143 } 2144 pr_info(")\n"); 2145 free(place); 2146 return ret; 2147} 2148 |
2134static int __show_perf_probe_events(int fd, bool is_kprobe) | 2149static bool filter_probe_trace_event(struct probe_trace_event *tev, 2150 struct strfilter *filter) |
2135{ | 2151{ |
2152 char tmp[128]; 2153 2154 /* At first, check the event name itself */ 2155 if (strfilter__compare(filter, tev->event)) 2156 return true; 2157 2158 /* Next, check the combination of name and group */ 2159 if (e_snprintf(tmp, 128, "%s:%s", tev->group, tev->event) < 0) 2160 return false; 2161 return strfilter__compare(filter, tmp); 2162} 2163 2164static int __show_perf_probe_events(int fd, bool is_kprobe, 2165 struct strfilter *filter) 2166{ |
|
2136 int ret = 0; 2137 struct probe_trace_event tev; 2138 struct perf_probe_event pev; 2139 struct strlist *rawlist; 2140 struct str_node *ent; 2141 2142 memset(&tev, 0, sizeof(tev)); 2143 memset(&pev, 0, sizeof(pev)); 2144 2145 rawlist = get_probe_trace_command_rawlist(fd); 2146 if (!rawlist) 2147 return -ENOMEM; 2148 2149 strlist__for_each(ent, rawlist) { 2150 ret = parse_probe_trace_command(ent->s, &tev); 2151 if (ret >= 0) { | 2167 int ret = 0; 2168 struct probe_trace_event tev; 2169 struct perf_probe_event pev; 2170 struct strlist *rawlist; 2171 struct str_node *ent; 2172 2173 memset(&tev, 0, sizeof(tev)); 2174 memset(&pev, 0, sizeof(pev)); 2175 2176 rawlist = get_probe_trace_command_rawlist(fd); 2177 if (!rawlist) 2178 return -ENOMEM; 2179 2180 strlist__for_each(ent, rawlist) { 2181 ret = parse_probe_trace_command(ent->s, &tev); 2182 if (ret >= 0) { |
2183 if (!filter_probe_trace_event(&tev, filter)) 2184 goto next; |
|
2152 ret = convert_to_perf_probe_event(&tev, &pev, 2153 is_kprobe); 2154 if (ret >= 0) 2155 ret = show_perf_probe_event(&pev, 2156 tev.point.module); 2157 } | 2185 ret = convert_to_perf_probe_event(&tev, &pev, 2186 is_kprobe); 2187 if (ret >= 0) 2188 ret = show_perf_probe_event(&pev, 2189 tev.point.module); 2190 } |
2191next: |
|
2158 clear_perf_probe_event(&pev); 2159 clear_probe_trace_event(&tev); 2160 if (ret < 0) 2161 break; 2162 } 2163 strlist__delete(rawlist); 2164 2165 return ret; 2166} 2167 2168/* List up current perf-probe events */ | 2192 clear_perf_probe_event(&pev); 2193 clear_probe_trace_event(&tev); 2194 if (ret < 0) 2195 break; 2196 } 2197 strlist__delete(rawlist); 2198 2199 return ret; 2200} 2201 2202/* List up current perf-probe events */ |
2169int show_perf_probe_events(void) | 2203int show_perf_probe_events(struct strfilter *filter) |
2170{ 2171 int kp_fd, up_fd, ret; 2172 2173 setup_pager(); 2174 2175 ret = init_symbol_maps(false); 2176 if (ret < 0) 2177 return ret; 2178 2179 kp_fd = open_kprobe_events(false); 2180 if (kp_fd >= 0) { | 2204{ 2205 int kp_fd, up_fd, ret; 2206 2207 setup_pager(); 2208 2209 ret = init_symbol_maps(false); 2210 if (ret < 0) 2211 return ret; 2212 2213 kp_fd = open_kprobe_events(false); 2214 if (kp_fd >= 0) { |
2181 ret = __show_perf_probe_events(kp_fd, true); | 2215 ret = __show_perf_probe_events(kp_fd, true, filter); |
2182 close(kp_fd); 2183 if (ret < 0) 2184 goto out; 2185 } 2186 2187 up_fd = open_uprobe_events(false); 2188 if (kp_fd < 0 && up_fd < 0) { 2189 print_both_open_warning(kp_fd, up_fd); 2190 ret = kp_fd; 2191 goto out; 2192 } 2193 2194 if (up_fd >= 0) { | 2216 close(kp_fd); 2217 if (ret < 0) 2218 goto out; 2219 } 2220 2221 up_fd = open_uprobe_events(false); 2222 if (kp_fd < 0 && up_fd < 0) { 2223 print_both_open_warning(kp_fd, up_fd); 2224 ret = kp_fd; 2225 goto out; 2226 } 2227 2228 if (up_fd >= 0) { |
2195 ret = __show_perf_probe_events(up_fd, false); | 2229 ret = __show_perf_probe_events(up_fd, false, filter); |
2196 close(up_fd); 2197 } 2198out: 2199 exit_symbol_maps(); 2200 return ret; 2201} 2202 2203/* Get current perf-probe event names */ --- 58 unchanged lines hidden (view full) --- 2262 return ret; 2263} 2264 2265static int get_new_event_name(char *buf, size_t len, const char *base, 2266 struct strlist *namelist, bool allow_suffix) 2267{ 2268 int i, ret; 2269 | 2230 close(up_fd); 2231 } 2232out: 2233 exit_symbol_maps(); 2234 return ret; 2235} 2236 2237/* Get current perf-probe event names */ --- 58 unchanged lines hidden (view full) --- 2296 return ret; 2297} 2298 2299static int get_new_event_name(char *buf, size_t len, const char *base, 2300 struct strlist *namelist, bool allow_suffix) 2301{ 2302 int i, ret; 2303 |
2304 if (*base == '.') 2305 base++; 2306 |
|
2270 /* Try no suffix */ 2271 ret = e_snprintf(buf, len, "%s", base); 2272 if (ret < 0) { 2273 pr_debug("snprintf() failed: %d\n", ret); 2274 return ret; 2275 } 2276 if (!strlist__has_entry(namelist, buf)) 2277 return 0; --- 64 unchanged lines hidden (view full) --- 2342 print_open_warning(fd, !pev->uprobes); 2343 return fd; 2344 } 2345 2346 /* Get current event names */ 2347 namelist = get_probe_trace_event_names(fd, false); 2348 if (!namelist) { 2349 pr_debug("Failed to get current event list.\n"); | 2307 /* Try no suffix */ 2308 ret = e_snprintf(buf, len, "%s", base); 2309 if (ret < 0) { 2310 pr_debug("snprintf() failed: %d\n", ret); 2311 return ret; 2312 } 2313 if (!strlist__has_entry(namelist, buf)) 2314 return 0; --- 64 unchanged lines hidden (view full) --- 2379 print_open_warning(fd, !pev->uprobes); 2380 return fd; 2381 } 2382 2383 /* Get current event names */ 2384 namelist = get_probe_trace_event_names(fd, false); 2385 if (!namelist) { 2386 pr_debug("Failed to get current event list.\n"); |
2350 return -EIO; | 2387 ret = -ENOMEM; 2388 goto close_out; |
2351 } 2352 /* Get kprobe blacklist if exists */ 2353 if (!pev->uprobes) { 2354 ret = kprobe_blacklist__load(&blacklist); 2355 if (ret < 0) 2356 pr_debug("No kprobe blacklist support, ignored\n"); 2357 } 2358 --- 66 unchanged lines hidden (view full) --- 2425 /* Show how to use the event. */ 2426 pr_info("\nYou can now use it in all perf tools, such as:\n\n"); 2427 pr_info("\tperf record -e %s:%s -aR sleep 1\n\n", tev->group, 2428 tev->event); 2429 } 2430 2431 kprobe_blacklist__delete(&blacklist); 2432 strlist__delete(namelist); | 2389 } 2390 /* Get kprobe blacklist if exists */ 2391 if (!pev->uprobes) { 2392 ret = kprobe_blacklist__load(&blacklist); 2393 if (ret < 0) 2394 pr_debug("No kprobe blacklist support, ignored\n"); 2395 } 2396 --- 66 unchanged lines hidden (view full) --- 2463 /* Show how to use the event. */ 2464 pr_info("\nYou can now use it in all perf tools, such as:\n\n"); 2465 pr_info("\tperf record -e %s:%s -aR sleep 1\n\n", tev->group, 2466 tev->event); 2467 } 2468 2469 kprobe_blacklist__delete(&blacklist); 2470 strlist__delete(namelist); |
2471close_out: |
|
2433 close(fd); 2434 return ret; 2435} 2436 2437static int find_probe_functions(struct map *map, char *name) 2438{ 2439 int found = 0; 2440 struct symbol *sym; 2441 2442 map__for_each_symbol_by_name(map, name, sym) { 2443 found++; 2444 } 2445 2446 return found; 2447} 2448 2449#define strdup_or_goto(str, label) \ 2450 ({ char *__p = strdup(str); if (!__p) goto label; __p; }) 2451 | 2472 close(fd); 2473 return ret; 2474} 2475 2476static int find_probe_functions(struct map *map, char *name) 2477{ 2478 int found = 0; 2479 struct symbol *sym; 2480 2481 map__for_each_symbol_by_name(map, name, sym) { 2482 found++; 2483 } 2484 2485 return found; 2486} 2487 2488#define strdup_or_goto(str, label) \ 2489 ({ char *__p = strdup(str); if (!__p) goto label; __p; }) 2490 |
2491void __weak arch__fix_tev_from_maps(struct perf_probe_event *pev __maybe_unused, 2492 struct probe_trace_event *tev __maybe_unused, 2493 struct map *map __maybe_unused) { } 2494 |
|
2452/* 2453 * Find probe function addresses from map. 2454 * Return an error or the number of found probe_trace_event 2455 */ 2456static int find_probe_trace_events_from_map(struct perf_probe_event *pev, 2457 struct probe_trace_event **tevs, 2458 int max_tevs, const char *target) 2459{ --- 90 unchanged lines hidden (view full) --- 2550 2551 tev->args[i].value = strdup_or_goto(pev->args[i].var, 2552 nomem_out); 2553 if (pev->args[i].type) 2554 tev->args[i].type = 2555 strdup_or_goto(pev->args[i].type, 2556 nomem_out); 2557 } | 2495/* 2496 * Find probe function addresses from map. 2497 * Return an error or the number of found probe_trace_event 2498 */ 2499static int find_probe_trace_events_from_map(struct perf_probe_event *pev, 2500 struct probe_trace_event **tevs, 2501 int max_tevs, const char *target) 2502{ --- 90 unchanged lines hidden (view full) --- 2593 2594 tev->args[i].value = strdup_or_goto(pev->args[i].var, 2595 nomem_out); 2596 if (pev->args[i].type) 2597 tev->args[i].type = 2598 strdup_or_goto(pev->args[i].type, 2599 nomem_out); 2600 } |
2601 arch__fix_tev_from_maps(pev, tev, map); |
|
2558 } 2559 2560out: 2561 put_target_map(map, pev->uprobes); 2562 return ret; 2563 2564nomem_out: 2565 ret = -ENOMEM; 2566err_out: 2567 clear_probe_trace_events(*tevs, num_matched_functions); 2568 zfree(tevs); 2569 goto out; 2570} 2571 | 2602 } 2603 2604out: 2605 put_target_map(map, pev->uprobes); 2606 return ret; 2607 2608nomem_out: 2609 ret = -ENOMEM; 2610err_out: 2611 clear_probe_trace_events(*tevs, num_matched_functions); 2612 zfree(tevs); 2613 goto out; 2614} 2615 |
2616bool __weak arch__prefers_symtab(void) { return false; } 2617 |
|
2572static int convert_to_probe_trace_events(struct perf_probe_event *pev, 2573 struct probe_trace_event **tevs, 2574 int max_tevs, const char *target) 2575{ 2576 int ret; 2577 2578 if (pev->uprobes && !pev->group) { 2579 /* Replace group name if not given */ 2580 ret = convert_exec_to_group(target, &pev->group); 2581 if (ret != 0) { 2582 pr_warning("Failed to make a group name.\n"); 2583 return ret; 2584 } 2585 } 2586 | 2618static int convert_to_probe_trace_events(struct perf_probe_event *pev, 2619 struct probe_trace_event **tevs, 2620 int max_tevs, const char *target) 2621{ 2622 int ret; 2623 2624 if (pev->uprobes && !pev->group) { 2625 /* Replace group name if not given */ 2626 ret = convert_exec_to_group(target, &pev->group); 2627 if (ret != 0) { 2628 pr_warning("Failed to make a group name.\n"); 2629 return ret; 2630 } 2631 } 2632 |
2633 if (arch__prefers_symtab() && !perf_probe_event_need_dwarf(pev)) { 2634 ret = find_probe_trace_events_from_map(pev, tevs, max_tevs, target); 2635 if (ret > 0) 2636 return ret; /* Found in symbol table */ 2637 } 2638 |
|
2587 /* Convert perf_probe_event with debuginfo */ 2588 ret = try_to_find_probe_trace_events(pev, tevs, max_tevs, target); 2589 if (ret != 0) 2590 return ret; /* Found in debuginfo or got an error */ 2591 2592 return find_probe_trace_events_from_map(pev, tevs, max_tevs, target); 2593} 2594 --- 84 unchanged lines hidden (view full) --- 2679 pr_info("Removed event: %s\n", ent->s); 2680 return 0; 2681error: 2682 pr_warning("Failed to delete event: %s\n", 2683 strerror_r(-ret, buf, sizeof(buf))); 2684 return ret; 2685} 2686 | 2639 /* Convert perf_probe_event with debuginfo */ 2640 ret = try_to_find_probe_trace_events(pev, tevs, max_tevs, target); 2641 if (ret != 0) 2642 return ret; /* Found in debuginfo or got an error */ 2643 2644 return find_probe_trace_events_from_map(pev, tevs, max_tevs, target); 2645} 2646 --- 84 unchanged lines hidden (view full) --- 2731 pr_info("Removed event: %s\n", ent->s); 2732 return 0; 2733error: 2734 pr_warning("Failed to delete event: %s\n", 2735 strerror_r(-ret, buf, sizeof(buf))); 2736 return ret; 2737} 2738 |
2687static int del_trace_probe_event(int fd, const char *buf, 2688 struct strlist *namelist) | 2739static int del_trace_probe_events(int fd, struct strfilter *filter, 2740 struct strlist *namelist) |
2689{ | 2741{ |
2690 struct str_node *ent, *n; 2691 int ret = -1; | 2742 struct str_node *ent; 2743 const char *p; 2744 int ret = -ENOENT; |
2692 | 2745 |
2693 if (strpbrk(buf, "*?")) { /* Glob-exp */ 2694 strlist__for_each_safe(ent, n, namelist) 2695 if (strglobmatch(ent->s, buf)) { 2696 ret = __del_trace_probe_event(fd, ent); 2697 if (ret < 0) 2698 break; 2699 strlist__remove(namelist, ent); 2700 } 2701 } else { 2702 ent = strlist__find(namelist, buf); 2703 if (ent) { | 2746 if (!namelist) 2747 return -ENOENT; 2748 2749 strlist__for_each(ent, namelist) { 2750 p = strchr(ent->s, ':'); 2751 if ((p && strfilter__compare(filter, p + 1)) || 2752 strfilter__compare(filter, ent->s)) { |
2704 ret = __del_trace_probe_event(fd, ent); | 2753 ret = __del_trace_probe_event(fd, ent); |
2705 if (ret >= 0) 2706 strlist__remove(namelist, ent); | 2754 if (ret < 0) 2755 break; |
2707 } 2708 } 2709 2710 return ret; 2711} 2712 | 2756 } 2757 } 2758 2759 return ret; 2760} 2761 |
2713int del_perf_probe_events(struct strlist *dellist) | 2762int del_perf_probe_events(struct strfilter *filter) |
2714{ | 2763{ |
2715 int ret = -1, ufd = -1, kfd = -1; 2716 char buf[128]; 2717 const char *group, *event; 2718 char *p, *str; 2719 struct str_node *ent; | 2764 int ret, ret2, ufd = -1, kfd = -1; |
2720 struct strlist *namelist = NULL, *unamelist = NULL; | 2765 struct strlist *namelist = NULL, *unamelist = NULL; |
2766 char *str = strfilter__string(filter); |
|
2721 | 2767 |
2768 if (!str) 2769 return -EINVAL; 2770 2771 pr_debug("Delete filter: \'%s\'\n", str); 2772 |
|
2722 /* Get current event names */ 2723 kfd = open_kprobe_events(true); 2724 if (kfd >= 0) 2725 namelist = get_probe_trace_event_names(kfd, true); 2726 2727 ufd = open_uprobe_events(true); 2728 if (ufd >= 0) 2729 unamelist = get_probe_trace_event_names(ufd, true); 2730 2731 if (kfd < 0 && ufd < 0) { 2732 print_both_open_warning(kfd, ufd); | 2773 /* Get current event names */ 2774 kfd = open_kprobe_events(true); 2775 if (kfd >= 0) 2776 namelist = get_probe_trace_event_names(kfd, true); 2777 2778 ufd = open_uprobe_events(true); 2779 if (ufd >= 0) 2780 unamelist = get_probe_trace_event_names(ufd, true); 2781 2782 if (kfd < 0 && ufd < 0) { 2783 print_both_open_warning(kfd, ufd); |
2784 ret = kfd; |
|
2733 goto error; 2734 } 2735 | 2785 goto error; 2786 } 2787 |
2736 if (namelist == NULL && unamelist == NULL) | 2788 ret = del_trace_probe_events(kfd, filter, namelist); 2789 if (ret < 0 && ret != -ENOENT) |
2737 goto error; 2738 | 2790 goto error; 2791 |
2739 strlist__for_each(ent, dellist) { 2740 str = strdup(ent->s); 2741 if (str == NULL) { 2742 ret = -ENOMEM; 2743 goto error; 2744 } 2745 pr_debug("Parsing: %s\n", str); 2746 p = strchr(str, ':'); 2747 if (p) { 2748 group = str; 2749 *p = '\0'; 2750 event = p + 1; 2751 } else { 2752 group = "*"; 2753 event = str; 2754 } 2755 2756 ret = e_snprintf(buf, 128, "%s:%s", group, event); 2757 if (ret < 0) { 2758 pr_err("Failed to copy event."); 2759 free(str); 2760 goto error; 2761 } 2762 2763 pr_debug("Group: %s, Event: %s\n", group, event); 2764 2765 if (namelist) 2766 ret = del_trace_probe_event(kfd, buf, namelist); 2767 2768 if (unamelist && ret != 0) 2769 ret = del_trace_probe_event(ufd, buf, unamelist); 2770 2771 if (ret != 0) 2772 pr_info("Info: Event \"%s\" does not exist.\n", buf); 2773 2774 free(str); | 2792 ret2 = del_trace_probe_events(ufd, filter, unamelist); 2793 if (ret2 < 0 && ret2 != -ENOENT) 2794 ret = ret2; 2795 else if (ret == -ENOENT && ret2 == -ENOENT) { 2796 pr_debug("\"%s\" does not hit any event.\n", str); 2797 /* Note that this is silently ignored */ 2798 ret = 0; |
2775 } 2776 2777error: 2778 if (kfd >= 0) { 2779 strlist__delete(namelist); 2780 close(kfd); 2781 } 2782 2783 if (ufd >= 0) { 2784 strlist__delete(unamelist); 2785 close(ufd); 2786 } | 2799 } 2800 2801error: 2802 if (kfd >= 0) { 2803 strlist__delete(namelist); 2804 close(kfd); 2805 } 2806 2807 if (ufd >= 0) { 2808 strlist__delete(unamelist); 2809 close(ufd); 2810 } |
2811 free(str); |
|
2787 2788 return ret; 2789} 2790 2791/* TODO: don't use a global variable for filter ... */ 2792static struct strfilter *available_func_filter; 2793 2794/* --- 53 unchanged lines hidden --- | 2812 2813 return ret; 2814} 2815 2816/* TODO: don't use a global variable for filter ... */ 2817static struct strfilter *available_func_filter; 2818 2819/* --- 53 unchanged lines hidden --- |