files.c revision 8f4aaae28c88c707853f8f28d8babc4efe0c1bf6
/*
Authors:
Jakub Hrozek <jhrozek@redhat.com>
Copyright (C) 2009 Red Hat
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
* 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 "config.h"
#include "tools/tools_util.h"
#ifdef HAVE_SELINUX
#endif
struct copy_ctx {
const char *src_orig;
const char *dst_orig;
};
#ifdef HAVE_SELINUX
/*
* selinux_file_context - Set the security context before any file or
* directory creation.
*
* selinux_file_context () should be called before any creation of file,
* symlink, directory, ...
*
* Callers may have to Reset SELinux to create files with default
* contexts:
* reset_selinux_file_context();
*/
int selinux_file_context(const char *dst_name)
{
if (is_selinux_enabled() == 1) {
/* Get the default security context for this file */
if (security_getenforce () != 0) {
return 1;
}
}
/* Set the security context for the next created file */
if (setfscreatecon(scontext) < 0) {
if (security_getenforce() != 0) {
return 1;
}
}
}
return 0;
}
int reset_selinux_file_context(void)
{
return EOK;
}
#else /* HAVE_SELINUX */
int selinux_file_context(const char *dst_name)
{
return EOK;
}
int reset_selinux_file_context(void)
{
return EOK;
}
#endif /* HAVE_SELINUX */
/* wrapper in order not to create a temporary context in
* every iteration */
const char *root);
int remove_tree(const char *root)
{
int ret;
if (!tmp_ctx) {
return ENOMEM;
}
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
*/
const char *root)
{
int ret;
goto fail;
}
/* End of directory */
break;
}
continue;
}
goto fail;
}
if (ret != 0) {
goto fail;
}
/* if directory, recursively descend, but check if on the same FS */
"will not follow\n", fullpath));
goto fail;
}
goto fail;
}
} else {
if (ret != 0) {
goto fail;
}
}
}
if (ret != 0) {
goto fail;
}
if (ret != 0) {
goto fail;
}
fail:
return ret;
}
{
int ret = 0;
/*
* Create a new target directory, make it owned by
* the user and then recursively copy that directory.
*/
if (ret != 0) {
return ret;
}
if (ret != 0) {
return ret;
}
if (ret != 0) {
return ret;
}
if (ret != 0) {
return ret;
}
if (ret != 0) {
return ret;
}
return EOK;
}
{
char *buffer;
if (!buffer) {
return NULL;
}
while (1) {
if (nchars < 0) {
return NULL;
}
/* The buffer was large enough */
break;
}
/* Try again with a bigger buffer */
size *= 2;
if (!buffer) {
return NULL;
}
}
/* readlink does not nul-terminate */
return buffer;
}
const char *src,
const char *dst,
{
int ret;
char *oldlink;
char *tmp;
if (!tmp_ctx) {
return ENOMEM;
}
/*
* Get the name of the file which the link points
* to. If that name begins with the original
* source directory name, that part of the link
* name will be replaced with the original
* destination directory name.
*/
goto done;
}
/* If src was a link to an entry of the src_orig directory itself,
* create a link to the corresponding entry in the dst_orig
* directory.
* FIXME: This may change a relative link to an absolute link
*/
goto done;
}
}
if (ret != 0) {
goto done;
}
if (ret != 0) {
goto done;
}
done:
return ret;
}
static int copy_special(const char *dst,
{
int ret = 0;
if (ret != 0) {
return ret;
}
if (ret != 0) {
return ret;
}
if (ret != 0) {
return ret;
}
if (ret != 0) {
return ret;
}
return EOK;
}
const char *dst,
{
int ret;
int ifd = -1;
int ofd = -1;
char buf[1024];
if (ifd < 0) {
goto fail;
}
if (ret != 0) {
goto fail;
}
goto fail;
}
if (ofd < 0) {
goto fail;
}
if (ret != 0) {
goto fail;
}
if (ret != 0) {
goto fail;
}
offset = 0;
while (cnt > 0) {
if (written == -1) {
goto fail;
}
}
}
if (cnt == -1) {
goto fail;
}
ifd = -1;
if (ret != 0) {
goto fail;
}
ifd = -1;
if (ret != 0) {
goto fail;
}
if (ret != 0) {
goto fail;
}
return EOK;
/* Reachable by jump only */
fail:
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 copy_tree() again
*/
const char *src,
const char *dst,
{
if (ret == -1) {
return ret;
}
}
return ret;
}
/* Check if we're still on the same FS */
/* Skip this without error */
return EOK;
}
/*
* Deal with FIFOs and special files. The user really
* shouldn't have any of these, but it seems like it
* would be nice to copy everything ...
*/
} else {
/*
* Create the new file and copy the contents. The new
* file will be owned by the provided UID and GID values.
*/
}
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 copy_tree() again
*/
const char *src_root,
const char *dst_root,
{
int ret;
goto fail;
}
/* End of directory */
break;
}
continue;
}
/* build src and dst paths */
goto fail;
}
/* copy */
goto fail;
}
}
if (ret != 0) {
goto fail;
}
fail:
return ret;
}
{
if (ret != 0) {
goto fail;
}
goto fail;
}
fail:
return ret;
}