aboutsummaryrefslogtreecommitdiff
path: root/libbb/concat_path_file.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--libbb/concat_path_file.c81
1 files changed, 81 insertions, 0 deletions
diff --git a/libbb/concat_path_file.c b/libbb/concat_path_file.c
index 5b4b7f113..96fcd4a1d 100644
--- a/libbb/concat_path_file.c
+++ b/libbb/concat_path_file.c
@@ -17,12 +17,93 @@
17 17
18char* FAST_FUNC concat_path_file(const char *path, const char *filename) 18char* 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)
23 path = ""; 24 path = "";
25#if ENABLE_PLATFORM_MINGW32
26 lc = last_char_is_dir_sep(path);
27 while (is_dir_sep(*filename))
28 filename++;
29#else
24 lc = last_char_is(path, '/'); 30 lc = last_char_is(path, '/');
25 while (*filename == '/') 31 while (*filename == '/')
26 filename++; 32 filename++;
33#endif
27 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
28} 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 */
77static 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
89char* 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