summaryrefslogtreecommitdiffstats
path: root/trunk/src/dso.c
diff options
context:
space:
mode:
Diffstat (limited to 'trunk/src/dso.c')
-rw-r--r--trunk/src/dso.c68
1 files changed, 60 insertions, 8 deletions
diff --git a/trunk/src/dso.c b/trunk/src/dso.c
index b3b6ee3..8ad93d3 100644
--- a/trunk/src/dso.c
+++ b/trunk/src/dso.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 Red Hat, Inc.
+/* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2010 Red Hat, Inc.
Written by Jakub Jelinek <jakub@redhat.com>, 2001.
This program is free software; you can redistribute it and/or modify
@@ -1707,8 +1707,9 @@ write_dso (DSO *dso)
return 0;
}
-int
-set_security_context (DSO *dso, const char *temp_name, const char *name)
+static int
+set_security_context (const char *temp_name, const char *name,
+ int ignore_errors)
{
#ifdef USE_SELINUX
static int selinux_enabled = -1;
@@ -1729,7 +1730,7 @@ set_security_context (DSO *dso, const char *temp_name, const char *name)
name);
return 1;
}
- if (setfilecon (temp_name, scontext) < 0)
+ if (setfilecon (temp_name, scontext) < 0 && !ignore_errors)
{
error (0, errno, "Could not set security context for %s",
name);
@@ -1752,6 +1753,7 @@ update_dso (DSO *dso, const char *orig_name)
char *name1, *name2;
struct utimbuf u;
struct stat64 st;
+ int fdin, fdout;
switch (write_dso (dso))
{
@@ -1774,30 +1776,80 @@ update_dso (DSO *dso, const char *orig_name)
close_dso (dso);
return 1;
}
- if (fchown (dso->fd, st.st_uid, st.st_gid) < 0
- || fchmod (dso->fd, st.st_mode & 07777) < 0)
+ if ((fchown (dso->fd, st.st_uid, st.st_gid) < 0
+ || fchmod (dso->fd, st.st_mode & 07777) < 0)
+ && orig_name == NULL)
{
error (0, errno, "Could not set %s owner or mode", dso->filename);
close_dso (dso);
return 1;
}
+ if (orig_name != NULL)
+ fdin = dup (dso->fd);
+ else
+ fdin = -1;
close_dso_1 (dso);
u.actime = time (NULL);
u.modtime = st.st_mtime;
wrap_utime (name2, &u);
- if (set_security_context (dso, name2, orig_name ? orig_name : name1))
+ if (set_security_context (name2, orig_name ? orig_name : name1,
+ orig_name != NULL))
{
+ if (fdin != -1)
+ close (fdin);
wrap_unlink (name2);
return 1;
}
- if (wrap_rename (name2, name1))
+ if ((orig_name != NULL && strcmp (name1, "-") == 0)
+ || wrap_rename (name2, name1))
{
+ if (fdin != -1)
+ {
+ struct stat64 stt;
+ off_t off = 0;
+ int err;
+ if (strcmp (name1, "-") == 0)
+ fdout = 1;
+ else
+ fdout = wrap_open (name1, O_WRONLY | O_CREAT, 0600);
+ if (fdout != -1
+ && fstat64 (fdin, &stt) >= 0
+ && send_file (fdout, fdin, &off, stt.st_size) == stt.st_size)
+ {
+ close (fdin);
+ if (fchown (fdout, st.st_uid, st.st_gid) >= 0)
+ fchmod (fdout, st.st_mode & 07777);
+ if (strcmp (name1, "-") != 0)
+ {
+ set_security_context (name1, name1, 1);
+ wrap_utime (name1, &u);
+ close (fdout);
+ }
+ wrap_unlink (name2);
+ return 0;
+ }
+ else if (fdout != -1)
+ {
+ err = errno;
+ if (strcmp (name1, "-") == 0)
+ close (fdout);
+ }
+ else
+ err = errno;
+ close (fdin);
+ wrap_unlink (name2);
+ error (0, err, "Could not rename nor copy temporary to %s",
+ name1);
+ return 1;
+ }
wrap_unlink (name2);
error (0, errno, "Could not rename temporary to %s", name1);
return 1;
}
+ if (fdin != -1)
+ close (fdin);
}
else
close_dso_1 (dso);