diff options
Diffstat (limited to 'libbb/concat_path_file.c')
-rw-r--r-- | libbb/concat_path_file.c | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/libbb/concat_path_file.c b/libbb/concat_path_file.c index 3afb0e3a4..96fcd4a1d 100644 --- a/libbb/concat_path_file.c +++ b/libbb/concat_path_file.c | |||
@@ -17,6 +17,7 @@ | |||
17 | 17 | ||
18 | char* FAST_FUNC concat_path_file(const char *path, const char *filename) | 18 | char* FAST_FUNC concat_path_file(const char *path, const char *filename) |
19 | { | 19 | { |
20 | #if 0 | ||
20 | char *lc; | 21 | char *lc; |
21 | 22 | ||
22 | if (!path) | 23 | if (!path) |
@@ -31,4 +32,78 @@ char* FAST_FUNC concat_path_file(const char *path, const char *filename) | |||
31 | filename++; | 32 | filename++; |
32 | #endif | 33 | #endif |
33 | return xasprintf("%s%s%s", path, (lc==NULL ? "/" : ""), filename); | 34 | return xasprintf("%s%s%s", path, (lc==NULL ? "/" : ""), filename); |
35 | #else | ||
36 | /* ^^^^^^^^^^^ timing of xasprintf-based code above: | ||
37 | * real 7.074s | ||
38 | * user 0.156s <<< | ||
39 | * sys 6.394s | ||
40 | * "rm -rf" of a Linux kernel tree from tmpfs (run time still dominated by in-kernel work, though) | ||
41 | * real 6.989s | ||
42 | * user 0.055s <<< 3 times less CPU used | ||
43 | * sys 6.450s | ||
44 | * vvvvvvvvvvv timing of open-coded malloc+memcpy code below (+59 bytes): | ||
45 | */ | ||
46 | char *buf, *p; | ||
47 | size_t n1, n2, n3; | ||
48 | |||
49 | while (*filename == '/') | ||
50 | filename++; | ||
51 | |||
52 | if (!path || !path[0]) | ||
53 | return xstrdup(filename); | ||
54 | |||
55 | n1 = strlen(path); | ||
56 | n2 = (path[n1 - 1] != '/'); /* 1: "path has no trailing slash" */ | ||
57 | n3 = strlen(filename) + 1; | ||
58 | |||
59 | buf = xmalloc(n1 + n2 + n3); | ||
60 | p = mempcpy(buf, path, n1); | ||
61 | if (n2) | ||
62 | *p++ = '/'; | ||
63 | memcpy(p, filename, n3); | ||
64 | return buf; | ||
65 | #endif | ||
34 | } | 66 | } |
67 | |||
68 | /* If second component comes from struct dirent, | ||
69 | * it's possible to eliminate one strlen() by using name length | ||
70 | * provided by kernel in struct dirent. See below. | ||
71 | * However, the win seems to be insignificant. | ||
72 | */ | ||
73 | |||
74 | #if 0 | ||
75 | |||
76 | /* Extract d_namlen from struct dirent */ | ||
77 | static size_t get_d_namlen(const struct dirent *de) | ||
78 | { | ||
79 | #if defined(_DIRENT_HAVE_D_NAMLEN) | ||
80 | return de->d_namlen; | ||
81 | #elif defined(_DIRENT_HAVE_D_RECLEN) | ||
82 | const size_t prefix_sz = offsetof(struct dirent, d_name); | ||
83 | return de->d_reclen - prefix_sz; | ||
84 | #else | ||
85 | return strlen(de->d_name); | ||
86 | #endif | ||
87 | } | ||
88 | |||
89 | char* FAST_FUNC concat_path_dirent(const char *path, const struct dirent *de) | ||
90 | { | ||
91 | char *buf, *p; | ||
92 | size_t n1, n2, n3; | ||
93 | |||
94 | if (!path || !path[0]) | ||
95 | return xstrdup(de->d_name); | ||
96 | |||
97 | n1 = strlen(path); | ||
98 | n2 = (path[n1 - 1] != '/'); | ||
99 | n3 = get_d_namlen(de) + 1; | ||
100 | |||
101 | buf = xmalloc(n1 + n2 + n3); | ||
102 | p = mempcpy(buf, path, n1); | ||
103 | if (n2) | ||
104 | *p++ = '/'; | ||
105 | memcpy(p, de->d_name, n3); | ||
106 | return buf; | ||
107 | } | ||
108 | |||
109 | #endif | ||