/
githubmirror
/
sssd
Обзор
Документация
Войти
/
githubmirror
/
sssd
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/util/files.c
266 строк
8 KB
Alexey Tikhonov
Fleet commander: store deskprofiles under user running SSSD
30 янв 2024, 21:01
30 янв 2024, 21:01
c11734e
Код
Авторство
О чём код?
/* Authors: Jakub Hrozek <jhrozek@redhat.com> Copyright (C) 2009 Red Hat 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 <http://www.gnu.org/licenses/>. */ /* * This file incorporates work covered by the following copyright and * permission notice: * * Copyright (c) 1991 - 1994, Julianne Frances Haugh * Copyright (c) 1996 - 2001, Marek Michałkiewicz * Copyright (c) 2003 - 2006, Tomasz Kłoczko * Copyright (c) 2007 - 2008, Nicolas François * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the copyright holders or contributors may not be used to * endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include <dirent.h> #include <fcntl.h> #include <errno.h> #include <talloc.h> #include "util/util.h" /* wrapper in order not to create a temporary context in * every iteration */ static int remove_tree_with_ctx(TALLOC_CTX *mem_ctx, int parent_fd, const char *dir_name, dev_t parent_dev, bool keep_root_dir); int sss_remove_tree(const char *root) { TALLOC_CTX *tmp_ctx = NULL; int ret; tmp_ctx = talloc_new(NULL); if (!tmp_ctx) { return ENOMEM; } ret = remove_tree_with_ctx(tmp_ctx, AT_FDCWD, root, 0, false); talloc_free(tmp_ctx); return ret; } int sss_remove_subtree(const char *root) { TALLOC_CTX *tmp_ctx = NULL; int ret; tmp_ctx = talloc_new(NULL); if (!tmp_ctx) { return ENOMEM; } ret = remove_tree_with_ctx(tmp_ctx, AT_FDCWD, root, 0, true); talloc_free(tmp_ctx); return ret; } /* * The context is not freed in case of error * because this is a recursive function, will be freed when we * reach the top level remove_tree() again */ static int remove_tree_with_ctx(TALLOC_CTX *mem_ctx, int parent_fd, const char *dir_name, dev_t parent_dev, bool keep_root_dir) { struct dirent *result; struct stat statres; DIR *rootdir = NULL; int ret, err; int dir_fd; int log_level; dir_fd = sss_openat_cloexec(parent_fd, dir_name, O_RDONLY | O_DIRECTORY | O_NOFOLLOW, &ret); if (dir_fd == -1) { ret = errno; if (ret == ENOENT) { log_level = SSSDBG_TRACE_FUNC; } else { log_level = SSSDBG_MINOR_FAILURE; } DEBUG(log_level, "Cannot open %s: [%d]: %s\n", dir_name, ret, strerror(ret)); return ret; } rootdir = fdopendir(dir_fd); if (rootdir == NULL) { ret = errno; DEBUG(SSSDBG_MINOR_FAILURE, "Cannot open directory: [%d][%s]\n", ret, strerror(ret)); close(dir_fd); goto fail; } while ((result = readdir(rootdir)) != NULL) { if (strcmp(result->d_name, ".") == 0 || strcmp(result->d_name, "..") == 0) { continue; } ret = fstatat(dir_fd, result->d_name, &statres, AT_SYMLINK_NOFOLLOW); if (ret != 0) { ret = errno; DEBUG(SSSDBG_MINOR_FAILURE, "stat failed: [%d][%s]\n", ret, strerror(ret)); goto fail; } if (S_ISDIR(statres.st_mode)) { /* if directory, recursively descend, but check if on the same FS */ if (parent_dev && parent_dev != statres.st_dev) { DEBUG(SSSDBG_MINOR_FAILURE, "Directory %s is on different filesystem, " "will not follow\n", result->d_name); ret = EFAULT; goto fail; } ret = remove_tree_with_ctx(mem_ctx, dir_fd, result->d_name, statres.st_dev, false); if (ret != EOK) { DEBUG(SSSDBG_MINOR_FAILURE, "Removing subdirectory failed: [%d][%s]\n", ret, strerror(ret)); goto fail; } } else { ret = unlinkat(dir_fd, result->d_name, 0); if (ret != 0) { ret = errno; DEBUG(SSSDBG_MINOR_FAILURE, "Removing file failed '%s': [%d][%s]\n", result->d_name, ret, strerror(ret)); goto fail; } } } ret = closedir(rootdir); rootdir = NULL; if (ret != 0) { ret = errno; goto fail; } if (!keep_root_dir) { /* Remove also root directory. */ ret = unlinkat(parent_fd, dir_name, AT_REMOVEDIR); if (ret == -1) { ret = errno; } } ret = EOK; fail: if (rootdir) { /* clean up on abnormal exit but retain return code */ err = closedir(rootdir); if (err) { DEBUG(SSSDBG_MINOR_FAILURE, "closedir failed, bad dirp?\n"); } } return ret; } int sss_create_dir(const char *parent_dir_path, const char *dir_name, mode_t mode) { TALLOC_CTX *tmp_ctx; char *dir_path; int ret = EOK; int parent_dir_fd = -1; tmp_ctx = talloc_new(NULL); if (tmp_ctx == NULL) { return ENOMEM; } parent_dir_fd = sss_open_cloexec(parent_dir_path, O_RDONLY | O_DIRECTORY, &ret); if (parent_dir_fd == -1) { DEBUG(SSSDBG_TRACE_FUNC, "Cannot open() directory '%s' [%d]: %s\n", parent_dir_path, ret, sss_strerror(ret)); goto fail; } dir_path = talloc_asprintf(tmp_ctx, "%s/%s", parent_dir_path, dir_name); if (dir_path == NULL) { ret = ENOMEM; goto fail; } errno = 0; ret = mkdirat(parent_dir_fd, dir_name, mode); if (ret == -1) { if (errno == EEXIST) { ret = EOK; DEBUG(SSSDBG_TRACE_FUNC, "Directory '%s' already created!\n", dir_path); } else { ret = errno; DEBUG(SSSDBG_CRIT_FAILURE, "Error reading '%s': %s\n", parent_dir_path, strerror(ret)); goto fail; } } ret = EOK; fail: if (parent_dir_fd != -1) { close(parent_dir_fd); } talloc_free(tmp_ctx); return ret; }