/* Unix SMB/CIFS implementation. Samba utility functions Copyright (C) Andrew Tridgell 1992-1998 Copyright (C) Jeremy Allison 2001-2007 Copyright (C) Simo Sorce 2001 Copyright (C) Jim McDonough 2003 Copyright (C) James Peach 2006 Copyright (c) 2020 Andreas Schneider This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include "replace.h" #include "dynconfig/dynconfig.h" #include "lib/util/util_paths.h" #include "system/passwd.h" #include "system/filesys.h" /** * @brief Returns an absolute path to a file in the Samba modules directory. * * @param name File to find, relative to MODULESDIR. * * @retval Pointer to a string containing the full path. **/ char *modules_path(TALLOC_CTX *mem_ctx, const char *name) { return talloc_asprintf(mem_ctx, "%s/%s", get_dyn_MODULESDIR(), name); } /** * @brief Returns an absolute path to a file in the Samba data directory. * * @param name File to find, relative to CODEPAGEDIR. * * @retval Pointer to a talloc'ed string containing the full path. **/ char *data_path(TALLOC_CTX *mem_ctx, const char *name) { return talloc_asprintf(mem_ctx, "%s/%s", get_dyn_CODEPAGEDIR(), name); } /** * @brief Returns the platform specific shared library extension. * * @retval Pointer to a const char * containing the extension. **/ const char *shlib_ext(void) { return get_dyn_SHLIBEXT(); } static char *get_user_home_dir(TALLOC_CTX *mem_ctx) { struct passwd pwd = {0}; struct passwd *pwdbuf = NULL; char *buf = NULL; char *out = NULL; long int initlen; size_t len; int rc; initlen = sysconf(_SC_GETPW_R_SIZE_MAX); if (initlen == -1) { len = 1024; } else { len = (size_t)initlen; } buf = talloc_size(mem_ctx, len); if (buf == NULL) { return NULL; } rc = getpwuid_r(getuid(), &pwd, buf, len, &pwdbuf); while (rc == ERANGE) { size_t newlen = 2 * len; if (newlen < len) { /* Overflow */ goto done; } len = newlen; buf = talloc_realloc_size(mem_ctx, buf, len); if (buf == NULL) { goto done; } rc = getpwuid_r(getuid(), &pwd, buf, len, &pwdbuf); } if (rc != 0 || pwdbuf == NULL ) { const char *szPath = getenv("HOME"); if (szPath == NULL) { goto done; } len = strnlen(szPath, PATH_MAX); if (len >= PATH_MAX) { goto done; } out = talloc_strdup(mem_ctx, szPath); goto done; } out = talloc_strdup(mem_ctx, pwd.pw_dir); done: TALLOC_FREE(buf); return out; } char *path_expand_tilde(TALLOC_CTX *mem_ctx, const char *d) { char *h = NULL, *r = NULL; const char *p = NULL; struct stat sb = {0}; int rc; if (d[0] != '~') { return talloc_strdup(mem_ctx, 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; } h = talloc_strdup(mem_ctx, pw->pw_dir); } else { p = d; h = get_user_home_dir(mem_ctx); } if (h == NULL) { return NULL; } rc = stat(h, &sb); if (rc != 0) { TALLOC_FREE(h); return NULL; } r = talloc_asprintf(mem_ctx, "%s%s", h, p); TALLOC_FREE(h); return r; }