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., 59 Temple Place - Suite 330, Boston, MA 19 02111-1307, 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 40static int simple_copy (const char *, const char *); 41 42/* The number of bytes to copy at once. */ 43#define COPY_BUF 8192 44 45/* Copy file FROM to file TO, performing no translations. 46 Return 0 if ok, -1 if error. */ 47 48static int 49simple_copy (const char *from, const char *to) 50{ 51 int fromfd, tofd, nread; 52 int saved; 53 char buf[COPY_BUF]; 54 55 fromfd = open (from, O_RDONLY | O_BINARY); 56 if (fromfd < 0) 57 return -1; 58#ifdef O_CREAT 59 tofd = open (to, O_CREAT | O_WRONLY | O_TRUNC | O_BINARY, 0777); 60#else 61 tofd = creat (to, 0777); 62#endif 63 if (tofd < 0) 64 { 65 saved = errno; 66 close (fromfd); 67 errno = saved; 68 return -1; 69 } 70 while ((nread = read (fromfd, buf, sizeof buf)) > 0) 71 { 72 if (write (tofd, buf, nread) != nread) 73 { 74 saved = errno; 75 close (fromfd); 76 close (tofd); 77 errno = saved; 78 return -1; 79 } 80 } 81 saved = errno; 82 close (fromfd); 83 close (tofd); 84 if (nread < 0) 85 { 86 errno = saved; 87 return -1; 88 } 89 return 0; 90} 91 92/* Set the times of the file DESTINATION to be the same as those in 93 STATBUF. */ 94 95void 96set_times (const char *destination, const struct stat *statbuf) 97{ 98 int result; 99 100 { 101#ifdef HAVE_GOOD_UTIME_H 102 struct utimbuf tb; 103 104 tb.actime = statbuf->st_atime; 105 tb.modtime = statbuf->st_mtime; 106 result = utime (destination, &tb); 107#else /* ! HAVE_GOOD_UTIME_H */ 108#ifndef HAVE_UTIMES 109 long tb[2]; 110 111 tb[0] = statbuf->st_atime; 112 tb[1] = statbuf->st_mtime; 113 result = utime (destination, tb); 114#else /* HAVE_UTIMES */ 115 struct timeval tv[2]; 116 117 tv[0].tv_sec = statbuf->st_atime; 118 tv[0].tv_usec = 0; 119 tv[1].tv_sec = statbuf->st_mtime; 120 tv[1].tv_usec = 0; 121 result = utimes (destination, tv); 122#endif /* HAVE_UTIMES */ 123#endif /* ! HAVE_GOOD_UTIME_H */ 124 } 125 126 if (result != 0) 127 non_fatal (_("%s: cannot set time: %s"), destination, strerror (errno)); 128} 129 130#ifndef S_ISLNK 131#ifdef S_IFLNK 132#define S_ISLNK(m) (((m) & S_IFMT) == S_IFLNK) 133#else 134#define S_ISLNK(m) 0 135#define lstat stat 136#endif 137#endif 138 139/* Rename FROM to TO, copying if TO is a link. 140 Return 0 if ok, -1 if error. */ 141 142int 143smart_rename (const char *from, const char *to, int preserve_dates) 144{ 145 bfd_boolean exists; 146 struct stat s; 147 int ret = 0; 148 149 exists = lstat (to, &s) == 0; 150 151#if defined (_WIN32) && !defined (__CYGWIN32__) 152 /* Win32, unlike unix, will not erase `to' in `rename(from, to)' but 153 fail instead. Also, chown is not present. */ 154 155 if (exists) 156 remove (to); 157 158 ret = rename (from, to); 159 if (ret != 0) 160 { 161 /* We have to clean up here. */ 162 non_fatal (_("unable to rename '%s' reason: %s"), to, strerror (errno)); 163 unlink (from); 164 } 165#else 166 /* Use rename only if TO is not a symbolic link and has 167 only one hard link, and we have permission to write to it. */ 168 if (! exists 169 || (!S_ISLNK (s.st_mode) 170 && S_ISREG (s.st_mode) 171 && (s.st_mode & S_IWUSR) 172 && s.st_nlink == 1) 173 ) 174 { 175 ret = rename (from, to); 176 if (ret == 0) 177 { 178 if (exists) 179 { 180 /* Try to preserve the permission bits of TO. Don't 181 * restore special bits. */ 182 chmod (to, s.st_mode & 0777); 183 } 184 } 185 else 186 { 187 /* We have to clean up here. */ 188 non_fatal (_("unable to rename '%s' reason: %s"), to, strerror (errno)); 189 unlink (from); 190 } 191 } 192 else 193 { 194 ret = simple_copy (from, to); 195 if (ret != 0) 196 non_fatal (_("unable to copy file '%s' reason: %s"), to, strerror (errno)); 197 198 if (preserve_dates) 199 set_times (to, &s); 200 unlink (from); 201 } 202#endif /* _WIN32 && !__CYGWIN32__ */ 203 204 return ret; 205} 206