summaryrefslogtreecommitdiff
path: root/usr.bin
diff options
context:
space:
mode:
authorDarren Tucker <dtucker@cvs.openbsd.org>2004-06-25 05:38:49 +0000
committerDarren Tucker <dtucker@cvs.openbsd.org>2004-06-25 05:38:49 +0000
commitcb6140012fe1ca285c4675a0a1f982665adbdb78 (patch)
treecc6393f1b53a97fc2e4d5a198f8358f10bd383fb /usr.bin
parent744669176f44b052fa178d68620d3a70d2fb2a44 (diff)
Fall back to stat+rename if filesystem doesn't doesn't support hard
links. bz#823, ok djm@
Diffstat (limited to 'usr.bin')
-rw-r--r--usr.bin/ssh/sftp-server.c24
1 files changed, 20 insertions, 4 deletions
diff --git a/usr.bin/ssh/sftp-server.c b/usr.bin/ssh/sftp-server.c
index 23f1ed6df4f..a660bef98cb 100644
--- a/usr.bin/ssh/sftp-server.c
+++ b/usr.bin/ssh/sftp-server.c
@@ -14,7 +14,7 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "includes.h"
-RCSID("$OpenBSD: sftp-server.c,v 1.46 2004/06/21 17:36:31 avsm Exp $");
+RCSID("$OpenBSD: sftp-server.c,v 1.47 2004/06/25 05:38:48 dtucker Exp $");
#include "buffer.h"
#include "bufaux.h"
@@ -819,9 +819,25 @@ process_rename(void)
status = errno_to_portable(errno);
else if (S_ISREG(sb.st_mode)) {
/* Race-free rename of regular files */
- if (link(oldpath, newpath) == -1)
- status = errno_to_portable(errno);
- else if (unlink(oldpath) == -1) {
+ if (link(oldpath, newpath) == -1) {
+ if (errno == EOPNOTSUPP) {
+ struct stat st;
+
+ /*
+ * fs doesn't support links, so fall back to
+ * stat+rename. This is racy.
+ */
+ if (stat(newpath, &st) == -1) {
+ if (rename(oldpath, newpath) == -1)
+ status =
+ errno_to_portable(errno);
+ else
+ status = SSH2_FX_OK;
+ }
+ } else {
+ status = errno_to_portable(errno);
+ }
+ } else if (unlink(oldpath) == -1) {
status = errno_to_portable(errno);
/* clean spare link */
unlink(newpath);