]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - binutils/rename.c
readelf/objdump: Handle DWARF info with mixed types of range section.
[thirdparty/binutils-gdb.git] / binutils / rename.c
CommitLineData
252b5132 1/* rename.c -- rename a file, preserving symlinks.
d87bef3a 2 Copyright (C) 1999-2023 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
985e0264 25#if defined HAVE_UTIMES
252b5132 26#include <sys/time.h>
985e0264
AM
27#elif defined HAVE_GOOD_UTIME_H
28#include <utime.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
37static int
40b02646
AM
38simple_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
985e0264
AM
89/* The following defines and inline functions are copied from gnulib.
90 FIXME: Use a gnulib import and stat-time.h instead. */
91#if defined HAVE_STRUCT_STAT_ST_ATIM_TV_NSEC
92# if defined TYPEOF_STRUCT_STAT_ST_ATIM_IS_STRUCT_TIMESPEC
93# define STAT_TIMESPEC(st, st_xtim) ((st)->st_xtim)
94# else
95# define STAT_TIMESPEC_NS(st, st_xtim) ((st)->st_xtim.tv_nsec)
96# endif
97#elif defined HAVE_STRUCT_STAT_ST_ATIMESPEC_TV_NSEC
98# define STAT_TIMESPEC(st, st_xtim) ((st)->st_xtim##espec)
99#elif defined HAVE_STRUCT_STAT_ST_ATIMENSEC
100# define STAT_TIMESPEC_NS(st, st_xtim) ((st)->st_xtim##ensec)
101#elif defined HAVE_STRUCT_STAT_ST_ATIM_ST__TIM_TV_NSEC
102# define STAT_TIMESPEC_NS(st, st_xtim) ((st)->st_xtim.st__tim.tv_nsec)
103#endif
104
4dee4f3e
NC
105static inline long int get_stat_atime_ns (struct stat const *) ATTRIBUTE_UNUSED;
106static inline long int get_stat_mtime_ns (struct stat const *) ATTRIBUTE_UNUSED;
107
985e0264 108/* Return the nanosecond component of *ST's access time. */
ad7c4616 109static inline long int
4c79248a 110get_stat_atime_ns (struct stat const *st ATTRIBUTE_UNUSED)
985e0264
AM
111{
112# if defined STAT_TIMESPEC
113 return STAT_TIMESPEC (st, st_atim).tv_nsec;
114# elif defined STAT_TIMESPEC_NS
115 return STAT_TIMESPEC_NS (st, st_atim);
116# else
117 return 0;
118# endif
119}
120
121/* Return the nanosecond component of *ST's data modification time. */
ad7c4616 122static inline long int
4c79248a 123get_stat_mtime_ns (struct stat const *st ATTRIBUTE_UNUSED)
985e0264
AM
124{
125# if defined STAT_TIMESPEC
126 return STAT_TIMESPEC (st, st_mtim).tv_nsec;
127# elif defined STAT_TIMESPEC_NS
128 return STAT_TIMESPEC_NS (st, st_mtim);
129# else
130 return 0;
131# endif
132}
133
47fcfcba 134#if defined HAVE_UTIMENSAT
985e0264 135/* Return *ST's access time. */
ad7c4616 136static inline struct timespec
985e0264
AM
137get_stat_atime (struct stat const *st)
138{
139#ifdef STAT_TIMESPEC
140 return STAT_TIMESPEC (st, st_atim);
141#else
142 struct timespec t;
143 t.tv_sec = st->st_atime;
144 t.tv_nsec = get_stat_atime_ns (st);
145 return t;
146#endif
147}
148
149/* Return *ST's data modification time. */
ad7c4616 150static inline struct timespec
985e0264
AM
151get_stat_mtime (struct stat const *st)
152{
153#ifdef STAT_TIMESPEC
154 return STAT_TIMESPEC (st, st_mtim);
155#else
156 struct timespec t;
157 t.tv_sec = st->st_mtime;
158 t.tv_nsec = get_stat_mtime_ns (st);
159 return t;
160#endif
161}
47fcfcba 162#endif
985e0264
AM
163/* End FIXME. */
164
252b5132
RH
165/* Set the times of the file DESTINATION to be the same as those in
166 STATBUF. */
167
168void
2da42df6 169set_times (const char *destination, const struct stat *statbuf)
252b5132
RH
170{
171 int result;
985e0264
AM
172#if defined HAVE_UTIMENSAT
173 struct timespec times[2];
174 times[0] = get_stat_atime (statbuf);
175 times[1] = get_stat_mtime (statbuf);
176 result = utimensat (AT_FDCWD, destination, times, 0);
cca8873d
AM
177#elif defined HAVE_UTIMES
178 struct timeval tv[2];
179
180 tv[0].tv_sec = statbuf->st_atime;
985e0264 181 tv[0].tv_usec = get_stat_atime_ns (statbuf) / 1000;
cca8873d 182 tv[1].tv_sec = statbuf->st_mtime;
985e0264 183 tv[1].tv_usec = get_stat_mtime_ns (statbuf) / 1000;
cca8873d 184 result = utimes (destination, tv);
985e0264
AM
185#elif defined HAVE_GOOD_UTIME_H
186 struct utimbuf tb;
187
188 tb.actime = statbuf->st_atime;
189 tb.modtime = statbuf->st_mtime;
190 result = utime (destination, &tb);
cca8873d
AM
191#else
192 long tb[2];
193
194 tb[0] = statbuf->st_atime;
195 tb[1] = statbuf->st_mtime;
196 result = utime (destination, tb);
197#endif
252b5132
RH
198
199 if (result != 0)
200 non_fatal (_("%s: cannot set time: %s"), destination, strerror (errno));
201}
202
cca8873d
AM
203/* Copy FROM to TO. TARGET_STAT has the file status that, if non-NULL,
204 is used to fix up timestamps. Return 0 if ok, -1 if error.
205 At one time this function renamed files, but file permissions are
206 tricky to update given the number of different schemes used by
207 various systems. So now we just copy. */
252b5132
RH
208
209int
c42c71a1 210smart_rename (const char *from, const char *to, int fromfd,
015dc7e1 211 struct stat *target_stat, bool preserve_dates)
252b5132 212{
d0ecdcdd 213 int ret = 0;
252b5132 214
d0ecdcdd
AM
215 if (to != from)
216 {
217 ret = simple_copy (fromfd, to, target_stat);
218 if (ret != 0)
219 non_fatal (_("unable to copy file '%s'; reason: %s"),
220 to, strerror (errno));
221 unlink (from);
222 }
252b5132 223
c42c71a1 224 if (preserve_dates)
cca8873d 225 set_times (to, target_stat);
252b5132
RH
226
227 return ret;
228}