PR binutils/11742
[binutils.git] / binutils / rename.c
blobc07150c955686ec889902a2eccc622577825f37c
1 /* rename.c -- rename a file, preserving symlinks.
2 Copyright 1999, 2002, 2003, 2005, 2007, 2008 Free Software Foundation, Inc.
4 This file is part of GNU Binutils.
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
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
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.
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
18 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
19 02110-1301, USA. */
21 #include "sysdep.h"
22 #include "bfd.h"
23 #include "bucomm.h"
25 #include <sys/stat.h>
27 #ifdef HAVE_GOOD_UTIME_H
28 #include <utime.h>
29 #else /* ! HAVE_GOOD_UTIME_H */
30 #ifdef HAVE_UTIMES
31 #include <sys/time.h>
32 #endif /* HAVE_UTIMES */
33 #endif /* ! HAVE_GOOD_UTIME_H */
35 #if ! defined (_WIN32) || defined (__CYGWIN32__)
36 static int simple_copy (const char *, const char *);
38 /* The number of bytes to copy at once. */
39 #define COPY_BUF 8192
41 /* Copy file FROM to file TO, performing no translations.
42 Return 0 if ok, -1 if error. */
44 static int
45 simple_copy (const char *from, const char *to)
47 int fromfd, tofd, nread;
48 int saved;
49 char buf[COPY_BUF];
51 fromfd = open (from, O_RDONLY | O_BINARY);
52 if (fromfd < 0)
53 return -1;
54 #ifdef O_CREAT
55 tofd = open (to, O_CREAT | O_WRONLY | O_TRUNC | O_BINARY, 0777);
56 #else
57 tofd = creat (to, 0777);
58 #endif
59 if (tofd < 0)
61 saved = errno;
62 close (fromfd);
63 errno = saved;
64 return -1;
66 while ((nread = read (fromfd, buf, sizeof buf)) > 0)
68 if (write (tofd, buf, nread) != nread)
70 saved = errno;
71 close (fromfd);
72 close (tofd);
73 errno = saved;
74 return -1;
77 saved = errno;
78 close (fromfd);
79 close (tofd);
80 if (nread < 0)
82 errno = saved;
83 return -1;
85 return 0;
87 #endif /* __CYGWIN32__ or not _WIN32 */
89 /* Set the times of the file DESTINATION to be the same as those in
90 STATBUF. */
92 void
93 set_times (const char *destination, const struct stat *statbuf)
95 int result;
98 #ifdef HAVE_GOOD_UTIME_H
99 struct utimbuf tb;
101 tb.actime = statbuf->st_atime;
102 tb.modtime = statbuf->st_mtime;
103 result = utime (destination, &tb);
104 #else /* ! HAVE_GOOD_UTIME_H */
105 #ifndef HAVE_UTIMES
106 long tb[2];
108 tb[0] = statbuf->st_atime;
109 tb[1] = statbuf->st_mtime;
110 result = utime (destination, tb);
111 #else /* HAVE_UTIMES */
112 struct timeval tv[2];
114 tv[0].tv_sec = statbuf->st_atime;
115 tv[0].tv_usec = 0;
116 tv[1].tv_sec = statbuf->st_mtime;
117 tv[1].tv_usec = 0;
118 result = utimes (destination, tv);
119 #endif /* HAVE_UTIMES */
120 #endif /* ! HAVE_GOOD_UTIME_H */
123 if (result != 0)
124 non_fatal (_("%s: cannot set time: %s"), destination, strerror (errno));
127 #ifndef S_ISLNK
128 #ifdef S_IFLNK
129 #define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK)
130 #else
131 #define S_ISLNK(m) 0
132 #define lstat stat
133 #endif
134 #endif
136 /* Rename FROM to TO, copying if TO is a link.
137 Return 0 if ok, -1 if error. */
140 smart_rename (const char *from, const char *to, int preserve_dates ATTRIBUTE_UNUSED)
142 bfd_boolean exists;
143 struct stat s;
144 int ret = 0;
146 exists = lstat (to, &s) == 0;
148 #if defined (_WIN32) && !defined (__CYGWIN32__)
149 /* Win32, unlike unix, will not erase `to' in `rename(from, to)' but
150 fail instead. Also, chown is not present. */
152 if (exists)
153 remove (to);
155 ret = rename (from, to);
156 if (ret != 0)
158 /* We have to clean up here. */
159 non_fatal (_("unable to rename '%s'; reason: %s"), to, strerror (errno));
160 unlink (from);
162 #else
163 /* Use rename only if TO is not a symbolic link and has
164 only one hard link, and we have permission to write to it. */
165 if (! exists
166 || (!S_ISLNK (s.st_mode)
167 && S_ISREG (s.st_mode)
168 && (s.st_mode & S_IWUSR)
169 && s.st_nlink == 1)
172 ret = rename (from, to);
173 if (ret == 0)
175 if (exists)
177 /* Try to preserve the permission bits and ownership of
178 TO. First get the mode right except for the setuid
179 bit. Then change the ownership. Then fix the setuid
180 bit. We do the chmod before the chown because if the
181 chown succeeds, and we are a normal user, we won't be
182 able to do the chmod afterward. We don't bother to
183 fix the setuid bit first because that might introduce
184 a fleeting security problem, and because the chown
185 will clear the setuid bit anyhow. We only fix the
186 setuid bit if the chown succeeds, because we don't
187 want to introduce an unexpected setuid file owned by
188 the user running objcopy. */
189 chmod (to, s.st_mode & 0777);
190 if (chown (to, s.st_uid, s.st_gid) >= 0)
191 chmod (to, s.st_mode & 07777);
194 else
196 /* We have to clean up here. */
197 non_fatal (_("unable to rename '%s'; reason: %s"), to, strerror (errno));
198 unlink (from);
201 else
203 ret = simple_copy (from, to);
204 if (ret != 0)
205 non_fatal (_("unable to copy file '%s'; reason: %s"), to, strerror (errno));
207 if (preserve_dates)
208 set_times (to, &s);
209 unlink (from);
211 #endif /* _WIN32 && !__CYGWIN32__ */
213 return ret;