diff options
-rw-r--r-- | include/libssh/misc.h | 2 | ||||
-rw-r--r-- | libssh/misc.c | 60 |
2 files changed, 62 insertions, 0 deletions
diff --git a/include/libssh/misc.h b/include/libssh/misc.h index 6d7aed96..05c6d493 100644 --- a/include/libssh/misc.h +++ b/include/libssh/misc.h @@ -28,6 +28,8 @@ char *ssh_get_user_home_dir(void); char *ssh_get_local_username(ssh_session session); int ssh_file_readaccess_ok(const char *file); +char *ssh_path_expand_tilde(const char *d); + /* macro for byte ordering */ uint64_t ntohll(uint64_t); #define htonll(x) ntohll(x) diff --git a/libssh/misc.c b/libssh/misc.c index ff44fb5c..7bef392b 100644 --- a/libssh/misc.c +++ b/libssh/misc.c @@ -520,6 +520,66 @@ int ssh_mkdir(const char *pathname, mode_t mode) { return r; } +/** + * @brief Expand a directory starting with a tilde '~' + * + * @param[in] session The ssh session to use. + * + * @param[in] d The directory to expand. + * + * @return The expanded directory, NULL on error. + */ +char *ssh_path_expand_tilde(const char *d) { + char *h, *r, *p; + size_t ld; + size_t lh = 0; + + if (d[0] != '~') { + return strdup(d); + } + d++; + + /* handle ~user/path */ + p = strchr(d, '/'); + if (p != NULL && p > d) { + struct passwd *pw; + size_t s = p - d; + char u[128]; + + if (s > sizeof(u)) { + return NULL; + } + memcpy(u, d, s); + u[s] = '\0'; + pw = getpwnam(u); + if (pw == NULL) { + return NULL; + } + ld = strlen(p); + h = strdup(pw->pw_dir); + } else { + ld = strlen(d); + p = (char *) d; + h = ssh_get_user_home_dir(); + } + if (h == NULL) { + return NULL; + } + lh = strlen(h); + + r = malloc(ld + lh + 1); + if (r == NULL) { + return NULL; + } + + if (lh > 0) { + memcpy(r, h, lh); + } + memcpy(r + lh, p, ld); + + return r; +} + /* @} */ /* vim: set ts=4 sw=4 et cindent: */ |