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