summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--trunk/ChangeLog10
-rw-r--r--trunk/src/dso.c76
-rw-r--r--trunk/src/main.c30
-rw-r--r--trunk/src/prelink.h1
-rw-r--r--trunk/src/undo.c3
5 files changed, 83 insertions, 37 deletions
diff --git a/trunk/ChangeLog b/trunk/ChangeLog
index df5308b..5275f74 100644
--- a/trunk/ChangeLog
+++ b/trunk/ChangeLog
@@ -1,3 +1,13 @@
+2010-07-14 Jakub Jelinek <jakub@redhat.com>
+
+ * src/prelink.h (copy_fd_to_file): New prototype.
+ * src/undo.c (prelink_undo): If undo_output and .gnu.prelink_undo
+ section is not present, don't reopen_dso, just return 0.
+ * src/main.c (main): If dso isn't writable with undo_output,
+ copy_fd_to_file dso->fd.
+ * src/dso.c (copy_fd_to_file): New function.
+ (update_dso): Use it.
+
2010-04-13 Jakub Jelinek <jakub@redhat.com>
* testsuite/reloc8.sh: Don't use -Wl,-z,nocopyreloc on
diff --git a/trunk/src/dso.c b/trunk/src/dso.c
index 309aeca..72f7fe5 100644
--- a/trunk/src/dso.c
+++ b/trunk/src/dso.c
@@ -1745,6 +1745,45 @@ set_security_context (const char *temp_name, const char *name,
}
int
+copy_fd_to_file (int fdin, const char *name, struct stat64 *st)
+{
+ struct stat64 stt;
+ off_t off = 0;
+ int err, fdout;
+ struct utimbuf u;
+
+ if (strcmp (name, "-") == 0)
+ fdout = 1;
+ else
+ fdout = wrap_open (name, O_WRONLY | O_CREAT, 0600);
+ if (fdout != -1
+ && fstat64 (fdin, &stt) >= 0
+ && send_file (fdout, fdin, &off, stt.st_size) == stt.st_size)
+ {
+ if (fchown (fdout, st->st_uid, st->st_gid) >= 0)
+ fchmod (fdout, st->st_mode & 07777);
+ if (strcmp (name, "-") != 0)
+ {
+ set_security_context (name, name, 1);
+ u.actime = time (NULL);
+ u.modtime = st->st_mtime;
+ wrap_utime (name, &u);
+ close (fdout);
+ }
+ return 0;
+ }
+ else if (fdout != -1)
+ {
+ err = errno;
+ if (strcmp (name, "-") == 0)
+ close (fdout);
+ }
+ else
+ err = errno;
+ return err;
+}
+
+int
update_dso (DSO *dso, const char *orig_name)
{
int rdwr = dso_is_rdwr (dso);
@@ -1754,7 +1793,7 @@ update_dso (DSO *dso, const char *orig_name)
char *name1, *name2;
struct utimbuf u;
struct stat64 st;
- int fdin, fdout;
+ int fdin;
switch (write_dso (dso))
{
@@ -1808,39 +1847,12 @@ update_dso (DSO *dso, const char *orig_name)
{
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;
+ int err = copy_fd_to_file (fdin, name1, &st);
+
close (fdin);
wrap_unlink (name2);
+ if (err == 0)
+ return 0;
error (0, err, "Could not rename nor copy temporary to %s",
name1);
return 1;
diff --git a/trunk/src/main.c b/trunk/src/main.c
index 4678ba4..3dccd1b 100644
--- a/trunk/src/main.c
+++ b/trunk/src/main.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007 Red Hat, Inc.
+/* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007, 2010 Red Hat, Inc.
Written by Jakub Jelinek <jakub@redhat.com>, 2001.
This program is free software; you can redistribute it and/or modify
@@ -421,8 +421,32 @@ main (int argc, char *argv[])
dso->permissive = 1;
else if (undo_output)
{
- const char *output = strdup (undo_output);
- const char *orig_filename;
+ const char *output, *orig_filename;
+
+ if (!dso_is_rdwr (dso))
+ {
+ struct stat64 st;
+ int err;
+
+ if (fstat64 (dso->fd, &st) < 0)
+ {
+ error (0, errno, "Could not stat %s", dso->filename);
+ ++failures;
+ close_dso (dso);
+ continue;
+ }
+ err = copy_fd_to_file (dso->fd, undo_output, &st);
+ if (err)
+ {
+ error (0, err, "Could not undo %s to %s", dso->filename,
+ undo_output);
+ ++failures;
+ }
+ close_dso (dso);
+ continue;
+ }
+
+ output = strdup (undo_output);
if (!output)
{
++failures;
diff --git a/trunk/src/prelink.h b/trunk/src/prelink.h
index bdf6879..96f1c46 100644
--- a/trunk/src/prelink.h
+++ b/trunk/src/prelink.h
@@ -289,6 +289,7 @@ int adjust_dwarf2 (DSO *dso, int n, GElf_Addr start, GElf_Addr adjust);
int adjust_mdebug (DSO *dso, int n, GElf_Addr start, GElf_Addr adjust);
int finalize_mdebug (DSO *dso);
int relocate_dso (DSO *dso, GElf_Addr base);
+int copy_fd_to_file (int fdin, const char *name, struct stat64 *st);
int update_dso (DSO *dso, const char *);
int prepare_write_dso (DSO *dso);
int write_dso (DSO *dso);
diff --git a/trunk/src/undo.c b/trunk/src/undo.c
index 4d1332c..8a55bf2 100644
--- a/trunk/src/undo.c
+++ b/trunk/src/undo.c
@@ -500,8 +500,7 @@ prelink_undo (DSO *dso)
if (undo == dso->ehdr.e_shnum)
{
if (undo_output)
- return reopen_dso (dso, NULL, strcmp (undo_output, "-") == 0
- ? "/tmp/undo" : undo_output);
+ return 0;
error (0, 0, "%s does not have .gnu.prelink_undo section", dso->filename);
return 1;
}