aboutsummaryrefslogtreecommitdiff
path: root/libbb/xreadlink.c
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2021-10-13 14:37:51 +0100
committerRon Yorston <rmy@pobox.com>2021-10-13 14:37:51 +0100
commit0ecf1aea459571b48dc68ddc2b7b9265740fa960 (patch)
tree491d6184a44b8b525a4ca35759d622aecd7f6344 /libbb/xreadlink.c
parent4859ddcb20616718efbea12c6bf8b27c469b68de (diff)
parentaaf3d5ba74c5da97ff80b61f30cb8dd225d39096 (diff)
downloadbusybox-w32-0ecf1aea459571b48dc68ddc2b7b9265740fa960.tar.gz
busybox-w32-0ecf1aea459571b48dc68ddc2b7b9265740fa960.tar.bz2
busybox-w32-0ecf1aea459571b48dc68ddc2b7b9265740fa960.zip
Merge branch 'busybox' into merge
Diffstat (limited to 'libbb/xreadlink.c')
-rw-r--r--libbb/xreadlink.c75
1 files changed, 45 insertions, 30 deletions
diff --git a/libbb/xreadlink.c b/libbb/xreadlink.c
index 31680810b..024ee9047 100644
--- a/libbb/xreadlink.c
+++ b/libbb/xreadlink.c
@@ -130,7 +130,7 @@ char* FAST_FUNC xmalloc_realpath(const char *path)
130#endif 130#endif
131} 131}
132 132
133char* FAST_FUNC xmalloc_realpath_coreutils(const char *path) 133char* FAST_FUNC xmalloc_realpath_coreutils(char *path)
134{ 134{
135 char *buf; 135 char *buf;
136 136
@@ -144,32 +144,19 @@ char* FAST_FUNC xmalloc_realpath_coreutils(const char *path)
144 * (the directory must exist). 144 * (the directory must exist).
145 */ 145 */
146 if (!buf && errno == ENOENT) { 146 if (!buf && errno == ENOENT) {
147 char *last_slash = strrchr(path, '/'); 147 char *target, c, *last_slash;
148 if (last_slash) { 148 size_t i;
149 *last_slash++ = '\0'; 149
150 buf = xmalloc_realpath(path); 150 target = xmalloc_readlink(path);
151 if (buf) { 151 if (target) {
152 unsigned len = strlen(buf); 152 /*
153 buf = xrealloc(buf, len + strlen(last_slash) + 2); 153 * $ ln -s /bin/qwe symlink # note: /bin is a link to /usr/bin
154 buf[len++] = '/'; 154 * $ readlink -f symlink
155 strcpy(buf + len, last_slash); 155 * /usr/bin/qwe
156 } 156 * $ realpath symlink
157 } else { 157 * /usr/bin/qwe
158 char *target = xmalloc_readlink(path); 158 */
159 if (target) { 159 if (target[0] != '/') {
160 char *cwd;
161 if (target[0] == '/') {
162 /*
163 * $ ln -s /bin/qwe symlink # note: /bin is a link to /usr/bin
164 * $ readlink -f symlink
165 * /usr/bin/qwe/target_does_not_exist
166 * $ realpath symlink
167 * /usr/bin/qwe/target_does_not_exist
168 */
169 buf = xmalloc_realpath_coreutils(target);
170 free(target);
171 return buf;
172 }
173 /* 160 /*
174 * $ ln -s target_does_not_exist symlink 161 * $ ln -s target_does_not_exist symlink
175 * $ readlink -f symlink 162 * $ readlink -f symlink
@@ -177,13 +164,41 @@ char* FAST_FUNC xmalloc_realpath_coreutils(const char *path)
177 * $ realpath symlink 164 * $ realpath symlink
178 * /CURDIR/target_does_not_exist 165 * /CURDIR/target_does_not_exist
179 */ 166 */
180 cwd = xrealloc_getcwd_or_warn(NULL); 167 char *cwd = xrealloc_getcwd_or_warn(NULL);
181 buf = concat_path_file(cwd, target); 168 char *tmp = concat_path_file(cwd, target);
182 free(cwd); 169 free(cwd);
183 free(target); 170 free(target);
184 return buf; 171 target = tmp;
172 }
173 buf = xmalloc_realpath_coreutils(target);
174 free(target);
175 return buf;
176 }
177
178 /* ignore leading and trailing slashes */
179 while (path[0] == '/' && path[1] == '/')
180 ++path;
181 i = strlen(path) - 1;
182 while (i > 0 && path[i] == '/')
183 i--;
184 c = path[i + 1];
185 path[i + 1] = '\0';
186
187 last_slash = strrchr(path, '/');
188 if (last_slash == path)
189 buf = xstrdup(path);
190 else if (last_slash) {
191 *last_slash = '\0';
192 buf = xmalloc_realpath(path);
193 *last_slash++ = '/';
194 if (buf) {
195 unsigned len = strlen(buf);
196 buf = xrealloc(buf, len + strlen(last_slash) + 2);
197 buf[len++] = '/';
198 strcpy(buf + len, last_slash);
185 } 199 }
186 } 200 }
201 path[i + 1] = c;
187 } 202 }
188 203
189 return buf; 204 return buf;