diff options
-rw-r--r-- | trunk/ChangeLog | 10 | ||||
-rw-r--r-- | trunk/src/dso.c | 76 | ||||
-rw-r--r-- | trunk/src/main.c | 30 | ||||
-rw-r--r-- | trunk/src/prelink.h | 1 | ||||
-rw-r--r-- | trunk/src/undo.c | 3 |
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; } |