]> andersk Git - gssapi-openssh.git/blobdiff - openssh/sftp-client.c
Import of OpenSSH 5.1p1
[gssapi-openssh.git] / openssh / sftp-client.c
index 69c6377859070b44555df41d8fb5fbe7eb63e286..5e39aa7d21bd6f8b309d1e774c0230ed7fc75aa9 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: sftp-client.c,v 1.81 2008/03/23 12:54:01 djm Exp $ */
+/* $OpenBSD: sftp-client.c,v 1.86 2008/06/26 06:10:09 djm Exp $ */
 /*
  * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
  *
@@ -24,6 +24,9 @@
 
 #include <sys/types.h>
 #include <sys/param.h>
+#ifdef HAVE_SYS_STATVFS_H
+#include <sys/statvfs.h>
+#endif
 #include "openbsd-compat/sys-queue.h"
 #ifdef HAVE_SYS_STAT_H
 # include <sys/stat.h>
@@ -65,7 +68,9 @@ struct sftp_conn {
        u_int num_requests;
        u_int version;
        u_int msg_id;
-#define SFTP_EXT_POSIX_RENAME  1
+#define SFTP_EXT_POSIX_RENAME  0x00000001
+#define SFTP_EXT_STATVFS       0x00000002
+#define SFTP_EXT_FSTATVFS      0x00000004
        u_int exts;
 };
 
@@ -238,6 +243,57 @@ get_decode_stat(int fd, u_int expected_id, int quiet)
        return(a);
 }
 
+static int
+get_decode_statvfs(int fd, struct sftp_statvfs *st, u_int expected_id,
+    int quiet)
+{
+       Buffer msg;
+       u_int type, id, flag;
+
+       buffer_init(&msg);
+       get_msg(fd, &msg);
+
+       type = buffer_get_char(&msg);
+       id = buffer_get_int(&msg);
+
+       debug3("Received statvfs reply T:%u I:%u", type, id);
+       if (id != expected_id)
+               fatal("ID mismatch (%u != %u)", id, expected_id);
+       if (type == SSH2_FXP_STATUS) {
+               int status = buffer_get_int(&msg);
+
+               if (quiet)
+                       debug("Couldn't statvfs: %s", fx2txt(status));
+               else
+                       error("Couldn't statvfs: %s", fx2txt(status));
+               buffer_free(&msg);
+               return -1;
+       } else if (type != SSH2_FXP_EXTENDED_REPLY) {
+               fatal("Expected SSH2_FXP_EXTENDED_REPLY(%u) packet, got %u",
+                   SSH2_FXP_EXTENDED_REPLY, type);
+       }
+
+       bzero(st, sizeof(*st));
+       st->f_bsize = buffer_get_int64(&msg);
+       st->f_frsize = buffer_get_int64(&msg);
+       st->f_blocks = buffer_get_int64(&msg);
+       st->f_bfree = buffer_get_int64(&msg);
+       st->f_bavail = buffer_get_int64(&msg);
+       st->f_files = buffer_get_int64(&msg);
+       st->f_ffree = buffer_get_int64(&msg);
+       st->f_favail = buffer_get_int64(&msg);
+       st->f_fsid = buffer_get_int64(&msg);
+       flag = buffer_get_int64(&msg);
+       st->f_namemax = buffer_get_int64(&msg);
+
+       st->f_flag = (flag & SSH2_FXE_STATVFS_ST_RDONLY) ? ST_RDONLY : 0;
+       st->f_flag |= (flag & SSH2_FXE_STATVFS_ST_NOSUID) ? ST_NOSUID : 0;
+
+       buffer_free(&msg);
+
+       return 0;
+}
+
 struct sftp_conn *
 do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests)
 {
@@ -270,10 +326,27 @@ do_init(int fd_in, int fd_out, u_int transfer_buflen, u_int num_requests)
        while (buffer_len(&msg) > 0) {
                char *name = buffer_get_string(&msg, NULL);
                char *value = buffer_get_string(&msg, NULL);
+               int known = 0;
 
-               debug2("Init extension: \"%s\"", name);
-               if (strcmp(name, "posix-rename@openssh.com") == 0)
+               if (strcmp(name, "posix-rename@openssh.com") == 0 &&
+                   strcmp(value, "1") == 0) {
                        exts |= SFTP_EXT_POSIX_RENAME;
+                       known = 1;
+               } else if (strcmp(name, "statvfs@openssh.com") == 0 &&
+                   strcmp(value, "2") == 0) {
+                       exts |= SFTP_EXT_STATVFS;
+                       known = 1;
+               } if (strcmp(name, "fstatvfs@openssh.com") == 0 &&
+                   strcmp(value, "2") == 0) {
+                       exts |= SFTP_EXT_FSTATVFS;
+                       known = 1;
+               }
+               if (known) {
+                       debug2("Server supports extension \"%s\" revision %s",
+                           name, value);
+               } else {
+                       debug2("Unrecognised server extension \"%s\"", name);
+               }
                xfree(name);
                xfree(value);
        }
@@ -749,6 +822,60 @@ do_readlink(struct sftp_conn *conn, char *path)
 }
 #endif
 
+int
+do_statvfs(struct sftp_conn *conn, const char *path, struct sftp_statvfs *st,
+    int quiet)
+{
+       Buffer msg;
+       u_int id;
+
+       if ((conn->exts & SFTP_EXT_STATVFS) == 0) {
+               error("Server does not support statvfs@openssh.com extension");
+               return -1;
+       }
+
+       id = conn->msg_id++;
+
+       buffer_init(&msg);
+       buffer_clear(&msg);
+       buffer_put_char(&msg, SSH2_FXP_EXTENDED);
+       buffer_put_int(&msg, id);
+       buffer_put_cstring(&msg, "statvfs@openssh.com");
+       buffer_put_cstring(&msg, path);
+       send_msg(conn->fd_out, &msg);
+       buffer_free(&msg);
+
+       return get_decode_statvfs(conn->fd_in, st, id, quiet);
+}
+
+#ifdef notyet
+int
+do_fstatvfs(struct sftp_conn *conn, const char *handle, u_int handle_len,
+    struct sftp_statvfs *st, int quiet)
+{
+       Buffer msg;
+       u_int id;
+
+       if ((conn->exts & SFTP_EXT_FSTATVFS) == 0) {
+               error("Server does not support fstatvfs@openssh.com extension");
+               return -1;
+       }
+
+       id = conn->msg_id++;
+
+       buffer_init(&msg);
+       buffer_clear(&msg);
+       buffer_put_char(&msg, SSH2_FXP_EXTENDED);
+       buffer_put_int(&msg, id);
+       buffer_put_cstring(&msg, "fstatvfs@openssh.com");
+       buffer_put_string(&msg, handle, handle_len);
+       send_msg(conn->fd_out, &msg);
+       buffer_free(&msg);
+
+       return get_decode_statvfs(conn->fd_in, st, id, quiet);
+}
+#endif
+
 static void
 send_read_request(int fd_out, u_int id, u_int64_t offset, u_int len,
     char *handle, u_int handle_len)
@@ -793,7 +920,7 @@ do_download(struct sftp_conn *conn, char *remote_path, char *local_path,
        if (a == NULL)
                return(-1);
 
-       /* XXX: should we preserve set[ug]id? */
+       /* Do not preserve set[ug]id here, as we do not preserve ownership */
        if (a->flags & SSH2_FILEXFER_ATTR_PERMISSIONS)
                mode = a->perm & 0777;
        else
@@ -1096,7 +1223,8 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
                        len = 0;
                else do
                        len = read(local_fd, data, conn->transfer_buflen);
-               while ((len == -1) && (errno == EINTR || errno == EAGAIN));
+               while ((len == -1) &&
+                   (errno == EINTR || errno == EAGAIN || errno == EWOULDBLOCK));
 
                if (len == -1)
                        fatal("Couldn't read from \"%s\": %s", local_path,
This page took 0.087224 seconds and 4 git commands to generate.