Commit | Line | Data |
---|---|---|
252b5132 | 1 | /* rename.c -- rename a file, preserving symlinks. |
250d07de | 2 | Copyright (C) 1999-2021 Free Software Foundation, Inc. |
252b5132 RH |
3 | |
4 | This file is part of GNU Binutils. | |
5 | ||
6 | This program is free software; you can redistribute it and/or modify | |
7 | it under the terms of the GNU General Public License as published by | |
32866df7 | 8 | the Free Software Foundation; either version 3 of the License, or |
252b5132 RH |
9 | (at your option) any later version. |
10 | ||
11 | This program is distributed in the hope that it will be useful, | |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | GNU General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
17 | along with this program; if not, write to the Free Software | |
b43b5d5f NC |
18 | Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA |
19 | 02110-1301, USA. */ | |
252b5132 | 20 | |
3db64b00 | 21 | #include "sysdep.h" |
252b5132 RH |
22 | #include "bfd.h" |
23 | #include "bucomm.h" | |
24 | ||
252b5132 RH |
25 | #ifdef HAVE_GOOD_UTIME_H |
26 | #include <utime.h> | |
cca8873d | 27 | #elif defined HAVE_UTIMES |
252b5132 | 28 | #include <sys/time.h> |
cca8873d | 29 | #endif |
252b5132 RH |
30 | |
31 | /* The number of bytes to copy at once. */ | |
32 | #define COPY_BUF 8192 | |
33 | ||
c42c71a1 | 34 | /* Copy file FROMFD to file TO, performing no translations. |
252b5132 RH |
35 | Return 0 if ok, -1 if error. */ |
36 | ||
37 | static int | |
40b02646 AM |
38 | simple_copy (int fromfd, const char *to, |
39 | struct stat *target_stat ATTRIBUTE_UNUSED) | |
252b5132 | 40 | { |
c42c71a1 | 41 | int tofd, nread; |
252b5132 RH |
42 | int saved; |
43 | char buf[COPY_BUF]; | |
44 | ||
c42c71a1 AM |
45 | if (fromfd < 0 |
46 | || lseek (fromfd, 0, SEEK_SET) != 0) | |
252b5132 | 47 | return -1; |
c42c71a1 AM |
48 | |
49 | tofd = open (to, O_WRONLY | O_TRUNC | O_BINARY); | |
252b5132 RH |
50 | if (tofd < 0) |
51 | { | |
52 | saved = errno; | |
53 | close (fromfd); | |
54 | errno = saved; | |
55 | return -1; | |
56 | } | |
c42c71a1 | 57 | |
252b5132 RH |
58 | while ((nread = read (fromfd, buf, sizeof buf)) > 0) |
59 | { | |
60 | if (write (tofd, buf, nread) != nread) | |
61 | { | |
62 | saved = errno; | |
63 | close (fromfd); | |
64 | close (tofd); | |
65 | errno = saved; | |
66 | return -1; | |
67 | } | |
68 | } | |
c42c71a1 | 69 | |
252b5132 | 70 | saved = errno; |
c42c71a1 AM |
71 | |
72 | #if !defined (_WIN32) || defined (__CYGWIN32__) | |
73 | /* Writing to a setuid/setgid file may clear S_ISUID and S_ISGID. | |
74 | Try to restore them, ignoring failure. */ | |
75 | if (target_stat != NULL) | |
76 | fchmod (tofd, target_stat->st_mode); | |
77 | #endif | |
78 | ||
252b5132 RH |
79 | close (fromfd); |
80 | close (tofd); | |
81 | if (nread < 0) | |
82 | { | |
83 | errno = saved; | |
84 | return -1; | |
85 | } | |
86 | return 0; | |
87 | } | |
88 | ||
89 | /* Set the times of the file DESTINATION to be the same as those in | |
90 | STATBUF. */ | |
91 | ||
92 | void | |
2da42df6 | 93 | set_times (const char *destination, const struct stat *statbuf) |
252b5132 RH |
94 | { |
95 | int result; | |
252b5132 | 96 | #ifdef HAVE_GOOD_UTIME_H |
cca8873d AM |
97 | struct utimbuf tb; |
98 | ||
99 | tb.actime = statbuf->st_atime; | |
100 | tb.modtime = statbuf->st_mtime; | |
101 | result = utime (destination, &tb); | |
102 | #elif defined HAVE_UTIMES | |
103 | struct timeval tv[2]; | |
104 | ||
105 | tv[0].tv_sec = statbuf->st_atime; | |
106 | tv[0].tv_usec = 0; | |
107 | tv[1].tv_sec = statbuf->st_mtime; | |
108 | tv[1].tv_usec = 0; | |
109 | result = utimes (destination, tv); | |
110 | #else | |
111 | long tb[2]; | |
112 | ||
113 | tb[0] = statbuf->st_atime; | |
114 | tb[1] = statbuf->st_mtime; | |
115 | result = utime (destination, tb); | |
116 | #endif | |
252b5132 RH |
117 | |
118 | if (result != 0) | |
119 | non_fatal (_("%s: cannot set time: %s"), destination, strerror (errno)); | |
120 | } | |
121 | ||
cca8873d AM |
122 | /* Copy FROM to TO. TARGET_STAT has the file status that, if non-NULL, |
123 | is used to fix up timestamps. Return 0 if ok, -1 if error. | |
124 | At one time this function renamed files, but file permissions are | |
125 | tricky to update given the number of different schemes used by | |
126 | various systems. So now we just copy. */ | |
252b5132 RH |
127 | |
128 | int | |
c42c71a1 AM |
129 | smart_rename (const char *from, const char *to, int fromfd, |
130 | struct stat *target_stat, bfd_boolean preserve_dates) | |
252b5132 | 131 | { |
cca8873d | 132 | int ret; |
252b5132 | 133 | |
c42c71a1 | 134 | ret = simple_copy (fromfd, to, target_stat); |
252b5132 | 135 | if (ret != 0) |
cca8873d AM |
136 | non_fatal (_("unable to copy file '%s'; reason: %s"), |
137 | to, strerror (errno)); | |
252b5132 | 138 | |
c42c71a1 | 139 | if (preserve_dates) |
cca8873d AM |
140 | set_times (to, target_stat); |
141 | unlink (from); | |
252b5132 RH |
142 | |
143 | return ret; | |
144 | } |